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 "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/mempool-internals.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 sigbuffer_add_value (&buf, 0x07);
826 sigbuffer_add_value (&buf, nl);
827 for (i = 0; i < nl; ++i) {
828 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
831 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
833 encode_reflection_type (assembly, lb->type, &buf);
835 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
836 sigbuffer_free (&buf);
838 if (assembly->standalonesig_cache == NULL)
839 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
840 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
844 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
845 idx = table->next_idx ++;
847 alloc_table (table, table->rows);
848 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
850 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
852 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
858 method_count_clauses (MonoReflectionILGen *ilgen)
860 guint32 num_clauses = 0;
863 MonoILExceptionInfo *ex_info;
864 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
865 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
866 if (ex_info->handlers)
867 num_clauses += mono_array_length (ex_info->handlers);
875 static MonoExceptionClause*
876 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
878 MonoExceptionClause *clauses;
879 MonoExceptionClause *clause;
880 MonoILExceptionInfo *ex_info;
881 MonoILExceptionBlock *ex_block;
882 guint32 finally_start;
883 int i, j, clause_index;;
885 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
888 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
889 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
890 finally_start = ex_info->start + ex_info->len;
891 if (!ex_info->handlers)
893 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
894 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
895 clause = &(clauses [clause_index]);
897 clause->flags = ex_block->type;
898 clause->try_offset = ex_info->start;
900 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
901 clause->try_len = finally_start - ex_info->start;
903 clause->try_len = ex_info->len;
904 clause->handler_offset = ex_block->start;
905 clause->handler_len = ex_block->len;
906 if (ex_block->extype) {
907 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
909 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
910 clause->data.filter_offset = ex_block->filter_offset;
912 clause->data.filter_offset = 0;
914 finally_start = ex_block->start + ex_block->len;
924 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
930 gint32 num_locals = 0;
931 gint32 num_exception = 0;
934 char fat_header [12];
937 guint32 local_sig = 0;
938 guint32 header_size = 12;
941 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
942 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
946 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
948 code = mb->ilgen->code;
949 code_size = mb->ilgen->code_len;
950 max_stack = mb->ilgen->max_stack;
951 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
952 if (mb->ilgen->ex_handlers)
953 num_exception = method_count_clauses (mb->ilgen);
957 char *name = mono_string_to_utf8 (mb->name);
958 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
959 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
962 mono_raise_exception (exception);
965 code_size = mono_array_length (code);
966 max_stack = 8; /* we probably need to run a verifier on the code... */
969 stream_data_align (&assembly->code);
971 /* check for exceptions, maxstack, locals */
972 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
974 if (code_size < 64 && !(code_size & 1)) {
975 flags = (code_size << 2) | 0x2;
976 } else if (code_size < 32 && (code_size & 1)) {
977 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
981 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
982 /* add to the fixup todo list */
983 if (mb->ilgen && mb->ilgen->num_token_fixups)
984 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
985 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
986 return assembly->text_rva + idx;
990 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
992 * FIXME: need to set also the header size in fat_flags.
993 * (and more sects and init locals flags)
997 fat_flags |= METHOD_HEADER_MORE_SECTS;
999 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1000 fat_header [0] = fat_flags;
1001 fat_header [1] = (header_size / 4 ) << 4;
1002 short_value = GUINT16_TO_LE (max_stack);
1003 memcpy (fat_header + 2, &short_value, 2);
1004 int_value = GUINT32_TO_LE (code_size);
1005 memcpy (fat_header + 4, &int_value, 4);
1006 int_value = GUINT32_TO_LE (local_sig);
1007 memcpy (fat_header + 8, &int_value, 4);
1008 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1009 /* add to the fixup todo list */
1010 if (mb->ilgen && mb->ilgen->num_token_fixups)
1011 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1013 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1014 if (num_exception) {
1015 unsigned char sheader [4];
1016 MonoILExceptionInfo * ex_info;
1017 MonoILExceptionBlock * ex_block;
1020 stream_data_align (&assembly->code);
1021 /* always use fat format for now */
1022 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1023 num_exception *= 6 * sizeof (guint32);
1024 num_exception += 4; /* include the size of the header */
1025 sheader [1] = num_exception & 0xff;
1026 sheader [2] = (num_exception >> 8) & 0xff;
1027 sheader [3] = (num_exception >> 16) & 0xff;
1028 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1029 /* fat header, so we are already aligned */
1031 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1032 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1033 if (ex_info->handlers) {
1034 int finally_start = ex_info->start + ex_info->len;
1035 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1037 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1039 val = GUINT32_TO_LE (ex_block->type);
1040 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1042 val = GUINT32_TO_LE (ex_info->start);
1043 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1044 /* need fault, too, probably */
1045 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1046 val = GUINT32_TO_LE (finally_start - ex_info->start);
1048 val = GUINT32_TO_LE (ex_info->len);
1049 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1050 /* handler offset */
1051 val = GUINT32_TO_LE (ex_block->start);
1052 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1054 val = GUINT32_TO_LE (ex_block->len);
1055 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1056 finally_start = ex_block->start + ex_block->len;
1057 if (ex_block->extype) {
1058 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1060 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1061 val = ex_block->filter_offset;
1065 val = GUINT32_TO_LE (val);
1066 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1067 /*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",
1068 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);*/
1071 g_error ("No clauses for ex info block %d", i);
1075 return assembly->text_rva + idx;
1079 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1082 MonoDynamicTable *table;
1085 table = &assembly->tables [table_idx];
1087 g_assert (col < table->columns);
1089 values = table->values + table->columns;
1090 for (i = 1; i <= table->rows; ++i) {
1091 if (values [col] == token)
1093 values += table->columns;
1099 * LOCKING: Acquires the loader lock.
1101 static MonoCustomAttrInfo*
1102 lookup_custom_attr (MonoImage *image, gpointer member)
1104 MonoCustomAttrInfo* res;
1106 mono_loader_lock ();
1107 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1108 mono_loader_unlock ();
1113 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1117 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1119 /* FIXME: Need to do more checks */
1120 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1121 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1123 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1130 static MonoCustomAttrInfo*
1131 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1133 int i, index, count, not_visible;
1134 MonoCustomAttrInfo *ainfo;
1135 MonoReflectionCustomAttr *cattr;
1139 /* FIXME: check in assembly the Run flag is set */
1141 count = mono_array_length (cattrs);
1143 /* Skip nonpublic attributes since MS.NET seems to do the same */
1144 /* FIXME: This needs to be done more globally */
1146 for (i = 0; i < count; ++i) {
1147 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1148 if (!custom_attr_visible (image, cattr))
1151 count -= not_visible;
1153 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1155 ainfo->image = image;
1156 ainfo->num_attrs = count;
1157 ainfo->cached = mp != NULL;
1159 mono_loader_lock ();
1160 for (i = 0; i < count; ++i) {
1161 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1162 if (custom_attr_visible (image, cattr)) {
1163 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1164 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1165 ainfo->attrs [index].ctor = cattr->ctor->method;
1166 ainfo->attrs [index].data = saved;
1167 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1171 mono_loader_unlock ();
1177 * LOCKING: Acquires the loader lock.
1180 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1182 MonoCustomAttrInfo *ainfo, *tmp;
1184 if (!cattrs || !mono_array_length (cattrs))
1187 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1188 mono_loader_lock ();
1189 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1191 mono_custom_attrs_free (tmp);
1192 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1193 mono_loader_unlock ();
1197 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1204 * idx is the table index of the object
1205 * type is one of MONO_CUSTOM_ATTR_*
1208 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1210 MonoDynamicTable *table;
1211 MonoReflectionCustomAttr *cattr;
1213 guint32 count, i, token;
1215 char *p = blob_size;
1217 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1220 count = mono_array_length (cattrs);
1221 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1222 table->rows += count;
1223 alloc_table (table, table->rows);
1224 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1225 idx <<= MONO_CUSTOM_ATTR_BITS;
1227 for (i = 0; i < count; ++i) {
1228 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1229 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1230 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1231 type = mono_metadata_token_index (token);
1232 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1233 switch (mono_metadata_token_table (token)) {
1234 case MONO_TABLE_METHOD:
1235 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1237 case MONO_TABLE_MEMBERREF:
1238 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1241 g_warning ("got wrong token in custom attr");
1244 values [MONO_CUSTOM_ATTR_TYPE] = type;
1246 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1247 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1248 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1249 values += MONO_CUSTOM_ATTR_SIZE;
1255 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1257 MonoDynamicTable *table;
1259 guint32 count, i, idx;
1260 MonoReflectionPermissionSet *perm;
1265 count = mono_array_length (permissions);
1266 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1267 table->rows += count;
1268 alloc_table (table, table->rows);
1270 for (i = 0; i < mono_array_length (permissions); ++i) {
1271 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1273 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1275 idx = mono_metadata_token_index (parent_token);
1276 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1277 switch (mono_metadata_token_table (parent_token)) {
1278 case MONO_TABLE_TYPEDEF:
1279 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1281 case MONO_TABLE_METHOD:
1282 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1284 case MONO_TABLE_ASSEMBLY:
1285 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1288 g_assert_not_reached ();
1291 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1292 values [MONO_DECL_SECURITY_PARENT] = idx;
1293 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1300 * Fill in the MethodDef and ParamDef tables for a method.
1301 * This is used for both normal methods and constructors.
1304 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1306 MonoDynamicTable *table;
1310 /* room in this table is already allocated */
1311 table = &assembly->tables [MONO_TABLE_METHOD];
1312 *mb->table_idx = table->next_idx ++;
1313 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1314 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1315 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1316 values [MONO_METHOD_FLAGS] = mb->attrs;
1317 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1318 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1319 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1321 table = &assembly->tables [MONO_TABLE_PARAM];
1322 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1324 mono_image_add_decl_security (assembly,
1325 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1328 MonoDynamicTable *mtable;
1331 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1332 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1335 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1336 if (mono_array_get (mb->pinfo, gpointer, i))
1339 table->rows += count;
1340 alloc_table (table, table->rows);
1341 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1342 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1343 MonoReflectionParamBuilder *pb;
1344 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1345 values [MONO_PARAM_FLAGS] = pb->attrs;
1346 values [MONO_PARAM_SEQUENCE] = i;
1347 if (pb->name != NULL) {
1348 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1350 values [MONO_PARAM_NAME] = 0;
1352 values += MONO_PARAM_SIZE;
1353 if (pb->marshal_info) {
1355 alloc_table (mtable, mtable->rows);
1356 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1357 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1358 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1360 pb->table_idx = table->next_idx++;
1361 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1362 guint32 field_type = 0;
1363 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1365 alloc_table (mtable, mtable->rows);
1366 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1367 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1368 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1369 mvalues [MONO_CONSTANT_TYPE] = field_type;
1370 mvalues [MONO_CONSTANT_PADDING] = 0;
1378 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1380 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1382 rmb->ilgen = mb->ilgen;
1383 rmb->rtype = mb->rtype;
1384 rmb->parameters = mb->parameters;
1385 rmb->generic_params = mb->generic_params;
1386 rmb->generic_container = mb->generic_container;
1387 rmb->opt_types = NULL;
1388 rmb->pinfo = mb->pinfo;
1389 rmb->attrs = mb->attrs;
1390 rmb->iattrs = mb->iattrs;
1391 rmb->call_conv = mb->call_conv;
1392 rmb->code = mb->code;
1393 rmb->type = mb->type;
1394 rmb->name = mb->name;
1395 rmb->table_idx = &mb->table_idx;
1396 rmb->init_locals = mb->init_locals;
1397 rmb->skip_visibility = FALSE;
1398 rmb->return_modreq = mb->return_modreq;
1399 rmb->return_modopt = mb->return_modopt;
1400 rmb->param_modreq = mb->param_modreq;
1401 rmb->param_modopt = mb->param_modopt;
1402 rmb->permissions = mb->permissions;
1403 rmb->mhandle = mb->mhandle;
1408 rmb->charset = mb->charset;
1409 rmb->extra_flags = mb->extra_flags;
1410 rmb->native_cc = mb->native_cc;
1411 rmb->dllentry = mb->dllentry;
1417 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1419 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1421 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1423 rmb->ilgen = mb->ilgen;
1424 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1425 rmb->parameters = mb->parameters;
1426 rmb->generic_params = NULL;
1427 rmb->generic_container = NULL;
1428 rmb->opt_types = NULL;
1429 rmb->pinfo = mb->pinfo;
1430 rmb->attrs = mb->attrs;
1431 rmb->iattrs = mb->iattrs;
1432 rmb->call_conv = mb->call_conv;
1434 rmb->type = mb->type;
1435 rmb->name = mono_string_new (mono_domain_get (), name);
1436 rmb->table_idx = &mb->table_idx;
1437 rmb->init_locals = mb->init_locals;
1438 rmb->skip_visibility = FALSE;
1439 rmb->return_modreq = NULL;
1440 rmb->return_modopt = NULL;
1441 rmb->param_modreq = mb->param_modreq;
1442 rmb->param_modopt = mb->param_modopt;
1443 rmb->permissions = mb->permissions;
1444 rmb->mhandle = mb->mhandle;
1450 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1452 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1454 rmb->ilgen = mb->ilgen;
1455 rmb->rtype = mb->rtype;
1456 rmb->parameters = mb->parameters;
1457 rmb->generic_params = NULL;
1458 rmb->generic_container = NULL;
1459 rmb->opt_types = NULL;
1461 rmb->attrs = mb->attrs;
1463 rmb->call_conv = mb->call_conv;
1465 rmb->type = (MonoObject *) mb->owner;
1466 rmb->name = mb->name;
1467 rmb->table_idx = NULL;
1468 rmb->init_locals = mb->init_locals;
1469 rmb->skip_visibility = mb->skip_visibility;
1470 rmb->return_modreq = NULL;
1471 rmb->return_modopt = NULL;
1472 rmb->param_modreq = NULL;
1473 rmb->param_modopt = NULL;
1474 rmb->permissions = NULL;
1475 rmb->mhandle = mb->mhandle;
1481 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1483 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1484 MonoDynamicTable *table;
1488 if (!mb->override_method)
1491 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1493 alloc_table (table, table->rows);
1494 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1495 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1496 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1498 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1499 switch (mono_metadata_token_table (tok)) {
1500 case MONO_TABLE_MEMBERREF:
1501 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1503 case MONO_TABLE_METHOD:
1504 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1507 g_assert_not_reached ();
1509 values [MONO_METHODIMPL_DECLARATION] = tok;
1513 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1515 MonoDynamicTable *table;
1517 ReflectionMethodBuilder rmb;
1520 reflection_methodbuilder_from_method_builder (&rmb, mb);
1522 mono_image_basic_method (&rmb, assembly);
1523 mb->table_idx = *rmb.table_idx;
1525 if (mb->dll) { /* It's a P/Invoke method */
1527 /* map CharSet values to on-disk values */
1528 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1529 int extra_flags = mb->extra_flags;
1530 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1532 alloc_table (table, table->rows);
1533 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1535 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1536 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1538 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1540 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1541 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1542 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1543 table = &assembly->tables [MONO_TABLE_MODULEREF];
1545 alloc_table (table, table->rows);
1546 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1547 values [MONO_IMPLMAP_SCOPE] = table->rows;
1551 if (mb->generic_params) {
1552 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1553 table->rows += mono_array_length (mb->generic_params);
1554 alloc_table (table, table->rows);
1555 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1556 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1558 mono_image_get_generic_param_info (
1559 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1566 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1568 ReflectionMethodBuilder rmb;
1570 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1572 mono_image_basic_method (&rmb, assembly);
1573 mb->table_idx = *rmb.table_idx;
1577 type_get_fully_qualified_name (MonoType *type)
1579 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1583 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1587 klass = my_mono_class_from_mono_type (type);
1589 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1590 ta = klass->image->assembly;
1591 if (ta->dynamic || (ta == ass)) {
1592 if (klass->generic_class || klass->generic_container)
1593 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1594 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1596 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1599 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1603 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1608 if (!assembly->save)
1611 sigbuffer_init (&buf, 32);
1613 sigbuffer_add_value (&buf, 0x06);
1614 /* encode custom attributes before the type */
1615 /* FIXME: This should probably go in encode_type () */
1616 if (type->num_mods) {
1617 for (i = 0; i < type->num_mods; ++i) {
1618 if (type->modifiers [i].required)
1619 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1621 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1622 sigbuffer_add_value (&buf, type->modifiers [i].token);
1625 encode_type (assembly, type, &buf);
1626 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1627 sigbuffer_free (&buf);
1632 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1637 sigbuffer_init (&buf, 32);
1639 sigbuffer_add_value (&buf, 0x06);
1640 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1641 /* encode custom attributes before the type */
1642 encode_reflection_type (assembly, fb->type, &buf);
1643 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1644 sigbuffer_free (&buf);
1649 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1650 char blob_size [64];
1651 char *b = blob_size;
1654 guint32 idx = 0, len = 0, dummy = 0;
1656 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1657 guint32 fpa_double [2];
1662 p = buf = g_malloc (64);
1664 *ret_type = MONO_TYPE_CLASS;
1666 box_val = (char*)&dummy;
1668 box_val = ((char*)val) + sizeof (MonoObject);
1669 *ret_type = val->vtable->klass->byval_arg.type;
1672 switch (*ret_type) {
1673 case MONO_TYPE_BOOLEAN:
1678 case MONO_TYPE_CHAR:
1695 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1696 fpa_p = (guint32*)box_val;
1697 fpa_double [0] = fpa_p [1];
1698 fpa_double [1] = fpa_p [0];
1699 box_val = (char*)fpa_double;
1703 case MONO_TYPE_VALUETYPE:
1704 if (val->vtable->klass->enumtype) {
1705 *ret_type = val->vtable->klass->enum_basetype->type;
1708 g_error ("we can't encode valuetypes");
1709 case MONO_TYPE_CLASS:
1711 case MONO_TYPE_STRING: {
1712 MonoString *str = (MonoString*)val;
1713 /* there is no signature */
1714 len = str->length * 2;
1715 mono_metadata_encode_value (len, b, &b);
1716 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1718 char *swapped = g_malloc (2 * mono_string_length (str));
1719 const char *p = (const char*)mono_string_chars (str);
1721 swap_with_size (swapped, p, 2, mono_string_length (str));
1722 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1726 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1732 case MONO_TYPE_GENERICINST:
1733 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1736 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1739 /* there is no signature */
1740 mono_metadata_encode_value (len, b, &b);
1741 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1742 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1743 swap_with_size (blob_size, box_val, len, 1);
1744 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1746 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1754 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1759 sigbuffer_init (&buf, 32);
1761 sigbuffer_add_value (&buf, minfo->type);
1763 switch (minfo->type) {
1764 case MONO_NATIVE_BYVALTSTR:
1765 case MONO_NATIVE_BYVALARRAY:
1766 sigbuffer_add_value (&buf, minfo->count);
1768 case MONO_NATIVE_LPARRAY:
1769 if (minfo->eltype || minfo->has_size) {
1770 sigbuffer_add_value (&buf, minfo->eltype);
1771 if (minfo->has_size) {
1772 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1773 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1775 /* LAMESPEC: ElemMult is undocumented */
1776 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1780 case MONO_NATIVE_CUSTOM:
1782 str = mono_string_to_utf8 (minfo->guid);
1784 sigbuffer_add_value (&buf, len);
1785 sigbuffer_add_mem (&buf, str, len);
1788 sigbuffer_add_value (&buf, 0);
1790 /* native type name */
1791 sigbuffer_add_value (&buf, 0);
1792 /* custom marshaler type name */
1793 if (minfo->marshaltype || minfo->marshaltyperef) {
1794 if (minfo->marshaltyperef)
1795 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1797 str = mono_string_to_utf8 (minfo->marshaltype);
1799 sigbuffer_add_value (&buf, len);
1800 sigbuffer_add_mem (&buf, str, len);
1803 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1804 sigbuffer_add_value (&buf, 0);
1806 if (minfo->mcookie) {
1807 str = mono_string_to_utf8 (minfo->mcookie);
1809 sigbuffer_add_value (&buf, len);
1810 sigbuffer_add_mem (&buf, str, len);
1813 sigbuffer_add_value (&buf, 0);
1819 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1820 sigbuffer_free (&buf);
1825 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1827 MonoDynamicTable *table;
1830 /* maybe this fixup should be done in the C# code */
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1832 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1833 table = &assembly->tables [MONO_TABLE_FIELD];
1834 fb->table_idx = table->next_idx ++;
1835 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1836 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1837 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1838 values [MONO_FIELD_FLAGS] = fb->attrs;
1839 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1841 if (fb->offset != -1) {
1842 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1844 alloc_table (table, table->rows);
1845 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1846 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1847 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1849 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1850 guint32 field_type = 0;
1851 table = &assembly->tables [MONO_TABLE_CONSTANT];
1853 alloc_table (table, table->rows);
1854 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1855 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1856 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1857 values [MONO_CONSTANT_TYPE] = field_type;
1858 values [MONO_CONSTANT_PADDING] = 0;
1860 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1862 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1864 alloc_table (table, table->rows);
1865 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1866 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1868 * We store it in the code section because it's simpler for now.
1871 if (mono_array_length (fb->rva_data) >= 10)
1872 stream_data_align (&assembly->code);
1873 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1875 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1876 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1878 if (fb->marshal_info) {
1879 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1881 alloc_table (table, table->rows);
1882 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1883 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1884 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1889 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1892 guint32 nparams = 0;
1893 MonoReflectionMethodBuilder *mb = fb->get_method;
1894 MonoReflectionMethodBuilder *smb = fb->set_method;
1897 if (mb && mb->parameters)
1898 nparams = mono_array_length (mb->parameters);
1899 if (!mb && smb && smb->parameters)
1900 nparams = mono_array_length (smb->parameters) - 1;
1901 sigbuffer_init (&buf, 32);
1902 sigbuffer_add_byte (&buf, 0x08);
1903 sigbuffer_add_value (&buf, nparams);
1905 encode_reflection_type (assembly, mb->rtype, &buf);
1906 for (i = 0; i < nparams; ++i) {
1907 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1908 encode_reflection_type (assembly, pt, &buf);
1910 } else if (smb && smb->parameters) {
1911 /* the property type is the last param */
1912 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1913 for (i = 0; i < nparams; ++i) {
1914 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1915 encode_reflection_type (assembly, pt, &buf);
1918 encode_reflection_type (assembly, fb->type, &buf);
1921 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1922 sigbuffer_free (&buf);
1927 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1929 MonoDynamicTable *table;
1931 guint num_methods = 0;
1935 * we need to set things in the following tables:
1936 * PROPERTYMAP (info already filled in _get_type_info ())
1937 * PROPERTY (rows already preallocated in _get_type_info ())
1938 * METHOD (method info already done with the generic method code)
1941 table = &assembly->tables [MONO_TABLE_PROPERTY];
1942 pb->table_idx = table->next_idx ++;
1943 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1944 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1945 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1946 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1948 /* FIXME: we still don't handle 'other' methods */
1949 if (pb->get_method) num_methods ++;
1950 if (pb->set_method) num_methods ++;
1952 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1953 table->rows += num_methods;
1954 alloc_table (table, table->rows);
1956 if (pb->get_method) {
1957 semaidx = table->next_idx ++;
1958 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1959 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1960 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1961 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1963 if (pb->set_method) {
1964 semaidx = table->next_idx ++;
1965 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1966 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1967 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1968 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1973 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1975 MonoDynamicTable *table;
1977 guint num_methods = 0;
1981 * we need to set things in the following tables:
1982 * EVENTMAP (info already filled in _get_type_info ())
1983 * EVENT (rows already preallocated in _get_type_info ())
1984 * METHOD (method info already done with the generic method code)
1987 table = &assembly->tables [MONO_TABLE_EVENT];
1988 eb->table_idx = table->next_idx ++;
1989 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1990 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1991 values [MONO_EVENT_FLAGS] = eb->attrs;
1992 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1995 * FIXME: we still don't handle 'other' methods
1997 if (eb->add_method) num_methods ++;
1998 if (eb->remove_method) num_methods ++;
1999 if (eb->raise_method) num_methods ++;
2001 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2002 table->rows += num_methods;
2003 alloc_table (table, table->rows);
2005 if (eb->add_method) {
2006 semaidx = table->next_idx ++;
2007 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2008 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2009 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2010 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2012 if (eb->remove_method) {
2013 semaidx = table->next_idx ++;
2014 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2015 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2016 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2017 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2019 if (eb->raise_method) {
2020 semaidx = table->next_idx ++;
2021 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2022 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2023 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2024 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2029 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2031 MonoDynamicTable *table;
2032 guint32 num_constraints, i;
2036 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2037 num_constraints = gparam->iface_constraints ?
2038 mono_array_length (gparam->iface_constraints) : 0;
2039 table->rows += num_constraints;
2040 if (gparam->base_type)
2042 alloc_table (table, table->rows);
2044 if (gparam->base_type) {
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2048 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2049 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2050 assembly, gparam->base_type->type);
2053 for (i = 0; i < num_constraints; i++) {
2054 MonoReflectionType *constraint = mono_array_get (
2055 gparam->iface_constraints, gpointer, i);
2057 table_idx = table->next_idx ++;
2058 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2060 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2061 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2062 assembly, constraint->type);
2067 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2069 GenericParamTableEntry *entry;
2072 * The GenericParam table must be sorted according to the `owner' field.
2073 * We need to do this sorting prior to writing the GenericParamConstraint
2074 * table, since we have to use the final GenericParam table indices there
2075 * and they must also be sorted.
2078 entry = g_new0 (GenericParamTableEntry, 1);
2079 entry->owner = owner;
2081 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2082 MONO_GC_REGISTER_ROOT (entry->gparam);
2084 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2086 g_ptr_array_add (assembly->gen_params, entry);
2090 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2092 MonoDynamicTable *table;
2093 MonoGenericParam *param;
2097 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2098 table_idx = table->next_idx ++;
2099 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2101 param = entry->gparam->type.type->data.generic_param;
2103 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2104 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2105 values [MONO_GENERICPARAM_NUMBER] = param->num;
2106 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2108 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2110 encode_constraints (entry->gparam, table_idx, assembly);
2114 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2116 MonoDynamicTable *table;
2119 guint32 cols [MONO_ASSEMBLY_SIZE];
2123 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2126 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2127 table = &assembly->tables [MONO_TABLE_MODULEREF];
2128 token = table->next_idx ++;
2130 alloc_table (table, table->rows);
2131 values = table->values + token * MONO_MODULEREF_SIZE;
2132 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2134 token <<= MONO_RESOLTION_SCOPE_BITS;
2135 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2136 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2141 if (image->assembly->dynamic)
2143 memset (cols, 0, sizeof (cols));
2145 /* image->assembly->image is the manifest module */
2146 image = image->assembly->image;
2147 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2150 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2151 token = table->next_idx ++;
2153 alloc_table (table, table->rows);
2154 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2155 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2156 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2157 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2158 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2159 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2160 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2161 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2162 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2164 if (strcmp ("", image->assembly->aname.culture)) {
2165 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2166 image->assembly->aname.culture);
2169 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2170 guchar pubtoken [9];
2172 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2173 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2175 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2177 token <<= MONO_RESOLTION_SCOPE_BITS;
2178 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2179 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2184 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2186 MonoDynamicTable *table;
2191 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2194 sigbuffer_init (&buf, 32);
2195 switch (type->type) {
2196 case MONO_TYPE_FNPTR:
2198 case MONO_TYPE_SZARRAY:
2199 case MONO_TYPE_ARRAY:
2201 case MONO_TYPE_MVAR:
2202 case MONO_TYPE_GENERICINST:
2203 encode_type (assembly, type, &buf);
2205 case MONO_TYPE_CLASS:
2206 case MONO_TYPE_VALUETYPE: {
2207 MonoClass *k = mono_class_from_mono_type (type);
2208 if (!k || !k->generic_container) {
2209 sigbuffer_free (&buf);
2212 encode_type (assembly, type, &buf);
2216 sigbuffer_free (&buf);
2220 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2221 if (assembly->save) {
2222 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2223 alloc_table (table, table->rows + 1);
2224 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2225 values [MONO_TYPESPEC_SIGNATURE] = token;
2227 sigbuffer_free (&buf);
2229 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2230 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2236 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2238 MonoDynamicTable *table;
2240 guint32 token, scope, enclosing;
2243 /* if the type requires a typespec, we must try that first*/
2244 if (try_typespec && (token = create_typespec (assembly, type)))
2246 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2249 klass = my_mono_class_from_mono_type (type);
2251 klass = mono_class_from_mono_type (type);
2254 * If it's in the same module and not a generic type parameter:
2256 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2257 (type->type != MONO_TYPE_MVAR)) {
2258 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2259 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2260 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2264 if (klass->nested_in) {
2265 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2266 /* get the typeref idx of the enclosing type */
2267 enclosing >>= MONO_TYPEDEFORREF_BITS;
2268 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2270 scope = resolution_scope_from_image (assembly, klass->image);
2272 table = &assembly->tables [MONO_TABLE_TYPEREF];
2273 if (assembly->save) {
2274 alloc_table (table, table->rows + 1);
2275 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2276 values [MONO_TYPEREF_SCOPE] = scope;
2277 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2278 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2280 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2281 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2283 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2288 * Despite the name, we handle also TypeSpec (with the above helper).
2291 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2293 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2297 * Insert a memberef row into the metadata: the token that point to the memberref
2298 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2299 * mono_image_get_fieldref_token()).
2300 * The sig param is an index to an already built signature.
2303 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2305 MonoDynamicTable *table;
2307 guint32 token, pclass;
2310 parent = mono_image_typedef_or_ref (assembly, type);
2311 switch (parent & MONO_TYPEDEFORREF_MASK) {
2312 case MONO_TYPEDEFORREF_TYPEREF:
2313 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2315 case MONO_TYPEDEFORREF_TYPESPEC:
2316 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2318 case MONO_TYPEDEFORREF_TYPEDEF:
2319 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2322 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2325 /* extract the index */
2326 parent >>= MONO_TYPEDEFORREF_BITS;
2328 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2330 if (assembly->save) {
2331 alloc_table (table, table->rows + 1);
2332 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2333 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2334 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2335 values [MONO_MEMBERREF_SIGNATURE] = sig;
2338 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2345 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2348 MonoMethodSignature *sig;
2350 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2355 * A methodref signature can't contain an unmanaged calling convention.
2357 sig = mono_metadata_signature_dup (mono_method_signature (method));
2358 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2359 sig->call_convention = MONO_CALL_DEFAULT;
2360 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2361 method->name, method_encode_signature (assembly, sig));
2363 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2368 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2371 ReflectionMethodBuilder rmb;
2374 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2378 name = mono_string_to_utf8 (method->name);
2379 reflection_methodbuilder_from_method_builder (&rmb, method);
2382 * A methodref signature can't contain an unmanaged calling convention.
2383 * Since some flags are encoded as part of call_conv, we need to check against it.
2385 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2386 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2387 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2388 name, method_builder_encode_signature (assembly, &rmb));
2391 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2396 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2397 const gchar *name, guint32 sig)
2399 MonoDynamicTable *table;
2403 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2405 if (assembly->save) {
2406 alloc_table (table, table->rows + 1);
2407 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2408 values [MONO_MEMBERREF_CLASS] = original;
2409 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2410 values [MONO_MEMBERREF_SIGNATURE] = sig;
2413 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2420 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2424 guint32 nparams = mono_array_length (mb->generic_params);
2427 if (!assembly->save)
2430 sigbuffer_init (&buf, 32);
2432 sigbuffer_add_value (&buf, 0xa);
2433 sigbuffer_add_value (&buf, nparams);
2435 for (i = 0; i < nparams; i++) {
2436 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2437 sigbuffer_add_value (&buf, i);
2440 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2441 sigbuffer_free (&buf);
2446 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2448 MonoDynamicTable *table;
2450 guint32 token, mtoken = 0;
2452 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2458 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2459 switch (mono_metadata_token_table (mtoken)) {
2460 case MONO_TABLE_MEMBERREF:
2461 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2463 case MONO_TABLE_METHOD:
2464 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2467 g_assert_not_reached ();
2470 if (assembly->save) {
2471 alloc_table (table, table->rows + 1);
2472 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2473 values [MONO_METHODSPEC_METHOD] = mtoken;
2474 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2477 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2480 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2485 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2489 if (mb->generic_params && create_methodspec)
2490 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2492 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2496 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2497 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2502 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2505 ReflectionMethodBuilder rmb;
2508 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2512 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2514 name = mono_string_to_utf8 (rmb.name);
2515 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2516 name, method_builder_encode_signature (assembly, &rmb));
2519 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2524 is_field_on_inst (MonoClassField *field)
2526 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2530 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2533 get_field_on_inst_generic_type (MonoClassField *field)
2535 MonoDynamicGenericClass *dgclass;
2538 g_assert (is_field_on_inst (field));
2540 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2541 field_index = field - dgclass->fields;
2543 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2544 return dgclass->field_generic_types [field_index];
2548 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2552 MonoClassField *field;
2554 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2557 g_assert (f->field->parent);
2560 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2561 int index = field - field->parent->fields;
2562 type = field->parent->generic_class->container_class->fields [index].type;
2564 if (is_field_on_inst (f->field))
2565 type = get_field_on_inst_generic_type (f->field);
2567 type = f->field->type;
2569 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2570 mono_field_get_name (f->field),
2571 fieldref_encode_signature (assembly, type));
2572 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2577 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2581 MonoGenericClass *gclass;
2582 MonoDynamicGenericClass *dgclass;
2583 MonoReflectionFieldBuilder *fb = f->fb;
2586 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2589 klass = mono_class_from_mono_type (f->inst->type.type);
2590 gclass = f->inst->type.type->data.generic_class;
2591 g_assert (gclass->is_dynamic);
2592 dgclass = (MonoDynamicGenericClass *) gclass;
2594 name = mono_string_to_utf8 (fb->name);
2595 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2596 field_encode_signature (assembly, fb));
2598 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2603 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2607 MonoGenericClass *gclass;
2608 MonoDynamicGenericClass *dgclass;
2609 MonoReflectionCtorBuilder *cb = c->cb;
2610 ReflectionMethodBuilder rmb;
2613 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2615 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2618 klass = mono_class_from_mono_type (c->inst->type.type);
2619 gclass = c->inst->type.type->data.generic_class;
2620 g_assert (gclass->is_dynamic);
2621 dgclass = (MonoDynamicGenericClass *) gclass;
2623 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2625 name = mono_string_to_utf8 (rmb.name);
2627 sig = method_builder_encode_signature (assembly, &rmb);
2629 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2632 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2637 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2641 MonoGenericClass *gclass;
2642 MonoReflectionMethodBuilder *mb = m->mb;
2643 ReflectionMethodBuilder rmb;
2646 if (create_methodspec && mb->generic_params)
2648 g_assert_not_reached ();
2650 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2653 klass = mono_class_from_mono_type (m->inst->type.type);
2654 gclass = m->inst->type.type->data.generic_class;
2655 g_assert (gclass->is_dynamic);
2657 reflection_methodbuilder_from_method_builder (&rmb, mb);
2659 name = mono_string_to_utf8 (rmb.name);
2661 sig = method_builder_encode_signature (assembly, &rmb);
2663 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2666 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2671 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2675 guint32 nparams = context->method_inst->type_argc;
2678 if (!assembly->save)
2681 sigbuffer_init (&buf, 32);
2683 * FIXME: vararg, explicit_this, differenc call_conv values...
2685 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2686 sigbuffer_add_value (&buf, nparams);
2688 for (i = 0; i < nparams; i++)
2689 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2691 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2692 sigbuffer_free (&buf);
2697 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2699 MonoDynamicTable *table;
2701 guint32 token, mtoken = 0, sig;
2702 MonoMethodInflated *imethod;
2703 MonoMethod *declaring;
2705 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2707 g_assert (method->is_inflated);
2708 imethod = (MonoMethodInflated *) method;
2709 declaring = imethod->declaring;
2711 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2712 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2714 if (!mono_method_signature (declaring)->generic_param_count)
2717 switch (mono_metadata_token_table (mtoken)) {
2718 case MONO_TABLE_MEMBERREF:
2719 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2721 case MONO_TABLE_METHOD:
2722 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2725 g_assert_not_reached ();
2728 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2730 if (assembly->save) {
2731 alloc_table (table, table->rows + 1);
2732 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2733 values [MONO_METHODSPEC_METHOD] = mtoken;
2734 values [MONO_METHODSPEC_SIGNATURE] = sig;
2737 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2744 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2746 MonoMethodInflated *imethod;
2749 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2753 g_assert (method->is_inflated);
2754 imethod = (MonoMethodInflated *) method;
2756 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2757 token = method_encode_methodspec (assembly, method);
2759 guint32 sig = method_encode_signature (
2760 assembly, mono_method_signature (imethod->declaring));
2761 token = mono_image_get_memberref_token (
2762 assembly, &method->klass->byval_arg, method->name, sig);
2765 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2770 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2772 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2775 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2776 token = mono_image_get_memberref_token (
2777 assembly, &m->klass->byval_arg, m->name, sig);
2783 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2785 MonoDynamicTable *table;
2793 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2794 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2795 * Because of this, we must not insert it into the `typeref' hash table.
2798 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2802 sigbuffer_init (&buf, 32);
2804 g_assert (tb->generic_params);
2805 klass = mono_class_from_mono_type (tb->type.type);
2807 if (tb->generic_container)
2808 mono_reflection_create_generic_class (tb);
2810 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2811 g_assert (klass->generic_container);
2812 sigbuffer_add_value (&buf, klass->byval_arg.type);
2813 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2815 count = mono_array_length (tb->generic_params);
2816 sigbuffer_add_value (&buf, count);
2817 for (i = 0; i < count; i++) {
2818 MonoReflectionGenericParam *gparam;
2820 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2822 encode_type (assembly, gparam->type.type, &buf);
2825 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2827 if (assembly->save) {
2828 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2829 alloc_table (table, table->rows + 1);
2830 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2831 values [MONO_TYPESPEC_SIGNATURE] = token;
2833 sigbuffer_free (&buf);
2835 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2836 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2842 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2845 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2847 int i, count, len, pos;
2852 count += mono_array_length (modreq);
2854 count += mono_array_length (modopt);
2857 return mono_metadata_type_dup (NULL, type);
2859 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2861 memcpy (t, type, len);
2863 t->num_mods = count;
2866 for (i = 0; i < mono_array_length (modreq); ++i) {
2867 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2868 t->modifiers [pos].required = 1;
2869 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2874 for (i = 0; i < mono_array_length (modopt); ++i) {
2875 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2876 t->modifiers [pos].required = 0;
2877 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2886 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2888 MonoDynamicTable *table;
2890 MonoType *custom = NULL;
2892 guint32 token, pclass, parent, sig;
2895 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2899 klass = mono_class_from_mono_type (fb->typeb->type);
2900 name = mono_string_to_utf8 (fb->name);
2902 /* fb->type does not include the custom modifiers */
2903 /* FIXME: We should do this in one place when a fieldbuilder is created */
2904 if (fb->modreq || fb->modopt) {
2905 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2906 sig = fieldref_encode_signature (assembly, custom);
2909 sig = fieldref_encode_signature (assembly, fb->type->type);
2912 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2913 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2915 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2916 parent >>= MONO_TYPEDEFORREF_BITS;
2918 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2920 if (assembly->save) {
2921 alloc_table (table, table->rows + 1);
2922 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2923 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2924 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2925 values [MONO_MEMBERREF_SIGNATURE] = sig;
2928 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2930 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2936 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2943 if (!assembly->save)
2946 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2947 g_assert (helper->type == 2);
2949 if (helper->arguments)
2950 nargs = mono_array_length (helper->arguments);
2954 size = 10 + (nargs * 10);
2956 sigbuffer_init (&buf, 32);
2958 /* Encode calling convention */
2959 /* Change Any to Standard */
2960 if ((helper->call_conv & 0x03) == 0x03)
2961 helper->call_conv = 0x01;
2962 /* explicit_this implies has_this */
2963 if (helper->call_conv & 0x40)
2964 helper->call_conv &= 0x20;
2966 if (helper->call_conv == 0) { /* Unmanaged */
2967 idx = helper->unmanaged_call_conv - 1;
2970 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2971 if (helper->call_conv & 0x02) /* varargs */
2975 sigbuffer_add_byte (&buf, idx);
2976 sigbuffer_add_value (&buf, nargs);
2977 encode_reflection_type (assembly, helper->return_type, &buf);
2978 for (i = 0; i < nargs; ++i) {
2979 MonoArray *modreqs = NULL;
2980 MonoArray *modopts = NULL;
2981 MonoReflectionType *pt;
2983 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2984 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2985 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2986 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2988 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2989 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2990 encode_reflection_type (assembly, pt, &buf);
2992 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2993 sigbuffer_free (&buf);
2999 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3002 MonoDynamicTable *table;
3005 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3006 idx = table->next_idx ++;
3008 alloc_table (table, table->rows);
3009 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3011 values [MONO_STAND_ALONE_SIGNATURE] =
3012 mono_reflection_encode_sighelper (assembly, helper);
3018 reflection_cc_to_file (int call_conv) {
3019 switch (call_conv & 0x3) {
3021 case 1: return MONO_CALL_DEFAULT;
3022 case 2: return MONO_CALL_VARARG;
3024 g_assert_not_reached ();
3031 MonoMethodSignature *sig;
3037 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3042 MonoMethodSignature *sig;
3045 name = mono_string_to_utf8 (m->name);
3046 nparams = mono_array_length (m->parameters);
3047 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3049 sig->sentinelpos = -1;
3050 sig->call_convention = reflection_cc_to_file (m->call_conv);
3051 sig->param_count = nparams;
3052 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3053 for (i = 0; i < nparams; ++i) {
3054 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3055 sig->params [i] = t->type;
3058 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3060 if (strcmp (name, am->name) == 0 &&
3061 mono_metadata_type_equal (am->parent, m->parent->type) &&
3062 mono_metadata_signature_equal (am->sig, sig)) {
3065 m->table_idx = am->token & 0xffffff;
3069 am = g_new0 (ArrayMethod, 1);
3072 am->parent = m->parent->type;
3073 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3074 method_encode_signature (assembly, sig));
3075 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3076 m->table_idx = am->token & 0xffffff;
3081 * Insert into the metadata tables all the info about the TypeBuilder tb.
3082 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3085 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3087 MonoDynamicTable *table;
3089 int i, is_object = 0, is_system = 0;
3092 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3093 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3094 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3095 n = mono_string_to_utf8 (tb->name);
3096 if (strcmp (n, "Object") == 0)
3098 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3100 n = mono_string_to_utf8 (tb->nspace);
3101 if (strcmp (n, "System") == 0)
3103 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3105 if (tb->parent && !(is_system && is_object) &&
3106 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3107 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3109 values [MONO_TYPEDEF_EXTENDS] = 0;
3111 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3112 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3115 * if we have explicitlayout or sequentiallayouts, output data in the
3116 * ClassLayout table.
3118 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3119 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3120 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3122 alloc_table (table, table->rows);
3123 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3124 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3125 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3126 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3129 /* handle interfaces */
3130 if (tb->interfaces) {
3131 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3133 table->rows += mono_array_length (tb->interfaces);
3134 alloc_table (table, table->rows);
3135 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3136 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3137 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3138 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3139 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3140 values += MONO_INTERFACEIMPL_SIZE;
3146 table = &assembly->tables [MONO_TABLE_FIELD];
3147 table->rows += tb->num_fields;
3148 alloc_table (table, table->rows);
3149 for (i = 0; i < tb->num_fields; ++i)
3150 mono_image_get_field_info (
3151 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3154 /* handle constructors */
3156 table = &assembly->tables [MONO_TABLE_METHOD];
3157 table->rows += mono_array_length (tb->ctors);
3158 alloc_table (table, table->rows);
3159 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3160 mono_image_get_ctor_info (domain,
3161 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3164 /* handle methods */
3166 table = &assembly->tables [MONO_TABLE_METHOD];
3167 table->rows += tb->num_methods;
3168 alloc_table (table, table->rows);
3169 for (i = 0; i < tb->num_methods; ++i)
3170 mono_image_get_method_info (
3171 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3174 /* Do the same with properties etc.. */
3175 if (tb->events && mono_array_length (tb->events)) {
3176 table = &assembly->tables [MONO_TABLE_EVENT];
3177 table->rows += mono_array_length (tb->events);
3178 alloc_table (table, table->rows);
3179 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3181 alloc_table (table, table->rows);
3182 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3183 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3184 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3185 for (i = 0; i < mono_array_length (tb->events); ++i)
3186 mono_image_get_event_info (
3187 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3189 if (tb->properties && mono_array_length (tb->properties)) {
3190 table = &assembly->tables [MONO_TABLE_PROPERTY];
3191 table->rows += mono_array_length (tb->properties);
3192 alloc_table (table, table->rows);
3193 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3195 alloc_table (table, table->rows);
3196 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3197 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3198 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3199 for (i = 0; i < mono_array_length (tb->properties); ++i)
3200 mono_image_get_property_info (
3201 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3204 /* handle generic parameters */
3205 if (tb->generic_params) {
3206 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3207 table->rows += mono_array_length (tb->generic_params);
3208 alloc_table (table, table->rows);
3209 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3210 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3212 mono_image_get_generic_param_info (
3213 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3217 mono_image_add_decl_security (assembly,
3218 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3221 MonoDynamicTable *ntable;
3223 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3224 ntable->rows += mono_array_length (tb->subtypes);
3225 alloc_table (ntable, ntable->rows);
3226 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3228 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3229 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3231 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3232 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3233 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3234 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3235 mono_string_to_utf8 (tb->name), tb->table_idx,
3236 ntable->next_idx, ntable->rows);*/
3237 values += MONO_NESTED_CLASS_SIZE;
3244 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3248 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3250 if (!type->subtypes)
3253 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3254 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3255 collect_types (types, subtype);
3260 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3262 if ((*type1)->table_idx < (*type2)->table_idx)
3265 if ((*type1)->table_idx > (*type2)->table_idx)
3272 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3277 for (i = 0; i < mono_array_length (pinfo); ++i) {
3278 MonoReflectionParamBuilder *pb;
3279 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3282 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3287 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3290 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3292 for (i = 0; i < tb->num_fields; ++i) {
3293 MonoReflectionFieldBuilder* fb;
3294 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3295 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3299 for (i = 0; i < mono_array_length (tb->events); ++i) {
3300 MonoReflectionEventBuilder* eb;
3301 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3302 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3305 if (tb->properties) {
3306 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3307 MonoReflectionPropertyBuilder* pb;
3308 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3309 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3313 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3314 MonoReflectionCtorBuilder* cb;
3315 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3316 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3317 params_add_cattrs (assembly, cb->pinfo);
3322 for (i = 0; i < tb->num_methods; ++i) {
3323 MonoReflectionMethodBuilder* mb;
3324 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3325 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3326 params_add_cattrs (assembly, mb->pinfo);
3331 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3332 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3337 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3341 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3343 if (moduleb->global_methods) {
3344 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3345 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3346 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3347 params_add_cattrs (assembly, mb->pinfo);
3351 if (moduleb->global_fields) {
3352 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3353 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3354 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3358 if (moduleb->types) {
3359 for (i = 0; i < moduleb->num_types; ++i)
3360 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3365 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3367 MonoDynamicTable *table;
3371 char *b = blob_size;
3374 table = &assembly->tables [MONO_TABLE_FILE];
3376 alloc_table (table, table->rows);
3377 values = table->values + table->next_idx * MONO_FILE_SIZE;
3378 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3379 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3380 if (module->image->dynamic) {
3381 /* This depends on the fact that the main module is emitted last */
3382 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3383 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3386 path = g_strdup (module->image->name);
3388 mono_sha1_get_digest_from_file (path, hash);
3391 mono_metadata_encode_value (20, b, &b);
3392 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3393 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3398 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3400 MonoDynamicTable *table;
3403 table = &assembly->tables [MONO_TABLE_MODULE];
3404 mb->table_idx = table->next_idx ++;
3405 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3406 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3409 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3410 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3411 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3412 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3416 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3417 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3419 MonoDynamicTable *table;
3423 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3424 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3427 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3429 alloc_table (table, table->rows);
3430 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3432 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3433 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3434 if (klass->nested_in)
3435 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3437 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3438 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3439 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3441 res = table->next_idx;
3445 /* Emit nested types */
3446 if (klass->nested_classes) {
3449 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3450 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3457 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3458 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3463 klass = mono_class_from_mono_type (tb->type.type);
3465 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3467 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3468 parent_index, assembly);
3472 * We need to do this ourselves since klass->nested_classes is not set up.
3475 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3476 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3481 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3482 guint32 module_index, MonoDynamicImage *assembly)
3484 MonoImage *image = module->image;
3488 t = &image->tables [MONO_TABLE_TYPEDEF];
3490 for (i = 0; i < t->rows; ++i) {
3491 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3493 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3494 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3499 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3501 MonoDynamicTable *table;
3507 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3509 if (assemblyb->type_forwarders) {
3510 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3511 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3517 klass = mono_class_from_mono_type (t->type);
3519 scope = resolution_scope_from_image (assembly, klass->image);
3520 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3521 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3524 alloc_table (table, table->rows);
3525 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3527 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3528 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3529 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3530 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3531 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3538 #define align_pointer(base,p)\
3540 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3542 (p) += 4 - (__diff & 3);\
3546 compare_constants (const void *a, const void *b)
3548 const guint32 *a_values = a;
3549 const guint32 *b_values = b;
3550 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3554 compare_semantics (const void *a, const void *b)
3556 const guint32 *a_values = a;
3557 const guint32 *b_values = b;
3558 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3561 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3565 compare_custom_attrs (const void *a, const void *b)
3567 const guint32 *a_values = a;
3568 const guint32 *b_values = b;
3570 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3574 compare_field_marshal (const void *a, const void *b)
3576 const guint32 *a_values = a;
3577 const guint32 *b_values = b;
3579 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3583 compare_nested (const void *a, const void *b)
3585 const guint32 *a_values = a;
3586 const guint32 *b_values = b;
3588 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3592 compare_genericparam (const void *a, const void *b)
3594 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3595 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3597 if ((*b_entry)->owner == (*a_entry)->owner)
3599 (*a_entry)->gparam->type.type->data.generic_param->num -
3600 (*b_entry)->gparam->type.type->data.generic_param->num;
3602 return (*a_entry)->owner - (*b_entry)->owner;
3606 compare_declsecurity_attrs (const void *a, const void *b)
3608 const guint32 *a_values = a;
3609 const guint32 *b_values = b;
3611 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3615 compare_interface_impl (const void *a, const void *b)
3617 const guint32 *a_values = a;
3618 const guint32 *b_values = b;
3620 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3624 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3628 pad_heap (MonoDynamicStream *sh)
3630 if (sh->index & 3) {
3631 int sz = 4 - (sh->index & 3);
3632 memset (sh->data + sh->index, 0, sz);
3639 MonoDynamicStream *stream;
3643 * build_compressed_metadata() fills in the blob of data that represents the
3644 * raw metadata as it will be saved in the PE file. The five streams are output
3645 * and the metadata tables are comnpressed from the guint32 array representation,
3646 * to the compressed on-disk format.
3649 build_compressed_metadata (MonoDynamicImage *assembly)
3651 MonoDynamicTable *table;
3653 guint64 valid_mask = 0;
3654 guint64 sorted_mask;
3655 guint32 heapt_size = 0;
3656 guint32 meta_size = 256; /* allow for header and other stuff */
3657 guint32 table_offset;
3658 guint32 ntables = 0;
3664 struct StreamDesc stream_desc [5];
3666 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3667 for (i = 0; i < assembly->gen_params->len; i++){
3668 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3669 write_generic_param_entry (assembly, entry);
3672 stream_desc [0].name = "#~";
3673 stream_desc [0].stream = &assembly->tstream;
3674 stream_desc [1].name = "#Strings";
3675 stream_desc [1].stream = &assembly->sheap;
3676 stream_desc [2].name = "#US";
3677 stream_desc [2].stream = &assembly->us;
3678 stream_desc [3].name = "#Blob";
3679 stream_desc [3].stream = &assembly->blob;
3680 stream_desc [4].name = "#GUID";
3681 stream_desc [4].stream = &assembly->guid;
3683 /* tables that are sorted */
3684 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3685 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3686 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3687 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3688 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3689 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3690 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3692 /* Compute table sizes */
3693 /* the MonoImage has already been created in mono_image_basic_init() */
3694 meta = &assembly->image;
3696 /* sizes should be multiple of 4 */
3697 pad_heap (&assembly->blob);
3698 pad_heap (&assembly->guid);
3699 pad_heap (&assembly->sheap);
3700 pad_heap (&assembly->us);
3702 /* Setup the info used by compute_sizes () */
3703 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3704 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3705 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3707 meta_size += assembly->blob.index;
3708 meta_size += assembly->guid.index;
3709 meta_size += assembly->sheap.index;
3710 meta_size += assembly->us.index;
3712 for (i=0; i < MONO_TABLE_NUM; ++i)
3713 meta->tables [i].rows = assembly->tables [i].rows;
3715 for (i = 0; i < MONO_TABLE_NUM; i++){
3716 if (meta->tables [i].rows == 0)
3718 valid_mask |= (guint64)1 << i;
3720 meta->tables [i].row_size = mono_metadata_compute_size (
3721 meta, i, &meta->tables [i].size_bitfield);
3722 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3724 heapt_size += 24; /* #~ header size */
3725 heapt_size += ntables * 4;
3726 /* make multiple of 4 */
3729 meta_size += heapt_size;
3730 meta->raw_metadata = g_malloc0 (meta_size);
3731 p = (unsigned char*)meta->raw_metadata;
3732 /* the metadata signature */
3733 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3734 /* version numbers and 4 bytes reserved */
3735 int16val = (guint16*)p;
3736 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3737 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3739 /* version string */
3740 int32val = (guint32*)p;
3741 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3743 memcpy (p, meta->version, strlen (meta->version));
3744 p += GUINT32_FROM_LE (*int32val);
3745 align_pointer (meta->raw_metadata, p);
3746 int16val = (guint16*)p;
3747 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3748 *int16val = GUINT16_TO_LE (5); /* number of streams */
3752 * write the stream info.
3754 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3755 table_offset += 3; table_offset &= ~3;
3757 assembly->tstream.index = heapt_size;
3758 for (i = 0; i < 5; ++i) {
3759 int32val = (guint32*)p;
3760 stream_desc [i].stream->offset = table_offset;
3761 *int32val++ = GUINT32_TO_LE (table_offset);
3762 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3763 table_offset += GUINT32_FROM_LE (*int32val);
3764 table_offset += 3; table_offset &= ~3;
3766 strcpy ((char*)p, stream_desc [i].name);
3767 p += strlen (stream_desc [i].name) + 1;
3768 align_pointer (meta->raw_metadata, p);
3771 * now copy the data, the table stream header and contents goes first.
3773 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3774 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3775 int32val = (guint32*)p;
3776 *int32val = GUINT32_TO_LE (0); /* reserved */
3779 if (mono_framework_version () > 1) {
3780 *p++ = 2; /* version */
3783 *p++ = 1; /* version */
3787 if (meta->idx_string_wide)
3789 if (meta->idx_guid_wide)
3791 if (meta->idx_blob_wide)
3794 *p++ = 1; /* reserved */
3795 int64val = (guint64*)p;
3796 *int64val++ = GUINT64_TO_LE (valid_mask);
3797 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3799 int32val = (guint32*)p;
3800 for (i = 0; i < MONO_TABLE_NUM; i++){
3801 if (meta->tables [i].rows == 0)
3803 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3805 p = (unsigned char*)int32val;
3807 /* sort the tables that still need sorting */
3808 table = &assembly->tables [MONO_TABLE_CONSTANT];
3810 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3811 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3813 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3814 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3816 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3817 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3819 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3820 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3822 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3823 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3824 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3826 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3827 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3829 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3831 /* compress the tables */
3832 for (i = 0; i < MONO_TABLE_NUM; i++){
3835 guint32 bitfield = meta->tables [i].size_bitfield;
3836 if (!meta->tables [i].rows)
3838 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3839 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3840 meta->tables [i].base = (char*)p;
3841 for (row = 1; row <= meta->tables [i].rows; ++row) {
3842 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3843 for (col = 0; col < assembly->tables [i].columns; ++col) {
3844 switch (mono_metadata_table_size (bitfield, col)) {
3846 *p++ = values [col];
3849 *p++ = values [col] & 0xff;
3850 *p++ = (values [col] >> 8) & 0xff;
3853 *p++ = values [col] & 0xff;
3854 *p++ = (values [col] >> 8) & 0xff;
3855 *p++ = (values [col] >> 16) & 0xff;
3856 *p++ = (values [col] >> 24) & 0xff;
3859 g_assert_not_reached ();
3863 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3866 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3867 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3868 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3869 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3870 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3872 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3876 * Some tables in metadata need to be sorted according to some criteria, but
3877 * when methods and fields are first created with reflection, they may be assigned a token
3878 * that doesn't correspond to the final token they will get assigned after the sorting.
3879 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3880 * with the reflection objects that represent them. Once all the tables are set up, the
3881 * reflection objects will contains the correct table index. fixup_method() will fixup the
3882 * tokens for the method with ILGenerator @ilgen.
3885 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3887 guint32 code_idx = GPOINTER_TO_UINT (value);
3888 MonoReflectionILTokenInfo *iltoken;
3889 MonoReflectionFieldBuilder *field;
3890 MonoReflectionCtorBuilder *ctor;
3891 MonoReflectionMethodBuilder *method;
3892 MonoReflectionTypeBuilder *tb;
3893 MonoReflectionArrayMethod *am;
3895 unsigned char *target;
3897 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3898 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3899 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3900 switch (target [3]) {
3901 case MONO_TABLE_FIELD:
3902 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3903 field = (MonoReflectionFieldBuilder *)iltoken->member;
3904 idx = field->table_idx;
3905 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3906 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3907 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3909 g_assert_not_reached ();
3912 case MONO_TABLE_METHOD:
3913 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3914 method = (MonoReflectionMethodBuilder *)iltoken->member;
3915 idx = method->table_idx;
3916 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3917 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3918 idx = ctor->table_idx;
3919 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3920 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3921 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3922 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3924 g_assert_not_reached ();
3927 case MONO_TABLE_TYPEDEF:
3928 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3929 g_assert_not_reached ();
3930 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3931 idx = tb->table_idx;
3933 case MONO_TABLE_MEMBERREF:
3934 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3935 am = (MonoReflectionArrayMethod*)iltoken->member;
3936 idx = am->table_idx;
3937 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3938 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3939 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3940 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3941 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3942 g_assert (m->klass->generic_class || m->klass->generic_container);
3944 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3946 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3947 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3948 g_assert (is_field_on_inst (f));
3950 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3951 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3953 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3955 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3957 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3960 g_assert_not_reached ();
3963 case MONO_TABLE_METHODSPEC:
3964 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3965 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3966 g_assert (mono_method_signature (m)->generic_param_count);
3968 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3971 g_assert_not_reached ();
3975 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3977 target [0] = idx & 0xff;
3978 target [1] = (idx >> 8) & 0xff;
3979 target [2] = (idx >> 16) & 0xff;
3986 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3987 * value is not known when the table is emitted.
3990 fixup_cattrs (MonoDynamicImage *assembly)
3992 MonoDynamicTable *table;
3994 guint32 type, i, idx, token;
3997 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3999 for (i = 0; i < table->rows; ++i) {
4000 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4002 type = values [MONO_CUSTOM_ATTR_TYPE];
4003 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4004 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4005 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4006 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4009 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4010 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4011 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4012 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4019 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4021 MonoDynamicTable *table;
4024 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4026 alloc_table (table, table->rows);
4027 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4028 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4029 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4030 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4031 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4036 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4038 MonoDynamicTable *table;
4042 char *b = blob_size;
4044 guint32 idx, offset;
4046 if (rsrc->filename) {
4047 name = mono_string_to_utf8 (rsrc->filename);
4048 sname = g_path_get_basename (name);
4050 table = &assembly->tables [MONO_TABLE_FILE];
4052 alloc_table (table, table->rows);
4053 values = table->values + table->next_idx * MONO_FILE_SIZE;
4054 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4055 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4058 mono_sha1_get_digest_from_file (name, hash);
4059 mono_metadata_encode_value (20, b, &b);
4060 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4061 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4063 idx = table->next_idx++;
4065 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4071 data = mono_array_addr (rsrc->data, char, 0);
4072 len = mono_array_length (rsrc->data);
4078 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4079 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4080 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4081 mono_image_add_stream_data (&assembly->resources, data, len);
4085 * The entry should be emitted into the MANIFESTRESOURCE table of
4086 * the main module, but that needs to reference the FILE table
4087 * which isn't emitted yet.
4094 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4098 set_version_from_string (MonoString *version, guint32 *values)
4100 gchar *ver, *p, *str;
4103 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4104 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4105 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4106 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4109 ver = str = mono_string_to_utf8 (version);
4110 for (i = 0; i < 4; ++i) {
4111 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4117 /* handle Revision and Build */
4127 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4131 char *b = blob_size;
4136 len = mono_array_length (pkey);
4137 mono_metadata_encode_value (len, b, &b);
4138 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4139 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4141 assembly->public_key = g_malloc (len);
4142 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4143 assembly->public_key_len = len;
4145 /* Special case: check for ECMA key (16 bytes) */
4146 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4147 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4148 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4149 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4150 /* minimum key size (in 2.0) is 384 bits */
4151 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4153 /* FIXME - verifier */
4154 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4155 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4157 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4163 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4165 MonoDynamicTable *table;
4166 MonoDynamicImage *assembly;
4167 MonoReflectionAssemblyBuilder *assemblyb;
4171 guint32 module_index;
4173 assemblyb = moduleb->assemblyb;
4174 assembly = moduleb->dynamic_image;
4175 domain = mono_object_domain (assemblyb);
4177 /* Emit ASSEMBLY table */
4178 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4179 alloc_table (table, 1);
4180 values = table->values + MONO_ASSEMBLY_SIZE;
4181 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4182 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4183 if (assemblyb->culture) {
4184 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4186 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4188 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4189 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4190 set_version_from_string (assemblyb->version, values);
4192 /* Emit FILE + EXPORTED_TYPE table */
4194 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4196 MonoReflectionModuleBuilder *file_module =
4197 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4198 if (file_module != moduleb) {
4199 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4201 if (file_module->types) {
4202 for (j = 0; j < file_module->num_types; ++j) {
4203 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4204 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4209 if (assemblyb->loaded_modules) {
4210 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4211 MonoReflectionModule *file_module =
4212 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4213 mono_image_fill_file_table (domain, file_module, assembly);
4215 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4218 if (assemblyb->type_forwarders)
4219 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4221 /* Emit MANIFESTRESOURCE table */
4223 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4225 MonoReflectionModuleBuilder *file_module =
4226 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4227 /* The table for the main module is emitted later */
4228 if (file_module != moduleb) {
4230 if (file_module->resources) {
4231 int len = mono_array_length (file_module->resources);
4232 for (j = 0; j < len; ++j) {
4233 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4234 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4241 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4244 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4245 * for the modulebuilder @moduleb.
4246 * At the end of the process, method and field tokens are fixed up and the
4247 * on-disk compressed metadata representation is created.
4250 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4252 MonoDynamicTable *table;
4253 MonoDynamicImage *assembly;
4254 MonoReflectionAssemblyBuilder *assemblyb;
4260 assemblyb = moduleb->assemblyb;
4261 assembly = moduleb->dynamic_image;
4262 domain = mono_object_domain (assemblyb);
4264 if (assembly->text_rva)
4267 assembly->text_rva = START_TEXT_RVA;
4269 if (moduleb->is_main) {
4270 mono_image_emit_manifest (moduleb);
4273 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4274 table->rows = 1; /* .<Module> */
4276 alloc_table (table, table->rows);
4278 * Set the first entry.
4280 values = table->values + table->columns;
4281 values [MONO_TYPEDEF_FLAGS] = 0;
4282 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4283 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4284 values [MONO_TYPEDEF_EXTENDS] = 0;
4285 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4286 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4289 * handle global methods
4290 * FIXME: test what to do when global methods are defined in multiple modules.
4292 if (moduleb->global_methods) {
4293 table = &assembly->tables [MONO_TABLE_METHOD];
4294 table->rows += mono_array_length (moduleb->global_methods);
4295 alloc_table (table, table->rows);
4296 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4297 mono_image_get_method_info (
4298 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4300 if (moduleb->global_fields) {
4301 table = &assembly->tables [MONO_TABLE_FIELD];
4302 table->rows += mono_array_length (moduleb->global_fields);
4303 alloc_table (table, table->rows);
4304 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4305 mono_image_get_field_info (
4306 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4309 table = &assembly->tables [MONO_TABLE_MODULE];
4310 alloc_table (table, 1);
4311 mono_image_fill_module_table (domain, moduleb, assembly);
4313 /* Collect all types into a list sorted by their table_idx */
4314 types = g_ptr_array_new ();
4317 for (i = 0; i < moduleb->num_types; ++i) {
4318 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4319 collect_types (types, type);
4322 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4323 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4324 table->rows += types->len;
4325 alloc_table (table, table->rows);
4328 * Emit type names + namespaces at one place inside the string heap,
4329 * so load_class_names () needs to touch fewer pages.
4331 for (i = 0; i < types->len; ++i) {
4332 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4333 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4335 for (i = 0; i < types->len; ++i) {
4336 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4337 string_heap_insert_mstring (&assembly->sheap, tb->name);
4340 for (i = 0; i < types->len; ++i) {
4341 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4342 mono_image_get_type_info (domain, type, assembly);
4346 * table->rows is already set above and in mono_image_fill_module_table.
4348 /* add all the custom attributes at the end, once all the indexes are stable */
4349 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4351 /* CAS assembly permissions */
4352 if (assemblyb->permissions_minimum)
4353 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4354 if (assemblyb->permissions_optional)
4355 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4356 if (assemblyb->permissions_refused)
4357 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4359 module_add_cattrs (assembly, moduleb);
4362 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4364 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4365 * the final tokens and don't need another fixup pass. */
4367 if (moduleb->global_methods) {
4368 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4369 MonoReflectionMethodBuilder *mb = mono_array_get (
4370 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4371 mono_image_add_methodimpl (assembly, mb);
4375 for (i = 0; i < types->len; ++i) {
4376 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4377 if (type->methods) {
4378 for (j = 0; j < type->num_methods; ++j) {
4379 MonoReflectionMethodBuilder *mb = mono_array_get (
4380 type->methods, MonoReflectionMethodBuilder*, j);
4382 mono_image_add_methodimpl (assembly, mb);
4387 g_ptr_array_free (types, TRUE);
4389 fixup_cattrs (assembly);
4392 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4395 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4397 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4400 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4402 #ifndef DISABLE_REFLECTION_EMIT
4405 * mono_image_insert_string:
4406 * @module: module builder object
4409 * Insert @str into the user string stream of @module.
4412 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4414 MonoDynamicImage *assembly;
4419 MONO_ARCH_SAVE_REGS;
4421 if (!module->dynamic_image)
4422 mono_image_module_basic_init (module);
4424 assembly = module->dynamic_image;
4426 if (assembly->save) {
4427 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4428 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4429 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4431 char *swapped = g_malloc (2 * mono_string_length (str));
4432 const char *p = (const char*)mono_string_chars (str);
4434 swap_with_size (swapped, p, 2, mono_string_length (str));
4435 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4439 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4441 mono_image_add_stream_data (&assembly->us, "", 1);
4443 idx = assembly->us.index ++;
4446 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4448 return MONO_TOKEN_STRING | idx;
4452 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4457 klass = obj->vtable->klass;
4458 if (strcmp (klass->name, "MonoMethod") == 0) {
4459 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4460 MonoMethodSignature *sig, *old;
4461 guint32 sig_token, parent;
4464 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4466 nargs = mono_array_length (opt_param_types);
4467 old = mono_method_signature (method);
4468 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4470 sig->hasthis = old->hasthis;
4471 sig->explicit_this = old->explicit_this;
4472 sig->call_convention = old->call_convention;
4473 sig->generic_param_count = old->generic_param_count;
4474 sig->param_count = old->param_count + nargs;
4475 sig->sentinelpos = old->param_count;
4476 sig->ret = old->ret;
4478 for (i = 0; i < old->param_count; i++)
4479 sig->params [i] = old->params [i];
4481 for (i = 0; i < nargs; i++) {
4482 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4483 sig->params [old->param_count + i] = rt->type;
4486 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4487 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4488 parent >>= MONO_TYPEDEFORREF_BITS;
4490 parent <<= MONO_MEMBERREF_PARENT_BITS;
4491 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4493 sig_token = method_encode_signature (assembly, sig);
4494 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4495 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4496 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4497 ReflectionMethodBuilder rmb;
4498 guint32 parent, sig;
4501 reflection_methodbuilder_from_method_builder (&rmb, mb);
4502 rmb.opt_types = opt_param_types;
4504 sig = method_builder_encode_signature (assembly, &rmb);
4506 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4507 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4509 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4510 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4512 name = mono_string_to_utf8 (rmb.name);
4513 token = mono_image_get_varargs_method_token (
4514 assembly, parent, name, sig);
4517 g_error ("requested method token for %s\n", klass->name);
4524 * mono_image_create_token:
4525 * @assembly: a dynamic assembly
4527 * @register_token: Whenever to register the token in the assembly->tokens hash.
4529 * Get a token to insert in the IL code stream for the given MemberInfo.
4530 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4531 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4535 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4536 gboolean create_methodspec, gboolean register_token)
4541 klass = obj->vtable->klass;
4542 if (strcmp (klass->name, "MethodBuilder") == 0) {
4543 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4546 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4547 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4549 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4550 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4551 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4552 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4553 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4555 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4556 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4558 token = mono_image_get_ctorbuilder_token (assembly, mb);
4559 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4560 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4561 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4562 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4563 if (tb->generic_params) {
4564 token = mono_image_get_generic_field_token (assembly, fb);
4566 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4568 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4569 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4570 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4571 } else if (strcmp (klass->name, "MonoType") == 0) {
4572 MonoReflectionType *tb = (MonoReflectionType *)obj;
4573 MonoClass *mc = mono_class_from_mono_type (tb->type);
4574 token = mono_metadata_token_from_dor (
4575 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4576 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4577 MonoReflectionType *tb = (MonoReflectionType *)obj;
4578 token = mono_metadata_token_from_dor (
4579 mono_image_typedef_or_ref (assembly, tb->type));
4580 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4581 MonoReflectionType *tb = (MonoReflectionType *)obj;
4582 token = mono_metadata_token_from_dor (
4583 mono_image_typedef_or_ref (assembly, tb->type));
4584 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4585 strcmp (klass->name, "MonoMethod") == 0 ||
4586 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4587 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4588 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4589 if (m->method->is_inflated) {
4590 if (create_methodspec)
4591 token = mono_image_get_methodspec_token (assembly, m->method);
4593 token = mono_image_get_inflated_method_token (assembly, m->method);
4594 } else if ((m->method->klass->image == &assembly->image) &&
4595 !m->method->klass->generic_class) {
4596 static guint32 method_table_idx = 0xffffff;
4597 if (m->method->klass->wastypebuilder) {
4598 /* we use the same token as the one that was assigned
4599 * to the Methodbuilder.
4600 * FIXME: do the equivalent for Fields.
4602 token = m->method->token;
4605 * Each token should have a unique index, but the indexes are
4606 * assigned by managed code, so we don't know about them. An
4607 * easy solution is to count backwards...
4609 method_table_idx --;
4610 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4613 token = mono_image_get_methodref_token (assembly, m->method);
4615 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4616 } else if (strcmp (klass->name, "MonoField") == 0) {
4617 MonoReflectionField *f = (MonoReflectionField *)obj;
4618 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4619 static guint32 field_table_idx = 0xffffff;
4621 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4623 token = mono_image_get_fieldref_token (assembly, f);
4625 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4626 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4627 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4628 token = mono_image_get_array_token (assembly, m);
4629 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4630 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4631 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4632 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4633 MonoReflectionType *tb = (MonoReflectionType *)obj;
4634 token = mono_metadata_token_from_dor (
4635 mono_image_typedef_or_ref (assembly, tb->type));
4636 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4637 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4638 token = mono_image_get_field_on_inst_token (assembly, f);
4639 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4640 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4641 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4642 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4643 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4644 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4646 g_error ("requested token for %s\n", klass->name);
4650 mono_image_register_token (assembly, token, obj);
4656 * mono_image_register_token:
4658 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4659 * the Module.ResolveXXXToken () methods to work.
4662 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4664 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4666 /* There could be multiple MethodInfo objects with the same token */
4667 //g_assert (prev == obj);
4669 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4673 #endif /* DISABLE_REFLECTION_EMIT */
4676 guint32 import_lookup_table;
4680 guint32 import_address_table_rva;
4688 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4690 static MonoDynamicImage*
4691 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4693 static const guchar entrycode [16] = {0xff, 0x25, 0};
4694 MonoDynamicImage *image;
4697 const char *version;
4699 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4700 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4702 version = mono_get_runtime_info ()->runtime_version;
4705 image = GC_MALLOC (sizeof (MonoDynamicImage));
4707 image = g_new0 (MonoDynamicImage, 1);
4710 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4712 /*g_print ("created image %p\n", image);*/
4713 /* keep in sync with image.c */
4714 image->image.name = assembly_name;
4715 image->image.assembly_name = image->image.name; /* they may be different */
4716 image->image.module_name = module_name;
4717 image->image.version = g_strdup (version);
4718 image->image.md_version_major = 1;
4719 image->image.md_version_minor = 1;
4720 image->image.dynamic = TRUE;
4722 image->image.references = g_new0 (MonoAssembly*, 1);
4723 image->image.references [0] = NULL;
4725 mono_image_init (&image->image);
4727 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4728 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4729 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4730 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4731 image->handleref = g_hash_table_new (NULL, NULL);
4732 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4733 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4734 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4735 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4736 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4737 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4738 image->gen_params = g_ptr_array_new ();
4740 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4741 string_heap_init (&image->sheap);
4742 mono_image_add_stream_data (&image->us, "", 1);
4743 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4744 /* import tables... */
4745 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4746 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4747 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4748 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4749 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4750 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4751 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4752 stream_data_align (&image->code);
4754 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4756 for (i=0; i < MONO_TABLE_NUM; ++i) {
4757 image->tables [i].next_idx = 1;
4758 image->tables [i].columns = table_sizes [i];
4761 image->image.assembly = (MonoAssembly*)assembly;
4762 image->run = assembly->run;
4763 image->save = assembly->save;
4764 image->pe_kind = 0x1; /* ILOnly */
4765 image->machine = 0x14c; /* I386 */
4767 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4773 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4779 mono_dynamic_image_free (MonoDynamicImage *image)
4781 MonoDynamicImage *di = image;
4786 mono_g_hash_table_destroy (di->methodspec);
4788 g_hash_table_destroy (di->typespec);
4790 g_hash_table_destroy (di->typeref);
4792 g_hash_table_destroy (di->handleref);
4794 mono_g_hash_table_destroy (di->tokens);
4795 if (di->generic_def_objects)
4796 mono_g_hash_table_destroy (di->generic_def_objects);
4797 if (di->blob_cache) {
4798 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4799 g_hash_table_destroy (di->blob_cache);
4801 if (di->standalonesig_cache)
4802 g_hash_table_destroy (di->standalonesig_cache);
4803 for (list = di->array_methods; list; list = list->next) {
4804 ArrayMethod *am = (ArrayMethod *)list->data;
4809 g_list_free (di->array_methods);
4810 if (di->gen_params) {
4811 for (i = 0; i < di->gen_params->len; i++) {
4812 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4813 if (entry->gparam->type.type) {
4814 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4815 g_free ((char*)param->name);
4817 g_free (entry->gparam->type.type);
4821 g_ptr_array_free (di->gen_params, TRUE);
4823 if (di->token_fixups)
4824 mono_g_hash_table_destroy (di->token_fixups);
4825 if (di->method_to_table_idx)
4826 g_hash_table_destroy (di->method_to_table_idx);
4827 if (di->field_to_table_idx)
4828 g_hash_table_destroy (di->field_to_table_idx);
4829 if (di->method_aux_hash)
4830 g_hash_table_destroy (di->method_aux_hash);
4831 g_free (di->strong_name);
4832 g_free (di->win32_res);
4834 g_free (di->public_key);
4836 /*g_print ("string heap destroy for image %p\n", di);*/
4837 mono_dynamic_stream_reset (&di->sheap);
4838 mono_dynamic_stream_reset (&di->code);
4839 mono_dynamic_stream_reset (&di->resources);
4840 mono_dynamic_stream_reset (&di->us);
4841 mono_dynamic_stream_reset (&di->blob);
4842 mono_dynamic_stream_reset (&di->tstream);
4843 mono_dynamic_stream_reset (&di->guid);
4844 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4845 g_free (di->tables [i].values);
4849 #ifndef DISABLE_REFLECTION_EMIT
4852 * mono_image_basic_init:
4853 * @assembly: an assembly builder object
4855 * Create the MonoImage that represents the assembly builder and setup some
4856 * of the helper hash table and the basic metadata streams.
4859 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4861 MonoDynamicAssembly *assembly;
4862 MonoDynamicImage *image;
4863 MonoDomain *domain = mono_object_domain (assemblyb);
4865 MONO_ARCH_SAVE_REGS;
4867 if (assemblyb->dynamic_assembly)
4871 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4873 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4876 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4878 assembly->assembly.ref_count = 1;
4879 assembly->assembly.dynamic = TRUE;
4880 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4881 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4882 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4883 if (assemblyb->culture)
4884 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4886 assembly->assembly.aname.culture = g_strdup ("");
4888 if (assemblyb->version) {
4889 char *vstr = mono_string_to_utf8 (assemblyb->version);
4890 char **version = g_strsplit (vstr, ".", 4);
4891 char **parts = version;
4892 assembly->assembly.aname.major = atoi (*parts++);
4893 assembly->assembly.aname.minor = atoi (*parts++);
4894 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4895 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4897 g_strfreev (version);
4900 assembly->assembly.aname.major = 0;
4901 assembly->assembly.aname.minor = 0;
4902 assembly->assembly.aname.build = 0;
4903 assembly->assembly.aname.revision = 0;
4906 assembly->run = assemblyb->access != 2;
4907 assembly->save = assemblyb->access != 1;
4909 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4910 image->initial_image = TRUE;
4911 assembly->assembly.aname.name = image->image.name;
4912 assembly->assembly.image = &image->image;
4914 mono_domain_assemblies_lock (domain);
4915 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4916 mono_domain_assemblies_unlock (domain);
4918 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4920 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4922 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4925 #endif /* DISABLE_REFLECTION_EMIT */
4928 calc_section_size (MonoDynamicImage *assembly)
4932 /* alignment constraints */
4933 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4934 g_assert ((assembly->code.index % 4) == 0);
4935 assembly->meta_size += 3;
4936 assembly->meta_size &= ~3;
4937 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4938 g_assert ((assembly->resources.index % 4) == 0);
4940 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4941 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4944 if (assembly->win32_res) {
4945 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4947 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4948 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4952 assembly->sections [MONO_SECTION_RELOC].size = 12;
4953 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4963 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4967 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4969 ResTreeNode *t1 = (ResTreeNode*)a;
4970 ResTreeNode *t2 = (ResTreeNode*)b;
4972 return t1->id - t2->id;
4976 * resource_tree_create:
4978 * Organize the resources into a resource tree.
4980 static ResTreeNode *
4981 resource_tree_create (MonoArray *win32_resources)
4983 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4987 tree = g_new0 (ResTreeNode, 1);
4989 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4990 MonoReflectionWin32Resource *win32_res =
4991 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4995 /* FIXME: BUG: this stores managed references in unmanaged memory */
4996 lang_node = g_new0 (ResTreeNode, 1);
4997 lang_node->id = win32_res->lang_id;
4998 lang_node->win32_res = win32_res;
5000 /* Create type node if neccesary */
5002 for (l = tree->children; l; l = l->next)
5003 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5004 type_node = (ResTreeNode*)l->data;
5009 type_node = g_new0 (ResTreeNode, 1);
5010 type_node->id = win32_res->res_type;
5013 * The resource types have to be sorted otherwise
5014 * Windows Explorer can't display the version information.
5016 tree->children = g_slist_insert_sorted (tree->children,
5017 type_node, resource_tree_compare_by_id);
5020 /* Create res node if neccesary */
5022 for (l = type_node->children; l; l = l->next)
5023 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5024 res_node = (ResTreeNode*)l->data;
5029 res_node = g_new0 (ResTreeNode, 1);
5030 res_node->id = win32_res->res_id;
5031 type_node->children = g_slist_append (type_node->children, res_node);
5034 res_node->children = g_slist_append (res_node->children, lang_node);
5041 * resource_tree_encode:
5043 * Encode the resource tree into the format used in the PE file.
5046 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5049 MonoPEResourceDir dir;
5050 MonoPEResourceDirEntry dir_entry;
5051 MonoPEResourceDataEntry data_entry;
5053 guint32 res_id_entries;
5056 * For the format of the resource directory, see the article
5057 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5061 memset (&dir, 0, sizeof (dir));
5062 memset (&dir_entry, 0, sizeof (dir_entry));
5063 memset (&data_entry, 0, sizeof (data_entry));
5065 g_assert (sizeof (dir) == 16);
5066 g_assert (sizeof (dir_entry) == 8);
5067 g_assert (sizeof (data_entry) == 16);
5069 node->offset = p - begin;
5071 /* IMAGE_RESOURCE_DIRECTORY */
5072 res_id_entries = g_slist_length (node->children);
5073 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5075 memcpy (p, &dir, sizeof (dir));
5078 /* Reserve space for entries */
5080 p += sizeof (dir_entry) * res_id_entries;
5082 /* Write children */
5083 for (l = node->children; l; l = l->next) {
5084 ResTreeNode *child = (ResTreeNode*)l->data;
5086 if (child->win32_res) {
5089 child->offset = p - begin;
5091 /* IMAGE_RESOURCE_DATA_ENTRY */
5092 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5093 size = mono_array_length (child->win32_res->res_data);
5094 data_entry.rde_size = GUINT32_TO_LE (size);
5096 memcpy (p, &data_entry, sizeof (data_entry));
5097 p += sizeof (data_entry);
5099 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5102 resource_tree_encode (child, begin, p, &p);
5106 /* IMAGE_RESOURCE_ENTRY */
5107 for (l = node->children; l; l = l->next) {
5108 ResTreeNode *child = (ResTreeNode*)l->data;
5110 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5111 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5113 memcpy (entries, &dir_entry, sizeof (dir_entry));
5114 entries += sizeof (dir_entry);
5121 resource_tree_free (ResTreeNode * node)
5124 for (list = node->children; list; list = list->next)
5125 resource_tree_free ((ResTreeNode*)list->data);
5126 g_slist_free(node->children);
5131 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5136 MonoReflectionWin32Resource *win32_res;
5139 if (!assemblyb->win32_resources)
5143 * Resources are stored in a three level tree inside the PE file.
5144 * - level one contains a node for each type of resource
5145 * - level two contains a node for each resource
5146 * - level three contains a node for each instance of a resource for a
5147 * specific language.
5150 tree = resource_tree_create (assemblyb->win32_resources);
5152 /* Estimate the size of the encoded tree */
5154 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5155 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5156 size += mono_array_length (win32_res->res_data);
5158 /* Directory structure */
5159 size += mono_array_length (assemblyb->win32_resources) * 256;
5160 p = buf = g_malloc (size);
5162 resource_tree_encode (tree, p, p, &p);
5164 g_assert (p - buf <= size);
5166 assembly->win32_res = g_malloc (p - buf);
5167 assembly->win32_res_size = p - buf;
5168 memcpy (assembly->win32_res, buf, p - buf);
5171 resource_tree_free (tree);
5175 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5177 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5180 p += sizeof (MonoPEResourceDir);
5181 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5182 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5183 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5184 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5185 fixup_resource_directory (res_section, child, rva);
5187 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5188 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5191 p += sizeof (MonoPEResourceDirEntry);
5196 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5199 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5200 g_error ("WriteFile returned %d\n", GetLastError ());
5203 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5206 * mono_image_create_pefile:
5207 * @mb: a module builder object
5209 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5210 * assembly->pefile where it can be easily retrieved later in chunks.
5213 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5215 MonoMSDOSHeader *msdos;
5216 MonoDotNetHeader *header;
5217 MonoSectionTable *section;
5218 MonoCLIHeader *cli_header;
5219 guint32 size, image_size, virtual_base, text_offset;
5220 guint32 header_start, section_start, file_offset, virtual_offset;
5221 MonoDynamicImage *assembly;
5222 MonoReflectionAssemblyBuilder *assemblyb;
5223 MonoDynamicStream pefile_stream = {0};
5224 MonoDynamicStream *pefile = &pefile_stream;
5226 guint32 *rva, value;
5228 static const unsigned char msheader[] = {
5229 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5230 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5233 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5234 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5235 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5236 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5239 assemblyb = mb->assemblyb;
5241 mono_image_basic_init (assemblyb);
5242 assembly = mb->dynamic_image;
5244 assembly->pe_kind = assemblyb->pe_kind;
5245 assembly->machine = assemblyb->machine;
5246 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5247 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5249 mono_image_build_metadata (mb);
5251 if (mb->is_main && assemblyb->resources) {
5252 int len = mono_array_length (assemblyb->resources);
5253 for (i = 0; i < len; ++i)
5254 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5257 if (mb->resources) {
5258 int len = mono_array_length (mb->resources);
5259 for (i = 0; i < len; ++i)
5260 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5263 build_compressed_metadata (assembly);
5266 assembly_add_win32_resources (assembly, assemblyb);
5268 nsections = calc_section_size (assembly);
5270 /* The DOS header and stub */
5271 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5272 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5274 /* the dotnet header */
5275 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5277 /* the section tables */
5278 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5280 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5281 virtual_offset = VIRT_ALIGN;
5284 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5285 if (!assembly->sections [i].size)
5288 file_offset += FILE_ALIGN - 1;
5289 file_offset &= ~(FILE_ALIGN - 1);
5290 virtual_offset += VIRT_ALIGN - 1;
5291 virtual_offset &= ~(VIRT_ALIGN - 1);
5293 assembly->sections [i].offset = file_offset;
5294 assembly->sections [i].rva = virtual_offset;
5296 file_offset += assembly->sections [i].size;
5297 virtual_offset += assembly->sections [i].size;
5298 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5301 file_offset += FILE_ALIGN - 1;
5302 file_offset &= ~(FILE_ALIGN - 1);
5304 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5306 /* back-patch info */
5307 msdos = (MonoMSDOSHeader*)pefile->data;
5308 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5310 header = (MonoDotNetHeader*)(pefile->data + header_start);
5311 header->pesig [0] = 'P';
5312 header->pesig [1] = 'E';
5314 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5315 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5316 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5317 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5318 if (assemblyb->pekind == 1) {
5320 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5323 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5326 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5328 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5329 header->pe.pe_major = 6;
5330 header->pe.pe_minor = 0;
5331 size = assembly->sections [MONO_SECTION_TEXT].size;
5332 size += FILE_ALIGN - 1;
5333 size &= ~(FILE_ALIGN - 1);
5334 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5335 size = assembly->sections [MONO_SECTION_RSRC].size;
5336 size += FILE_ALIGN - 1;
5337 size &= ~(FILE_ALIGN - 1);
5338 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5339 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5340 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5341 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5342 /* pe_rva_entry_point always at the beginning of the text section */
5343 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5345 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5346 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5347 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5348 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5349 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5350 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5351 size = section_start;
5352 size += FILE_ALIGN - 1;
5353 size &= ~(FILE_ALIGN - 1);
5354 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5356 size += VIRT_ALIGN - 1;
5357 size &= ~(VIRT_ALIGN - 1);
5358 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5361 // Translate the PEFileKind value to the value expected by the Windows loader
5367 // PEFileKinds.Dll == 1
5368 // PEFileKinds.ConsoleApplication == 2
5369 // PEFileKinds.WindowApplication == 3
5372 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5373 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5375 if (assemblyb->pekind == 3)
5380 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5382 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5383 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5384 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5385 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5386 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5387 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5389 /* fill data directory entries */
5391 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5392 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5394 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5395 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5397 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5398 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5399 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5400 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5401 /* patch entrypoint name */
5402 if (assemblyb->pekind == 1)
5403 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5405 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5406 /* patch imported function RVA name */
5407 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5408 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5410 /* the import table */
5411 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5412 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5413 /* patch imported dll RVA name and other entries in the dir */
5414 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5415 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5416 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5417 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5418 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5419 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5421 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5422 value = (assembly->text_rva + assembly->imp_names_offset);
5423 *p++ = (value) & 0xff;
5424 *p++ = (value >> 8) & (0xff);
5425 *p++ = (value >> 16) & (0xff);
5426 *p++ = (value >> 24) & (0xff);
5428 /* the CLI header info */
5429 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5430 cli_header->ch_size = GUINT32_FROM_LE (72);
5431 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5432 if (mono_framework_version () > 1)
5433 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5435 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5436 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5437 if (assemblyb->entry_point) {
5438 guint32 table_idx = 0;
5439 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5440 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5441 table_idx = methodb->table_idx;
5443 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5445 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5447 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5449 /* The embedded managed resources */
5450 text_offset = assembly->text_rva + assembly->code.index;
5451 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5452 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5453 text_offset += assembly->resources.index;
5454 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5455 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5456 text_offset += assembly->meta_size;
5457 if (assembly->strong_name_size) {
5458 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5459 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5460 text_offset += assembly->strong_name_size;
5463 /* write the section tables and section content */
5464 section = (MonoSectionTable*)(pefile->data + section_start);
5465 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5466 static const char section_names [][7] = {
5467 ".text", ".rsrc", ".reloc"
5469 if (!assembly->sections [i].size)
5471 strcpy (section->st_name, section_names [i]);
5472 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5473 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5474 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5475 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5476 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5477 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5478 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5482 checked_write_file (file, pefile->data, pefile->index);
5484 mono_dynamic_stream_reset (pefile);
5486 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5487 if (!assembly->sections [i].size)
5490 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5491 g_error ("SetFilePointer returned %d\n", GetLastError ());
5494 case MONO_SECTION_TEXT:
5495 /* patch entry point */
5496 p = (guchar*)(assembly->code.data + 2);
5497 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5498 *p++ = (value) & 0xff;
5499 *p++ = (value >> 8) & 0xff;
5500 *p++ = (value >> 16) & 0xff;
5501 *p++ = (value >> 24) & 0xff;
5503 checked_write_file (file, assembly->code.data, assembly->code.index);
5504 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5505 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5506 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5509 g_free (assembly->image.raw_metadata);
5511 case MONO_SECTION_RELOC: {
5515 guint16 type_and_offset;
5519 g_assert (sizeof (reloc) == 12);
5521 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5522 reloc.block_size = GUINT32_FROM_LE (12);
5525 * the entrypoint is always at the start of the text section
5526 * 3 is IMAGE_REL_BASED_HIGHLOW
5527 * 2 is patch_size_rva - text_rva
5529 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5532 checked_write_file (file, &reloc, sizeof (reloc));
5536 case MONO_SECTION_RSRC:
5537 if (assembly->win32_res) {
5539 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5540 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5541 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5545 g_assert_not_reached ();
5549 /* check that the file is properly padded */
5550 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5551 g_error ("SetFilePointer returned %d\n", GetLastError ());
5552 if (! SetEndOfFile (file))
5553 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5555 mono_dynamic_stream_reset (&assembly->code);
5556 mono_dynamic_stream_reset (&assembly->us);
5557 mono_dynamic_stream_reset (&assembly->blob);
5558 mono_dynamic_stream_reset (&assembly->guid);
5559 mono_dynamic_stream_reset (&assembly->sheap);
5561 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5562 g_hash_table_destroy (assembly->blob_cache);
5563 assembly->blob_cache = NULL;
5566 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5569 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5571 g_assert_not_reached ();
5574 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5576 #ifndef DISABLE_REFLECTION_EMIT
5578 MonoReflectionModule *
5579 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5583 MonoImageOpenStatus status;
5584 MonoDynamicAssembly *assembly;
5585 guint32 module_count;
5586 MonoImage **new_modules;
5587 gboolean *new_modules_loaded;
5589 name = mono_string_to_utf8 (fileName);
5591 image = mono_image_open (name, &status);
5594 if (status == MONO_IMAGE_ERROR_ERRNO)
5595 exc = mono_get_exception_file_not_found (fileName);
5597 exc = mono_get_exception_bad_image_format (name);
5599 mono_raise_exception (exc);
5604 assembly = ab->dynamic_assembly;
5605 image->assembly = (MonoAssembly*)assembly;
5607 module_count = image->assembly->image->module_count;
5608 new_modules = g_new0 (MonoImage *, module_count + 1);
5609 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5611 if (image->assembly->image->modules)
5612 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5613 if (image->assembly->image->modules_loaded)
5614 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5615 new_modules [module_count] = image;
5616 new_modules_loaded [module_count] = TRUE;
5617 mono_image_addref (image);
5619 g_free (image->assembly->image->modules);
5620 image->assembly->image->modules = new_modules;
5621 image->assembly->image->modules_loaded = new_modules_loaded;
5622 image->assembly->image->module_count ++;
5624 mono_assembly_load_references (image, &status);
5626 mono_image_close (image);
5627 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5630 return mono_module_get_object (mono_domain_get (), image);
5633 #endif /* DISABLE_REFLECTION_EMIT */
5636 * We need to return always the same object for MethodInfo, FieldInfo etc..
5637 * but we need to consider the reflected type.
5638 * type uses a different hash, since it uses custom hash/equal functions.
5643 MonoClass *refclass;
5647 reflected_equal (gconstpointer a, gconstpointer b) {
5648 const ReflectedEntry *ea = a;
5649 const ReflectedEntry *eb = b;
5651 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5655 reflected_hash (gconstpointer a) {
5656 const ReflectedEntry *ea = a;
5657 return mono_aligned_addr_hash (ea->item);
5660 #define CHECK_OBJECT(t,p,k) \
5666 mono_domain_lock (domain); \
5667 if (!domain->refobject_hash) \
5668 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5669 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5670 mono_domain_unlock (domain); \
5673 mono_domain_unlock (domain); \
5676 #ifndef HAVE_NULL_GC
5677 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5679 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5682 #define CACHE_OBJECT(t,p,o,k) \
5685 ReflectedEntry pe; \
5687 pe.refclass = (k); \
5688 mono_domain_lock (domain); \
5689 if (!domain->refobject_hash) \
5690 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5691 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5693 ReflectedEntry *e = ALLOC_REFENTRY; \
5695 e->refclass = (k); \
5696 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5699 mono_domain_unlock (domain); \
5704 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5706 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5710 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5712 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5715 #ifndef DISABLE_REFLECTION_EMIT
5718 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5720 MonoDynamicImage *image = moduleb->dynamic_image;
5721 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5724 MonoImage **new_modules;
5727 * FIXME: we already created an image in mono_image_basic_init (), but
5728 * we don't know which module it belongs to, since that is only
5729 * determined at assembly save time.
5731 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5732 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5734 moduleb->module.image = &image->image;
5735 moduleb->dynamic_image = image;
5736 register_module (mono_object_domain (moduleb), moduleb, image);
5738 /* register the module with the assembly */
5739 ass = ab->dynamic_assembly->assembly.image;
5740 module_count = ass->module_count;
5741 new_modules = g_new0 (MonoImage *, module_count + 1);
5744 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5745 new_modules [module_count] = &image->image;
5746 mono_image_addref (&image->image);
5748 g_free (ass->modules);
5749 ass->modules = new_modules;
5750 ass->module_count ++;
5757 * mono_assembly_get_object:
5758 * @domain: an app domain
5759 * @assembly: an assembly
5761 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5763 MonoReflectionAssembly*
5764 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5766 static MonoClass *System_Reflection_Assembly;
5767 MonoReflectionAssembly *res;
5769 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5770 if (!System_Reflection_Assembly)
5771 System_Reflection_Assembly = mono_class_from_name (
5772 mono_defaults.corlib, "System.Reflection", "Assembly");
5773 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5774 res->assembly = assembly;
5776 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5781 MonoReflectionModule*
5782 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5784 static MonoClass *System_Reflection_Module;
5785 MonoReflectionModule *res;
5788 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5789 if (!System_Reflection_Module)
5790 System_Reflection_Module = mono_class_from_name (
5791 mono_defaults.corlib, "System.Reflection", "Module");
5792 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5795 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5797 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5798 basename = g_path_get_basename (image->name);
5799 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5800 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5804 if (image->assembly->image == image) {
5805 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5809 if (image->assembly->image->modules) {
5810 for (i = 0; i < image->assembly->image->module_count; i++) {
5811 if (image->assembly->image->modules [i] == image)
5812 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5814 g_assert (res->token);
5818 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5821 MonoReflectionModule*
5822 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5824 static MonoClass *System_Reflection_Module;
5825 MonoReflectionModule *res;
5826 MonoTableInfo *table;
5827 guint32 cols [MONO_FILE_SIZE];
5829 guint32 i, name_idx;
5832 if (!System_Reflection_Module)
5833 System_Reflection_Module = mono_class_from_name (
5834 mono_defaults.corlib, "System.Reflection", "Module");
5835 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5837 table = &image->tables [MONO_TABLE_FILE];
5838 g_assert (table_index < table->rows);
5839 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5842 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5843 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5845 /* Check whenever the row has a corresponding row in the moduleref table */
5846 table = &image->tables [MONO_TABLE_MODULEREF];
5847 for (i = 0; i < table->rows; ++i) {
5848 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5849 val = mono_metadata_string_heap (image, name_idx);
5850 if (strcmp (val, name) == 0)
5851 res->image = image->modules [i];
5854 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5855 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5856 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5857 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5858 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5864 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5866 if ((t1->type != t2->type) ||
5867 (t1->byref != t2->byref))
5871 case MONO_TYPE_VOID:
5872 case MONO_TYPE_BOOLEAN:
5873 case MONO_TYPE_CHAR:
5884 case MONO_TYPE_STRING:
5887 case MONO_TYPE_OBJECT:
5888 case MONO_TYPE_TYPEDBYREF:
5890 case MONO_TYPE_VALUETYPE:
5891 case MONO_TYPE_CLASS:
5892 case MONO_TYPE_SZARRAY:
5893 return t1->data.klass == t2->data.klass;
5895 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5896 case MONO_TYPE_ARRAY:
5897 if (t1->data.array->rank != t2->data.array->rank)
5899 return t1->data.array->eklass == t2->data.array->eklass;
5900 case MONO_TYPE_GENERICINST: {
5902 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5903 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5904 if (i1->type_argc != i2->type_argc)
5906 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5907 &t2->data.generic_class->container_class->byval_arg))
5909 /* FIXME: we should probably just compare the instance pointers directly. */
5910 for (i = 0; i < i1->type_argc; ++i) {
5911 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5917 case MONO_TYPE_MVAR:
5918 return t1->data.generic_param == t2->data.generic_param;
5920 g_error ("implement type compare for %0x!", t1->type);
5928 mymono_metadata_type_hash (MonoType *t1)
5934 hash |= t1->byref << 6; /* do not collide with t1->type values */
5936 case MONO_TYPE_VALUETYPE:
5937 case MONO_TYPE_CLASS:
5938 case MONO_TYPE_SZARRAY:
5939 /* check if the distribution is good enough */
5940 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5942 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5943 case MONO_TYPE_GENERICINST: {
5945 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5946 hash += g_str_hash (t1->data.generic_class->container_class->name);
5948 for (i = 0; i < inst->type_argc; ++i) {
5949 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5958 static MonoReflectionGenericClass*
5959 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5961 static MonoClass *System_Reflection_MonoGenericClass;
5962 MonoReflectionGenericClass *res;
5963 MonoClass *klass, *gklass;
5965 if (!System_Reflection_MonoGenericClass) {
5966 System_Reflection_MonoGenericClass = mono_class_from_name (
5967 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5968 g_assert (System_Reflection_MonoGenericClass);
5971 klass = mono_class_from_mono_type (geninst);
5972 gklass = klass->generic_class->container_class;
5974 mono_class_init (klass);
5977 /* FIXME: allow unpinned later */
5978 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5980 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5983 res->type.type = geninst;
5984 g_assert (gklass->reflection_info);
5985 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5986 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5992 verify_safe_for_managed_space (MonoType *type)
5994 switch (type->type) {
5996 case MONO_TYPE_ARRAY:
5997 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5999 return verify_safe_for_managed_space (type->data.type);
6000 case MONO_TYPE_SZARRAY:
6001 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6002 case MONO_TYPE_GENERICINST: {
6003 MonoGenericInst *inst = type->data.generic_class->inst;
6007 for (i = 0; i < inst->type_argc; ++i)
6008 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6014 case MONO_TYPE_MVAR:
6021 * mono_type_get_object:
6022 * @domain: an app domain
6025 * Return an System.MonoType object representing the type @type.
6028 mono_type_get_object (MonoDomain *domain, MonoType *type)
6030 MonoReflectionType *res;
6031 MonoClass *klass = mono_class_from_mono_type (type);
6033 /*we must avoid using @type as it might have come
6034 * from a mono_metadata_type_dup and the caller
6035 * expects that is can be freed.
6036 * Using the right type from
6038 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6040 /* void is very common */
6041 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6042 return (MonoReflectionType*)domain->typeof_void;
6045 * If the vtable of the given class was already created, we can use
6046 * the MonoType from there and avoid all locking and hash table lookups.
6048 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6049 * that the resulting object is diferent.
6051 if (type == &klass->byval_arg && !klass->image->dynamic) {
6052 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6053 if (vtable && vtable->type)
6054 return vtable->type;
6057 mono_domain_lock (domain);
6058 if (!domain->type_hash)
6059 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6060 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6061 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6062 mono_domain_unlock (domain);
6065 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6066 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6067 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6068 mono_g_hash_table_insert (domain->type_hash, type, res);
6069 mono_domain_unlock (domain);
6073 if (!verify_safe_for_managed_space (type)) {
6074 mono_domain_unlock (domain);
6075 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6078 if (klass->reflection_info && !klass->wastypebuilder) {
6079 /* g_assert_not_reached (); */
6080 /* should this be considered an error condition? */
6082 mono_domain_unlock (domain);
6083 return klass->reflection_info;
6086 // FIXME: Get rid of this, do it in the icalls for Type
6087 mono_class_init (klass);
6089 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6091 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6094 mono_g_hash_table_insert (domain->type_hash, type, res);
6096 if (type->type == MONO_TYPE_VOID)
6097 MONO_OBJECT_SETREF (domain, typeof_void, res);
6099 mono_domain_unlock (domain);
6104 * mono_method_get_object:
6105 * @domain: an app domain
6107 * @refclass: the reflected type (can be NULL)
6109 * Return an System.Reflection.MonoMethod object representing the method @method.
6111 MonoReflectionMethod*
6112 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6115 * We use the same C representation for methods and constructors, but the type
6116 * name in C# is different.
6118 static MonoClass *System_Reflection_MonoMethod = NULL;
6119 static MonoClass *System_Reflection_MonoCMethod = NULL;
6120 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6121 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6123 MonoReflectionMethod *ret;
6126 * Don't let static RGCTX invoke wrappers get into
6127 * MonoReflectionMethods.
6129 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6130 method = mono_marshal_method_from_wrapper (method);
6132 if (method->is_inflated) {
6133 MonoReflectionGenericMethod *gret;
6135 refclass = method->klass;
6136 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6137 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6138 if (!System_Reflection_MonoGenericCMethod)
6139 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6140 klass = System_Reflection_MonoGenericCMethod;
6142 if (!System_Reflection_MonoGenericMethod)
6143 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6144 klass = System_Reflection_MonoGenericMethod;
6146 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6147 gret->method.method = method;
6148 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6149 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6150 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6154 refclass = method->klass;
6156 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6157 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6158 if (!System_Reflection_MonoCMethod)
6159 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6160 klass = System_Reflection_MonoCMethod;
6163 if (!System_Reflection_MonoMethod)
6164 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6165 klass = System_Reflection_MonoMethod;
6167 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6168 ret->method = method;
6169 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6170 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6174 * mono_field_get_object:
6175 * @domain: an app domain
6179 * Return an System.Reflection.MonoField object representing the field @field
6182 MonoReflectionField*
6183 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6185 MonoReflectionField *res;
6186 static MonoClass *monofield_klass;
6188 CHECK_OBJECT (MonoReflectionField *, field, klass);
6189 if (!monofield_klass)
6190 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6191 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6194 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6195 if (is_field_on_inst (field))
6196 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6198 res->attrs = field->type->attrs;
6199 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6200 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6204 * mono_property_get_object:
6205 * @domain: an app domain
6207 * @property: a property
6209 * Return an System.Reflection.MonoProperty object representing the property @property
6212 MonoReflectionProperty*
6213 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6215 MonoReflectionProperty *res;
6216 static MonoClass *monoproperty_klass;
6218 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6219 if (!monoproperty_klass)
6220 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6221 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6223 res->property = property;
6224 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6228 * mono_event_get_object:
6229 * @domain: an app domain
6233 * Return an System.Reflection.MonoEvent object representing the event @event
6236 MonoReflectionEvent*
6237 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6239 MonoReflectionEvent *res;
6240 static MonoClass *monoevent_klass;
6242 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6243 if (!monoevent_klass)
6244 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6245 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6248 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6252 * mono_get_reflection_missing_object:
6253 * @domain: Domain where the object lives
6255 * Returns the System.Reflection.Missing.Value singleton object
6256 * (of type System.Reflection.Missing).
6258 * Used as the value for ParameterInfo.DefaultValue when Optional
6262 mono_get_reflection_missing_object (MonoDomain *domain)
6265 static MonoClassField *missing_value_field = NULL;
6267 if (!missing_value_field) {
6268 MonoClass *missing_klass;
6269 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6270 mono_class_init (missing_klass);
6271 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6272 g_assert (missing_value_field);
6274 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6280 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6283 *dbnull = mono_get_dbnull_object (domain);
6288 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6290 if (!*reflection_missing)
6291 *reflection_missing = mono_get_reflection_missing_object (domain);
6292 return *reflection_missing;
6296 * mono_param_get_objects:
6297 * @domain: an app domain
6300 * Return an System.Reflection.ParameterInfo array object representing the parameters
6301 * in the method @method.
6304 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6306 static MonoClass *System_Reflection_ParameterInfo;
6307 static MonoClass *System_Reflection_ParameterInfo_array;
6308 MonoArray *res = NULL;
6309 MonoReflectionMethod *member = NULL;
6310 MonoReflectionParameter *param = NULL;
6311 char **names, **blobs = NULL;
6312 guint32 *types = NULL;
6313 MonoType *type = NULL;
6314 MonoObject *dbnull = NULL;
6315 MonoObject *missing = NULL;
6316 MonoMarshalSpec **mspecs;
6317 MonoMethodSignature *sig;
6318 MonoVTable *pinfo_vtable;
6321 if (!System_Reflection_ParameterInfo_array) {
6324 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6325 mono_memory_barrier ();
6326 System_Reflection_ParameterInfo = klass;
6328 klass = mono_array_class_get (klass, 1);
6329 mono_memory_barrier ();
6330 System_Reflection_ParameterInfo_array = klass;
6333 if (!mono_method_signature (method)->param_count)
6334 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6336 /* Note: the cache is based on the address of the signature into the method
6337 * since we already cache MethodInfos with the method as keys.
6339 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6341 sig = mono_method_signature (method);
6342 member = mono_method_get_object (domain, method, NULL);
6343 names = g_new (char *, sig->param_count);
6344 mono_method_get_param_names (method, (const char **) names);
6346 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6347 mono_method_get_marshal_info (method, mspecs);
6349 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6350 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6351 for (i = 0; i < sig->param_count; ++i) {
6352 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6353 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6354 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6355 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6356 param->PositionImpl = i;
6357 param->AttrsImpl = sig->params [i]->attrs;
6359 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6360 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6361 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6363 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6367 blobs = g_new0 (char *, sig->param_count);
6368 types = g_new0 (guint32, sig->param_count);
6369 get_default_param_value_blobs (method, blobs, types);
6372 /* Build MonoType for the type from the Constant Table */
6374 type = g_new0 (MonoType, 1);
6375 type->type = types [i];
6376 type->data.klass = NULL;
6377 if (types [i] == MONO_TYPE_CLASS)
6378 type->data.klass = mono_defaults.object_class;
6379 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6380 /* For enums, types [i] contains the base type */
6382 type->type = MONO_TYPE_VALUETYPE;
6383 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6385 type->data.klass = mono_class_from_mono_type (type);
6387 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6389 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6390 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6391 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6392 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6394 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6400 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6402 mono_array_setref (res, i, param);
6409 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6411 mono_metadata_free_marshal_spec (mspecs [i]);
6414 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6418 * mono_method_body_get_object:
6419 * @domain: an app domain
6422 * Return an System.Reflection.MethodBody object representing the method @method.
6424 MonoReflectionMethodBody*
6425 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6427 static MonoClass *System_Reflection_MethodBody = NULL;
6428 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6429 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6430 MonoReflectionMethodBody *ret;
6431 MonoMethodNormal *mn;
6432 MonoMethodHeader *header;
6433 guint32 method_rva, local_var_sig_token;
6435 unsigned char format, flags;
6438 if (!System_Reflection_MethodBody)
6439 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6440 if (!System_Reflection_LocalVariableInfo)
6441 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6442 if (!System_Reflection_ExceptionHandlingClause)
6443 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6445 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6447 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6448 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6449 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6450 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6452 mn = (MonoMethodNormal *)method;
6453 header = mono_method_get_header (method);
6455 /* Obtain local vars signature token */
6456 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6457 ptr = mono_image_rva_map (method->klass->image, method_rva);
6458 flags = *(const unsigned char *) ptr;
6459 format = flags & METHOD_HEADER_FORMAT_MASK;
6461 case METHOD_HEADER_TINY_FORMAT:
6462 case METHOD_HEADER_TINY_FORMAT1:
6463 local_var_sig_token = 0;
6465 case METHOD_HEADER_FAT_FORMAT:
6469 local_var_sig_token = read32 (ptr);
6472 g_assert_not_reached ();
6475 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6477 ret->init_locals = header->init_locals;
6478 ret->max_stack = header->max_stack;
6479 ret->local_var_sig_token = local_var_sig_token;
6480 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6481 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6484 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6485 for (i = 0; i < header->num_locals; ++i) {
6486 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6487 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6488 info->is_pinned = header->locals [i]->pinned;
6489 info->local_index = i;
6490 mono_array_setref (ret->locals, i, info);
6494 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6495 for (i = 0; i < header->num_clauses; ++i) {
6496 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6497 MonoExceptionClause *clause = &header->clauses [i];
6499 info->flags = clause->flags;
6500 info->try_offset = clause->try_offset;
6501 info->try_length = clause->try_len;
6502 info->handler_offset = clause->handler_offset;
6503 info->handler_length = clause->handler_len;
6504 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6505 info->filter_offset = clause->data.filter_offset;
6506 else if (clause->data.catch_class)
6507 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6509 mono_array_setref (ret->clauses, i, info);
6512 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6517 * mono_get_dbnull_object:
6518 * @domain: Domain where the object lives
6520 * Returns the System.DBNull.Value singleton object
6522 * Used as the value for ParameterInfo.DefaultValue
6525 mono_get_dbnull_object (MonoDomain *domain)
6528 static MonoClassField *dbnull_value_field = NULL;
6530 if (!dbnull_value_field) {
6531 MonoClass *dbnull_klass;
6532 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6533 mono_class_init (dbnull_klass);
6534 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6535 g_assert (dbnull_value_field);
6537 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6543 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6545 guint32 param_index, i, lastp, crow = 0;
6546 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6549 MonoClass *klass = method->klass;
6550 MonoImage *image = klass->image;
6551 MonoMethodSignature *methodsig = mono_method_signature (method);
6553 MonoTableInfo *constt;
6554 MonoTableInfo *methodt;
6555 MonoTableInfo *paramt;
6557 if (!methodsig->param_count)
6560 mono_class_init (klass);
6562 if (klass->image->dynamic) {
6563 MonoReflectionMethodAux *aux;
6564 if (method->is_inflated)
6565 method = ((MonoMethodInflated*)method)->declaring;
6566 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6567 if (aux && aux->param_defaults) {
6568 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6569 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6574 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6575 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6576 constt = &image->tables [MONO_TABLE_CONSTANT];
6578 idx = mono_method_get_index (method) - 1;
6579 g_assert (idx != -1);
6581 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6582 if (idx + 1 < methodt->rows)
6583 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6585 lastp = paramt->rows + 1;
6587 for (i = param_index; i < lastp; ++i) {
6590 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6591 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6593 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6596 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6601 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6602 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6603 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6610 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6615 MonoType *basetype = type;
6620 klass = mono_class_from_mono_type (type);
6621 if (klass->valuetype) {
6622 object = mono_object_new (domain, klass);
6623 retval = ((gchar *) object + sizeof (MonoObject));
6624 if (klass->enumtype)
6625 basetype = klass->enum_basetype;
6630 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6637 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6641 memset (assembly, 0, sizeof (MonoAssemblyName));
6643 assembly->culture = "";
6644 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6646 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6649 while (g_ascii_isspace (*p) || *p == ',') {
6658 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6660 assembly->major = strtoul (p, &s, 10);
6661 if (s == p || *s != '.')
6664 assembly->minor = strtoul (p, &s, 10);
6665 if (s == p || *s != '.')
6668 assembly->build = strtoul (p, &s, 10);
6669 if (s == p || *s != '.')
6672 assembly->revision = strtoul (p, &s, 10);
6676 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6678 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6679 assembly->culture = "";
6682 assembly->culture = p;
6683 while (*p && *p != ',') {
6687 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6689 if (strncmp (p, "null", 4) == 0) {
6694 while (*p && *p != ',') {
6697 len = (p - start + 1);
6698 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6699 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6700 g_strlcpy ((char*)assembly->public_key_token, start, len);
6703 while (*p && *p != ',')
6707 while (g_ascii_isspace (*p) || *p == ',') {
6721 * mono_reflection_parse_type:
6724 * Parse a type name as accepted by the GetType () method and output the info
6725 * extracted in the info structure.
6726 * the name param will be mangled, so, make a copy before passing it to this function.
6727 * The fields in info will be valid until the memory pointed to by name is valid.
6729 * See also mono_type_get_name () below.
6731 * Returns: 0 on parse error.
6734 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6735 MonoTypeNameParse *info)
6737 char *start, *p, *w, *temp, *last_point, *startn;
6738 int in_modifiers = 0;
6739 int isbyref = 0, rank, arity = 0, i;
6741 start = p = w = name;
6743 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6744 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6745 info->name = info->name_space = NULL;
6746 info->nested = NULL;
6747 info->modifiers = NULL;
6748 info->type_arguments = NULL;
6750 /* last_point separates the namespace from the name */
6753 while (*p == ' ') p++, start++, w++, name++;
6758 *p = 0; /* NULL terminate the name */
6760 info->nested = g_list_append (info->nested, startn);
6761 /* we have parsed the nesting namespace + name */
6765 info->name_space = start;
6767 info->name = last_point + 1;
6769 info->name_space = (char *)"";
6788 i = strtol (p, &temp, 10);
6805 info->name_space = start;
6807 info->name = last_point + 1;
6809 info->name_space = (char *)"";
6816 if (isbyref) /* only one level allowed by the spec */
6819 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6823 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6829 info->type_arguments = g_ptr_array_new ();
6830 for (i = 0; i < arity; i++) {
6831 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6832 gboolean fqname = FALSE;
6834 g_ptr_array_add (info->type_arguments, subinfo);
6841 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6852 while (*p && (*p != ']'))
6860 if (g_ascii_isspace (*aname)) {
6867 !assembly_name_to_aname (&subinfo->assembly, aname))
6871 if (i + 1 < arity) {
6891 else if (*p == '*') /* '*' means unknown lower bound */
6892 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6899 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6910 if (g_ascii_isspace (*p)) {
6917 return 0; /* missing assembly name */
6918 if (!assembly_name_to_aname (&info->assembly, p))
6924 if (info->assembly.name)
6927 // *w = 0; /* terminate class name */
6929 if (!info->name || !*info->name)
6933 /* add other consistency checks */
6938 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6940 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6944 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6946 gboolean type_resolve = FALSE;
6948 MonoImage *rootimage = image;
6950 if (info->assembly.name) {
6951 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6952 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6954 * This could happen in the AOT compiler case when the search hook is not
6957 assembly = image->assembly;
6959 /* then we must load the assembly ourselve - see #60439 */
6960 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6964 image = assembly->image;
6965 } else if (!image) {
6966 image = mono_defaults.corlib;
6969 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6970 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6971 image = mono_defaults.corlib;
6972 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6979 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6984 gboolean bounded = FALSE;
6987 image = mono_defaults.corlib;
6990 klass = mono_class_from_name_case (image, info->name_space, info->name);
6992 klass = mono_class_from_name (image, info->name_space, info->name);
6995 for (mod = info->nested; mod; mod = mod->next) {
6996 gpointer iter = NULL;
7000 mono_class_init (parent);
7002 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7004 if (g_strcasecmp (klass->name, mod->data) == 0)
7007 if (strcmp (klass->name, mod->data) == 0)
7016 mono_class_init (klass);
7018 if (info->type_arguments) {
7019 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7020 MonoReflectionType *the_type;
7024 for (i = 0; i < info->type_arguments->len; i++) {
7025 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7027 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7028 if (!type_args [i]) {
7034 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7036 instance = mono_reflection_bind_generic_parameters (
7037 the_type, info->type_arguments->len, type_args);
7043 klass = mono_class_from_mono_type (instance);
7046 for (mod = info->modifiers; mod; mod = mod->next) {
7047 modval = GPOINTER_TO_UINT (mod->data);
7048 if (!modval) { /* byref: must be last modifier */
7049 return &klass->this_arg;
7050 } else if (modval == -1) {
7051 klass = mono_ptr_class_get (&klass->byval_arg);
7052 } else if (modval == -2) {
7054 } else { /* array rank */
7055 klass = mono_bounded_array_class_get (klass, modval, bounded);
7057 mono_class_init (klass);
7060 return &klass->byval_arg;
7064 * mono_reflection_get_type:
7065 * @image: a metadata context
7066 * @info: type description structure
7067 * @ignorecase: flag for case-insensitive string compares
7068 * @type_resolve: whenever type resolve was already tried
7070 * Build a MonoType from the type description in @info.
7075 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7076 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7080 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7082 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7086 g_assert (assembly->dynamic);
7088 /* Enumerate all modules */
7091 if (abuilder->modules) {
7092 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7093 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7094 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7100 if (!type && abuilder->loaded_modules) {
7101 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7102 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7103 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7113 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7116 MonoReflectionAssembly *assembly;
7120 if (image && image->dynamic)
7121 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7123 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7126 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7133 *type_resolve = TRUE;
7136 /* Reconstruct the type name */
7137 fullName = g_string_new ("");
7138 if (info->name_space && (info->name_space [0] != '\0'))
7139 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7141 g_string_printf (fullName, info->name);
7142 for (mod = info->nested; mod; mod = mod->next)
7143 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7145 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7147 if (assembly->assembly->dynamic)
7148 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7150 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7153 g_string_free (fullName, TRUE);
7158 mono_reflection_free_type_info (MonoTypeNameParse *info)
7160 g_list_free (info->modifiers);
7161 g_list_free (info->nested);
7163 if (info->type_arguments) {
7166 for (i = 0; i < info->type_arguments->len; i++) {
7167 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7169 mono_reflection_free_type_info (subinfo);
7170 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7174 g_ptr_array_free (info->type_arguments, TRUE);
7179 * mono_reflection_type_from_name:
7181 * @image: a metadata context (can be NULL).
7183 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7184 * it defaults to get the type from @image or, if @image is NULL or loading
7185 * from it fails, uses corlib.
7189 mono_reflection_type_from_name (char *name, MonoImage *image)
7191 MonoType *type = NULL;
7192 MonoTypeNameParse info;
7195 /* Make a copy since parse_type modifies its argument */
7196 tmp = g_strdup (name);
7198 /*g_print ("requested type %s\n", str);*/
7199 if (mono_reflection_parse_type (tmp, &info)) {
7200 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7204 mono_reflection_free_type_info (&info);
7209 * mono_reflection_get_token:
7211 * Return the metadata token of OBJ which should be an object
7212 * representing a metadata element.
7215 mono_reflection_get_token (MonoObject *obj)
7220 klass = obj->vtable->klass;
7222 if (strcmp (klass->name, "MethodBuilder") == 0) {
7223 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7225 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7226 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7227 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7229 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7230 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7231 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7233 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7234 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7235 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7236 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7237 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7238 } else if (strcmp (klass->name, "MonoType") == 0) {
7239 MonoReflectionType *tb = (MonoReflectionType *)obj;
7240 token = mono_class_from_mono_type (tb->type)->type_token;
7241 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7242 strcmp (klass->name, "MonoMethod") == 0 ||
7243 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7244 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7245 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7246 if (m->method->is_inflated) {
7247 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7248 return inflated->declaring->token;
7250 token = m->method->token;
7252 } else if (strcmp (klass->name, "MonoField") == 0) {
7253 MonoReflectionField *f = (MonoReflectionField*)obj;
7255 if (is_field_on_inst (f->field)) {
7256 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7257 int field_index = f->field - dgclass->fields;
7260 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7261 obj = dgclass->field_objects [field_index];
7262 return mono_reflection_get_token (obj);
7264 token = mono_class_get_field_token (f->field);
7265 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7266 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7268 token = mono_class_get_property_token (p->property);
7269 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7270 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7272 token = mono_class_get_event_token (p->event);
7273 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7274 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7276 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7277 } else if (strcmp (klass->name, "Module") == 0) {
7278 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7281 } else if (strcmp (klass->name, "Assembly") == 0) {
7282 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7284 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7285 MonoException *ex = mono_get_exception_not_implemented (msg);
7287 mono_raise_exception (ex);
7294 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7296 int slen, type = t->type;
7297 MonoClass *tklass = t->data.klass;
7303 case MONO_TYPE_BOOLEAN: {
7304 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7309 case MONO_TYPE_CHAR:
7311 case MONO_TYPE_I2: {
7312 guint16 *val = g_malloc (sizeof (guint16));
7317 #if SIZEOF_VOID_P == 4
7323 case MONO_TYPE_I4: {
7324 guint32 *val = g_malloc (sizeof (guint32));
7329 #if SIZEOF_VOID_P == 8
7330 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7334 case MONO_TYPE_I8: {
7335 guint64 *val = g_malloc (sizeof (guint64));
7340 case MONO_TYPE_R8: {
7341 double *val = g_malloc (sizeof (double));
7346 case MONO_TYPE_VALUETYPE:
7347 if (t->data.klass->enumtype) {
7348 type = t->data.klass->enum_basetype->type;
7351 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7354 case MONO_TYPE_STRING:
7355 if (*p == (char)0xFF) {
7359 slen = mono_metadata_decode_value (p, &p);
7361 return mono_string_new_len (mono_domain_get (), p, slen);
7362 case MONO_TYPE_CLASS: {
7365 if (*p == (char)0xFF) {
7370 slen = mono_metadata_decode_value (p, &p);
7371 n = g_memdup (p, slen + 1);
7373 t = mono_reflection_type_from_name (n, image);
7375 g_warning ("Cannot load type '%s'", n);
7379 return mono_type_get_object (mono_domain_get (), t);
7383 case MONO_TYPE_OBJECT: {
7386 MonoClass *subc = NULL;
7391 } else if (subt == 0x0E) {
7392 type = MONO_TYPE_STRING;
7394 } else if (subt == 0x1D) {
7395 MonoType simple_type = {{0}};
7400 /* See Partition II, Appendix B3 */
7401 etype = MONO_TYPE_OBJECT;
7402 type = MONO_TYPE_SZARRAY;
7403 simple_type.type = etype;
7404 tklass = mono_class_from_mono_type (&simple_type);
7406 } else if (subt == 0x55) {
7409 slen = mono_metadata_decode_value (p, &p);
7410 n = g_memdup (p, slen + 1);
7412 t = mono_reflection_type_from_name (n, image);
7414 g_error ("Cannot load type '%s'", n);
7417 subc = mono_class_from_mono_type (t);
7418 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7419 MonoType simple_type = {{0}};
7420 simple_type.type = subt;
7421 subc = mono_class_from_mono_type (&simple_type);
7423 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7425 val = load_cattr_value (image, &subc->byval_arg, p, end);
7426 obj = mono_object_new (mono_domain_get (), subc);
7427 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7431 case MONO_TYPE_SZARRAY: {
7433 guint32 i, alen, basetype;
7436 if (alen == 0xffffffff) {
7440 arr = mono_array_new (mono_domain_get(), tklass, alen);
7441 basetype = tklass->byval_arg.type;
7442 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7443 basetype = tklass->enum_basetype->type;
7448 case MONO_TYPE_BOOLEAN:
7449 for (i = 0; i < alen; i++) {
7450 MonoBoolean val = *p++;
7451 mono_array_set (arr, MonoBoolean, i, val);
7454 case MONO_TYPE_CHAR:
7457 for (i = 0; i < alen; i++) {
7458 guint16 val = read16 (p);
7459 mono_array_set (arr, guint16, i, val);
7466 for (i = 0; i < alen; i++) {
7467 guint32 val = read32 (p);
7468 mono_array_set (arr, guint32, i, val);
7473 for (i = 0; i < alen; i++) {
7476 mono_array_set (arr, double, i, val);
7482 for (i = 0; i < alen; i++) {
7483 guint64 val = read64 (p);
7484 mono_array_set (arr, guint64, i, val);
7488 case MONO_TYPE_CLASS:
7489 case MONO_TYPE_OBJECT:
7490 case MONO_TYPE_STRING:
7491 for (i = 0; i < alen; i++) {
7492 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7493 mono_array_setref (arr, i, item);
7497 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7503 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7509 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7511 static MonoClass *klass;
7512 static MonoMethod *ctor;
7514 void *params [2], *unboxed;
7517 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7519 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7521 params [0] = mono_type_get_object (mono_domain_get (), t);
7523 retval = mono_object_new (mono_domain_get (), klass);
7524 unboxed = mono_object_unbox (retval);
7525 mono_runtime_invoke (ctor, unboxed, params, NULL);
7531 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7533 static MonoClass *klass;
7534 static MonoMethod *ctor;
7536 void *unboxed, *params [2];
7539 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7541 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7544 params [1] = typedarg;
7545 retval = mono_object_new (mono_domain_get (), klass);
7546 unboxed = mono_object_unbox (retval);
7547 mono_runtime_invoke (ctor, unboxed, params, NULL);
7553 type_is_reference (MonoType *type)
7555 switch (type->type) {
7556 case MONO_TYPE_BOOLEAN:
7557 case MONO_TYPE_CHAR:
7570 case MONO_TYPE_VALUETYPE:
7578 free_param_data (MonoMethodSignature *sig, void **params) {
7580 for (i = 0; i < sig->param_count; ++i) {
7581 if (!type_is_reference (sig->params [i]))
7582 g_free (params [i]);
7587 * Find the field index in the metadata FieldDef table.
7590 find_field_index (MonoClass *klass, MonoClassField *field) {
7593 for (i = 0; i < klass->field.count; ++i) {
7594 if (field == &klass->fields [i])
7595 return klass->field.first + 1 + i;
7601 * Find the property index in the metadata Property table.
7604 find_property_index (MonoClass *klass, MonoProperty *property) {
7607 for (i = 0; i < klass->property.count; ++i) {
7608 if (property == &klass->properties [i])
7609 return klass->property.first + 1 + i;
7615 * Find the event index in the metadata Event table.
7618 find_event_index (MonoClass *klass, MonoEvent *event) {
7621 for (i = 0; i < klass->event.count; ++i) {
7622 if (event == &klass->events [i])
7623 return klass->event.first + 1 + i;
7629 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7631 const char *p = (const char*)data;
7633 guint32 i, j, num_named;
7637 mono_class_init (method->klass);
7640 attr = mono_object_new (mono_domain_get (), method->klass);
7641 mono_runtime_invoke (method, attr, NULL, NULL);
7645 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7648 /*g_print ("got attr %s\n", method->klass->name);*/
7650 /* Allocate using alloca so it gets GC tracking */
7651 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7655 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7656 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7660 attr = mono_object_new (mono_domain_get (), method->klass);
7661 mono_runtime_invoke (method, attr, params, NULL);
7662 free_param_data (method->signature, params);
7663 num_named = read16 (named);
7665 for (j = 0; j < num_named; j++) {
7667 char *name, named_type, data_type;
7668 named_type = *named++;
7669 data_type = *named++; /* type of data */
7670 if (data_type == MONO_TYPE_SZARRAY)
7671 data_type = *named++;
7672 if (data_type == MONO_TYPE_ENUM) {
7675 type_len = mono_metadata_decode_blob_size (named, &named);
7676 type_name = g_malloc (type_len + 1);
7677 memcpy (type_name, named, type_len);
7678 type_name [type_len] = 0;
7680 /* FIXME: lookup the type and check type consistency */
7683 name_len = mono_metadata_decode_blob_size (named, &named);
7684 name = g_malloc (name_len + 1);
7685 memcpy (name, named, name_len);
7686 name [name_len] = 0;
7688 if (named_type == 0x53) {
7689 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7690 void *val = load_cattr_value (image, field->type, named, &named);
7691 mono_field_set_value (attr, field, val);
7692 if (!type_is_reference (field->type))
7694 } else if (named_type == 0x54) {
7697 MonoType *prop_type;
7699 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7700 /* can we have more that 1 arg in a custom attr named property? */
7701 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7702 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7703 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7704 mono_property_set_value (prop, attr, pparams, NULL);
7705 if (!type_is_reference (prop_type))
7706 g_free (pparams [0]);
7715 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7717 MonoArray *typedargs, *namedargs;
7718 MonoClass *attrklass;
7719 static MonoMethod *ctor;
7722 const char *p = (const char*)data;
7724 guint32 i, j, num_named;
7727 mono_class_init (method->klass);
7730 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7732 domain = mono_domain_get ();
7734 /* This is for Attributes with no parameters */
7735 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7736 params [0] = mono_method_get_object (domain, method, NULL);
7737 params [1] = params [2] = NULL;
7738 mono_runtime_invoke (method, attr, params, NULL);
7742 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7745 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7749 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7750 MonoObject *obj, *typedarg;
7753 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7754 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7755 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7756 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7757 mono_array_setref (typedargs, i, typedarg);
7759 if (!type_is_reference (mono_method_signature (method)->params [i]))
7764 num_named = read16 (named);
7765 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7767 attrklass = method->klass;
7768 for (j = 0; j < num_named; j++) {
7770 char *name, named_type, data_type;
7771 named_type = *named++;
7772 data_type = *named++; /* type of data */
7773 if (data_type == MONO_TYPE_SZARRAY)
7774 data_type = *named++;
7775 if (data_type == MONO_TYPE_ENUM) {
7778 type_len = mono_metadata_decode_blob_size (named, &named);
7779 type_name = g_malloc (type_len + 1);
7780 memcpy (type_name, named, type_len);
7781 type_name [type_len] = 0;
7783 /* FIXME: lookup the type and check type consistency */
7786 name_len = mono_metadata_decode_blob_size (named, &named);
7787 name = g_malloc (name_len + 1);
7788 memcpy (name, named, name_len);
7789 name [name_len] = 0;
7791 if (named_type == 0x53) {
7792 MonoObject *obj, *typedarg, *namedarg;
7793 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7794 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7796 minfo = mono_field_get_object (domain, NULL, field);
7797 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7798 typedarg = create_cattr_typed_arg (field->type, obj);
7799 namedarg = create_cattr_named_arg (minfo, typedarg);
7800 mono_array_setref (namedargs, j, namedarg);
7801 if (!type_is_reference (field->type))
7803 } else if (named_type == 0x54) {
7804 MonoObject *obj, *typedarg, *namedarg;
7805 MonoType *prop_type;
7807 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7809 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7810 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7811 minfo = mono_property_get_object (domain, NULL, prop);
7812 val = load_cattr_value (image, prop_type, named, &named);
7813 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7814 typedarg = create_cattr_typed_arg (prop_type, obj);
7815 namedarg = create_cattr_named_arg (minfo, typedarg);
7816 mono_array_setref (namedargs, j, namedarg);
7817 if (!type_is_reference (prop_type))
7822 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7823 params [0] = mono_method_get_object (domain, method, NULL);
7824 params [1] = typedargs;
7825 params [2] = namedargs;
7826 mono_runtime_invoke (ctor, attr, params, NULL);
7831 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7837 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7838 for (i = 0; i < cinfo->num_attrs; ++i) {
7839 if (!cinfo->attrs [i].ctor)
7840 /* The cattr type is not finished yet */
7841 /* We should include the type name but cinfo doesn't contain it */
7842 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7843 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7844 mono_array_setref (result, i, attr);
7850 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7857 for (i = 0; i < cinfo->num_attrs; ++i) {
7858 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7862 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7864 for (i = 0; i < cinfo->num_attrs; ++i) {
7865 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7866 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7867 mono_array_setref (result, n, attr);
7875 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7881 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7882 for (i = 0; i < cinfo->num_attrs; ++i) {
7883 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7884 mono_array_setref (result, i, attr);
7890 * mono_custom_attrs_from_index:
7892 * Returns: NULL if no attributes are found or if a loading error occurs.
7895 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7897 guint32 mtoken, i, len;
7898 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7900 MonoCustomAttrInfo *ainfo;
7901 GList *tmp, *list = NULL;
7904 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7906 i = mono_metadata_custom_attrs_from_index (image, idx);
7910 while (i < ca->rows) {
7911 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7913 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7916 len = g_list_length (list);
7919 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7920 ainfo->num_attrs = len;
7921 ainfo->image = image;
7922 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7923 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7924 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7925 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7926 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7927 mtoken |= MONO_TOKEN_METHOD_DEF;
7929 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7930 mtoken |= MONO_TOKEN_MEMBER_REF;
7933 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7936 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7937 if (!ainfo->attrs [i].ctor) {
7938 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7943 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7944 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7945 ainfo->attrs [i].data = (guchar*)data;
7953 mono_custom_attrs_from_method (MonoMethod *method)
7958 * An instantiated method has the same cattrs as the generic method definition.
7960 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7961 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7963 if (method->is_inflated)
7964 method = ((MonoMethodInflated *) method)->declaring;
7966 if (method->dynamic || method->klass->image->dynamic)
7967 return lookup_custom_attr (method->klass->image, method);
7969 idx = mono_method_get_index (method);
7970 idx <<= MONO_CUSTOM_ATTR_BITS;
7971 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7972 return mono_custom_attrs_from_index (method->klass->image, idx);
7976 mono_custom_attrs_from_class (MonoClass *klass)
7980 if (klass->generic_class)
7981 klass = klass->generic_class->container_class;
7983 if (klass->image->dynamic)
7984 return lookup_custom_attr (klass->image, klass);
7986 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7987 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7988 idx <<= MONO_CUSTOM_ATTR_BITS;
7989 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7991 idx = mono_metadata_token_index (klass->type_token);
7992 idx <<= MONO_CUSTOM_ATTR_BITS;
7993 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7995 return mono_custom_attrs_from_index (klass->image, idx);
7999 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8003 if (assembly->image->dynamic)
8004 return lookup_custom_attr (assembly->image, assembly);
8005 idx = 1; /* there is only one assembly */
8006 idx <<= MONO_CUSTOM_ATTR_BITS;
8007 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8008 return mono_custom_attrs_from_index (assembly->image, idx);
8011 static MonoCustomAttrInfo*
8012 mono_custom_attrs_from_module (MonoImage *image)
8017 return lookup_custom_attr (image, image);
8018 idx = 1; /* there is only one module */
8019 idx <<= MONO_CUSTOM_ATTR_BITS;
8020 idx |= MONO_CUSTOM_ATTR_MODULE;
8021 return mono_custom_attrs_from_index (image, idx);
8025 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8029 if (klass->image->dynamic) {
8030 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8031 return lookup_custom_attr (klass->image, property);
8033 idx = find_property_index (klass, property);
8034 idx <<= MONO_CUSTOM_ATTR_BITS;
8035 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8036 return mono_custom_attrs_from_index (klass->image, idx);
8040 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8044 if (klass->image->dynamic) {
8045 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8046 return lookup_custom_attr (klass->image, event);
8048 idx = find_event_index (klass, event);
8049 idx <<= MONO_CUSTOM_ATTR_BITS;
8050 idx |= MONO_CUSTOM_ATTR_EVENT;
8051 return mono_custom_attrs_from_index (klass->image, idx);
8055 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8058 if (klass->image->dynamic) {
8059 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8060 return lookup_custom_attr (klass->image, field);
8062 idx = find_field_index (klass, field);
8063 idx <<= MONO_CUSTOM_ATTR_BITS;
8064 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8065 return mono_custom_attrs_from_index (klass->image, idx);
8069 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8072 guint32 i, idx, method_index;
8073 guint32 param_list, param_last, param_pos, found;
8075 MonoReflectionMethodAux *aux;
8078 * An instantiated method has the same cattrs as the generic method definition.
8080 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8081 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8083 if (method->is_inflated)
8084 method = ((MonoMethodInflated *) method)->declaring;
8086 if (method->klass->image->dynamic) {
8087 MonoCustomAttrInfo *res, *ainfo;
8090 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8091 if (!aux || !aux->param_cattr)
8094 /* Need to copy since it will be freed later */
8095 ainfo = aux->param_cattr [param];
8096 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8097 res = g_malloc0 (size);
8098 memcpy (res, ainfo, size);
8102 image = method->klass->image;
8103 method_index = mono_method_get_index (method);
8104 ca = &image->tables [MONO_TABLE_METHOD];
8106 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8107 if (method_index == ca->rows) {
8108 ca = &image->tables [MONO_TABLE_PARAM];
8109 param_last = ca->rows + 1;
8111 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8112 ca = &image->tables [MONO_TABLE_PARAM];
8115 for (i = param_list; i < param_last; ++i) {
8116 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8117 if (param_pos == param) {
8125 idx <<= MONO_CUSTOM_ATTR_BITS;
8126 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8127 return mono_custom_attrs_from_index (image, idx);
8131 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8135 for (i = 0; i < ainfo->num_attrs; ++i) {
8136 klass = ainfo->attrs [i].ctor->klass;
8137 if (mono_class_has_parent (klass, attr_klass))
8144 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8151 for (i = 0; i < ainfo->num_attrs; ++i) {
8152 klass = ainfo->attrs [i].ctor->klass;
8153 if (mono_class_has_parent (klass, attr_klass)) {
8158 if (attr_index == -1)
8161 attrs = mono_custom_attrs_construct (ainfo);
8163 return mono_array_get (attrs, MonoObject*, attr_index);
8169 * mono_reflection_get_custom_attrs_info:
8170 * @obj: a reflection object handle
8172 * Return the custom attribute info for attributes defined for the
8173 * reflection handle @obj. The objects.
8176 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8179 MonoCustomAttrInfo *cinfo = NULL;
8181 klass = obj->vtable->klass;
8182 if (klass == mono_defaults.monotype_class) {
8183 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8184 klass = mono_class_from_mono_type (rtype->type);
8185 cinfo = mono_custom_attrs_from_class (klass);
8186 } else if (strcmp ("Assembly", klass->name) == 0) {
8187 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8188 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8189 } else if (strcmp ("Module", klass->name) == 0) {
8190 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8191 cinfo = mono_custom_attrs_from_module (module->image);
8192 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8193 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8194 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8195 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8196 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8197 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8198 } else if (strcmp ("MonoField", klass->name) == 0) {
8199 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8200 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8201 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8202 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8203 cinfo = mono_custom_attrs_from_method (rmethod->method);
8204 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8205 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8206 cinfo = mono_custom_attrs_from_method (rmethod->method);
8207 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8208 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8209 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8210 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8211 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8212 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8213 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8214 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8215 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8216 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8217 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8218 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8219 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8220 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8221 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8222 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8223 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8224 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8225 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8226 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8227 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8228 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8229 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8230 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8231 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8232 } else { /* handle other types here... */
8233 g_error ("get custom attrs not yet supported for %s", klass->name);
8240 * mono_reflection_get_custom_attrs_by_type:
8241 * @obj: a reflection object handle
8243 * Return an array with all the custom attributes defined of the
8244 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8245 * of that type are returned. The objects are fully build. Return NULL if a loading error
8249 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8252 MonoCustomAttrInfo *cinfo;
8254 cinfo = mono_reflection_get_custom_attrs_info (obj);
8257 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8259 result = mono_custom_attrs_construct (cinfo);
8261 mono_custom_attrs_free (cinfo);
8263 if (mono_loader_get_last_error ())
8265 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8272 * mono_reflection_get_custom_attrs:
8273 * @obj: a reflection object handle
8275 * Return an array with all the custom attributes defined of the
8276 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8280 mono_reflection_get_custom_attrs (MonoObject *obj)
8282 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8286 * mono_reflection_get_custom_attrs_data:
8287 * @obj: a reflection obj handle
8289 * Returns an array of System.Reflection.CustomAttributeData,
8290 * which include information about attributes reflected on
8291 * types loaded using the Reflection Only methods
8294 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8297 MonoCustomAttrInfo *cinfo;
8299 cinfo = mono_reflection_get_custom_attrs_info (obj);
8301 result = mono_custom_attrs_data_construct (cinfo);
8303 mono_custom_attrs_free (cinfo);
8305 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8310 static MonoReflectionType*
8311 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8313 MonoMethod *method_get_underlying_system_type;
8315 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8316 mono_class_get_method_from_name (mono_object_class (t),
8317 "get_UnderlyingSystemType",
8319 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8323 mono_reflection_type_get_handle (MonoReflectionType* t)
8328 t = mono_reflection_type_get_underlying_system_type (t);
8336 * LOCKING: Assumes the loader lock is held.
8338 static MonoMethodSignature*
8339 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8340 MonoMethodSignature *sig;
8343 count = parameters? mono_array_length (parameters): 0;
8345 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8346 sig->param_count = count;
8347 sig->sentinelpos = -1; /* FIXME */
8348 for (i = 0; i < count; ++i) {
8349 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8350 sig->params [i] = mono_reflection_type_get_handle (pt);
8356 * LOCKING: Assumes the loader lock is held.
8358 static MonoMethodSignature*
8359 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8360 MonoMethodSignature *sig;
8362 sig = parameters_to_signature (mp, ctor->parameters);
8363 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8364 sig->ret = &mono_defaults.void_class->byval_arg;
8369 * LOCKING: Assumes the loader lock is held.
8371 static MonoMethodSignature*
8372 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8373 MonoMethodSignature *sig;
8375 sig = parameters_to_signature (mp, method->parameters);
8376 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8377 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8378 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8382 static MonoMethodSignature*
8383 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8384 MonoMethodSignature *sig;
8386 sig = parameters_to_signature (NULL, method->parameters);
8387 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8388 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8389 sig->generic_param_count = 0;
8394 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8396 MonoClass *klass = mono_object_class (prop);
8397 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8398 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8399 *name = mono_string_to_utf8 (pb->name);
8400 *type = pb->type->type;
8402 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8403 *name = g_strdup (p->property->name);
8404 if (p->property->get)
8405 *type = mono_method_signature (p->property->get)->ret;
8407 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8412 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8414 MonoClass *klass = mono_object_class (field);
8415 if (strcmp (klass->name, "FieldBuilder") == 0) {
8416 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8417 *name = mono_string_to_utf8 (fb->name);
8418 *type = fb->type->type;
8420 MonoReflectionField *f = (MonoReflectionField *)field;
8421 *name = g_strdup (mono_field_get_name (f->field));
8422 *type = f->field->type;
8427 * Encode a value in a custom attribute stream of bytes.
8428 * The value to encode is either supplied as an object in argument val
8429 * (valuetypes are boxed), or as a pointer to the data in the
8431 * @type represents the type of the value
8432 * @buffer is the start of the buffer
8433 * @p the current position in the buffer
8434 * @buflen contains the size of the buffer and is used to return the new buffer size
8435 * if this needs to be realloced.
8436 * @retbuffer and @retp return the start and the position of the buffer
8439 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8441 MonoTypeEnum simple_type;
8443 if ((p-buffer) + 10 >= *buflen) {
8446 newbuf = g_realloc (buffer, *buflen);
8447 p = newbuf + (p-buffer);
8451 argval = ((char*)arg + sizeof (MonoObject));
8452 simple_type = type->type;
8454 switch (simple_type) {
8455 case MONO_TYPE_BOOLEAN:
8460 case MONO_TYPE_CHAR:
8463 swap_with_size (p, argval, 2, 1);
8469 swap_with_size (p, argval, 4, 1);
8473 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8483 swap_with_size (p, argval, 8, 1);
8489 swap_with_size (p, argval, 8, 1);
8492 case MONO_TYPE_VALUETYPE:
8493 if (type->data.klass->enumtype) {
8494 simple_type = type->data.klass->enum_basetype->type;
8497 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8500 case MONO_TYPE_STRING: {
8507 str = mono_string_to_utf8 ((MonoString*)arg);
8508 slen = strlen (str);
8509 if ((p-buffer) + 10 + slen >= *buflen) {
8513 newbuf = g_realloc (buffer, *buflen);
8514 p = newbuf + (p-buffer);
8517 mono_metadata_encode_value (slen, p, &p);
8518 memcpy (p, str, slen);
8523 case MONO_TYPE_CLASS: {
8531 k = mono_object_class (arg);
8532 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8533 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8534 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8537 if (rt && (rtc = mono_object_class (rt)) &&
8538 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8539 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8540 arg = (MonoObject *) rt;
8543 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8546 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8547 slen = strlen (str);
8548 if ((p-buffer) + 10 + slen >= *buflen) {
8552 newbuf = g_realloc (buffer, *buflen);
8553 p = newbuf + (p-buffer);
8556 mono_metadata_encode_value (slen, p, &p);
8557 memcpy (p, str, slen);
8562 case MONO_TYPE_SZARRAY: {
8564 MonoClass *eclass, *arg_eclass;
8567 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8570 len = mono_array_length ((MonoArray*)arg);
8572 *p++ = (len >> 8) & 0xff;
8573 *p++ = (len >> 16) & 0xff;
8574 *p++ = (len >> 24) & 0xff;
8576 *retbuffer = buffer;
8577 eclass = type->data.klass;
8578 arg_eclass = mono_object_class (arg)->element_class;
8581 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8582 eclass = mono_defaults.object_class;
8584 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8585 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8586 int elsize = mono_class_array_element_size (arg_eclass);
8587 for (i = 0; i < len; ++i) {
8588 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8591 } else if (eclass->valuetype && arg_eclass->valuetype) {
8592 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8593 int elsize = mono_class_array_element_size (eclass);
8594 for (i = 0; i < len; ++i) {
8595 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8599 for (i = 0; i < len; ++i) {
8600 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8605 case MONO_TYPE_OBJECT: {
8611 * The parameter type is 'object' but the type of the actual
8612 * argument is not. So we have to add type information to the blob
8613 * too. This is completely undocumented in the spec.
8617 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8622 klass = mono_object_class (arg);
8624 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8627 } else if (klass->enumtype) {
8629 } else if (klass == mono_defaults.string_class) {
8630 simple_type = MONO_TYPE_STRING;
8633 } else if (klass->rank == 1) {
8635 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8636 /* See Partition II, Appendix B3 */
8639 *p++ = klass->element_class->byval_arg.type;
8640 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8642 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8643 *p++ = simple_type = klass->byval_arg.type;
8646 g_error ("unhandled type in custom attr");
8648 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8649 slen = strlen (str);
8650 if ((p-buffer) + 10 + slen >= *buflen) {
8654 newbuf = g_realloc (buffer, *buflen);
8655 p = newbuf + (p-buffer);
8658 mono_metadata_encode_value (slen, p, &p);
8659 memcpy (p, str, slen);
8662 simple_type = klass->enum_basetype->type;
8666 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8669 *retbuffer = buffer;
8673 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8675 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8676 char *str = type_get_qualified_name (type, NULL);
8677 int slen = strlen (str);
8681 * This seems to be optional...
8684 mono_metadata_encode_value (slen, p, &p);
8685 memcpy (p, str, slen);
8688 } else if (type->type == MONO_TYPE_OBJECT) {
8690 } else if (type->type == MONO_TYPE_CLASS) {
8691 /* it should be a type: encode_cattr_value () has the check */
8694 mono_metadata_encode_value (type->type, p, &p);
8695 if (type->type == MONO_TYPE_SZARRAY)
8696 /* See the examples in Partition VI, Annex B */
8697 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8704 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8707 /* Preallocate a large enough buffer */
8708 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8709 char *str = type_get_qualified_name (type, NULL);
8712 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8713 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8719 len += strlen (name);
8721 if ((p-buffer) + 20 + len >= *buflen) {
8725 newbuf = g_realloc (buffer, *buflen);
8726 p = newbuf + (p-buffer);
8730 encode_field_or_prop_type (type, p, &p);
8732 len = strlen (name);
8733 mono_metadata_encode_value (len, p, &p);
8734 memcpy (p, name, len);
8736 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8738 *retbuffer = buffer;
8741 #ifndef DISABLE_REFLECTION_EMIT
8744 * mono_reflection_get_custom_attrs_blob:
8745 * @ctor: custom attribute constructor
8746 * @ctorArgs: arguments o the constructor
8752 * Creates the blob of data that needs to be saved in the metadata and that represents
8753 * the custom attributed described by @ctor, @ctorArgs etc.
8754 * Returns: a Byte array representing the blob of data.
8757 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8760 MonoMethodSignature *sig;
8765 MONO_ARCH_SAVE_REGS;
8767 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8768 /* sig is freed later so allocate it in the heap */
8769 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8771 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8774 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8776 p = buffer = g_malloc (buflen);
8777 /* write the prolog */
8780 for (i = 0; i < sig->param_count; ++i) {
8781 arg = mono_array_get (ctorArgs, MonoObject*, i);
8782 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8786 i += mono_array_length (properties);
8788 i += mono_array_length (fields);
8790 *p++ = (i >> 8) & 0xff;
8793 for (i = 0; i < mono_array_length (properties); ++i) {
8797 prop = mono_array_get (properties, gpointer, i);
8798 get_prop_name_and_type (prop, &pname, &ptype);
8799 *p++ = 0x54; /* PROPERTY signature */
8800 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8807 for (i = 0; i < mono_array_length (fields); ++i) {
8811 field = mono_array_get (fields, gpointer, i);
8812 get_field_name_and_type (field, &fname, &ftype);
8813 *p++ = 0x53; /* FIELD signature */
8814 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8819 g_assert (p - buffer <= buflen);
8820 buflen = p - buffer;
8821 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8822 p = mono_array_addr (result, char, 0);
8823 memcpy (p, buffer, buflen);
8825 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8831 static void* reflection_info_desc = NULL;
8832 #define MOVING_GC_REGISTER(addr) do { \
8833 if (!reflection_info_desc) { \
8835 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8837 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8840 #define MOVING_GC_REGISTER(addr)
8844 * mono_reflection_setup_internal_class:
8845 * @tb: a TypeBuilder object
8847 * Creates a MonoClass that represents the TypeBuilder.
8848 * This is a trick that lets us simplify a lot of reflection code
8849 * (and will allow us to support Build and Run assemblies easier).
8852 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8854 MonoClass *klass, *parent;
8856 MONO_ARCH_SAVE_REGS;
8858 mono_loader_lock ();
8861 /* check so we can compile corlib correctly */
8862 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8863 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8864 parent = tb->parent->type->data.klass;
8866 parent = my_mono_class_from_mono_type (tb->parent->type);
8872 /* the type has already being created: it means we just have to change the parent */
8873 if (tb->type.type) {
8874 klass = mono_class_from_mono_type (tb->type.type);
8875 klass->parent = NULL;
8876 /* fool mono_class_setup_parent */
8877 klass->supertypes = NULL;
8878 mono_class_setup_parent (klass, parent);
8879 mono_class_setup_mono_type (klass);
8880 mono_loader_unlock ();
8884 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8886 klass->image = &tb->module->dynamic_image->image;
8888 klass->inited = 1; /* we lie to the runtime */
8889 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8890 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8891 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8892 klass->flags = tb->attrs;
8894 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8896 klass->element_class = klass;
8898 MOVING_GC_REGISTER (&klass->reflection_info);
8899 klass->reflection_info = tb;
8901 /* Put into cache so mono_class_get () will find it */
8902 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8904 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8905 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8907 if (parent != NULL) {
8908 mono_class_setup_parent (klass, parent);
8909 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8910 const char *old_n = klass->name;
8911 /* trick to get relative numbering right when compiling corlib */
8912 klass->name = "BuildingObject";
8913 mono_class_setup_parent (klass, mono_defaults.object_class);
8914 klass->name = old_n;
8917 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8918 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8919 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8920 klass->instance_size = sizeof (MonoObject);
8921 klass->size_inited = 1;
8922 mono_class_setup_vtable_general (klass, NULL, 0);
8925 mono_class_setup_mono_type (klass);
8927 mono_class_setup_supertypes (klass);
8930 * FIXME: handle interfaces.
8933 tb->type.type = &klass->byval_arg;
8935 if (tb->nesting_type) {
8936 g_assert (tb->nesting_type->type);
8937 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8940 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8942 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8944 mono_loader_unlock ();
8948 * mono_reflection_setup_generic_class:
8949 * @tb: a TypeBuilder object
8951 * Setup the generic class before adding the first generic parameter.
8954 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8958 MONO_ARCH_SAVE_REGS;
8960 klass = my_mono_class_from_mono_type (tb->type.type);
8961 if (tb->generic_container)
8964 tb->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8965 tb->generic_container->owner.klass = klass;
8969 * mono_reflection_create_generic_class:
8970 * @tb: a TypeBuilder object
8972 * Creates the generic class after all generic parameters have been added.
8975 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8980 MONO_ARCH_SAVE_REGS;
8982 klass = my_mono_class_from_mono_type (tb->type.type);
8984 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8986 if (klass->generic_container || (count == 0))
8989 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8991 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8993 klass->generic_container->owner.klass = klass;
8994 klass->generic_container->type_argc = count;
8995 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
8997 for (i = 0; i < count; i++) {
8998 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8999 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9000 /*Make sure we are a diferent type instance */
9001 klass->generic_container->type_params [i].owner = klass->generic_container;
9002 klass->generic_container->type_params [i].pklass = NULL;
9004 g_assert (klass->generic_container->type_params [i].owner);
9007 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9011 * mono_reflection_create_internal_class:
9012 * @tb: a TypeBuilder object
9014 * Actually create the MonoClass that is associated with the TypeBuilder.
9017 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9021 MONO_ARCH_SAVE_REGS;
9023 klass = my_mono_class_from_mono_type (tb->type.type);
9025 mono_loader_lock ();
9026 if (klass->enumtype && klass->enum_basetype == NULL) {
9027 MonoReflectionFieldBuilder *fb;
9030 g_assert (tb->fields != NULL);
9031 g_assert (mono_array_length (tb->fields) >= 1);
9033 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9035 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9036 mono_loader_unlock ();
9040 klass->enum_basetype = fb->type->type;
9041 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9042 if (!klass->element_class)
9043 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9046 * get the element_class from the current corlib.
9048 ec = default_class_from_mono_type (klass->enum_basetype);
9049 klass->instance_size = ec->instance_size;
9050 klass->size_inited = 1;
9052 * this is almost safe to do with enums and it's needed to be able
9053 * to create objects of the enum type (for use in SetConstant).
9055 /* FIXME: Does this mean enums can't have method overrides ? */
9056 mono_class_setup_vtable_general (klass, NULL, 0);
9058 mono_loader_unlock ();
9061 #endif /* DISABLE_REFLECTION_EMIT */
9063 static MonoMarshalSpec*
9064 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9065 MonoReflectionMarshal *minfo)
9067 MonoMarshalSpec *res;
9069 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9070 res->native = minfo->type;
9072 switch (minfo->type) {
9073 case MONO_NATIVE_LPARRAY:
9074 res->data.array_data.elem_type = minfo->eltype;
9075 if (minfo->has_size) {
9076 res->data.array_data.param_num = minfo->param_num;
9077 res->data.array_data.num_elem = minfo->count;
9078 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9081 res->data.array_data.param_num = -1;
9082 res->data.array_data.num_elem = -1;
9083 res->data.array_data.elem_mult = -1;
9087 case MONO_NATIVE_BYVALTSTR:
9088 case MONO_NATIVE_BYVALARRAY:
9089 res->data.array_data.num_elem = minfo->count;
9092 case MONO_NATIVE_CUSTOM:
9093 if (minfo->marshaltyperef)
9094 res->data.custom_data.custom_name =
9095 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9097 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9107 MonoReflectionMarshal*
9108 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9109 MonoMarshalSpec *spec)
9111 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9112 MonoReflectionMarshal *minfo;
9115 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9116 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9117 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9118 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9121 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9122 minfo->type = spec->native;
9124 switch (minfo->type) {
9125 case MONO_NATIVE_LPARRAY:
9126 minfo->eltype = spec->data.array_data.elem_type;
9127 minfo->count = spec->data.array_data.num_elem;
9128 minfo->param_num = spec->data.array_data.param_num;
9131 case MONO_NATIVE_BYVALTSTR:
9132 case MONO_NATIVE_BYVALARRAY:
9133 minfo->count = spec->data.array_data.num_elem;
9136 case MONO_NATIVE_CUSTOM:
9137 if (spec->data.custom_data.custom_name) {
9138 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9140 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9142 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9144 if (spec->data.custom_data.cookie)
9145 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9156 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9157 ReflectionMethodBuilder *rmb,
9158 MonoMethodSignature *sig)
9161 MonoMethodNormal *pm;
9162 MonoMarshalSpec **specs;
9163 MonoReflectionMethodAux *method_aux;
9169 * Methods created using a MethodBuilder should have their memory allocated
9170 * inside the image mempool, while dynamic methods should have their memory
9173 dynamic = rmb->refs != NULL;
9174 mp = dynamic ? NULL : klass->image->mempool;
9177 g_assert (!klass->generic_class);
9179 mono_loader_lock ();
9181 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9182 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9183 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9185 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9187 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9189 pm = (MonoMethodNormal*)m;
9191 m->dynamic = dynamic;
9193 m->flags = rmb->attrs;
9194 m->iflags = rmb->iattrs;
9195 m->name = mp_string_to_utf8 (mp, rmb->name);
9198 m->skip_visibility = rmb->skip_visibility;
9200 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9202 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9203 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9206 m->signature->pinvoke = 1;
9207 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9208 m->signature->pinvoke = 1;
9210 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9212 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9213 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9215 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9217 if (klass->image->dynamic)
9218 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9220 mono_loader_unlock ();
9223 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9224 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9225 MonoMethodHeader *header;
9227 gint32 max_stack, i;
9228 gint32 num_locals = 0;
9229 gint32 num_clauses = 0;
9233 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9234 code_size = rmb->ilgen->code_len;
9235 max_stack = rmb->ilgen->max_stack;
9236 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9237 if (rmb->ilgen->ex_handlers)
9238 num_clauses = method_count_clauses (rmb->ilgen);
9241 code = mono_array_addr (rmb->code, guint8, 0);
9242 code_size = mono_array_length (rmb->code);
9243 /* we probably need to run a verifier on the code... */
9253 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9254 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9255 header->code_size = code_size;
9256 header->code = mp_g_malloc (mp, code_size);
9257 memcpy ((char*)header->code, code, code_size);
9258 header->max_stack = max_stack;
9259 header->init_locals = rmb->init_locals;
9260 header->num_locals = num_locals;
9262 for (i = 0; i < num_locals; ++i) {
9263 MonoReflectionLocalBuilder *lb =
9264 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9266 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9267 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9270 header->num_clauses = num_clauses;
9272 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9273 rmb->ilgen, num_clauses);
9276 pm->header = header;
9279 if (rmb->generic_params) {
9280 int count = mono_array_length (rmb->generic_params);
9281 MonoGenericContainer *container;
9283 container = rmb->generic_container;
9285 m->is_generic = TRUE;
9286 mono_method_set_generic_container (m, container);
9288 container->type_argc = count;
9289 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9290 container->owner.method = m;
9292 for (i = 0; i < count; i++) {
9293 MonoReflectionGenericParam *gp =
9294 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9296 container->type_params [i] = *gp->type.type->data.generic_param;
9299 if (klass->generic_container) {
9300 container->parent = klass->generic_container;
9301 container->context.class_inst = klass->generic_container->context.class_inst;
9303 container->context.method_inst = mono_get_shared_generic_inst (container);
9307 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9311 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9313 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9314 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9315 for (i = 0; i < rmb->nrefs; ++i)
9316 data [i + 1] = rmb->refs [i];
9321 /* Parameter info */
9324 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9325 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9326 for (i = 0; i <= m->signature->param_count; ++i) {
9327 MonoReflectionParamBuilder *pb;
9328 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9329 if ((i > 0) && (pb->attrs)) {
9330 /* Make a copy since it might point to a shared type structure */
9331 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9332 m->signature->params [i - 1]->attrs = pb->attrs;
9335 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9336 MonoDynamicImage *assembly;
9337 guint32 idx, def_type, len;
9341 if (!method_aux->param_defaults) {
9342 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9343 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9345 assembly = (MonoDynamicImage*)klass->image;
9346 idx = encode_constant (assembly, pb->def_value, &def_type);
9347 /* Copy the data from the blob since it might get realloc-ed */
9348 p = assembly->blob.data + idx;
9349 len = mono_metadata_decode_blob_size (p, &p2);
9351 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9352 method_aux->param_default_types [i] = def_type;
9353 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9357 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9359 if (!method_aux->param_cattr)
9360 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9361 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9367 /* Parameter marshalling */
9370 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9371 MonoReflectionParamBuilder *pb;
9372 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9373 if (pb->marshal_info) {
9375 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9376 specs [pb->position] =
9377 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9381 if (specs != NULL) {
9383 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9384 method_aux->param_marshall = specs;
9387 if (klass->image->dynamic && method_aux)
9388 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9390 mono_loader_unlock ();
9396 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9398 ReflectionMethodBuilder rmb;
9399 MonoMethodSignature *sig;
9401 mono_loader_lock ();
9402 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9403 mono_loader_unlock ();
9405 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9407 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9408 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9410 /* If we are in a generic class, we might be called multiple times from inflate_method */
9411 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9412 /* ilgen is no longer needed */
9420 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9422 ReflectionMethodBuilder rmb;
9423 MonoMethodSignature *sig;
9425 mono_loader_lock ();
9426 sig = method_builder_to_signature (klass->image->mempool, mb);
9427 mono_loader_unlock ();
9429 reflection_methodbuilder_from_method_builder (&rmb, mb);
9431 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9432 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9434 /* If we are in a generic class, we might be called multiple times from inflate_method */
9435 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9436 /* ilgen is no longer needed */
9442 static MonoClassField*
9443 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9445 MonoClassField *field;
9448 field = g_new0 (MonoClassField, 1);
9450 field->name = mono_string_to_utf8 (fb->name);
9451 if (fb->attrs || fb->modreq || fb->modopt) {
9452 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9453 field->type->attrs = fb->attrs;
9455 g_assert (klass->image->dynamic);
9456 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9457 g_free (field->type);
9458 field->type = custom;
9460 field->type = fb->type->type;
9462 if (fb->offset != -1)
9463 field->offset = fb->offset;
9464 field->parent = klass;
9465 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9467 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9473 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9476 MonoReflectionTypeBuilder *tb = NULL;
9477 gboolean is_dynamic = FALSE;
9481 mono_loader_lock ();
9483 domain = mono_object_domain (type);
9485 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9486 tb = (MonoReflectionTypeBuilder *) type;
9489 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9490 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9492 tb = rgi->generic_type;
9496 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9497 if (tb && tb->generic_container)
9498 mono_reflection_create_generic_class (tb);
9500 klass = mono_class_from_mono_type (type->type);
9501 if (!klass->generic_container) {
9502 mono_loader_unlock ();
9506 if (klass->wastypebuilder) {
9507 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9512 mono_loader_unlock ();
9514 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9516 return &geninst->byval_arg;
9520 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9522 MonoGenericClass *gclass;
9523 MonoGenericInst *inst;
9525 g_assert (klass->generic_container);
9527 inst = mono_metadata_get_generic_inst (type_argc, types);
9528 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9530 return mono_generic_class_get_class (gclass);
9533 MonoReflectionMethod*
9534 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9537 MonoMethod *method, *inflated;
9538 MonoMethodInflated *imethod;
9539 MonoReflectionMethodBuilder *mb = NULL;
9540 MonoGenericContext tmp_context;
9541 MonoGenericInst *ginst;
9542 MonoType **type_argv;
9545 MONO_ARCH_SAVE_REGS;
9547 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9548 #ifndef DISABLE_REFLECTION_EMIT
9549 MonoReflectionTypeBuilder *tb;
9552 mb = (MonoReflectionMethodBuilder *) rmethod;
9553 tb = (MonoReflectionTypeBuilder *) mb->type;
9554 klass = mono_class_from_mono_type (tb->type.type);
9556 method = methodbuilder_to_mono_method (klass, mb);
9558 g_assert_not_reached ();
9562 method = rmethod->method;
9565 klass = method->klass;
9567 if (method->is_inflated)
9568 method = ((MonoMethodInflated *) method)->declaring;
9570 count = mono_method_signature (method)->generic_param_count;
9571 if (count != mono_array_length (types))
9574 type_argv = g_new0 (MonoType *, count);
9575 for (i = 0; i < count; i++) {
9576 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9577 type_argv [i] = garg->type;
9579 ginst = mono_metadata_get_generic_inst (count, type_argv);
9582 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9583 tmp_context.method_inst = ginst;
9585 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9586 imethod = (MonoMethodInflated *) inflated;
9588 if (method->klass->image->dynamic) {
9589 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9591 * This table maps metadata structures representing inflated methods/fields
9592 * to the reflection objects representing their generic definitions.
9594 mono_loader_lock ();
9595 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9596 mono_loader_unlock ();
9599 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9602 #ifndef DISABLE_REFLECTION_EMIT
9605 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9607 MonoMethodInflated *imethod;
9608 MonoGenericContext *context;
9612 * With generic code sharing the klass might not be inflated.
9613 * This can happen because classes inflated with their own
9614 * type arguments are "normalized" to the uninflated class.
9616 if (!klass->generic_class)
9619 context = mono_class_get_context (klass);
9621 if (klass->method.count) {
9622 /* Find the already created inflated method */
9623 for (i = 0; i < klass->method.count; ++i) {
9624 g_assert (klass->methods [i]->is_inflated);
9625 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9628 g_assert (i < klass->method.count);
9629 imethod = (MonoMethodInflated*)klass->methods [i];
9631 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9634 if (method->is_generic && method->klass->image->dynamic) {
9635 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9637 mono_loader_lock ();
9638 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9639 mono_loader_unlock ();
9641 return (MonoMethod *) imethod;
9645 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9650 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9652 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9653 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9654 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9656 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9657 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9658 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9659 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9660 method = ((MonoReflectionMethod *) obj)->method;
9662 method = NULL; /* prevent compiler warning */
9663 g_assert_not_reached ();
9666 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9669 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9671 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9672 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9675 MonoGenericClass *gclass;
9676 MonoDynamicGenericClass *dgclass;
9677 MonoClass *klass, *gklass;
9680 MONO_ARCH_SAVE_REGS;
9682 klass = mono_class_from_mono_type (type->type.type);
9683 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9684 gclass = type->type.type->data.generic_class;
9686 g_assert (gclass->is_dynamic);
9687 dgclass = (MonoDynamicGenericClass *) gclass;
9689 if (dgclass->initialized)
9692 gklass = gclass->container_class;
9693 mono_class_init (gklass);
9695 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9696 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9697 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9698 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9699 dgclass->count_events = events ? mono_array_length (events) : 0;
9701 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9702 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9703 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9704 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9705 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9706 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9707 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9709 for (i = 0; i < dgclass->count_methods; i++) {
9710 MonoObject *obj = mono_array_get (methods, gpointer, i);
9712 dgclass->methods [i] = inflate_method (type, obj);
9715 for (i = 0; i < dgclass->count_ctors; i++) {
9716 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9718 dgclass->ctors [i] = inflate_method (type, obj);
9721 for (i = 0; i < dgclass->count_fields; i++) {
9722 MonoObject *obj = mono_array_get (fields, gpointer, i);
9723 MonoClassField *field, *inflated_field = NULL;
9725 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9726 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9727 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9728 field = ((MonoReflectionField *) obj)->field;
9730 field = NULL; /* prevent compiler warning */
9731 g_assert_not_reached ();
9734 dgclass->fields [i] = *field;
9735 dgclass->fields [i].parent = klass;
9736 dgclass->fields [i].type = mono_class_inflate_generic_type (
9737 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9738 dgclass->field_generic_types [i] = field->type;
9739 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9740 dgclass->field_objects [i] = obj;
9742 if (inflated_field) {
9743 g_free (inflated_field);
9745 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9749 for (i = 0; i < dgclass->count_properties; i++) {
9750 MonoObject *obj = mono_array_get (properties, gpointer, i);
9751 MonoProperty *property = &dgclass->properties [i];
9753 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9754 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9756 property->parent = klass;
9757 property->attrs = pb->attrs;
9758 property->name = mono_string_to_utf8 (pb->name);
9760 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9762 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9763 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9764 *property = *((MonoReflectionProperty *) obj)->property;
9765 property->name = g_strdup (property->name);
9768 property->get = inflate_mono_method (klass, property->get, NULL);
9770 property->set = inflate_mono_method (klass, property->set, NULL);
9772 g_assert_not_reached ();
9775 for (i = 0; i < dgclass->count_events; i++) {
9776 MonoObject *obj = mono_array_get (events, gpointer, i);
9777 MonoEvent *event = &dgclass->events [i];
9779 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9780 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9782 event->parent = klass;
9783 event->attrs = eb->attrs;
9784 event->name = mono_string_to_utf8 (eb->name);
9786 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9787 if (eb->remove_method)
9788 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9789 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9790 *event = *((MonoReflectionEvent *) obj)->event;
9791 event->name = g_strdup (event->name);
9794 event->add = inflate_mono_method (klass, event->add, NULL);
9796 event->remove = inflate_mono_method (klass, event->remove, NULL);
9798 g_assert_not_reached ();
9801 dgclass->initialized = TRUE;
9805 ensure_runtime_vtable (MonoClass *klass)
9807 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9810 if (!tb || klass->wastypebuilder)
9813 ensure_runtime_vtable (klass->parent);
9815 num = tb->ctors? mono_array_length (tb->ctors): 0;
9816 num += tb->num_methods;
9817 klass->method.count = num;
9818 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9819 num = tb->ctors? mono_array_length (tb->ctors): 0;
9820 for (i = 0; i < num; ++i)
9821 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9822 num = tb->num_methods;
9824 for (i = 0; i < num; ++i)
9825 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9827 if (tb->interfaces) {
9828 klass->interface_count = mono_array_length (tb->interfaces);
9829 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9830 for (i = 0; i < klass->interface_count; ++i) {
9831 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9832 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9836 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9837 for (i = 0; i < klass->method.count; ++i)
9838 klass->methods [i]->slot = i;
9840 mono_class_setup_interface_offsets (klass);
9844 * The generic vtable is needed even if image->run is not set since some
9845 * runtime code like ves_icall_Type_GetMethodsByName depends on
9846 * method->slot being defined.
9850 * tb->methods could not be freed since it is used for determining
9851 * overrides during dynamic vtable construction.
9856 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9858 MonoReflectionTypeBuilder *tb;
9864 g_assert (klass->image->dynamic);
9866 if (!klass->reflection_info)
9869 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9871 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9875 for (i = 0; i < tb->num_methods; ++i) {
9876 MonoReflectionMethodBuilder *mb =
9877 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9878 if (mb->override_method)
9884 *overrides = g_new0 (MonoMethod*, onum * 2);
9887 for (i = 0; i < tb->num_methods; ++i) {
9888 MonoReflectionMethodBuilder *mb =
9889 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9890 if (mb->override_method) {
9891 (*overrides) [onum * 2] =
9892 mb->override_method->method;
9893 (*overrides) [onum * 2 + 1] =
9896 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9897 g_assert (mb->override_method->method);
9898 g_assert (mb->mhandle);
9905 *num_overrides = onum;
9909 typebuilder_setup_fields (MonoClass *klass)
9911 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9912 MonoReflectionFieldBuilder *fb;
9913 MonoClassField *field;
9914 MonoMemPool *mp = klass->image->mempool;
9917 guint32 len, idx, real_size = 0;
9919 klass->field.count = tb->num_fields;
9920 klass->field.first = 0;
9922 if (tb->class_size) {
9923 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9924 klass->packing_size = tb->packing_size;
9925 real_size = klass->instance_size + tb->class_size;
9928 if (!klass->field.count) {
9929 klass->instance_size = MAX (klass->instance_size, real_size);
9933 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9934 klass->field_def_values = mp_g_new0 (mp, MonoFieldDefaultValue, klass->field.count);
9936 for (i = 0; i < klass->field.count; ++i) {
9937 fb = mono_array_get (tb->fields, gpointer, i);
9938 field = &klass->fields [i];
9939 field->name = mp_string_to_utf8 (mp, fb->name);
9941 field->type = mono_metadata_type_dup (mp, fb->type->type);
9942 field->type->attrs = fb->attrs;
9944 field->type = fb->type->type;
9946 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9947 klass->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
9948 if (fb->offset != -1)
9949 field->offset = fb->offset;
9950 field->parent = klass;
9952 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9954 if (fb->def_value) {
9955 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9956 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9957 idx = encode_constant (assembly, fb->def_value, &klass->field_def_values [i].def_type);
9958 /* Copy the data from the blob since it might get realloc-ed */
9959 p = assembly->blob.data + idx;
9960 len = mono_metadata_decode_blob_size (p, &p2);
9962 klass->field_def_values [i].data = mono_mempool_alloc (mp, len);
9963 memcpy ((gpointer)klass->field_def_values [i].data, p, len);
9967 klass->instance_size = MAX (klass->instance_size, real_size);
9968 mono_class_layout_fields (klass);
9972 typebuilder_setup_properties (MonoClass *klass)
9974 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9975 MonoReflectionPropertyBuilder *pb;
9976 MonoMemPool *mp = klass->image->mempool;
9979 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9980 klass->property.first = 0;
9982 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9983 for (i = 0; i < klass->property.count; ++i) {
9984 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9985 klass->properties [i].parent = klass;
9986 klass->properties [i].attrs = pb->attrs;
9987 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9989 klass->properties [i].get = pb->get_method->mhandle;
9991 klass->properties [i].set = pb->set_method->mhandle;
9993 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9997 MonoReflectionEvent *
9998 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10000 MonoEvent *event = g_new0 (MonoEvent, 1);
10004 klass = my_mono_class_from_mono_type (tb->type.type);
10006 event->parent = klass;
10007 event->attrs = eb->attrs;
10008 event->name = mono_string_to_utf8 (eb->name);
10009 if (eb->add_method)
10010 event->add = eb->add_method->mhandle;
10011 if (eb->remove_method)
10012 event->remove = eb->remove_method->mhandle;
10013 if (eb->raise_method)
10014 event->raise = eb->raise_method->mhandle;
10016 if (eb->other_methods) {
10017 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10018 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10019 MonoReflectionMethodBuilder *mb =
10020 mono_array_get (eb->other_methods,
10021 MonoReflectionMethodBuilder*, j);
10022 event->other [j] = mb->mhandle;
10026 return mono_event_get_object (mono_object_domain (tb), klass, event);
10030 typebuilder_setup_events (MonoClass *klass)
10032 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10033 MonoReflectionEventBuilder *eb;
10034 MonoMemPool *mp = klass->image->mempool;
10037 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10038 klass->event.first = 0;
10040 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10041 for (i = 0; i < klass->event.count; ++i) {
10042 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10043 klass->events [i].parent = klass;
10044 klass->events [i].attrs = eb->attrs;
10045 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10046 if (eb->add_method)
10047 klass->events [i].add = eb->add_method->mhandle;
10048 if (eb->remove_method)
10049 klass->events [i].remove = eb->remove_method->mhandle;
10050 if (eb->raise_method)
10051 klass->events [i].raise = eb->raise_method->mhandle;
10053 if (eb->other_methods) {
10054 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10055 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10056 MonoReflectionMethodBuilder *mb =
10057 mono_array_get (eb->other_methods,
10058 MonoReflectionMethodBuilder*, j);
10059 klass->events [i].other [j] = mb->mhandle;
10062 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10067 remove_instantiations_of (gpointer key,
10069 gpointer user_data)
10071 MonoType *type = (MonoType*)key;
10072 MonoClass *klass = (MonoClass*)user_data;
10074 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10080 MonoReflectionType*
10081 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10084 MonoDomain* domain;
10085 MonoReflectionType* res;
10088 MONO_ARCH_SAVE_REGS;
10090 domain = mono_object_domain (tb);
10091 klass = my_mono_class_from_mono_type (tb->type.type);
10093 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10096 * we need to lock the domain because the lock will be taken inside
10097 * So, we need to keep the locking order correct.
10099 mono_domain_lock (domain);
10100 mono_loader_lock ();
10101 if (klass->wastypebuilder) {
10102 mono_loader_unlock ();
10103 mono_domain_unlock (domain);
10104 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10107 * Fields to set in klass:
10108 * the various flags: delegate/unicode/contextbound etc.
10110 klass->flags = tb->attrs;
10111 klass->has_cctor = 1;
10112 klass->has_finalize = 1;
10115 if (!((MonoDynamicImage*)klass->image)->run) {
10116 if (klass->generic_container) {
10117 /* FIXME: The code below can't handle generic classes */
10118 klass->wastypebuilder = TRUE;
10119 mono_loader_unlock ();
10120 mono_domain_unlock (domain);
10121 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10126 /* enums are done right away */
10127 if (!klass->enumtype)
10128 ensure_runtime_vtable (klass);
10130 if (tb->subtypes) {
10131 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10132 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10133 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10137 klass->nested_classes_inited = TRUE;
10139 /* fields and object layout */
10140 if (klass->parent) {
10141 if (!klass->parent->size_inited)
10142 mono_class_init (klass->parent);
10143 klass->instance_size = klass->parent->instance_size;
10144 klass->sizes.class_size = 0;
10145 klass->min_align = klass->parent->min_align;
10146 /* if the type has no fields we won't call the field_setup
10147 * routine which sets up klass->has_references.
10149 klass->has_references |= klass->parent->has_references;
10151 klass->instance_size = sizeof (MonoObject);
10152 klass->min_align = 1;
10155 /* FIXME: handle packing_size and instance_size */
10156 typebuilder_setup_fields (klass);
10158 typebuilder_setup_properties (klass);
10160 typebuilder_setup_events (klass);
10162 klass->wastypebuilder = TRUE;
10165 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10166 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10167 * we want to return normal System.MonoType objects, so clear these out from the cache.
10169 if (domain->type_hash && klass->generic_container)
10170 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10172 mono_loader_unlock ();
10173 mono_domain_unlock (domain);
10175 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10176 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10177 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10180 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10181 g_assert (res != (MonoReflectionType*)tb);
10187 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10189 MonoGenericParam *param;
10192 MONO_ARCH_SAVE_REGS;
10194 param = g_new0 (MonoGenericParam, 1);
10196 if (gparam->mbuilder) {
10197 if (!gparam->mbuilder->generic_container) {
10198 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10199 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10200 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10201 gparam->mbuilder->generic_container->is_method = TRUE;
10203 param->owner = gparam->mbuilder->generic_container;
10204 } else if (gparam->tbuilder) {
10205 g_assert (gparam->tbuilder->generic_container);
10206 param->owner = gparam->tbuilder->generic_container;
10209 param->name = mono_string_to_utf8 (gparam->name);
10210 param->num = gparam->index;
10212 image = &gparam->tbuilder->module->dynamic_image->image;
10213 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10215 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10216 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10218 gparam->type.type = g_new0 (MonoType, 1);
10219 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10220 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10221 gparam->type.type->data.generic_param = param;
10225 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10227 MonoDynamicImage *assembly = sig->module->dynamic_image;
10228 guint32 na = mono_array_length (sig->arguments);
10233 sigbuffer_init (&buf, 32);
10235 sigbuffer_add_value (&buf, 0x07);
10236 sigbuffer_add_value (&buf, na);
10237 for (i = 0; i < na; ++i) {
10238 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10239 encode_reflection_type (assembly, type, &buf);
10242 buflen = buf.p - buf.buf;
10243 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10244 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10245 sigbuffer_free (&buf);
10251 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10253 MonoDynamicImage *assembly = sig->module->dynamic_image;
10254 guint32 na = mono_array_length (sig->arguments);
10259 sigbuffer_init (&buf, 32);
10261 sigbuffer_add_value (&buf, 0x06);
10262 for (i = 0; i < na; ++i) {
10263 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10264 encode_reflection_type (assembly, type, &buf);
10267 buflen = buf.p - buf.buf;
10268 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10269 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10270 sigbuffer_free (&buf);
10276 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10278 ReflectionMethodBuilder rmb;
10279 MonoMethodSignature *sig;
10284 sig = dynamic_method_to_signature (mb);
10286 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10289 * Resolve references.
10292 * Every second entry in the refs array is reserved for storing handle_class,
10293 * which is needed by the ldtoken implementation in the JIT.
10295 rmb.nrefs = mb->nrefs;
10296 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10297 for (i = 0; i < mb->nrefs; i += 2) {
10298 MonoClass *handle_class;
10300 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10302 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10303 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10305 * The referenced DynamicMethod should already be created by the managed
10306 * code, except in the case of circular references. In that case, we store
10307 * method in the refs array, and fix it up later when the referenced
10308 * DynamicMethod is created.
10310 if (method->mhandle) {
10311 ref = method->mhandle;
10313 /* FIXME: GC object stored in unmanaged memory */
10316 /* FIXME: GC object stored in unmanaged memory */
10317 method->referenced_by = g_slist_append (method->referenced_by, mb);
10319 handle_class = mono_defaults.methodhandle_class;
10321 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10324 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10329 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10330 rmb.refs [i + 1] = handle_class;
10333 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10335 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10337 /* Fix up refs entries pointing at us */
10338 for (l = mb->referenced_by; l; l = l->next) {
10339 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10340 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10343 g_assert (method->mhandle);
10345 data = (gpointer*)wrapper->method_data;
10346 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10347 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10348 data [i + 1] = mb->mhandle;
10351 g_slist_free (mb->referenced_by);
10355 /* ilgen is no longer needed */
10359 #endif /* DISABLE_REFLECTION_EMIT */
10362 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10367 mono_runtime_free_method (
10368 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10373 * mono_reflection_is_valid_dynamic_token:
10375 * Returns TRUE if token is valid.
10379 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10381 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10384 #ifndef DISABLE_REFLECTION_EMIT
10387 * mono_reflection_lookup_dynamic_token:
10389 * Finish the Builder object pointed to by TOKEN and return the corresponding
10390 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10391 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10395 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10397 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10401 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10404 g_assert_not_reached ();
10410 handle_class = &klass;
10411 return resolve_object (image, obj, handle_class, context);
10415 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10417 gpointer result = NULL;
10419 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10420 result = mono_string_intern ((MonoString*)obj);
10421 *handle_class = NULL;
10423 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10424 MonoReflectionType *tb = (MonoReflectionType*)obj;
10426 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10427 result = mono_class_from_mono_type (inflated);
10428 mono_metadata_free_type (inflated);
10430 result = mono_class_from_mono_type (tb->type);
10432 *handle_class = mono_defaults.typehandle_class;
10434 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10435 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10436 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10437 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10438 result = ((MonoReflectionMethod*)obj)->method;
10440 result = mono_class_inflate_generic_method (result, context);
10441 *handle_class = mono_defaults.methodhandle_class;
10443 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10444 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10445 result = mb->mhandle;
10447 /* Type is not yet created */
10448 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10450 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10453 * Hopefully this has been filled in by calling CreateType() on the
10457 * TODO: This won't work if the application finishes another
10458 * TypeBuilder instance instead of this one.
10460 result = mb->mhandle;
10463 result = mono_class_inflate_generic_method (result, context);
10464 *handle_class = mono_defaults.methodhandle_class;
10465 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10466 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10468 result = cb->mhandle;
10470 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10472 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10473 result = cb->mhandle;
10476 result = mono_class_inflate_generic_method (result, context);
10477 *handle_class = mono_defaults.methodhandle_class;
10478 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10479 result = ((MonoReflectionField*)obj)->field;
10480 *handle_class = mono_defaults.fieldhandle_class;
10482 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10483 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10484 result = fb->handle;
10487 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10489 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10490 result = fb->handle;
10493 if (fb->handle && fb->handle->parent->generic_container) {
10494 MonoClass *klass = fb->handle->parent;
10495 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10496 MonoClass *inflated = mono_class_from_mono_type (type);
10498 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10500 mono_metadata_free_type (type);
10502 *handle_class = mono_defaults.fieldhandle_class;
10503 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10504 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10507 klass = tb->type.type->data.klass;
10508 if (klass->wastypebuilder) {
10509 /* Already created */
10513 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10514 result = tb->type.type->data.klass;
10517 *handle_class = mono_defaults.typehandle_class;
10518 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10519 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10520 MonoMethodSignature *sig;
10523 if (helper->arguments)
10524 nargs = mono_array_length (helper->arguments);
10528 sig = mono_metadata_signature_alloc (image, nargs);
10529 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10530 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10532 if (helper->call_conv == 0) /* unmanaged */
10533 sig->call_convention = helper->unmanaged_call_conv - 1;
10535 if (helper->call_conv & 0x02)
10536 sig->call_convention = MONO_CALL_VARARG;
10538 sig->call_convention = MONO_CALL_DEFAULT;
10540 sig->param_count = nargs;
10541 /* TODO: Copy type ? */
10542 sig->ret = helper->return_type->type;
10543 for (i = 0; i < nargs; ++i) {
10544 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10545 sig->params [i] = rt->type;
10549 *handle_class = NULL;
10550 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10551 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10552 /* Already created by the managed code */
10553 g_assert (method->mhandle);
10554 result = method->mhandle;
10555 *handle_class = mono_defaults.methodhandle_class;
10556 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10557 MonoReflectionType *tb = (MonoReflectionType*)obj;
10558 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10559 result = mono_class_from_mono_type (type);
10560 *handle_class = mono_defaults.typehandle_class;
10562 mono_metadata_free_type (type);
10563 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10564 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10565 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10566 result = mono_class_from_mono_type (type);
10567 *handle_class = mono_defaults.typehandle_class;
10569 mono_metadata_free_type (type);
10570 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10571 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10572 MonoClass *inflated;
10575 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10576 inflated = mono_class_from_mono_type (type);
10578 g_assert (f->fb->handle);
10579 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10581 mono_metadata_free_type (type);
10582 *handle_class = mono_defaults.fieldhandle_class;
10583 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10584 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10585 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10586 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10587 g_assert (c->cb->mhandle);
10588 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10589 *handle_class = mono_defaults.methodhandle_class;
10590 mono_metadata_free_type (type);
10591 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10592 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10593 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10594 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10595 g_assert (m->mb->mhandle);
10596 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10597 *handle_class = mono_defaults.methodhandle_class;
10598 mono_metadata_free_type (type);
10600 g_print (obj->vtable->klass->name);
10601 g_assert_not_reached ();
10606 #else /* DISABLE_REFLECTION_EMIT */
10609 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10611 g_assert_not_reached ();
10616 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10618 g_assert_not_reached ();
10622 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10624 g_assert_not_reached ();
10628 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10630 g_assert_not_reached ();
10634 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10636 g_assert_not_reached ();
10640 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10642 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10646 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10648 g_assert_not_reached ();
10651 MonoReflectionModule *
10652 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10654 g_assert_not_reached ();
10659 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10661 g_assert_not_reached ();
10666 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10668 g_assert_not_reached ();
10673 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10674 gboolean create_methodspec, gboolean register_token)
10676 g_assert_not_reached ();
10681 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10686 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10687 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10690 g_assert_not_reached ();
10694 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10697 *num_overrides = 0;
10700 MonoReflectionEvent *
10701 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10703 g_assert_not_reached ();
10707 MonoReflectionType*
10708 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10710 g_assert_not_reached ();
10715 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10717 g_assert_not_reached ();
10721 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10723 g_assert_not_reached ();
10728 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10730 g_assert_not_reached ();
10735 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10740 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10745 #endif /* DISABLE_REFLECTION_EMIT */
10747 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10748 const static guint32 declsec_flags_map[] = {
10749 0x00000000, /* empty */
10750 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10751 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10752 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10753 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10754 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10755 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10756 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10757 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10758 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10759 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10760 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10761 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10762 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10763 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10764 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10765 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10766 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10767 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10771 * Returns flags that includes all available security action associated to the handle.
10772 * @token: metadata token (either for a class or a method)
10773 * @image: image where resides the metadata.
10776 mono_declsec_get_flags (MonoImage *image, guint32 token)
10778 int index = mono_metadata_declsec_from_index (image, token);
10779 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10780 guint32 result = 0;
10784 /* HasSecurity can be present for other, not specially encoded, attributes,
10785 e.g. SuppressUnmanagedCodeSecurityAttribute */
10789 for (i = index; i < t->rows; i++) {
10790 guint32 cols [MONO_DECL_SECURITY_SIZE];
10792 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10793 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10796 action = cols [MONO_DECL_SECURITY_ACTION];
10797 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10798 result |= declsec_flags_map [action];
10800 g_assert_not_reached ();
10807 * Get the security actions (in the form of flags) associated with the specified method.
10809 * @method: The method for which we want the declarative security flags.
10810 * Return the declarative security flags for the method (only).
10812 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10813 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10816 mono_declsec_flags_from_method (MonoMethod *method)
10818 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10819 /* FIXME: No cache (for the moment) */
10820 guint32 idx = mono_method_get_index (method);
10821 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10822 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10823 return mono_declsec_get_flags (method->klass->image, idx);
10829 * Get the security actions (in the form of flags) associated with the specified class.
10831 * @klass: The class for which we want the declarative security flags.
10832 * Return the declarative security flags for the class.
10834 * Note: We cache the flags inside the MonoClass structure as this will get
10835 * called very often (at least for each method).
10838 mono_declsec_flags_from_class (MonoClass *klass)
10840 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10841 if (!klass->declsec_flags) {
10842 guint32 idx = mono_metadata_token_index (klass->type_token);
10843 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10844 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10845 /* we cache the flags on classes */
10846 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10848 return klass->declsec_flags;
10854 * Get the security actions (in the form of flags) associated with the specified assembly.
10856 * @assembly: The assembly for which we want the declarative security flags.
10857 * Return the declarative security flags for the assembly.
10860 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10862 guint32 idx = 1; /* there is only one assembly */
10863 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10864 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10865 return mono_declsec_get_flags (assembly->image, idx);
10870 * Fill actions for the specific index (which may either be an encoded class token or
10871 * an encoded method token) from the metadata image.
10872 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10875 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10876 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10878 MonoBoolean result = FALSE;
10880 guint32 cols [MONO_DECL_SECURITY_SIZE];
10881 int index = mono_metadata_declsec_from_index (image, token);
10884 t = &image->tables [MONO_TABLE_DECLSECURITY];
10885 for (i = index; i < t->rows; i++) {
10886 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10888 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10891 /* if present only replace (class) permissions with method permissions */
10892 /* if empty accept either class or method permissions */
10893 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10894 if (!actions->demand.blob) {
10895 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10896 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10897 actions->demand.blob = (char*) (blob + 2);
10898 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10901 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10902 if (!actions->noncasdemand.blob) {
10903 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10904 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10905 actions->noncasdemand.blob = (char*) (blob + 2);
10906 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10909 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10910 if (!actions->demandchoice.blob) {
10911 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10912 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10913 actions->demandchoice.blob = (char*) (blob + 2);
10914 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10924 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10925 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10927 guint32 idx = mono_metadata_token_index (klass->type_token);
10928 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10929 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10930 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10934 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10935 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10937 guint32 idx = mono_method_get_index (method);
10938 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10939 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10940 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10944 * Collect all actions (that requires to generate code in mini) assigned for
10945 * the specified method.
10946 * Note: Don't use the content of actions if the function return FALSE.
10949 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10951 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10952 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10953 MonoBoolean result = FALSE;
10956 /* quick exit if no declarative security is present in the metadata */
10957 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10960 /* we want the original as the wrapper is "free" of the security informations */
10961 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10962 method = mono_marshal_method_from_wrapper (method);
10967 /* First we look for method-level attributes */
10968 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10969 mono_class_init (method->klass);
10970 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10972 result = mono_declsec_get_method_demands_params (method, demands,
10973 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10976 /* Here we use (or create) the class declarative cache to look for demands */
10977 flags = mono_declsec_flags_from_class (method->klass);
10978 if (flags & mask) {
10980 mono_class_init (method->klass);
10981 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10983 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10984 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10987 /* The boolean return value is used as a shortcut in case nothing needs to
10988 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10994 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10996 * Note: Don't use the content of actions if the function return FALSE.
10999 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11001 MonoBoolean result = FALSE;
11004 /* quick exit if no declarative security is present in the metadata */
11005 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11008 /* we want the original as the wrapper is "free" of the security informations */
11009 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11010 method = mono_marshal_method_from_wrapper (method);
11015 /* results are independant - zeroize both */
11016 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11017 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11019 /* First we look for method-level attributes */
11020 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11021 mono_class_init (method->klass);
11023 result = mono_declsec_get_method_demands_params (method, cmethod,
11024 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11027 /* Here we use (or create) the class declarative cache to look for demands */
11028 flags = mono_declsec_flags_from_class (method->klass);
11029 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11030 mono_class_init (method->klass);
11032 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11033 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11040 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11042 * @klass The inherited class - this is the class that provides the security check (attributes)
11044 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11046 * Note: Don't use the content of actions if the function return FALSE.
11049 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11051 MonoBoolean result = FALSE;
11054 /* quick exit if no declarative security is present in the metadata */
11055 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11058 /* Here we use (or create) the class declarative cache to look for demands */
11059 flags = mono_declsec_flags_from_class (klass);
11060 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11061 mono_class_init (klass);
11062 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11064 result |= mono_declsec_get_class_demands_params (klass, demands,
11065 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11072 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11074 * Note: Don't use the content of actions if the function return FALSE.
11077 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11079 /* quick exit if no declarative security is present in the metadata */
11080 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11083 /* we want the original as the wrapper is "free" of the security informations */
11084 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11085 method = mono_marshal_method_from_wrapper (method);
11090 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11091 mono_class_init (method->klass);
11092 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11094 return mono_declsec_get_method_demands_params (method, demands,
11095 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11102 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11104 guint32 cols [MONO_DECL_SECURITY_SIZE];
11108 int index = mono_metadata_declsec_from_index (image, token);
11112 t = &image->tables [MONO_TABLE_DECLSECURITY];
11113 for (i = index; i < t->rows; i++) {
11114 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11116 /* shortcut - index are ordered */
11117 if (token != cols [MONO_DECL_SECURITY_PARENT])
11120 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11121 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11122 entry->blob = (char*) (metadata + 2);
11123 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11132 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11134 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11135 guint32 idx = mono_method_get_index (method);
11136 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11137 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11138 return get_declsec_action (method->klass->image, idx, action, entry);
11144 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11147 guint32 flags = mono_declsec_flags_from_class (klass);
11148 if (declsec_flags_map [action] & flags) {
11149 guint32 idx = mono_metadata_token_index (klass->type_token);
11150 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11151 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11152 return get_declsec_action (klass->image, idx, action, entry);
11158 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11160 guint32 idx = 1; /* there is only one assembly */
11161 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11162 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11164 return get_declsec_action (assembly->image, idx, action, entry);
11168 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11170 MonoObject *res, *exc;
11172 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11173 static MonoMethod *method = NULL;
11175 if (!System_Reflection_Emit_TypeBuilder) {
11176 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11177 g_assert (System_Reflection_Emit_TypeBuilder);
11179 if (method == NULL) {
11180 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11185 * The result of mono_type_get_object () might be a System.MonoType but we
11186 * need a TypeBuilder so use klass->reflection_info.
11188 g_assert (klass->reflection_info);
11189 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11191 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11193 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11197 return *(MonoBoolean*)mono_object_unbox (res);