2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/utils/mono-membar.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/metadata-internals.h"
16 #include <mono/metadata/profiler-private.h>
17 #include "mono/metadata/class-internals.h"
18 #include "mono/metadata/gc-internal.h"
19 #include "mono/metadata/tokentype.h"
20 #include "mono/metadata/domain-internals.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/assembly.h"
23 #include "mono/metadata/object-internals.h"
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/marshal.h>
26 #include <mono/metadata/security-manager.h>
35 #include "rawbuffer.h"
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
45 #define TEXT_OFFSET 512
46 #define CLI_H_SIZE 136
47 #define FILE_ALIGN 512
48 #define VIRT_ALIGN 8192
49 #define START_TEXT_RVA 0x00002000
52 MonoReflectionILGen *ilgen;
53 MonoReflectionType *rtype;
54 MonoArray *parameters;
55 MonoArray *generic_params;
56 MonoGenericContainer *generic_container;
62 guint32 *table_idx; /* note: it's a pointer */
66 MonoBoolean init_locals;
67 MonoBoolean skip_visibility;
68 MonoArray *return_modreq;
69 MonoArray *return_modopt;
70 MonoArray *param_modreq;
71 MonoArray *param_modopt;
72 MonoArray *permissions;
77 int charset, extra_flags, native_cc;
78 MonoString *dll, *dllentry;
79 } ReflectionMethodBuilder;
83 MonoReflectionGenericParam *gparam;
84 } GenericParamTableEntry;
86 const unsigned char table_sizes [MONO_TABLE_NUM] = {
96 MONO_INTERFACEIMPL_SIZE,
97 MONO_MEMBERREF_SIZE, /* 0x0A */
99 MONO_CUSTOM_ATTR_SIZE,
100 MONO_FIELD_MARSHAL_SIZE,
101 MONO_DECL_SECURITY_SIZE,
102 MONO_CLASS_LAYOUT_SIZE,
103 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
104 MONO_STAND_ALONE_SIGNATURE_SIZE,
108 MONO_PROPERTY_MAP_SIZE,
111 MONO_METHOD_SEMA_SIZE,
112 MONO_METHODIMPL_SIZE,
113 MONO_MODULEREF_SIZE, /* 0x1A */
119 MONO_ASSEMBLY_SIZE, /* 0x20 */
120 MONO_ASSEMBLY_PROCESSOR_SIZE,
121 MONO_ASSEMBLYOS_SIZE,
122 MONO_ASSEMBLYREF_SIZE,
123 MONO_ASSEMBLYREFPROC_SIZE,
124 MONO_ASSEMBLYREFOS_SIZE,
128 MONO_NESTED_CLASS_SIZE,
130 MONO_GENERICPARAM_SIZE, /* 0x2A */
131 MONO_METHODSPEC_SIZE,
132 MONO_GENPARCONSTRAINT_SIZE
136 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
137 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
138 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
139 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
140 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
141 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
142 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
143 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
144 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
145 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
146 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
147 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
148 static void ensure_runtime_vtable (MonoClass *klass);
149 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
150 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
151 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
152 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
153 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
154 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
157 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
158 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
159 static CRITICAL_SECTION reflection_mutex;
162 mono_reflection_init (void)
164 InitializeCriticalSection (&reflection_mutex);
168 sigbuffer_init (SigBuffer *buf, int size)
170 buf->buf = g_malloc (size);
172 buf->end = buf->buf + size;
176 sigbuffer_make_room (SigBuffer *buf, int size)
178 if (buf->end - buf->p < size) {
179 int new_size = buf->end - buf->buf + size + 32;
180 char *p = g_realloc (buf->buf, new_size);
181 size = buf->p - buf->buf;
184 buf->end = buf->buf + new_size;
189 sigbuffer_add_value (SigBuffer *buf, guint32 val)
191 sigbuffer_make_room (buf, 6);
192 mono_metadata_encode_value (val, buf->p, &buf->p);
196 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
198 sigbuffer_make_room (buf, 1);
204 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
206 sigbuffer_make_room (buf, size);
207 memcpy (buf->p, p, size);
212 sigbuffer_free (SigBuffer *buf)
220 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
224 mp_g_malloc (MonoMemPool *mp, guint size)
227 return mono_mempool_alloc (mp, size);
229 return g_malloc (size);
235 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
239 mp_g_malloc0 (MonoMemPool *mp, guint size)
242 return mono_mempool_alloc0 (mp, size);
244 return g_malloc0 (size);
250 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
251 * memory from the C heap.
254 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
257 return mono_string_to_utf8_mp (mp, s);
259 return mono_string_to_utf8 (s);
262 #define mp_g_new(mp,struct_type, n_structs) \
263 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
265 #define mp_g_new0(mp,struct_type, n_structs) \
266 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
269 alloc_table (MonoDynamicTable *table, guint nrows)
272 g_assert (table->columns);
273 if (nrows + 1 >= table->alloc_rows) {
274 while (nrows + 1 >= table->alloc_rows) {
275 if (table->alloc_rows == 0)
276 table->alloc_rows = 16;
278 table->alloc_rows *= 2;
281 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
286 make_room_in_stream (MonoDynamicStream *stream, int size)
288 if (size <= stream->alloc_size)
291 while (stream->alloc_size <= size) {
292 if (stream->alloc_size < 4096)
293 stream->alloc_size = 4096;
295 stream->alloc_size *= 2;
298 stream->data = g_realloc (stream->data, stream->alloc_size);
302 string_heap_insert (MonoDynamicStream *sh, const char *str)
306 gpointer oldkey, oldval;
308 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
309 return GPOINTER_TO_UINT (oldval);
311 len = strlen (str) + 1;
314 make_room_in_stream (sh, idx + len);
317 * We strdup the string even if we already copy them in sh->data
318 * so that the string pointers in the hash remain valid even if
319 * we need to realloc sh->data. We may want to avoid that later.
321 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
322 memcpy (sh->data + idx, str, len);
328 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
330 char *name = mono_string_to_utf8 (str);
332 idx = string_heap_insert (sh, name);
338 string_heap_init (MonoDynamicStream *sh)
341 sh->alloc_size = 4096;
342 sh->data = g_malloc (4096);
343 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
344 string_heap_insert (sh, "");
348 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
352 make_room_in_stream (stream, stream->index + len);
353 memcpy (stream->data + stream->index, data, len);
355 stream->index += len;
357 * align index? Not without adding an additional param that controls it since
358 * we may store a blob value in pieces.
364 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
368 make_room_in_stream (stream, stream->index + len);
369 memset (stream->data + stream->index, 0, len);
371 stream->index += len;
376 stream_data_align (MonoDynamicStream *stream)
379 guint32 count = stream->index % 4;
381 /* we assume the stream data will be aligned */
383 mono_image_add_stream_data (stream, buf, 4 - count);
387 mono_blob_entry_hash (const char* str)
391 len = mono_metadata_decode_blob_size (str, &str);
395 for (str += 1; str < end; str++)
396 h = (h << 5) - h + *str;
404 mono_blob_entry_equal (const char *str1, const char *str2) {
408 len = mono_metadata_decode_blob_size (str1, &end1);
409 len2 = mono_metadata_decode_blob_size (str2, &end2);
412 return memcmp (end1, end2, len) == 0;
416 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
420 gpointer oldkey, oldval;
422 copy = g_malloc (s1+s2);
423 memcpy (copy, b1, s1);
424 memcpy (copy + s1, b2, s2);
425 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
427 idx = GPOINTER_TO_UINT (oldval);
429 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
430 mono_image_add_stream_data (&assembly->blob, b2, s2);
431 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
437 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
441 guint32 size = buf->p - buf->buf;
443 g_assert (size <= (buf->end - buf->buf));
444 mono_metadata_encode_value (size, b, &b);
445 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
449 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
450 * dest may be misaligned.
453 swap_with_size (char *dest, const char* val, int len, int nelem) {
454 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
457 for (elem = 0; elem < nelem; ++elem) {
483 g_assert_not_reached ();
489 memcpy (dest, val, len * nelem);
494 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
498 guint32 idx = 0, len;
500 len = str->length * 2;
501 mono_metadata_encode_value (len, b, &b);
502 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
504 char *swapped = g_malloc (2 * mono_string_length (str));
505 const char *p = (const char*)mono_string_chars (str);
507 swap_with_size (swapped, p, 2, mono_string_length (str));
508 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
512 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
517 /* modified version needed to handle building corlib */
519 my_mono_class_from_mono_type (MonoType *type) {
520 switch (type->type) {
521 case MONO_TYPE_ARRAY:
523 case MONO_TYPE_SZARRAY:
524 case MONO_TYPE_GENERICINST:
525 return mono_class_from_mono_type (type);
528 g_assert (type->data.generic_param->pklass);
529 return type->data.generic_param->pklass;
531 /* should be always valid when we reach this case... */
532 return type->data.klass;
537 default_class_from_mono_type (MonoType *type)
539 switch (type->type) {
540 case MONO_TYPE_OBJECT:
541 return mono_defaults.object_class;
543 return mono_defaults.void_class;
544 case MONO_TYPE_BOOLEAN:
545 return mono_defaults.boolean_class;
547 return mono_defaults.char_class;
549 return mono_defaults.sbyte_class;
551 return mono_defaults.byte_class;
553 return mono_defaults.int16_class;
555 return mono_defaults.uint16_class;
557 return mono_defaults.int32_class;
559 return mono_defaults.uint32_class;
561 return mono_defaults.int_class;
563 return mono_defaults.uint_class;
565 return mono_defaults.int64_class;
567 return mono_defaults.uint64_class;
569 return mono_defaults.single_class;
571 return mono_defaults.double_class;
572 case MONO_TYPE_STRING:
573 return mono_defaults.string_class;
575 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
576 g_assert_not_reached ();
583 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
586 MonoGenericInst *class_inst;
591 class_inst = gclass->context.class_inst;
593 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
594 klass = gclass->container_class;
595 sigbuffer_add_value (buf, klass->byval_arg.type);
596 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
598 sigbuffer_add_value (buf, class_inst->type_argc);
599 for (i = 0; i < class_inst->type_argc; ++i)
600 encode_type (assembly, class_inst->type_argv [i], buf);
605 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
608 g_assert_not_reached ();
613 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
617 case MONO_TYPE_BOOLEAN:
631 case MONO_TYPE_STRING:
632 case MONO_TYPE_OBJECT:
633 case MONO_TYPE_TYPEDBYREF:
634 sigbuffer_add_value (buf, type->type);
637 sigbuffer_add_value (buf, type->type);
638 encode_type (assembly, type->data.type, buf);
640 case MONO_TYPE_SZARRAY:
641 sigbuffer_add_value (buf, type->type);
642 encode_type (assembly, &type->data.klass->byval_arg, buf);
644 case MONO_TYPE_VALUETYPE:
645 case MONO_TYPE_CLASS: {
646 MonoClass *k = mono_class_from_mono_type (type);
648 if (k->generic_container) {
649 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
650 encode_generic_class (assembly, gclass, buf);
653 * Make sure we use the correct type.
655 sigbuffer_add_value (buf, k->byval_arg.type);
657 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
658 * otherwise two typerefs could point to the same type, leading to
659 * verification errors.
661 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
665 case MONO_TYPE_ARRAY:
666 sigbuffer_add_value (buf, type->type);
667 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
668 sigbuffer_add_value (buf, type->data.array->rank);
669 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
670 sigbuffer_add_value (buf, 0);
672 case MONO_TYPE_GENERICINST:
673 encode_generic_class (assembly, type->data.generic_class, buf);
677 sigbuffer_add_value (buf, type->type);
678 sigbuffer_add_value (buf, type->data.generic_param->num);
681 g_error ("need to encode type %x", type->type);
686 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
689 sigbuffer_add_value (buf, MONO_TYPE_VOID);
694 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
695 encode_type (assembly, type->type, buf);
699 g_assert_not_reached ();
704 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
709 for (i = 0; i < mono_array_length (modreq); ++i) {
710 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
711 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
712 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
716 for (i = 0; i < mono_array_length (modopt); ++i) {
717 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
718 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
725 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
729 guint32 nparams = sig->param_count;
735 sigbuffer_init (&buf, 32);
737 * FIXME: vararg, explicit_this, differenc call_conv values...
739 idx = sig->call_convention;
741 idx |= 0x20; /* hasthis */
742 if (sig->generic_param_count)
743 idx |= 0x10; /* generic */
744 sigbuffer_add_byte (&buf, idx);
745 if (sig->generic_param_count)
746 sigbuffer_add_value (&buf, sig->generic_param_count);
747 sigbuffer_add_value (&buf, nparams);
748 encode_type (assembly, sig->ret, &buf);
749 for (i = 0; i < nparams; ++i) {
750 if (i == sig->sentinelpos)
751 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
752 encode_type (assembly, sig->params [i], &buf);
754 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
755 sigbuffer_free (&buf);
760 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
763 * FIXME: reuse code from method_encode_signature().
767 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
768 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
769 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
772 sigbuffer_init (&buf, 32);
773 /* LAMESPEC: all the call conv spec is foobared */
774 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
775 if (mb->call_conv & 2)
776 idx |= 0x5; /* vararg */
777 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
778 idx |= 0x20; /* hasthis */
780 idx |= 0x10; /* generic */
781 sigbuffer_add_byte (&buf, idx);
783 sigbuffer_add_value (&buf, ngparams);
784 sigbuffer_add_value (&buf, nparams + notypes);
785 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
786 encode_reflection_type (assembly, mb->rtype, &buf);
787 for (i = 0; i < nparams; ++i) {
788 MonoArray *modreq = NULL;
789 MonoArray *modopt = NULL;
790 MonoReflectionType *pt;
792 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
793 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
794 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
795 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
796 encode_custom_modifiers (assembly, modreq, modopt, &buf);
797 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
798 encode_reflection_type (assembly, pt, &buf);
801 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
802 for (i = 0; i < notypes; ++i) {
803 MonoReflectionType *pt;
805 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
806 encode_reflection_type (assembly, pt, &buf);
809 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
810 sigbuffer_free (&buf);
815 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
817 MonoDynamicTable *table;
819 guint32 idx, sig_idx;
820 guint nl = mono_array_length (ilgen->locals);
824 sigbuffer_init (&buf, 32);
825 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
826 idx = table->next_idx ++;
828 alloc_table (table, table->rows);
829 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
831 sigbuffer_add_value (&buf, 0x07);
832 sigbuffer_add_value (&buf, nl);
833 for (i = 0; i < nl; ++i) {
834 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
837 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
839 encode_reflection_type (assembly, lb->type, &buf);
841 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
842 sigbuffer_free (&buf);
844 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
850 method_count_clauses (MonoReflectionILGen *ilgen)
852 guint32 num_clauses = 0;
855 MonoILExceptionInfo *ex_info;
856 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
857 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
858 if (ex_info->handlers)
859 num_clauses += mono_array_length (ex_info->handlers);
867 static MonoExceptionClause*
868 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
870 MonoExceptionClause *clauses;
871 MonoExceptionClause *clause;
872 MonoILExceptionInfo *ex_info;
873 MonoILExceptionBlock *ex_block;
874 guint32 finally_start;
875 int i, j, clause_index;;
877 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
880 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
881 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
882 finally_start = ex_info->start + ex_info->len;
883 if (!ex_info->handlers)
885 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
886 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
887 clause = &(clauses [clause_index]);
889 clause->flags = ex_block->type;
890 clause->try_offset = ex_info->start;
892 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
893 clause->try_len = finally_start - ex_info->start;
895 clause->try_len = ex_info->len;
896 clause->handler_offset = ex_block->start;
897 clause->handler_len = ex_block->len;
898 if (ex_block->extype) {
899 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
901 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
902 clause->data.filter_offset = ex_block->filter_offset;
904 clause->data.filter_offset = 0;
906 finally_start = ex_block->start + ex_block->len;
916 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
922 gint32 num_locals = 0;
923 gint32 num_exception = 0;
926 char fat_header [12];
929 guint32 local_sig = 0;
930 guint32 header_size = 12;
933 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
934 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
938 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
940 code = mb->ilgen->code;
941 code_size = mb->ilgen->code_len;
942 max_stack = mb->ilgen->max_stack;
943 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
944 if (mb->ilgen->ex_handlers)
945 num_exception = method_count_clauses (mb->ilgen);
949 char *name = mono_string_to_utf8 (mb->name);
950 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
951 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
954 mono_raise_exception (exception);
957 code_size = mono_array_length (code);
958 max_stack = 8; /* we probably need to run a verifier on the code... */
961 stream_data_align (&assembly->code);
963 /* check for exceptions, maxstack, locals */
964 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
966 if (code_size < 64 && !(code_size & 1)) {
967 flags = (code_size << 2) | 0x2;
968 } else if (code_size < 32 && (code_size & 1)) {
969 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
973 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
974 /* add to the fixup todo list */
975 if (mb->ilgen && mb->ilgen->num_token_fixups)
976 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
977 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
978 return assembly->text_rva + idx;
982 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
984 * FIXME: need to set also the header size in fat_flags.
985 * (and more sects and init locals flags)
989 fat_flags |= METHOD_HEADER_MORE_SECTS;
991 fat_flags |= METHOD_HEADER_INIT_LOCALS;
992 fat_header [0] = fat_flags;
993 fat_header [1] = (header_size / 4 ) << 4;
994 short_value = GUINT16_TO_LE (max_stack);
995 memcpy (fat_header + 2, &short_value, 2);
996 int_value = GUINT32_TO_LE (code_size);
997 memcpy (fat_header + 4, &int_value, 4);
998 int_value = GUINT32_TO_LE (local_sig);
999 memcpy (fat_header + 8, &int_value, 4);
1000 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1001 /* add to the fixup todo list */
1002 if (mb->ilgen && mb->ilgen->num_token_fixups)
1003 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1005 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1006 if (num_exception) {
1007 unsigned char sheader [4];
1008 MonoILExceptionInfo * ex_info;
1009 MonoILExceptionBlock * ex_block;
1012 stream_data_align (&assembly->code);
1013 /* always use fat format for now */
1014 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1015 num_exception *= 6 * sizeof (guint32);
1016 num_exception += 4; /* include the size of the header */
1017 sheader [1] = num_exception & 0xff;
1018 sheader [2] = (num_exception >> 8) & 0xff;
1019 sheader [3] = (num_exception >> 16) & 0xff;
1020 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1021 /* fat header, so we are already aligned */
1023 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1024 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1025 if (ex_info->handlers) {
1026 int finally_start = ex_info->start + ex_info->len;
1027 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1029 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1031 val = GUINT32_TO_LE (ex_block->type);
1032 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 val = GUINT32_TO_LE (ex_info->start);
1035 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1036 /* need fault, too, probably */
1037 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1038 val = GUINT32_TO_LE (finally_start - ex_info->start);
1040 val = GUINT32_TO_LE (ex_info->len);
1041 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1042 /* handler offset */
1043 val = GUINT32_TO_LE (ex_block->start);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 val = GUINT32_TO_LE (ex_block->len);
1047 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1048 finally_start = ex_block->start + ex_block->len;
1049 if (ex_block->extype) {
1050 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1052 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1053 val = ex_block->filter_offset;
1057 val = GUINT32_TO_LE (val);
1058 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1060 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1063 g_error ("No clauses for ex info block %d", i);
1067 return assembly->text_rva + idx;
1071 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1074 MonoDynamicTable *table;
1077 table = &assembly->tables [table_idx];
1079 g_assert (col < table->columns);
1081 values = table->values + table->columns;
1082 for (i = 1; i <= table->rows; ++i) {
1083 if (values [col] == token)
1085 values += table->columns;
1091 * LOCKING: Acquires the loader lock.
1093 static MonoCustomAttrInfo*
1094 lookup_custom_attr (MonoImage *image, gpointer member)
1096 MonoCustomAttrInfo* res;
1098 mono_loader_lock ();
1099 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1100 mono_loader_unlock ();
1105 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1109 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1111 /* FIXME: Need to do more checks */
1112 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1113 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1115 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1122 static MonoCustomAttrInfo*
1123 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1125 int i, index, count, not_visible;
1126 MonoCustomAttrInfo *ainfo;
1127 MonoReflectionCustomAttr *cattr;
1131 /* FIXME: check in assembly the Run flag is set */
1133 count = mono_array_length (cattrs);
1135 /* Skip nonpublic attributes since MS.NET seems to do the same */
1136 /* FIXME: This needs to be done more globally */
1138 for (i = 0; i < count; ++i) {
1139 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1140 if (!custom_attr_visible (image, cattr))
1143 count -= not_visible;
1145 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1147 ainfo->image = image;
1148 ainfo->num_attrs = count;
1149 ainfo->cached = mp != NULL;
1151 mono_loader_lock ();
1152 for (i = 0; i < count; ++i) {
1153 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1154 if (custom_attr_visible (image, cattr)) {
1155 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1156 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1157 ainfo->attrs [index].ctor = cattr->ctor->method;
1158 ainfo->attrs [index].data = saved;
1159 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1163 mono_loader_unlock ();
1169 * LOCKING: Acquires the loader lock.
1172 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1174 MonoCustomAttrInfo *ainfo, *tmp;
1176 if (!cattrs || !mono_array_length (cattrs))
1179 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1180 mono_loader_lock ();
1181 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1183 mono_custom_attrs_free (tmp);
1184 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1185 mono_loader_unlock ();
1189 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1196 * idx is the table index of the object
1197 * type is one of MONO_CUSTOM_ATTR_*
1200 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1202 MonoDynamicTable *table;
1203 MonoReflectionCustomAttr *cattr;
1205 guint32 count, i, token;
1207 char *p = blob_size;
1209 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1212 count = mono_array_length (cattrs);
1213 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1214 table->rows += count;
1215 alloc_table (table, table->rows);
1216 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1217 idx <<= MONO_CUSTOM_ATTR_BITS;
1219 for (i = 0; i < count; ++i) {
1220 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1221 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1222 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1223 type = mono_metadata_token_index (token);
1224 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1225 switch (mono_metadata_token_table (token)) {
1226 case MONO_TABLE_METHOD:
1227 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1229 case MONO_TABLE_MEMBERREF:
1230 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1233 g_warning ("got wrong token in custom attr");
1236 values [MONO_CUSTOM_ATTR_TYPE] = type;
1238 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1239 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1240 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1241 values += MONO_CUSTOM_ATTR_SIZE;
1247 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1249 MonoDynamicTable *table;
1251 guint32 count, i, idx;
1252 MonoReflectionPermissionSet *perm;
1257 count = mono_array_length (permissions);
1258 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1259 table->rows += count;
1260 alloc_table (table, table->rows);
1262 for (i = 0; i < mono_array_length (permissions); ++i) {
1263 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1265 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1267 idx = mono_metadata_token_index (parent_token);
1268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1269 switch (mono_metadata_token_table (parent_token)) {
1270 case MONO_TABLE_TYPEDEF:
1271 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1273 case MONO_TABLE_METHOD:
1274 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1276 case MONO_TABLE_ASSEMBLY:
1277 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1280 g_assert_not_reached ();
1283 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1284 values [MONO_DECL_SECURITY_PARENT] = idx;
1285 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1292 * Fill in the MethodDef and ParamDef tables for a method.
1293 * This is used for both normal methods and constructors.
1296 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1298 MonoDynamicTable *table;
1302 /* room in this table is already allocated */
1303 table = &assembly->tables [MONO_TABLE_METHOD];
1304 *mb->table_idx = table->next_idx ++;
1305 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1306 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1307 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1308 values [MONO_METHOD_FLAGS] = mb->attrs;
1309 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1310 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1311 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1313 table = &assembly->tables [MONO_TABLE_PARAM];
1314 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1316 mono_image_add_decl_security (assembly,
1317 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1320 MonoDynamicTable *mtable;
1323 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1324 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1327 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1328 if (mono_array_get (mb->pinfo, gpointer, i))
1331 table->rows += count;
1332 alloc_table (table, table->rows);
1333 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1334 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1335 MonoReflectionParamBuilder *pb;
1336 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1337 values [MONO_PARAM_FLAGS] = pb->attrs;
1338 values [MONO_PARAM_SEQUENCE] = i;
1339 if (pb->name != NULL) {
1340 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1342 values [MONO_PARAM_NAME] = 0;
1344 values += MONO_PARAM_SIZE;
1345 if (pb->marshal_info) {
1347 alloc_table (mtable, mtable->rows);
1348 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1349 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1350 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1352 pb->table_idx = table->next_idx++;
1353 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1354 guint32 field_type = 0;
1355 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1357 alloc_table (mtable, mtable->rows);
1358 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1359 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1360 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1361 mvalues [MONO_CONSTANT_TYPE] = field_type;
1362 mvalues [MONO_CONSTANT_PADDING] = 0;
1370 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1372 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1374 rmb->ilgen = mb->ilgen;
1375 rmb->rtype = mb->rtype;
1376 rmb->parameters = mb->parameters;
1377 rmb->generic_params = mb->generic_params;
1378 rmb->generic_container = mb->generic_container;
1379 rmb->opt_types = NULL;
1380 rmb->pinfo = mb->pinfo;
1381 rmb->attrs = mb->attrs;
1382 rmb->iattrs = mb->iattrs;
1383 rmb->call_conv = mb->call_conv;
1384 rmb->code = mb->code;
1385 rmb->type = mb->type;
1386 rmb->name = mb->name;
1387 rmb->table_idx = &mb->table_idx;
1388 rmb->init_locals = mb->init_locals;
1389 rmb->skip_visibility = FALSE;
1390 rmb->return_modreq = mb->return_modreq;
1391 rmb->return_modopt = mb->return_modopt;
1392 rmb->param_modreq = mb->param_modreq;
1393 rmb->param_modopt = mb->param_modopt;
1394 rmb->permissions = mb->permissions;
1395 rmb->mhandle = mb->mhandle;
1400 rmb->charset = mb->charset;
1401 rmb->extra_flags = mb->extra_flags;
1402 rmb->native_cc = mb->native_cc;
1403 rmb->dllentry = mb->dllentry;
1409 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1411 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1413 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1415 rmb->ilgen = mb->ilgen;
1416 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1417 rmb->parameters = mb->parameters;
1418 rmb->generic_params = NULL;
1419 rmb->generic_container = NULL;
1420 rmb->opt_types = NULL;
1421 rmb->pinfo = mb->pinfo;
1422 rmb->attrs = mb->attrs;
1423 rmb->iattrs = mb->iattrs;
1424 rmb->call_conv = mb->call_conv;
1426 rmb->type = mb->type;
1427 rmb->name = mono_string_new (mono_domain_get (), name);
1428 rmb->table_idx = &mb->table_idx;
1429 rmb->init_locals = mb->init_locals;
1430 rmb->skip_visibility = FALSE;
1431 rmb->return_modreq = NULL;
1432 rmb->return_modopt = NULL;
1433 rmb->param_modreq = mb->param_modreq;
1434 rmb->param_modopt = mb->param_modopt;
1435 rmb->permissions = mb->permissions;
1436 rmb->mhandle = mb->mhandle;
1442 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1444 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1446 rmb->ilgen = mb->ilgen;
1447 rmb->rtype = mb->rtype;
1448 rmb->parameters = mb->parameters;
1449 rmb->generic_params = NULL;
1450 rmb->generic_container = NULL;
1451 rmb->opt_types = NULL;
1453 rmb->attrs = mb->attrs;
1455 rmb->call_conv = mb->call_conv;
1457 rmb->type = (MonoObject *) mb->owner;
1458 rmb->name = mb->name;
1459 rmb->table_idx = NULL;
1460 rmb->init_locals = mb->init_locals;
1461 rmb->skip_visibility = mb->skip_visibility;
1462 rmb->return_modreq = NULL;
1463 rmb->return_modopt = NULL;
1464 rmb->param_modreq = NULL;
1465 rmb->param_modopt = NULL;
1466 rmb->permissions = NULL;
1467 rmb->mhandle = mb->mhandle;
1473 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1475 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1476 MonoDynamicTable *table;
1480 if (!mb->override_method)
1483 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1485 alloc_table (table, table->rows);
1486 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1487 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1488 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1490 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1491 switch (mono_metadata_token_table (tok)) {
1492 case MONO_TABLE_MEMBERREF:
1493 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1495 case MONO_TABLE_METHOD:
1496 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1499 g_assert_not_reached ();
1501 values [MONO_METHODIMPL_DECLARATION] = tok;
1505 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1507 MonoDynamicTable *table;
1509 ReflectionMethodBuilder rmb;
1512 reflection_methodbuilder_from_method_builder (&rmb, mb);
1514 mono_image_basic_method (&rmb, assembly);
1515 mb->table_idx = *rmb.table_idx;
1517 if (mb->dll) { /* It's a P/Invoke method */
1519 /* map CharSet values to on-disk values */
1520 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1521 int extra_flags = mb->extra_flags;
1522 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1524 alloc_table (table, table->rows);
1525 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1527 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1528 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1530 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1532 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1533 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1534 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1535 table = &assembly->tables [MONO_TABLE_MODULEREF];
1537 alloc_table (table, table->rows);
1538 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1539 values [MONO_IMPLMAP_SCOPE] = table->rows;
1543 if (mb->generic_params) {
1544 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1545 table->rows += mono_array_length (mb->generic_params);
1546 alloc_table (table, table->rows);
1547 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1548 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1550 mono_image_get_generic_param_info (
1551 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1558 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1560 ReflectionMethodBuilder rmb;
1562 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1564 mono_image_basic_method (&rmb, assembly);
1565 mb->table_idx = *rmb.table_idx;
1569 type_get_fully_qualified_name (MonoType *type)
1571 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1575 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1579 klass = my_mono_class_from_mono_type (type);
1581 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1582 ta = klass->image->assembly;
1583 if (ta->dynamic || (ta == ass)) {
1584 if (klass->generic_class || klass->generic_container)
1585 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1588 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1595 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1600 if (!assembly->save)
1603 sigbuffer_init (&buf, 32);
1605 sigbuffer_add_value (&buf, 0x06);
1606 /* encode custom attributes before the type */
1607 encode_type (assembly, type, &buf);
1608 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1609 sigbuffer_free (&buf);
1614 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1619 sigbuffer_init (&buf, 32);
1621 sigbuffer_add_value (&buf, 0x06);
1622 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1623 /* encode custom attributes before the type */
1624 encode_reflection_type (assembly, fb->type, &buf);
1625 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1626 sigbuffer_free (&buf);
1631 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1632 char blob_size [64];
1633 char *b = blob_size;
1636 guint32 idx = 0, len = 0, dummy = 0;
1638 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1639 guint32 fpa_double [2];
1644 p = buf = g_malloc (64);
1646 *ret_type = MONO_TYPE_CLASS;
1648 box_val = (char*)&dummy;
1650 box_val = ((char*)val) + sizeof (MonoObject);
1651 *ret_type = val->vtable->klass->byval_arg.type;
1654 switch (*ret_type) {
1655 case MONO_TYPE_BOOLEAN:
1660 case MONO_TYPE_CHAR:
1677 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1678 fpa_p = (guint32*)box_val;
1679 fpa_double [0] = fpa_p [1];
1680 fpa_double [1] = fpa_p [0];
1681 box_val = (char*)fpa_double;
1685 case MONO_TYPE_VALUETYPE:
1686 if (val->vtable->klass->enumtype) {
1687 *ret_type = val->vtable->klass->enum_basetype->type;
1690 g_error ("we can't encode valuetypes");
1691 case MONO_TYPE_CLASS:
1693 case MONO_TYPE_STRING: {
1694 MonoString *str = (MonoString*)val;
1695 /* there is no signature */
1696 len = str->length * 2;
1697 mono_metadata_encode_value (len, b, &b);
1698 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1700 char *swapped = g_malloc (2 * mono_string_length (str));
1701 const char *p = (const char*)mono_string_chars (str);
1703 swap_with_size (swapped, p, 2, mono_string_length (str));
1704 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1708 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1714 case MONO_TYPE_GENERICINST:
1715 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1718 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1721 /* there is no signature */
1722 mono_metadata_encode_value (len, b, &b);
1723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1724 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1725 swap_with_size (blob_size, box_val, len, 1);
1726 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1728 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1736 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1741 sigbuffer_init (&buf, 32);
1743 sigbuffer_add_value (&buf, minfo->type);
1745 switch (minfo->type) {
1746 case MONO_NATIVE_BYVALTSTR:
1747 case MONO_NATIVE_BYVALARRAY:
1748 sigbuffer_add_value (&buf, minfo->count);
1750 case MONO_NATIVE_LPARRAY:
1751 if (minfo->eltype || minfo->has_size) {
1752 sigbuffer_add_value (&buf, minfo->eltype);
1753 if (minfo->has_size) {
1754 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1755 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1757 /* LAMESPEC: ElemMult is undocumented */
1758 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1762 case MONO_NATIVE_CUSTOM:
1764 str = mono_string_to_utf8 (minfo->guid);
1766 sigbuffer_add_value (&buf, len);
1767 sigbuffer_add_mem (&buf, str, len);
1770 sigbuffer_add_value (&buf, 0);
1772 /* native type name */
1773 sigbuffer_add_value (&buf, 0);
1774 /* custom marshaler type name */
1775 if (minfo->marshaltype || minfo->marshaltyperef) {
1776 if (minfo->marshaltyperef)
1777 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1779 str = mono_string_to_utf8 (minfo->marshaltype);
1781 sigbuffer_add_value (&buf, len);
1782 sigbuffer_add_mem (&buf, str, len);
1785 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1786 sigbuffer_add_value (&buf, 0);
1788 if (minfo->mcookie) {
1789 str = mono_string_to_utf8 (minfo->mcookie);
1791 sigbuffer_add_value (&buf, len);
1792 sigbuffer_add_mem (&buf, str, len);
1795 sigbuffer_add_value (&buf, 0);
1801 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1802 sigbuffer_free (&buf);
1807 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1809 MonoDynamicTable *table;
1812 /* maybe this fixup should be done in the C# code */
1813 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1814 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1815 table = &assembly->tables [MONO_TABLE_FIELD];
1816 fb->table_idx = table->next_idx ++;
1817 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1818 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1819 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1820 values [MONO_FIELD_FLAGS] = fb->attrs;
1821 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1823 if (fb->offset != -1) {
1824 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1828 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1829 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1831 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1832 guint32 field_type = 0;
1833 table = &assembly->tables [MONO_TABLE_CONSTANT];
1835 alloc_table (table, table->rows);
1836 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1837 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1838 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1839 values [MONO_CONSTANT_TYPE] = field_type;
1840 values [MONO_CONSTANT_PADDING] = 0;
1842 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1844 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1846 alloc_table (table, table->rows);
1847 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1848 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1850 * We store it in the code section because it's simpler for now.
1853 if (mono_array_length (fb->rva_data) >= 10)
1854 stream_data_align (&assembly->code);
1855 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1857 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1858 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1860 if (fb->marshal_info) {
1861 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1863 alloc_table (table, table->rows);
1864 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1865 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1866 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1871 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1874 guint32 nparams = 0;
1875 MonoReflectionMethodBuilder *mb = fb->get_method;
1876 MonoReflectionMethodBuilder *smb = fb->set_method;
1879 if (mb && mb->parameters)
1880 nparams = mono_array_length (mb->parameters);
1881 if (!mb && smb && smb->parameters)
1882 nparams = mono_array_length (smb->parameters) - 1;
1883 sigbuffer_init (&buf, 32);
1884 sigbuffer_add_byte (&buf, 0x08);
1885 sigbuffer_add_value (&buf, nparams);
1887 encode_reflection_type (assembly, mb->rtype, &buf);
1888 for (i = 0; i < nparams; ++i) {
1889 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1890 encode_reflection_type (assembly, pt, &buf);
1892 } else if (smb && smb->parameters) {
1893 /* the property type is the last param */
1894 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1895 for (i = 0; i < nparams; ++i) {
1896 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1897 encode_reflection_type (assembly, pt, &buf);
1900 encode_reflection_type (assembly, fb->type, &buf);
1903 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1904 sigbuffer_free (&buf);
1909 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1911 MonoDynamicTable *table;
1913 guint num_methods = 0;
1917 * we need to set things in the following tables:
1918 * PROPERTYMAP (info already filled in _get_type_info ())
1919 * PROPERTY (rows already preallocated in _get_type_info ())
1920 * METHOD (method info already done with the generic method code)
1923 table = &assembly->tables [MONO_TABLE_PROPERTY];
1924 pb->table_idx = table->next_idx ++;
1925 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1926 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1927 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1928 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1930 /* FIXME: we still don't handle 'other' methods */
1931 if (pb->get_method) num_methods ++;
1932 if (pb->set_method) num_methods ++;
1934 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1935 table->rows += num_methods;
1936 alloc_table (table, table->rows);
1938 if (pb->get_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1942 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1945 if (pb->set_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1949 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1955 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1957 MonoDynamicTable *table;
1959 guint num_methods = 0;
1963 * we need to set things in the following tables:
1964 * EVENTMAP (info already filled in _get_type_info ())
1965 * EVENT (rows already preallocated in _get_type_info ())
1966 * METHOD (method info already done with the generic method code)
1969 table = &assembly->tables [MONO_TABLE_EVENT];
1970 eb->table_idx = table->next_idx ++;
1971 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1972 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1973 values [MONO_EVENT_FLAGS] = eb->attrs;
1974 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1977 * FIXME: we still don't handle 'other' methods
1979 if (eb->add_method) num_methods ++;
1980 if (eb->remove_method) num_methods ++;
1981 if (eb->raise_method) num_methods ++;
1983 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1984 table->rows += num_methods;
1985 alloc_table (table, table->rows);
1987 if (eb->add_method) {
1988 semaidx = table->next_idx ++;
1989 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1990 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1991 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1992 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1994 if (eb->remove_method) {
1995 semaidx = table->next_idx ++;
1996 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1997 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1998 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1999 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2001 if (eb->raise_method) {
2002 semaidx = table->next_idx ++;
2003 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2004 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2005 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2006 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2011 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2013 MonoDynamicTable *table;
2014 guint32 num_constraints, i;
2018 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2019 num_constraints = gparam->iface_constraints ?
2020 mono_array_length (gparam->iface_constraints) : 0;
2021 table->rows += num_constraints;
2022 if (gparam->base_type)
2024 alloc_table (table, table->rows);
2026 if (gparam->base_type) {
2027 table_idx = table->next_idx ++;
2028 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2030 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2031 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2032 assembly, gparam->base_type->type);
2035 for (i = 0; i < num_constraints; i++) {
2036 MonoReflectionType *constraint = mono_array_get (
2037 gparam->iface_constraints, gpointer, i);
2039 table_idx = table->next_idx ++;
2040 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2042 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2043 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2044 assembly, constraint->type);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2063 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2064 MONO_GC_REGISTER_ROOT (entry->gparam);
2066 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2068 g_ptr_array_add (assembly->gen_params, entry);
2072 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2074 MonoDynamicTable *table;
2075 MonoGenericParam *param;
2079 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2080 table_idx = table->next_idx ++;
2081 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2083 param = entry->gparam->type.type->data.generic_param;
2085 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2086 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2087 values [MONO_GENERICPARAM_NUMBER] = param->num;
2088 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2092 encode_constraints (entry->gparam, table_idx, assembly);
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2098 MonoDynamicTable *table;
2101 guint32 cols [MONO_ASSEMBLY_SIZE];
2105 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2108 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_MODULEREF_SIZE;
2114 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2116 token <<= MONO_RESOLTION_SCOPE_BITS;
2117 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2123 if (image->assembly->dynamic)
2125 memset (cols, 0, sizeof (cols));
2127 /* image->assembly->image is the manifest module */
2128 image = image->assembly->image;
2129 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2132 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133 token = table->next_idx ++;
2135 alloc_table (table, table->rows);
2136 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2146 if (strcmp ("", image->assembly->aname.culture)) {
2147 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148 image->assembly->aname.culture);
2151 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152 guchar pubtoken [9];
2154 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2155 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2159 token <<= MONO_RESOLTION_SCOPE_BITS;
2160 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2168 MonoDynamicTable *table;
2173 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2176 sigbuffer_init (&buf, 32);
2177 switch (type->type) {
2178 case MONO_TYPE_FNPTR:
2180 case MONO_TYPE_SZARRAY:
2181 case MONO_TYPE_ARRAY:
2183 case MONO_TYPE_MVAR:
2184 case MONO_TYPE_GENERICINST:
2185 encode_type (assembly, type, &buf);
2187 case MONO_TYPE_CLASS:
2188 case MONO_TYPE_VALUETYPE: {
2189 MonoClass *k = mono_class_from_mono_type (type);
2190 if (!k || !k->generic_container) {
2191 sigbuffer_free (&buf);
2194 encode_type (assembly, type, &buf);
2198 sigbuffer_free (&buf);
2202 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2203 if (assembly->save) {
2204 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2209 sigbuffer_free (&buf);
2211 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2212 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2218 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2220 MonoDynamicTable *table;
2222 guint32 token, scope, enclosing;
2225 /* if the type requires a typespec, we must try that first*/
2226 if (try_typespec && (token = create_typespec (assembly, type)))
2228 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2231 klass = my_mono_class_from_mono_type (type);
2233 klass = mono_class_from_mono_type (type);
2236 * If it's in the same module and not a generic type parameter:
2238 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2239 (type->type != MONO_TYPE_MVAR)) {
2240 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 if (klass->nested_in) {
2247 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2248 /* get the typeref idx of the enclosing type */
2249 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2252 scope = resolution_scope_from_image (assembly, klass->image);
2254 table = &assembly->tables [MONO_TABLE_TYPEREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258 values [MONO_TYPEREF_SCOPE] = scope;
2259 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2262 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2265 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270 * Despite the name, we handle also TypeSpec (with the above helper).
2273 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2275 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2279 * Insert a memberef row into the metadata: the token that point to the memberref
2280 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2281 * mono_image_get_fieldref_token()).
2282 * The sig param is an index to an already built signature.
2285 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2287 MonoDynamicTable *table;
2289 guint32 token, pclass;
2292 parent = mono_image_typedef_or_ref (assembly, type);
2293 switch (parent & MONO_TYPEDEFORREF_MASK) {
2294 case MONO_TYPEDEFORREF_TYPEREF:
2295 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2297 case MONO_TYPEDEFORREF_TYPESPEC:
2298 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2300 case MONO_TYPEDEFORREF_TYPEDEF:
2301 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2304 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2307 /* extract the index */
2308 parent >>= MONO_TYPEDEFORREF_BITS;
2310 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2312 if (assembly->save) {
2313 alloc_table (table, table->rows + 1);
2314 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2315 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2316 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2317 values [MONO_MEMBERREF_SIGNATURE] = sig;
2320 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2327 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2330 MonoMethodSignature *sig;
2332 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2337 * A methodref signature can't contain an unmanaged calling convention.
2339 sig = mono_metadata_signature_dup (mono_method_signature (method));
2340 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2341 sig->call_convention = MONO_CALL_DEFAULT;
2342 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2343 method->name, method_encode_signature (assembly, sig));
2345 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2350 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2353 ReflectionMethodBuilder rmb;
2356 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2360 name = mono_string_to_utf8 (method->name);
2361 reflection_methodbuilder_from_method_builder (&rmb, method);
2364 * A methodref signature can't contain an unmanaged calling convention.
2365 * Since some flags are encoded as part of call_conv, we need to check against it.
2367 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2368 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2369 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2370 name, method_builder_encode_signature (assembly, &rmb));
2373 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2378 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2379 const gchar *name, guint32 sig)
2381 MonoDynamicTable *table;
2385 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2387 if (assembly->save) {
2388 alloc_table (table, table->rows + 1);
2389 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2390 values [MONO_MEMBERREF_CLASS] = original;
2391 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2392 values [MONO_MEMBERREF_SIGNATURE] = sig;
2395 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2402 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2406 guint32 nparams = mono_array_length (mb->generic_params);
2409 if (!assembly->save)
2412 sigbuffer_init (&buf, 32);
2414 sigbuffer_add_value (&buf, 0xa);
2415 sigbuffer_add_value (&buf, nparams);
2417 for (i = 0; i < nparams; i++) {
2418 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2419 sigbuffer_add_value (&buf, i);
2422 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2423 sigbuffer_free (&buf);
2428 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2430 MonoDynamicTable *table;
2432 guint32 token, mtoken = 0;
2434 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2438 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2440 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2441 switch (mono_metadata_token_table (mtoken)) {
2442 case MONO_TABLE_MEMBERREF:
2443 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2445 case MONO_TABLE_METHOD:
2446 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2449 g_assert_not_reached ();
2452 if (assembly->save) {
2453 alloc_table (table, table->rows + 1);
2454 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2455 values [MONO_METHODSPEC_METHOD] = mtoken;
2456 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2459 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2462 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2467 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2471 if (mb->generic_params && create_methodspec)
2472 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2474 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2478 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2479 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2484 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2487 ReflectionMethodBuilder rmb;
2490 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2494 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2496 name = mono_string_to_utf8 (rmb.name);
2497 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2498 name, method_builder_encode_signature (assembly, &rmb));
2501 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2506 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2514 g_assert (f->field->parent);
2515 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2516 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2517 f->field->name, fieldref_encode_signature (assembly, type));
2518 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2523 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2527 MonoGenericClass *gclass;
2528 MonoDynamicGenericClass *dgclass;
2529 MonoReflectionFieldBuilder *fb = f->fb;
2532 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2535 klass = mono_class_from_mono_type (f->inst->type.type);
2536 gclass = f->inst->type.type->data.generic_class;
2537 g_assert (gclass->is_dynamic);
2538 dgclass = (MonoDynamicGenericClass *) gclass;
2540 name = mono_string_to_utf8 (fb->name);
2541 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2542 fieldref_encode_signature (assembly, fb->type->type));
2544 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2549 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2553 MonoGenericClass *gclass;
2554 MonoDynamicGenericClass *dgclass;
2555 MonoReflectionCtorBuilder *cb = c->cb;
2556 ReflectionMethodBuilder rmb;
2559 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2564 klass = mono_class_from_mono_type (c->inst->type.type);
2565 gclass = c->inst->type.type->data.generic_class;
2566 g_assert (gclass->is_dynamic);
2567 dgclass = (MonoDynamicGenericClass *) gclass;
2569 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2571 name = mono_string_to_utf8 (rmb.name);
2573 sig = method_builder_encode_signature (assembly, &rmb);
2575 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2578 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2583 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2587 MonoGenericClass *gclass;
2588 MonoReflectionMethodBuilder *mb = m->mb;
2589 ReflectionMethodBuilder rmb;
2592 if (create_methodspec && mb->generic_params)
2594 g_assert_not_reached ();
2596 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2599 klass = mono_class_from_mono_type (m->inst->type.type);
2600 gclass = m->inst->type.type->data.generic_class;
2601 g_assert (gclass->is_dynamic);
2603 reflection_methodbuilder_from_method_builder (&rmb, mb);
2605 name = mono_string_to_utf8 (rmb.name);
2607 sig = method_builder_encode_signature (assembly, &rmb);
2609 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2612 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2617 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2621 guint32 nparams = context->method_inst->type_argc;
2624 if (!assembly->save)
2627 sigbuffer_init (&buf, 32);
2629 * FIXME: vararg, explicit_this, differenc call_conv values...
2631 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2632 sigbuffer_add_value (&buf, nparams);
2634 for (i = 0; i < nparams; i++)
2635 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2637 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2638 sigbuffer_free (&buf);
2643 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2645 MonoDynamicTable *table;
2647 guint32 token, mtoken = 0, sig;
2648 MonoMethodInflated *imethod;
2649 MonoMethod *declaring;
2651 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2653 g_assert (method->is_inflated);
2654 imethod = (MonoMethodInflated *) method;
2655 declaring = imethod->declaring;
2657 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2658 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2660 if (!mono_method_signature (declaring)->generic_param_count)
2663 switch (mono_metadata_token_table (mtoken)) {
2664 case MONO_TABLE_MEMBERREF:
2665 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2667 case MONO_TABLE_METHOD:
2668 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2671 g_assert_not_reached ();
2674 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2676 if (assembly->save) {
2677 alloc_table (table, table->rows + 1);
2678 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2679 values [MONO_METHODSPEC_METHOD] = mtoken;
2680 values [MONO_METHODSPEC_SIGNATURE] = sig;
2683 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2690 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2692 MonoMethodInflated *imethod;
2695 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2699 g_assert (method->is_inflated);
2700 imethod = (MonoMethodInflated *) method;
2702 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2703 token = method_encode_methodspec (assembly, method);
2705 guint32 sig = method_encode_signature (
2706 assembly, mono_method_signature (imethod->declaring));
2707 token = mono_image_get_memberref_token (
2708 assembly, &method->klass->byval_arg, method->name, sig);
2711 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2716 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2718 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2721 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2722 token = mono_image_get_memberref_token (
2723 assembly, &m->klass->byval_arg, m->name, sig);
2729 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2731 MonoDynamicTable *table;
2739 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2740 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2741 * Because of this, we must not insert it into the `typeref' hash table.
2744 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2748 sigbuffer_init (&buf, 32);
2750 g_assert (tb->generic_params);
2751 klass = mono_class_from_mono_type (tb->type.type);
2753 if (tb->generic_container)
2754 mono_reflection_create_generic_class (tb);
2756 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2757 g_assert (klass->generic_container);
2758 sigbuffer_add_value (&buf, klass->byval_arg.type);
2759 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2761 count = mono_array_length (tb->generic_params);
2762 sigbuffer_add_value (&buf, count);
2763 for (i = 0; i < count; i++) {
2764 MonoReflectionGenericParam *gparam;
2766 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2768 encode_type (assembly, gparam->type.type, &buf);
2771 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2773 if (assembly->save) {
2774 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2775 alloc_table (table, table->rows + 1);
2776 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2777 values [MONO_TYPESPEC_SIGNATURE] = token;
2779 sigbuffer_free (&buf);
2781 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2782 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2788 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2790 MonoDynamicTable *table;
2793 guint32 token, pclass, parent, sig;
2796 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2800 klass = mono_class_from_mono_type (fb->typeb->type);
2801 name = mono_string_to_utf8 (fb->name);
2803 sig = fieldref_encode_signature (assembly, fb->type->type);
2805 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2806 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2808 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2809 parent >>= MONO_TYPEDEFORREF_BITS;
2811 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2813 if (assembly->save) {
2814 alloc_table (table, table->rows + 1);
2815 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2816 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2817 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2818 values [MONO_MEMBERREF_SIGNATURE] = sig;
2821 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2823 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2829 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2836 if (!assembly->save)
2839 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2840 g_assert (helper->type == 2);
2842 if (helper->arguments)
2843 nargs = mono_array_length (helper->arguments);
2847 size = 10 + (nargs * 10);
2849 sigbuffer_init (&buf, 32);
2851 /* Encode calling convention */
2852 /* Change Any to Standard */
2853 if ((helper->call_conv & 0x03) == 0x03)
2854 helper->call_conv = 0x01;
2855 /* explicit_this implies has_this */
2856 if (helper->call_conv & 0x40)
2857 helper->call_conv &= 0x20;
2859 if (helper->call_conv == 0) { /* Unmanaged */
2860 idx = helper->unmanaged_call_conv - 1;
2863 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2864 if (helper->call_conv & 0x02) /* varargs */
2868 sigbuffer_add_byte (&buf, idx);
2869 sigbuffer_add_value (&buf, nargs);
2870 encode_reflection_type (assembly, helper->return_type, &buf);
2871 for (i = 0; i < nargs; ++i) {
2872 MonoArray *modreqs = NULL;
2873 MonoArray *modopts = NULL;
2874 MonoReflectionType *pt;
2876 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2877 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2878 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2879 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2881 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2882 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2883 encode_reflection_type (assembly, pt, &buf);
2885 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2886 sigbuffer_free (&buf);
2892 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2895 MonoDynamicTable *table;
2898 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2899 idx = table->next_idx ++;
2901 alloc_table (table, table->rows);
2902 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2904 values [MONO_STAND_ALONE_SIGNATURE] =
2905 mono_reflection_encode_sighelper (assembly, helper);
2911 reflection_cc_to_file (int call_conv) {
2912 switch (call_conv & 0x3) {
2914 case 1: return MONO_CALL_DEFAULT;
2915 case 2: return MONO_CALL_VARARG;
2917 g_assert_not_reached ();
2924 MonoMethodSignature *sig;
2930 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2935 MonoMethodSignature *sig;
2938 name = mono_string_to_utf8 (m->name);
2939 nparams = mono_array_length (m->parameters);
2940 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2942 sig->sentinelpos = -1;
2943 sig->call_convention = reflection_cc_to_file (m->call_conv);
2944 sig->param_count = nparams;
2945 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2946 for (i = 0; i < nparams; ++i) {
2947 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2948 sig->params [i] = t->type;
2951 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2953 if (strcmp (name, am->name) == 0 &&
2954 mono_metadata_type_equal (am->parent, m->parent->type) &&
2955 mono_metadata_signature_equal (am->sig, sig)) {
2958 m->table_idx = am->token & 0xffffff;
2962 am = g_new0 (ArrayMethod, 1);
2965 am->parent = m->parent->type;
2966 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2967 method_encode_signature (assembly, sig));
2968 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2969 m->table_idx = am->token & 0xffffff;
2974 * Insert into the metadata tables all the info about the TypeBuilder tb.
2975 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2978 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2980 MonoDynamicTable *table;
2982 int i, is_object = 0, is_system = 0;
2985 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2986 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2987 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2988 n = mono_string_to_utf8 (tb->name);
2989 if (strcmp (n, "Object") == 0)
2991 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2993 n = mono_string_to_utf8 (tb->nspace);
2994 if (strcmp (n, "System") == 0)
2996 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2998 if (tb->parent && !(is_system && is_object) &&
2999 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3000 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3002 values [MONO_TYPEDEF_EXTENDS] = 0;
3004 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3005 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3008 * if we have explicitlayout or sequentiallayouts, output data in the
3009 * ClassLayout table.
3011 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3012 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3013 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3015 alloc_table (table, table->rows);
3016 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3017 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3018 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3019 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3022 /* handle interfaces */
3023 if (tb->interfaces) {
3024 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3026 table->rows += mono_array_length (tb->interfaces);
3027 alloc_table (table, table->rows);
3028 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3029 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3030 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3031 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3032 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3033 values += MONO_INTERFACEIMPL_SIZE;
3039 table = &assembly->tables [MONO_TABLE_FIELD];
3040 table->rows += tb->num_fields;
3041 alloc_table (table, table->rows);
3042 for (i = 0; i < tb->num_fields; ++i)
3043 mono_image_get_field_info (
3044 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3047 /* handle constructors */
3049 table = &assembly->tables [MONO_TABLE_METHOD];
3050 table->rows += mono_array_length (tb->ctors);
3051 alloc_table (table, table->rows);
3052 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3053 mono_image_get_ctor_info (domain,
3054 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3057 /* handle methods */
3059 table = &assembly->tables [MONO_TABLE_METHOD];
3060 table->rows += tb->num_methods;
3061 alloc_table (table, table->rows);
3062 for (i = 0; i < tb->num_methods; ++i)
3063 mono_image_get_method_info (
3064 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3067 /* Do the same with properties etc.. */
3068 if (tb->events && mono_array_length (tb->events)) {
3069 table = &assembly->tables [MONO_TABLE_EVENT];
3070 table->rows += mono_array_length (tb->events);
3071 alloc_table (table, table->rows);
3072 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3074 alloc_table (table, table->rows);
3075 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3076 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3077 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3078 for (i = 0; i < mono_array_length (tb->events); ++i)
3079 mono_image_get_event_info (
3080 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3082 if (tb->properties && mono_array_length (tb->properties)) {
3083 table = &assembly->tables [MONO_TABLE_PROPERTY];
3084 table->rows += mono_array_length (tb->properties);
3085 alloc_table (table, table->rows);
3086 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3088 alloc_table (table, table->rows);
3089 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3090 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3091 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3092 for (i = 0; i < mono_array_length (tb->properties); ++i)
3093 mono_image_get_property_info (
3094 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3097 /* handle generic parameters */
3098 if (tb->generic_params) {
3099 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3100 table->rows += mono_array_length (tb->generic_params);
3101 alloc_table (table, table->rows);
3102 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3103 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3105 mono_image_get_generic_param_info (
3106 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3110 mono_image_add_decl_security (assembly,
3111 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3114 MonoDynamicTable *ntable;
3116 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3117 ntable->rows += mono_array_length (tb->subtypes);
3118 alloc_table (ntable, ntable->rows);
3119 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3121 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3122 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3124 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3125 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3126 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3127 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3128 mono_string_to_utf8 (tb->name), tb->table_idx,
3129 ntable->next_idx, ntable->rows);*/
3130 values += MONO_NESTED_CLASS_SIZE;
3137 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3141 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3143 if (!type->subtypes)
3146 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3147 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3148 collect_types (types, subtype);
3153 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3155 if ((*type1)->table_idx < (*type2)->table_idx)
3158 if ((*type1)->table_idx > (*type2)->table_idx)
3165 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3170 for (i = 0; i < mono_array_length (pinfo); ++i) {
3171 MonoReflectionParamBuilder *pb;
3172 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3175 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3180 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3183 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3185 for (i = 0; i < tb->num_fields; ++i) {
3186 MonoReflectionFieldBuilder* fb;
3187 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3188 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3192 for (i = 0; i < mono_array_length (tb->events); ++i) {
3193 MonoReflectionEventBuilder* eb;
3194 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3195 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3198 if (tb->properties) {
3199 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3200 MonoReflectionPropertyBuilder* pb;
3201 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3202 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3206 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3207 MonoReflectionCtorBuilder* cb;
3208 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3209 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3210 params_add_cattrs (assembly, cb->pinfo);
3215 for (i = 0; i < tb->num_methods; ++i) {
3216 MonoReflectionMethodBuilder* mb;
3217 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3218 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3219 params_add_cattrs (assembly, mb->pinfo);
3224 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3225 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3230 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3234 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3236 if (moduleb->global_methods) {
3237 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3238 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3239 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3240 params_add_cattrs (assembly, mb->pinfo);
3244 if (moduleb->global_fields) {
3245 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3246 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3247 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3251 if (moduleb->types) {
3252 for (i = 0; i < moduleb->num_types; ++i)
3253 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3258 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3260 MonoDynamicTable *table;
3264 char *b = blob_size;
3267 table = &assembly->tables [MONO_TABLE_FILE];
3269 alloc_table (table, table->rows);
3270 values = table->values + table->next_idx * MONO_FILE_SIZE;
3271 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3272 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3273 if (module->image->dynamic) {
3274 /* This depends on the fact that the main module is emitted last */
3275 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3276 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3279 path = g_strdup (module->image->name);
3281 mono_sha1_get_digest_from_file (path, hash);
3284 mono_metadata_encode_value (20, b, &b);
3285 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3286 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3291 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3293 MonoDynamicTable *table;
3296 table = &assembly->tables [MONO_TABLE_MODULE];
3297 mb->table_idx = table->next_idx ++;
3298 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3299 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3302 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3303 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3304 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3305 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3309 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3310 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3312 MonoDynamicTable *table;
3316 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3317 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3320 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3322 alloc_table (table, table->rows);
3323 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3325 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3326 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3327 if (klass->nested_in)
3328 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3330 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3331 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3332 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3334 res = table->next_idx;
3338 /* Emit nested types */
3339 if (klass->nested_classes) {
3342 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3343 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3350 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3351 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3356 klass = mono_class_from_mono_type (tb->type.type);
3358 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3360 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3361 parent_index, assembly);
3365 * We need to do this ourselves since klass->nested_classes is not set up.
3368 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3369 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3374 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3375 guint32 module_index, MonoDynamicImage *assembly)
3377 MonoImage *image = module->image;
3381 t = &image->tables [MONO_TABLE_TYPEDEF];
3383 for (i = 0; i < t->rows; ++i) {
3384 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3386 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3387 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3392 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3394 MonoDynamicTable *table;
3400 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3402 if (assemblyb->type_forwarders) {
3403 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3404 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3410 klass = mono_class_from_mono_type (t->type);
3412 scope = resolution_scope_from_image (assembly, klass->image);
3413 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3414 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3417 alloc_table (table, table->rows);
3418 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3420 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3421 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3422 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3423 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3424 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3429 #define align_pointer(base,p)\
3431 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3433 (p) += 4 - (__diff & 3);\
3437 compare_constants (const void *a, const void *b)
3439 const guint32 *a_values = a;
3440 const guint32 *b_values = b;
3441 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3445 compare_semantics (const void *a, const void *b)
3447 const guint32 *a_values = a;
3448 const guint32 *b_values = b;
3449 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3452 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3456 compare_custom_attrs (const void *a, const void *b)
3458 const guint32 *a_values = a;
3459 const guint32 *b_values = b;
3461 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3465 compare_field_marshal (const void *a, const void *b)
3467 const guint32 *a_values = a;
3468 const guint32 *b_values = b;
3470 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3474 compare_nested (const void *a, const void *b)
3476 const guint32 *a_values = a;
3477 const guint32 *b_values = b;
3479 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3483 compare_genericparam (const void *a, const void *b)
3485 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3486 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3488 if ((*b_entry)->owner == (*a_entry)->owner)
3490 (*a_entry)->gparam->type.type->data.generic_param->num -
3491 (*b_entry)->gparam->type.type->data.generic_param->num;
3493 return (*a_entry)->owner - (*b_entry)->owner;
3497 compare_declsecurity_attrs (const void *a, const void *b)
3499 const guint32 *a_values = a;
3500 const guint32 *b_values = b;
3502 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3506 pad_heap (MonoDynamicStream *sh)
3508 if (sh->index & 3) {
3509 int sz = 4 - (sh->index & 3);
3510 memset (sh->data + sh->index, 0, sz);
3517 MonoDynamicStream *stream;
3521 * build_compressed_metadata() fills in the blob of data that represents the
3522 * raw metadata as it will be saved in the PE file. The five streams are output
3523 * and the metadata tables are comnpressed from the guint32 array representation,
3524 * to the compressed on-disk format.
3527 build_compressed_metadata (MonoDynamicImage *assembly)
3529 MonoDynamicTable *table;
3531 guint64 valid_mask = 0;
3532 guint64 sorted_mask;
3533 guint32 heapt_size = 0;
3534 guint32 meta_size = 256; /* allow for header and other stuff */
3535 guint32 table_offset;
3536 guint32 ntables = 0;
3542 struct StreamDesc stream_desc [5];
3544 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3545 for (i = 0; i < assembly->gen_params->len; i++){
3546 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3547 write_generic_param_entry (assembly, entry);
3550 stream_desc [0].name = "#~";
3551 stream_desc [0].stream = &assembly->tstream;
3552 stream_desc [1].name = "#Strings";
3553 stream_desc [1].stream = &assembly->sheap;
3554 stream_desc [2].name = "#US";
3555 stream_desc [2].stream = &assembly->us;
3556 stream_desc [3].name = "#Blob";
3557 stream_desc [3].stream = &assembly->blob;
3558 stream_desc [4].name = "#GUID";
3559 stream_desc [4].stream = &assembly->guid;
3561 /* tables that are sorted */
3562 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3563 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3564 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3565 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3566 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3567 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3569 /* Compute table sizes */
3570 /* the MonoImage has already been created in mono_image_basic_init() */
3571 meta = &assembly->image;
3573 /* sizes should be multiple of 4 */
3574 pad_heap (&assembly->blob);
3575 pad_heap (&assembly->guid);
3576 pad_heap (&assembly->sheap);
3577 pad_heap (&assembly->us);
3579 /* Setup the info used by compute_sizes () */
3580 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3581 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3582 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3584 meta_size += assembly->blob.index;
3585 meta_size += assembly->guid.index;
3586 meta_size += assembly->sheap.index;
3587 meta_size += assembly->us.index;
3589 for (i=0; i < MONO_TABLE_NUM; ++i)
3590 meta->tables [i].rows = assembly->tables [i].rows;
3592 for (i = 0; i < MONO_TABLE_NUM; i++){
3593 if (meta->tables [i].rows == 0)
3595 valid_mask |= (guint64)1 << i;
3597 meta->tables [i].row_size = mono_metadata_compute_size (
3598 meta, i, &meta->tables [i].size_bitfield);
3599 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3601 heapt_size += 24; /* #~ header size */
3602 heapt_size += ntables * 4;
3603 /* make multiple of 4 */
3606 meta_size += heapt_size;
3607 meta->raw_metadata = g_malloc0 (meta_size);
3608 p = (unsigned char*)meta->raw_metadata;
3609 /* the metadata signature */
3610 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3611 /* version numbers and 4 bytes reserved */
3612 int16val = (guint16*)p;
3613 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3614 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3616 /* version string */
3617 int32val = (guint32*)p;
3618 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3620 memcpy (p, meta->version, strlen (meta->version));
3621 p += GUINT32_FROM_LE (*int32val);
3622 align_pointer (meta->raw_metadata, p);
3623 int16val = (guint16*)p;
3624 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3625 *int16val = GUINT16_TO_LE (5); /* number of streams */
3629 * write the stream info.
3631 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3632 table_offset += 3; table_offset &= ~3;
3634 assembly->tstream.index = heapt_size;
3635 for (i = 0; i < 5; ++i) {
3636 int32val = (guint32*)p;
3637 stream_desc [i].stream->offset = table_offset;
3638 *int32val++ = GUINT32_TO_LE (table_offset);
3639 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3640 table_offset += GUINT32_FROM_LE (*int32val);
3641 table_offset += 3; table_offset &= ~3;
3643 strcpy ((char*)p, stream_desc [i].name);
3644 p += strlen (stream_desc [i].name) + 1;
3645 align_pointer (meta->raw_metadata, p);
3648 * now copy the data, the table stream header and contents goes first.
3650 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3651 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3652 int32val = (guint32*)p;
3653 *int32val = GUINT32_TO_LE (0); /* reserved */
3656 if (mono_get_runtime_info ()->framework_version [0] > '1') {
3657 *p++ = 2; /* version */
3660 *p++ = 1; /* version */
3664 if (meta->idx_string_wide)
3666 if (meta->idx_guid_wide)
3668 if (meta->idx_blob_wide)
3671 *p++ = 1; /* reserved */
3672 int64val = (guint64*)p;
3673 *int64val++ = GUINT64_TO_LE (valid_mask);
3674 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3676 int32val = (guint32*)p;
3677 for (i = 0; i < MONO_TABLE_NUM; i++){
3678 if (meta->tables [i].rows == 0)
3680 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3682 p = (unsigned char*)int32val;
3684 /* sort the tables that still need sorting */
3685 table = &assembly->tables [MONO_TABLE_CONSTANT];
3687 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3688 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3690 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3691 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3693 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3694 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3696 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3697 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3699 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3700 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3701 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3703 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3705 /* compress the tables */
3706 for (i = 0; i < MONO_TABLE_NUM; i++){
3709 guint32 bitfield = meta->tables [i].size_bitfield;
3710 if (!meta->tables [i].rows)
3712 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3713 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3714 meta->tables [i].base = (char*)p;
3715 for (row = 1; row <= meta->tables [i].rows; ++row) {
3716 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3717 for (col = 0; col < assembly->tables [i].columns; ++col) {
3718 switch (mono_metadata_table_size (bitfield, col)) {
3720 *p++ = values [col];
3723 *p++ = values [col] & 0xff;
3724 *p++ = (values [col] >> 8) & 0xff;
3727 *p++ = values [col] & 0xff;
3728 *p++ = (values [col] >> 8) & 0xff;
3729 *p++ = (values [col] >> 16) & 0xff;
3730 *p++ = (values [col] >> 24) & 0xff;
3733 g_assert_not_reached ();
3737 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3740 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3741 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3742 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3743 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3744 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3746 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3750 * Some tables in metadata need to be sorted according to some criteria, but
3751 * when methods and fields are first created with reflection, they may be assigned a token
3752 * that doesn't correspond to the final token they will get assigned after the sorting.
3753 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3754 * with the reflection objects that represent them. Once all the tables are set up, the
3755 * reflection objects will contains the correct table index. fixup_method() will fixup the
3756 * tokens for the method with ILGenerator @ilgen.
3759 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3761 guint32 code_idx = GPOINTER_TO_UINT (value);
3762 MonoReflectionILTokenInfo *iltoken;
3763 MonoReflectionFieldBuilder *field;
3764 MonoReflectionCtorBuilder *ctor;
3765 MonoReflectionMethodBuilder *method;
3766 MonoReflectionTypeBuilder *tb;
3767 MonoReflectionArrayMethod *am;
3769 unsigned char *target;
3771 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3772 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3773 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3774 switch (target [3]) {
3775 case MONO_TABLE_FIELD:
3776 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3777 field = (MonoReflectionFieldBuilder *)iltoken->member;
3778 idx = field->table_idx;
3779 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3780 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3781 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3783 g_assert_not_reached ();
3786 case MONO_TABLE_METHOD:
3787 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3788 method = (MonoReflectionMethodBuilder *)iltoken->member;
3789 idx = method->table_idx;
3790 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3791 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3792 idx = ctor->table_idx;
3793 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3794 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3795 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3796 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3798 g_assert_not_reached ();
3801 case MONO_TABLE_TYPEDEF:
3802 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3803 g_assert_not_reached ();
3804 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3805 idx = tb->table_idx;
3807 case MONO_TABLE_MEMBERREF:
3808 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3809 am = (MonoReflectionArrayMethod*)iltoken->member;
3810 idx = am->table_idx;
3811 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3812 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3813 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3814 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3815 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3816 g_assert (m->klass->generic_class || m->klass->generic_container);
3818 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3820 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3821 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3822 g_assert (f->generic_info);
3824 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3825 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3827 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3829 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3831 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3834 g_assert_not_reached ();
3837 case MONO_TABLE_METHODSPEC:
3838 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3839 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3840 g_assert (mono_method_signature (m)->generic_param_count);
3842 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3845 g_assert_not_reached ();
3849 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3851 target [0] = idx & 0xff;
3852 target [1] = (idx >> 8) & 0xff;
3853 target [2] = (idx >> 16) & 0xff;
3860 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3861 * value is not known when the table is emitted.
3864 fixup_cattrs (MonoDynamicImage *assembly)
3866 MonoDynamicTable *table;
3868 guint32 type, i, idx, token;
3871 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3873 for (i = 0; i < table->rows; ++i) {
3874 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3876 type = values [MONO_CUSTOM_ATTR_TYPE];
3877 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3878 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3879 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3880 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3883 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3884 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3885 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3886 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3893 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3895 MonoDynamicTable *table;
3898 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3900 alloc_table (table, table->rows);
3901 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3902 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3903 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3904 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3905 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3910 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3912 MonoDynamicTable *table;
3916 char *b = blob_size;
3918 guint32 idx, offset;
3920 if (rsrc->filename) {
3921 name = mono_string_to_utf8 (rsrc->filename);
3922 sname = g_path_get_basename (name);
3924 table = &assembly->tables [MONO_TABLE_FILE];
3926 alloc_table (table, table->rows);
3927 values = table->values + table->next_idx * MONO_FILE_SIZE;
3928 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3929 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3932 mono_sha1_get_digest_from_file (name, hash);
3933 mono_metadata_encode_value (20, b, &b);
3934 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3935 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3937 idx = table->next_idx++;
3939 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3945 data = mono_array_addr (rsrc->data, char, 0);
3946 len = mono_array_length (rsrc->data);
3952 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3953 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3954 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3955 mono_image_add_stream_data (&assembly->resources, data, len);
3959 * The entry should be emitted into the MANIFESTRESOURCE table of
3960 * the main module, but that needs to reference the FILE table
3961 * which isn't emitted yet.
3968 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3972 set_version_from_string (MonoString *version, guint32 *values)
3974 gchar *ver, *p, *str;
3977 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3978 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3979 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3980 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3983 ver = str = mono_string_to_utf8 (version);
3984 for (i = 0; i < 4; ++i) {
3985 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3991 /* handle Revision and Build */
4001 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4005 char *b = blob_size;
4010 len = mono_array_length (pkey);
4011 mono_metadata_encode_value (len, b, &b);
4012 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4013 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4015 assembly->public_key = g_malloc (len);
4016 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4017 assembly->public_key_len = len;
4019 /* Special case: check for ECMA key (16 bytes) */
4020 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4021 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4022 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4023 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4024 /* minimum key size (in 2.0) is 384 bits */
4025 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4027 /* FIXME - verifier */
4028 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4029 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4031 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4037 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4039 MonoDynamicTable *table;
4040 MonoDynamicImage *assembly;
4041 MonoReflectionAssemblyBuilder *assemblyb;
4045 guint32 module_index;
4047 assemblyb = moduleb->assemblyb;
4048 assembly = moduleb->dynamic_image;
4049 domain = mono_object_domain (assemblyb);
4051 /* Emit ASSEMBLY table */
4052 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4053 alloc_table (table, 1);
4054 values = table->values + MONO_ASSEMBLY_SIZE;
4055 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4056 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4057 if (assemblyb->culture) {
4058 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4060 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4062 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4063 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4064 set_version_from_string (assemblyb->version, values);
4066 /* Emit FILE + EXPORTED_TYPE table */
4068 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4070 MonoReflectionModuleBuilder *file_module =
4071 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4072 if (file_module != moduleb) {
4073 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4075 if (file_module->types) {
4076 for (j = 0; j < file_module->num_types; ++j) {
4077 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4078 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4083 if (assemblyb->loaded_modules) {
4084 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4085 MonoReflectionModule *file_module =
4086 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4087 mono_image_fill_file_table (domain, file_module, assembly);
4089 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4092 if (assemblyb->type_forwarders)
4093 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4095 /* Emit MANIFESTRESOURCE table */
4097 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4099 MonoReflectionModuleBuilder *file_module =
4100 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4101 /* The table for the main module is emitted later */
4102 if (file_module != moduleb) {
4104 if (file_module->resources) {
4105 int len = mono_array_length (file_module->resources);
4106 for (j = 0; j < len; ++j) {
4107 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4108 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4116 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4117 * for the modulebuilder @moduleb.
4118 * At the end of the process, method and field tokens are fixed up and the
4119 * on-disk compressed metadata representation is created.
4122 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4124 MonoDynamicTable *table;
4125 MonoDynamicImage *assembly;
4126 MonoReflectionAssemblyBuilder *assemblyb;
4132 assemblyb = moduleb->assemblyb;
4133 assembly = moduleb->dynamic_image;
4134 domain = mono_object_domain (assemblyb);
4136 if (assembly->text_rva)
4139 assembly->text_rva = START_TEXT_RVA;
4141 if (moduleb->is_main) {
4142 mono_image_emit_manifest (moduleb);
4145 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4146 table->rows = 1; /* .<Module> */
4148 alloc_table (table, table->rows);
4150 * Set the first entry.
4152 values = table->values + table->columns;
4153 values [MONO_TYPEDEF_FLAGS] = 0;
4154 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4155 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4156 values [MONO_TYPEDEF_EXTENDS] = 0;
4157 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4158 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4161 * handle global methods
4162 * FIXME: test what to do when global methods are defined in multiple modules.
4164 if (moduleb->global_methods) {
4165 table = &assembly->tables [MONO_TABLE_METHOD];
4166 table->rows += mono_array_length (moduleb->global_methods);
4167 alloc_table (table, table->rows);
4168 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4169 mono_image_get_method_info (
4170 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4172 if (moduleb->global_fields) {
4173 table = &assembly->tables [MONO_TABLE_FIELD];
4174 table->rows += mono_array_length (moduleb->global_fields);
4175 alloc_table (table, table->rows);
4176 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4177 mono_image_get_field_info (
4178 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4181 table = &assembly->tables [MONO_TABLE_MODULE];
4182 alloc_table (table, 1);
4183 mono_image_fill_module_table (domain, moduleb, assembly);
4185 /* Collect all types into a list sorted by their table_idx */
4186 types = g_ptr_array_new ();
4189 for (i = 0; i < moduleb->num_types; ++i) {
4190 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4191 collect_types (types, type);
4194 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4195 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4196 table->rows += types->len;
4197 alloc_table (table, table->rows);
4200 * Emit type names + namespaces at one place inside the string heap,
4201 * so load_class_names () needs to touch fewer pages.
4203 for (i = 0; i < types->len; ++i) {
4204 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4205 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4207 for (i = 0; i < types->len; ++i) {
4208 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4209 string_heap_insert_mstring (&assembly->sheap, tb->name);
4212 for (i = 0; i < types->len; ++i) {
4213 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4214 mono_image_get_type_info (domain, type, assembly);
4218 * table->rows is already set above and in mono_image_fill_module_table.
4220 /* add all the custom attributes at the end, once all the indexes are stable */
4221 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4223 /* CAS assembly permissions */
4224 if (assemblyb->permissions_minimum)
4225 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4226 if (assemblyb->permissions_optional)
4227 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4228 if (assemblyb->permissions_refused)
4229 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4231 module_add_cattrs (assembly, moduleb);
4234 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4236 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4237 * the final tokens and don't need another fixup pass. */
4239 if (moduleb->global_methods) {
4240 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4241 MonoReflectionMethodBuilder *mb = mono_array_get (
4242 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4243 mono_image_add_methodimpl (assembly, mb);
4247 for (i = 0; i < types->len; ++i) {
4248 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4249 if (type->methods) {
4250 for (j = 0; j < type->num_methods; ++j) {
4251 MonoReflectionMethodBuilder *mb = mono_array_get (
4252 type->methods, MonoReflectionMethodBuilder*, j);
4254 mono_image_add_methodimpl (assembly, mb);
4259 g_ptr_array_free (types, TRUE);
4261 fixup_cattrs (assembly);
4265 * mono_image_insert_string:
4266 * @module: module builder object
4269 * Insert @str into the user string stream of @module.
4272 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4274 MonoDynamicImage *assembly;
4279 MONO_ARCH_SAVE_REGS;
4281 if (!module->dynamic_image)
4282 mono_image_module_basic_init (module);
4284 assembly = module->dynamic_image;
4286 if (assembly->save) {
4287 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4288 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4289 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4291 char *swapped = g_malloc (2 * mono_string_length (str));
4292 const char *p = (const char*)mono_string_chars (str);
4294 swap_with_size (swapped, p, 2, mono_string_length (str));
4295 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4299 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4301 mono_image_add_stream_data (&assembly->us, "", 1);
4303 idx = assembly->us.index ++;
4306 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4308 return MONO_TOKEN_STRING | idx;
4312 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4317 klass = obj->vtable->klass;
4318 if (strcmp (klass->name, "MonoMethod") == 0) {
4319 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4320 MonoMethodSignature *sig, *old;
4321 guint32 sig_token, parent;
4324 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4326 nargs = mono_array_length (opt_param_types);
4327 old = mono_method_signature (method);
4328 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4330 sig->hasthis = old->hasthis;
4331 sig->explicit_this = old->explicit_this;
4332 sig->call_convention = old->call_convention;
4333 sig->generic_param_count = old->generic_param_count;
4334 sig->param_count = old->param_count + nargs;
4335 sig->sentinelpos = old->param_count;
4336 sig->ret = old->ret;
4338 for (i = 0; i < old->param_count; i++)
4339 sig->params [i] = old->params [i];
4341 for (i = 0; i < nargs; i++) {
4342 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4343 sig->params [old->param_count + i] = rt->type;
4346 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4347 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4348 parent >>= MONO_TYPEDEFORREF_BITS;
4350 parent <<= MONO_MEMBERREF_PARENT_BITS;
4351 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4353 sig_token = method_encode_signature (assembly, sig);
4354 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4355 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4356 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4357 ReflectionMethodBuilder rmb;
4358 guint32 parent, sig;
4361 reflection_methodbuilder_from_method_builder (&rmb, mb);
4362 rmb.opt_types = opt_param_types;
4364 sig = method_builder_encode_signature (assembly, &rmb);
4366 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4367 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4369 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4370 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4372 name = mono_string_to_utf8 (rmb.name);
4373 token = mono_image_get_varargs_method_token (
4374 assembly, parent, name, sig);
4377 g_error ("requested method token for %s\n", klass->name);
4384 * mono_image_create_token:
4385 * @assembly: a dynamic assembly
4387 * @register_token: Whenever to register the token in the assembly->tokens hash.
4389 * Get a token to insert in the IL code stream for the given MemberInfo.
4390 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4391 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4395 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4396 gboolean create_methodspec, gboolean register_token)
4401 klass = obj->vtable->klass;
4402 if (strcmp (klass->name, "MethodBuilder") == 0) {
4403 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4404 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4406 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4407 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4409 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4410 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4411 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4412 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4415 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4416 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4418 token = mono_image_get_ctorbuilder_token (assembly, mb);
4419 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4420 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4421 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4422 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4423 if (tb->generic_params) {
4424 token = mono_image_get_generic_field_token (assembly, fb);
4426 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4428 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4429 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4430 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4431 } else if (strcmp (klass->name, "MonoType") == 0) {
4432 MonoReflectionType *tb = (MonoReflectionType *)obj;
4433 MonoClass *mc = mono_class_from_mono_type (tb->type);
4434 token = mono_metadata_token_from_dor (
4435 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4436 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4437 MonoReflectionType *tb = (MonoReflectionType *)obj;
4438 token = mono_metadata_token_from_dor (
4439 mono_image_typedef_or_ref (assembly, tb->type));
4440 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4441 MonoReflectionType *tb = (MonoReflectionType *)obj;
4442 token = mono_metadata_token_from_dor (
4443 mono_image_typedef_or_ref (assembly, tb->type));
4444 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4445 strcmp (klass->name, "MonoMethod") == 0 ||
4446 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4447 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4448 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4449 if (m->method->is_inflated) {
4450 if (create_methodspec)
4451 token = mono_image_get_methodspec_token (assembly, m->method);
4453 token = mono_image_get_inflated_method_token (assembly, m->method);
4454 } else if ((m->method->klass->image == &assembly->image) &&
4455 !m->method->klass->generic_class) {
4456 static guint32 method_table_idx = 0xffffff;
4457 if (m->method->klass->wastypebuilder) {
4458 /* we use the same token as the one that was assigned
4459 * to the Methodbuilder.
4460 * FIXME: do the equivalent for Fields.
4462 token = m->method->token;
4465 * Each token should have a unique index, but the indexes are
4466 * assigned by managed code, so we don't know about them. An
4467 * easy solution is to count backwards...
4469 method_table_idx --;
4470 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4473 token = mono_image_get_methodref_token (assembly, m->method);
4475 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4476 } else if (strcmp (klass->name, "MonoField") == 0) {
4477 MonoReflectionField *f = (MonoReflectionField *)obj;
4478 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4479 static guint32 field_table_idx = 0xffffff;
4481 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4483 token = mono_image_get_fieldref_token (assembly, f);
4485 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4486 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4487 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4488 token = mono_image_get_array_token (assembly, m);
4489 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4490 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4491 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4492 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4493 MonoReflectionType *tb = (MonoReflectionType *)obj;
4494 token = mono_metadata_token_from_dor (
4495 mono_image_typedef_or_ref (assembly, tb->type));
4496 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4497 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4498 token = mono_image_get_field_on_inst_token (assembly, f);
4499 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4500 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4501 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4502 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4503 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4504 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4506 g_error ("requested token for %s\n", klass->name);
4510 mono_image_register_token (assembly, token, obj);
4516 * mono_image_register_token:
4518 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4519 * the Module.ResolveXXXToken () methods to work.
4522 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4524 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4526 /* There could be multiple MethodInfo objects with the same token */
4527 //g_assert (prev == obj);
4529 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4534 guint32 import_lookup_table;
4538 guint32 import_address_table_rva;
4546 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4548 static MonoDynamicImage*
4549 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4551 static const guchar entrycode [16] = {0xff, 0x25, 0};
4552 MonoDynamicImage *image;
4555 const char *version = mono_get_runtime_info ()->runtime_version;
4558 image = GC_MALLOC (sizeof (MonoDynamicImage));
4560 image = g_new0 (MonoDynamicImage, 1);
4563 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4565 /*g_print ("created image %p\n", image);*/
4566 /* keep in sync with image.c */
4567 image->image.name = assembly_name;
4568 image->image.assembly_name = image->image.name; /* they may be different */
4569 image->image.module_name = module_name;
4570 image->image.version = g_strdup (version);
4571 image->image.md_version_major = 1;
4572 image->image.md_version_minor = 1;
4573 image->image.dynamic = TRUE;
4575 image->image.references = g_new0 (MonoAssembly*, 1);
4576 image->image.references [0] = NULL;
4578 mono_image_init (&image->image);
4580 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4581 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4582 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4583 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4584 image->handleref = g_hash_table_new (NULL, NULL);
4585 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4586 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4587 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4588 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4589 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4590 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4591 image->gen_params = g_ptr_array_new ();
4593 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4594 string_heap_init (&image->sheap);
4595 mono_image_add_stream_data (&image->us, "", 1);
4596 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4597 /* import tables... */
4598 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4599 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4600 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4601 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4602 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4603 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4604 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4605 stream_data_align (&image->code);
4607 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4609 for (i=0; i < MONO_TABLE_NUM; ++i) {
4610 image->tables [i].next_idx = 1;
4611 image->tables [i].columns = table_sizes [i];
4614 image->image.assembly = (MonoAssembly*)assembly;
4615 image->run = assembly->run;
4616 image->save = assembly->save;
4617 image->pe_kind = 0x1; /* ILOnly */
4618 image->machine = 0x14c; /* I386 */
4620 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4626 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4632 mono_dynamic_image_free (MonoDynamicImage *image)
4634 MonoDynamicImage *di = image;
4639 mono_g_hash_table_destroy (di->methodspec);
4641 g_hash_table_destroy (di->typespec);
4643 g_hash_table_destroy (di->typeref);
4645 g_hash_table_destroy (di->handleref);
4647 mono_g_hash_table_destroy (di->tokens);
4648 if (di->generic_def_objects)
4649 mono_g_hash_table_destroy (di->generic_def_objects);
4650 if (di->blob_cache) {
4651 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4652 g_hash_table_destroy (di->blob_cache);
4654 for (list = di->array_methods; list; list = list->next) {
4655 ArrayMethod *am = (ArrayMethod *)list->data;
4660 g_list_free (di->array_methods);
4661 if (di->gen_params) {
4662 for (i = 0; i < di->gen_params->len; i++) {
4663 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4664 if (entry->gparam->type.type) {
4665 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4666 g_free ((char*)param->name);
4668 g_free (entry->gparam->type.type);
4672 g_ptr_array_free (di->gen_params, TRUE);
4674 if (di->token_fixups)
4675 mono_g_hash_table_destroy (di->token_fixups);
4676 if (di->method_to_table_idx)
4677 g_hash_table_destroy (di->method_to_table_idx);
4678 if (di->field_to_table_idx)
4679 g_hash_table_destroy (di->field_to_table_idx);
4680 if (di->method_aux_hash)
4681 g_hash_table_destroy (di->method_aux_hash);
4682 g_free (di->strong_name);
4683 g_free (di->win32_res);
4685 g_free (di->public_key);
4687 /*g_print ("string heap destroy for image %p\n", di);*/
4688 mono_dynamic_stream_reset (&di->sheap);
4689 mono_dynamic_stream_reset (&di->code);
4690 mono_dynamic_stream_reset (&di->resources);
4691 mono_dynamic_stream_reset (&di->us);
4692 mono_dynamic_stream_reset (&di->blob);
4693 mono_dynamic_stream_reset (&di->tstream);
4694 mono_dynamic_stream_reset (&di->guid);
4695 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4696 g_free (di->tables [i].values);
4701 * mono_image_basic_init:
4702 * @assembly: an assembly builder object
4704 * Create the MonoImage that represents the assembly builder and setup some
4705 * of the helper hash table and the basic metadata streams.
4708 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4710 MonoDynamicAssembly *assembly;
4711 MonoDynamicImage *image;
4712 MonoDomain *domain = mono_object_domain (assemblyb);
4714 MONO_ARCH_SAVE_REGS;
4716 if (assemblyb->dynamic_assembly)
4720 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4722 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4725 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4727 assembly->assembly.ref_count = 1;
4728 assembly->assembly.dynamic = TRUE;
4729 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4730 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4731 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4732 if (assemblyb->culture)
4733 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4735 assembly->assembly.aname.culture = g_strdup ("");
4737 if (assemblyb->version) {
4738 char *vstr = mono_string_to_utf8 (assemblyb->version);
4739 char **version = g_strsplit (vstr, ".", 4);
4740 char **parts = version;
4741 assembly->assembly.aname.major = atoi (*parts++);
4742 assembly->assembly.aname.minor = atoi (*parts++);
4743 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4744 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4746 g_strfreev (version);
4749 assembly->assembly.aname.major = 0;
4750 assembly->assembly.aname.minor = 0;
4751 assembly->assembly.aname.build = 0;
4752 assembly->assembly.aname.revision = 0;
4755 assembly->run = assemblyb->access != 2;
4756 assembly->save = assemblyb->access != 1;
4758 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4759 image->initial_image = TRUE;
4760 assembly->assembly.aname.name = image->image.name;
4761 assembly->assembly.image = &image->image;
4763 mono_domain_assemblies_lock (domain);
4764 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4765 mono_domain_assemblies_unlock (domain);
4767 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4769 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4771 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4775 calc_section_size (MonoDynamicImage *assembly)
4779 /* alignment constraints */
4780 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4781 g_assert ((assembly->code.index % 4) == 0);
4782 assembly->meta_size += 3;
4783 assembly->meta_size &= ~3;
4784 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4785 g_assert ((assembly->resources.index % 4) == 0);
4787 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4788 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4791 if (assembly->win32_res) {
4792 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4794 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4795 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4799 assembly->sections [MONO_SECTION_RELOC].size = 12;
4800 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4810 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4814 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4816 ResTreeNode *t1 = (ResTreeNode*)a;
4817 ResTreeNode *t2 = (ResTreeNode*)b;
4819 return t1->id - t2->id;
4823 * resource_tree_create:
4825 * Organize the resources into a resource tree.
4827 static ResTreeNode *
4828 resource_tree_create (MonoArray *win32_resources)
4830 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4834 tree = g_new0 (ResTreeNode, 1);
4836 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4837 MonoReflectionWin32Resource *win32_res =
4838 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4842 /* FIXME: BUG: this stores managed references in unmanaged memory */
4843 lang_node = g_new0 (ResTreeNode, 1);
4844 lang_node->id = win32_res->lang_id;
4845 lang_node->win32_res = win32_res;
4847 /* Create type node if neccesary */
4849 for (l = tree->children; l; l = l->next)
4850 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4851 type_node = (ResTreeNode*)l->data;
4856 type_node = g_new0 (ResTreeNode, 1);
4857 type_node->id = win32_res->res_type;
4860 * The resource types have to be sorted otherwise
4861 * Windows Explorer can't display the version information.
4863 tree->children = g_slist_insert_sorted (tree->children,
4864 type_node, resource_tree_compare_by_id);
4867 /* Create res node if neccesary */
4869 for (l = type_node->children; l; l = l->next)
4870 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4871 res_node = (ResTreeNode*)l->data;
4876 res_node = g_new0 (ResTreeNode, 1);
4877 res_node->id = win32_res->res_id;
4878 type_node->children = g_slist_append (type_node->children, res_node);
4881 res_node->children = g_slist_append (res_node->children, lang_node);
4888 * resource_tree_encode:
4890 * Encode the resource tree into the format used in the PE file.
4893 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4896 MonoPEResourceDir dir;
4897 MonoPEResourceDirEntry dir_entry;
4898 MonoPEResourceDataEntry data_entry;
4902 * For the format of the resource directory, see the article
4903 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4907 memset (&dir, 0, sizeof (dir));
4908 memset (&dir_entry, 0, sizeof (dir_entry));
4909 memset (&data_entry, 0, sizeof (data_entry));
4911 g_assert (sizeof (dir) == 16);
4912 g_assert (sizeof (dir_entry) == 8);
4913 g_assert (sizeof (data_entry) == 16);
4915 node->offset = p - begin;
4917 /* IMAGE_RESOURCE_DIRECTORY */
4918 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4920 memcpy (p, &dir, sizeof (dir));
4923 /* Reserve space for entries */
4925 p += sizeof (dir_entry) * dir.res_id_entries;
4927 /* Write children */
4928 for (l = node->children; l; l = l->next) {
4929 ResTreeNode *child = (ResTreeNode*)l->data;
4931 if (child->win32_res) {
4933 child->offset = p - begin;
4935 /* IMAGE_RESOURCE_DATA_ENTRY */
4936 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4937 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4939 memcpy (p, &data_entry, sizeof (data_entry));
4940 p += sizeof (data_entry);
4942 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4943 p += data_entry.rde_size;
4945 resource_tree_encode (child, begin, p, &p);
4949 /* IMAGE_RESOURCE_ENTRY */
4950 for (l = node->children; l; l = l->next) {
4951 ResTreeNode *child = (ResTreeNode*)l->data;
4952 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4954 dir_entry.is_dir = child->win32_res ? 0 : 1;
4955 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4957 memcpy (entries, &dir_entry, sizeof (dir_entry));
4958 entries += sizeof (dir_entry);
4965 resource_tree_free (ResTreeNode * node)
4968 for (list = node->children; list; list = list->next)
4969 resource_tree_free ((ResTreeNode*)list->data);
4970 g_slist_free(node->children);
4975 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4980 MonoReflectionWin32Resource *win32_res;
4983 if (!assemblyb->win32_resources)
4987 * Resources are stored in a three level tree inside the PE file.
4988 * - level one contains a node for each type of resource
4989 * - level two contains a node for each resource
4990 * - level three contains a node for each instance of a resource for a
4991 * specific language.
4994 tree = resource_tree_create (assemblyb->win32_resources);
4996 /* Estimate the size of the encoded tree */
4998 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4999 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5000 size += mono_array_length (win32_res->res_data);
5002 /* Directory structure */
5003 size += mono_array_length (assemblyb->win32_resources) * 256;
5004 p = buf = g_malloc (size);
5006 resource_tree_encode (tree, p, p, &p);
5008 g_assert (p - buf <= size);
5010 assembly->win32_res = g_malloc (p - buf);
5011 assembly->win32_res_size = p - buf;
5012 memcpy (assembly->win32_res, buf, p - buf);
5015 resource_tree_free (tree);
5019 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5021 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5024 p += sizeof (MonoPEResourceDir);
5025 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
5026 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5027 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
5028 if (dir_entry->is_dir) {
5029 fixup_resource_directory (res_section, child, rva);
5031 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5032 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5035 p += sizeof (MonoPEResourceDirEntry);
5040 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5043 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5044 g_error ("WriteFile returned %d\n", GetLastError ());
5048 * mono_image_create_pefile:
5049 * @mb: a module builder object
5051 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5052 * assembly->pefile where it can be easily retrieved later in chunks.
5055 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
5056 MonoMSDOSHeader *msdos;
5057 MonoDotNetHeader *header;
5058 MonoSectionTable *section;
5059 MonoCLIHeader *cli_header;
5060 guint32 size, image_size, virtual_base, text_offset;
5061 guint32 header_start, section_start, file_offset, virtual_offset;
5062 MonoDynamicImage *assembly;
5063 MonoReflectionAssemblyBuilder *assemblyb;
5064 MonoDynamicStream pefile_stream = {0};
5065 MonoDynamicStream *pefile = &pefile_stream;
5067 guint32 *rva, value;
5069 static const unsigned char msheader[] = {
5070 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5071 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5072 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5073 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5074 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5075 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5076 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5077 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5080 assemblyb = mb->assemblyb;
5082 mono_image_basic_init (assemblyb);
5083 assembly = mb->dynamic_image;
5085 assembly->pe_kind = assemblyb->pe_kind;
5086 assembly->machine = assemblyb->machine;
5087 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5088 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5090 mono_image_build_metadata (mb);
5092 if (mb->is_main && assemblyb->resources) {
5093 int len = mono_array_length (assemblyb->resources);
5094 for (i = 0; i < len; ++i)
5095 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5098 if (mb->resources) {
5099 int len = mono_array_length (mb->resources);
5100 for (i = 0; i < len; ++i)
5101 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5104 build_compressed_metadata (assembly);
5107 assembly_add_win32_resources (assembly, assemblyb);
5109 nsections = calc_section_size (assembly);
5111 /* The DOS header and stub */
5112 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5113 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5115 /* the dotnet header */
5116 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5118 /* the section tables */
5119 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5121 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5122 virtual_offset = VIRT_ALIGN;
5125 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5126 if (!assembly->sections [i].size)
5129 file_offset += FILE_ALIGN - 1;
5130 file_offset &= ~(FILE_ALIGN - 1);
5131 virtual_offset += VIRT_ALIGN - 1;
5132 virtual_offset &= ~(VIRT_ALIGN - 1);
5134 assembly->sections [i].offset = file_offset;
5135 assembly->sections [i].rva = virtual_offset;
5137 file_offset += assembly->sections [i].size;
5138 virtual_offset += assembly->sections [i].size;
5139 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5142 file_offset += FILE_ALIGN - 1;
5143 file_offset &= ~(FILE_ALIGN - 1);
5145 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5147 /* back-patch info */
5148 msdos = (MonoMSDOSHeader*)pefile->data;
5149 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5151 header = (MonoDotNetHeader*)(pefile->data + header_start);
5152 header->pesig [0] = 'P';
5153 header->pesig [1] = 'E';
5155 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5156 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5157 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5158 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5159 if (assemblyb->pekind == 1) {
5161 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5164 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5167 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5169 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5170 header->pe.pe_major = 6;
5171 header->pe.pe_minor = 0;
5172 size = assembly->sections [MONO_SECTION_TEXT].size;
5173 size += FILE_ALIGN - 1;
5174 size &= ~(FILE_ALIGN - 1);
5175 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5176 size = assembly->sections [MONO_SECTION_RSRC].size;
5177 size += FILE_ALIGN - 1;
5178 size &= ~(FILE_ALIGN - 1);
5179 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5180 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5181 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5182 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5183 /* pe_rva_entry_point always at the beginning of the text section */
5184 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5186 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5187 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5188 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5189 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5190 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5191 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5192 size = section_start;
5193 size += FILE_ALIGN - 1;
5194 size &= ~(FILE_ALIGN - 1);
5195 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5197 size += VIRT_ALIGN - 1;
5198 size &= ~(VIRT_ALIGN - 1);
5199 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5202 // Translate the PEFileKind value to the value expected by the Windows loader
5208 // PEFileKinds.Dll == 1
5209 // PEFileKinds.ConsoleApplication == 2
5210 // PEFileKinds.WindowApplication == 3
5213 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5214 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5216 if (assemblyb->pekind == 3)
5221 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5223 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5224 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5225 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5226 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5227 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5228 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5230 /* fill data directory entries */
5232 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5233 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5235 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5236 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5238 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5239 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5240 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5241 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5242 /* patch entrypoint name */
5243 if (assemblyb->pekind == 1)
5244 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5246 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5247 /* patch imported function RVA name */
5248 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5249 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5251 /* the import table */
5252 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5253 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5254 /* patch imported dll RVA name and other entries in the dir */
5255 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5256 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5257 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5258 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5259 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5260 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5262 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5263 value = (assembly->text_rva + assembly->imp_names_offset);
5264 *p++ = (value) & 0xff;
5265 *p++ = (value >> 8) & (0xff);
5266 *p++ = (value >> 16) & (0xff);
5267 *p++ = (value >> 24) & (0xff);
5269 /* the CLI header info */
5270 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5271 cli_header->ch_size = GUINT32_FROM_LE (72);
5272 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5273 if (mono_get_runtime_info ()->framework_version [0] > '1')
5274 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5276 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5277 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5278 if (assemblyb->entry_point) {
5279 guint32 table_idx = 0;
5280 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5281 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5282 table_idx = methodb->table_idx;
5284 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5286 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5288 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5290 /* The embedded managed resources */
5291 text_offset = assembly->text_rva + assembly->code.index;
5292 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5293 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5294 text_offset += assembly->resources.index;
5295 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5296 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5297 text_offset += assembly->meta_size;
5298 if (assembly->strong_name_size) {
5299 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5300 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5301 text_offset += assembly->strong_name_size;
5304 /* write the section tables and section content */
5305 section = (MonoSectionTable*)(pefile->data + section_start);
5306 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5307 static const char section_names [][7] = {
5308 ".text", ".rsrc", ".reloc"
5310 if (!assembly->sections [i].size)
5312 strcpy (section->st_name, section_names [i]);
5313 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5314 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5315 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5316 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5317 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5318 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5319 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5323 checked_write_file (file, pefile->data, pefile->index);
5325 mono_dynamic_stream_reset (pefile);
5327 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5328 if (!assembly->sections [i].size)
5331 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5332 g_error ("SetFilePointer returned %d\n", GetLastError ());
5335 case MONO_SECTION_TEXT:
5336 /* patch entry point */
5337 p = (guchar*)(assembly->code.data + 2);
5338 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5339 *p++ = (value) & 0xff;
5340 *p++ = (value >> 8) & 0xff;
5341 *p++ = (value >> 16) & 0xff;
5342 *p++ = (value >> 24) & 0xff;
5344 checked_write_file (file, assembly->code.data, assembly->code.index);
5345 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5346 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5347 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5350 g_free (assembly->image.raw_metadata);
5352 case MONO_SECTION_RELOC: {
5356 guint16 type_and_offset;
5360 g_assert (sizeof (reloc) == 12);
5362 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5363 reloc.block_size = GUINT32_FROM_LE (12);
5366 * the entrypoint is always at the start of the text section
5367 * 3 is IMAGE_REL_BASED_HIGHLOW
5368 * 2 is patch_size_rva - text_rva
5370 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5373 checked_write_file (file, &reloc, sizeof (reloc));
5377 case MONO_SECTION_RSRC:
5378 if (assembly->win32_res) {
5380 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5381 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5382 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5386 g_assert_not_reached ();
5390 /* check that the file is properly padded */
5391 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5392 g_error ("SetFilePointer returned %d\n", GetLastError ());
5393 if (! SetEndOfFile (file))
5394 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5396 mono_dynamic_stream_reset (&assembly->code);
5397 mono_dynamic_stream_reset (&assembly->us);
5398 mono_dynamic_stream_reset (&assembly->blob);
5399 mono_dynamic_stream_reset (&assembly->guid);
5400 mono_dynamic_stream_reset (&assembly->sheap);
5402 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5403 g_hash_table_destroy (assembly->blob_cache);
5404 assembly->blob_cache = NULL;
5407 MonoReflectionModule *
5408 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5412 MonoImageOpenStatus status;
5413 MonoDynamicAssembly *assembly;
5414 guint32 module_count;
5415 MonoImage **new_modules;
5416 gboolean *new_modules_loaded;
5418 name = mono_string_to_utf8 (fileName);
5420 image = mono_image_open (name, &status);
5423 if (status == MONO_IMAGE_ERROR_ERRNO)
5424 exc = mono_get_exception_file_not_found (fileName);
5426 exc = mono_get_exception_bad_image_format (name);
5428 mono_raise_exception (exc);
5433 assembly = ab->dynamic_assembly;
5434 image->assembly = (MonoAssembly*)assembly;
5436 module_count = image->assembly->image->module_count;
5437 new_modules = g_new0 (MonoImage *, module_count + 1);
5438 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5440 if (image->assembly->image->modules)
5441 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5442 if (image->assembly->image->modules_loaded)
5443 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5444 new_modules [module_count] = image;
5445 new_modules_loaded [module_count] = TRUE;
5446 mono_image_addref (image);
5448 g_free (image->assembly->image->modules);
5449 image->assembly->image->modules = new_modules;
5450 image->assembly->image->modules_loaded = new_modules_loaded;
5451 image->assembly->image->module_count ++;
5453 mono_assembly_load_references (image, &status);
5455 mono_image_close (image);
5456 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5459 return mono_module_get_object (mono_domain_get (), image);
5463 * We need to return always the same object for MethodInfo, FieldInfo etc..
5464 * but we need to consider the reflected type.
5465 * type uses a different hash, since it uses custom hash/equal functions.
5470 MonoClass *refclass;
5474 reflected_equal (gconstpointer a, gconstpointer b) {
5475 const ReflectedEntry *ea = a;
5476 const ReflectedEntry *eb = b;
5478 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5482 reflected_hash (gconstpointer a) {
5483 const ReflectedEntry *ea = a;
5484 return mono_aligned_addr_hash (ea->item);
5487 #define CHECK_OBJECT(t,p,k) \
5493 mono_domain_lock (domain); \
5494 if (!domain->refobject_hash) \
5495 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5496 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5497 mono_domain_unlock (domain); \
5500 mono_domain_unlock (domain); \
5503 #ifndef HAVE_NULL_GC
5504 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5506 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5509 #define CACHE_OBJECT(t,p,o,k) \
5512 ReflectedEntry pe; \
5514 pe.refclass = (k); \
5515 mono_domain_lock (domain); \
5516 if (!domain->refobject_hash) \
5517 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5518 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5520 ReflectedEntry *e = ALLOC_REFENTRY; \
5522 e->refclass = (k); \
5523 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5526 mono_domain_unlock (domain); \
5531 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5533 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5537 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5539 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5543 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5545 MonoDynamicImage *image = moduleb->dynamic_image;
5546 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5549 MonoImage **new_modules;
5552 * FIXME: we already created an image in mono_image_basic_init (), but
5553 * we don't know which module it belongs to, since that is only
5554 * determined at assembly save time.
5556 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5557 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5559 moduleb->module.image = &image->image;
5560 moduleb->dynamic_image = image;
5561 register_module (mono_object_domain (moduleb), moduleb, image);
5563 /* register the module with the assembly */
5564 ass = ab->dynamic_assembly->assembly.image;
5565 module_count = ass->module_count;
5566 new_modules = g_new0 (MonoImage *, module_count + 1);
5569 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5570 new_modules [module_count] = &image->image;
5571 mono_image_addref (&image->image);
5573 g_free (ass->modules);
5574 ass->modules = new_modules;
5575 ass->module_count ++;
5580 * mono_assembly_get_object:
5581 * @domain: an app domain
5582 * @assembly: an assembly
5584 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5586 MonoReflectionAssembly*
5587 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5589 static MonoClass *System_Reflection_Assembly;
5590 MonoReflectionAssembly *res;
5592 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5593 if (!System_Reflection_Assembly)
5594 System_Reflection_Assembly = mono_class_from_name (
5595 mono_defaults.corlib, "System.Reflection", "Assembly");
5596 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5597 res->assembly = assembly;
5599 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5604 MonoReflectionModule*
5605 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5607 static MonoClass *System_Reflection_Module;
5608 MonoReflectionModule *res;
5611 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5612 if (!System_Reflection_Module)
5613 System_Reflection_Module = mono_class_from_name (
5614 mono_defaults.corlib, "System.Reflection", "Module");
5615 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5618 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5620 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5621 basename = g_path_get_basename (image->name);
5622 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5623 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5627 if (image->assembly->image == image) {
5628 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5632 if (image->assembly->image->modules) {
5633 for (i = 0; i < image->assembly->image->module_count; i++) {
5634 if (image->assembly->image->modules [i] == image)
5635 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5637 g_assert (res->token);
5641 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5644 MonoReflectionModule*
5645 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5647 static MonoClass *System_Reflection_Module;
5648 MonoReflectionModule *res;
5649 MonoTableInfo *table;
5650 guint32 cols [MONO_FILE_SIZE];
5652 guint32 i, name_idx;
5655 if (!System_Reflection_Module)
5656 System_Reflection_Module = mono_class_from_name (
5657 mono_defaults.corlib, "System.Reflection", "Module");
5658 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5660 table = &image->tables [MONO_TABLE_FILE];
5661 g_assert (table_index < table->rows);
5662 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5665 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5666 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5668 /* Check whenever the row has a corresponding row in the moduleref table */
5669 table = &image->tables [MONO_TABLE_MODULEREF];
5670 for (i = 0; i < table->rows; ++i) {
5671 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5672 val = mono_metadata_string_heap (image, name_idx);
5673 if (strcmp (val, name) == 0)
5674 res->image = image->modules [i];
5677 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5678 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5679 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5680 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5681 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5687 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5689 if ((t1->type != t2->type) ||
5690 (t1->byref != t2->byref))
5694 case MONO_TYPE_VOID:
5695 case MONO_TYPE_BOOLEAN:
5696 case MONO_TYPE_CHAR:
5707 case MONO_TYPE_STRING:
5710 case MONO_TYPE_OBJECT:
5711 case MONO_TYPE_TYPEDBYREF:
5713 case MONO_TYPE_VALUETYPE:
5714 case MONO_TYPE_CLASS:
5715 case MONO_TYPE_SZARRAY:
5716 return t1->data.klass == t2->data.klass;
5718 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5719 case MONO_TYPE_ARRAY:
5720 if (t1->data.array->rank != t2->data.array->rank)
5722 return t1->data.array->eklass == t2->data.array->eklass;
5723 case MONO_TYPE_GENERICINST: {
5725 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5726 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5727 if (i1->type_argc != i2->type_argc)
5729 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5730 &t2->data.generic_class->container_class->byval_arg))
5732 /* FIXME: we should probably just compare the instance pointers directly. */
5733 for (i = 0; i < i1->type_argc; ++i) {
5734 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5740 case MONO_TYPE_MVAR:
5741 return t1->data.generic_param == t2->data.generic_param;
5743 g_error ("implement type compare for %0x!", t1->type);
5751 mymono_metadata_type_hash (MonoType *t1)
5757 hash |= t1->byref << 6; /* do not collide with t1->type values */
5759 case MONO_TYPE_VALUETYPE:
5760 case MONO_TYPE_CLASS:
5761 case MONO_TYPE_SZARRAY:
5762 /* check if the distribution is good enough */
5763 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5765 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5766 case MONO_TYPE_GENERICINST: {
5768 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5769 hash += g_str_hash (t1->data.generic_class->container_class->name);
5771 for (i = 0; i < inst->type_argc; ++i) {
5772 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5781 static MonoReflectionGenericClass*
5782 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5784 static MonoClass *System_Reflection_MonoGenericClass;
5785 MonoReflectionGenericClass *res;
5786 MonoClass *klass, *gklass;
5788 if (!System_Reflection_MonoGenericClass) {
5789 System_Reflection_MonoGenericClass = mono_class_from_name (
5790 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5791 g_assert (System_Reflection_MonoGenericClass);
5794 klass = mono_class_from_mono_type (geninst);
5795 gklass = klass->generic_class->container_class;
5797 mono_class_init (klass);
5800 /* FIXME: allow unpinned later */
5801 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5803 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5806 res->type.type = geninst;
5807 g_assert (gklass->reflection_info);
5808 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5809 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5815 verify_safe_for_managed_space (MonoType *type)
5817 switch (type->type) {
5819 case MONO_TYPE_ARRAY:
5820 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5822 return verify_safe_for_managed_space (type->data.type);
5823 case MONO_TYPE_SZARRAY:
5824 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5825 case MONO_TYPE_GENERICINST: {
5826 MonoGenericInst *inst = type->data.generic_class->inst;
5830 for (i = 0; i < inst->type_argc; ++i)
5831 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5837 case MONO_TYPE_MVAR:
5844 * mono_type_get_object:
5845 * @domain: an app domain
5848 * Return an System.MonoType object representing the type @type.
5851 mono_type_get_object (MonoDomain *domain, MonoType *type)
5853 MonoReflectionType *res;
5854 MonoClass *klass = mono_class_from_mono_type (type);
5856 /*we must avoid using @type as it might have come
5857 * from a mono_metadata_type_dup and the caller
5858 * expects that is can be freed.
5859 * Using the right type from
5861 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
5864 * If the vtable of the given class was already created, we can use
5865 * the MonoType from there and avoid all locking and hash table lookups.
5867 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
5868 * that the resulting object is diferent.
5870 if (type == &klass->byval_arg && !klass->image->dynamic) {
5871 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
5872 if (vtable && vtable->type)
5873 return vtable->type;
5876 mono_domain_lock (domain);
5877 if (!domain->type_hash)
5878 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5879 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5880 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5881 mono_domain_unlock (domain);
5884 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
5885 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
5886 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5887 mono_g_hash_table_insert (domain->type_hash, type, res);
5888 mono_domain_unlock (domain);
5892 if (!verify_safe_for_managed_space (type)) {
5893 mono_domain_unlock (domain);
5894 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5897 if (klass->reflection_info && !klass->wastypebuilder) {
5898 /* g_assert_not_reached (); */
5899 /* should this be considered an error condition? */
5901 mono_domain_unlock (domain);
5902 return klass->reflection_info;
5905 // FIXME: Get rid of this, do it in the icalls for Type
5906 mono_class_init (klass);
5908 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5910 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5913 mono_g_hash_table_insert (domain->type_hash, type, res);
5914 mono_domain_unlock (domain);
5919 * mono_method_get_object:
5920 * @domain: an app domain
5922 * @refclass: the reflected type (can be NULL)
5924 * Return an System.Reflection.MonoMethod object representing the method @method.
5926 MonoReflectionMethod*
5927 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5930 * We use the same C representation for methods and constructors, but the type
5931 * name in C# is different.
5933 static MonoClass *System_Reflection_MonoMethod = NULL;
5934 static MonoClass *System_Reflection_MonoCMethod = NULL;
5935 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5936 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5938 MonoReflectionMethod *ret;
5940 if (method->is_inflated) {
5941 MonoReflectionGenericMethod *gret;
5943 refclass = method->klass;
5944 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5945 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5946 if (!System_Reflection_MonoGenericCMethod)
5947 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5948 klass = System_Reflection_MonoGenericCMethod;
5950 if (!System_Reflection_MonoGenericMethod)
5951 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5952 klass = System_Reflection_MonoGenericMethod;
5954 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5955 gret->method.method = method;
5956 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5957 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5958 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5962 refclass = method->klass;
5964 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5965 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5966 if (!System_Reflection_MonoCMethod)
5967 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5968 klass = System_Reflection_MonoCMethod;
5971 if (!System_Reflection_MonoMethod)
5972 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5973 klass = System_Reflection_MonoMethod;
5975 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5976 ret->method = method;
5977 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5978 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5982 * mono_field_get_object:
5983 * @domain: an app domain
5987 * Return an System.Reflection.MonoField object representing the field @field
5990 MonoReflectionField*
5991 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5993 MonoReflectionField *res;
5994 static MonoClass *monofield_klass;
5996 CHECK_OBJECT (MonoReflectionField *, field, klass);
5997 if (!monofield_klass)
5998 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5999 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6002 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6003 if (field->generic_info)
6004 res->attrs = field->generic_info->generic_type->attrs;
6006 res->attrs = field->type->attrs;
6007 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6008 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6012 * mono_property_get_object:
6013 * @domain: an app domain
6015 * @property: a property
6017 * Return an System.Reflection.MonoProperty object representing the property @property
6020 MonoReflectionProperty*
6021 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6023 MonoReflectionProperty *res;
6024 static MonoClass *monoproperty_klass;
6026 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6027 if (!monoproperty_klass)
6028 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6029 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6031 res->property = property;
6032 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6036 * mono_event_get_object:
6037 * @domain: an app domain
6041 * Return an System.Reflection.MonoEvent object representing the event @event
6044 MonoReflectionEvent*
6045 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6047 MonoReflectionEvent *res;
6048 static MonoClass *monoevent_klass;
6050 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6051 if (!monoevent_klass)
6052 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6053 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6056 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6060 * mono_get_reflection_missing_object:
6061 * @domain: Domain where the object lives
6063 * Returns the System.Reflection.Missing.Value singleton object
6064 * (of type System.Reflection.Missing).
6066 * Used as the value for ParameterInfo.DefaultValue when Optional
6070 mono_get_reflection_missing_object (MonoDomain *domain)
6073 static MonoClassField *missing_value_field = NULL;
6075 if (!missing_value_field) {
6076 MonoClass *missing_klass;
6077 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6078 mono_class_init (missing_klass);
6079 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6080 g_assert (missing_value_field);
6082 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6088 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6091 *dbnull = mono_get_dbnull_object (domain);
6096 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6098 if (!*reflection_missing)
6099 *reflection_missing = mono_get_reflection_missing_object (domain);
6100 return *reflection_missing;
6104 * mono_param_get_objects:
6105 * @domain: an app domain
6108 * Return an System.Reflection.ParameterInfo array object representing the parameters
6109 * in the method @method.
6112 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6114 static MonoClass *System_Reflection_ParameterInfo;
6115 static MonoClass *System_Reflection_ParameterInfo_array;
6116 MonoArray *res = NULL;
6117 MonoReflectionMethod *member = NULL;
6118 MonoReflectionParameter *param = NULL;
6119 char **names, **blobs = NULL;
6120 guint32 *types = NULL;
6121 MonoType *type = NULL;
6122 MonoObject *dbnull = NULL;
6123 MonoObject *missing = NULL;
6124 MonoMarshalSpec **mspecs;
6125 MonoMethodSignature *sig;
6126 MonoVTable *pinfo_vtable;
6129 if (!System_Reflection_ParameterInfo_array) {
6132 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6133 mono_memory_barrier ();
6134 System_Reflection_ParameterInfo = klass;
6136 klass = mono_array_class_get (klass, 1);
6137 mono_memory_barrier ();
6138 System_Reflection_ParameterInfo_array = klass;
6141 if (!mono_method_signature (method)->param_count)
6142 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6144 /* Note: the cache is based on the address of the signature into the method
6145 * since we already cache MethodInfos with the method as keys.
6147 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6149 sig = mono_method_signature (method);
6150 member = mono_method_get_object (domain, method, NULL);
6151 names = g_new (char *, sig->param_count);
6152 mono_method_get_param_names (method, (const char **) names);
6154 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6155 mono_method_get_marshal_info (method, mspecs);
6157 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6158 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6159 for (i = 0; i < sig->param_count; ++i) {
6160 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6161 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6162 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6163 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6164 param->PositionImpl = i;
6165 param->AttrsImpl = sig->params [i]->attrs;
6167 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6168 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6169 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6171 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6175 blobs = g_new0 (char *, sig->param_count);
6176 types = g_new0 (guint32, sig->param_count);
6177 get_default_param_value_blobs (method, blobs, types);
6180 /* Build MonoType for the type from the Constant Table */
6182 type = g_new0 (MonoType, 1);
6183 type->type = types [i];
6184 type->data.klass = NULL;
6185 if (types [i] == MONO_TYPE_CLASS)
6186 type->data.klass = mono_defaults.object_class;
6187 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6188 /* For enums, types [i] contains the base type */
6190 type->type = MONO_TYPE_VALUETYPE;
6191 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6193 type->data.klass = mono_class_from_mono_type (type);
6195 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6197 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6198 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6199 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6200 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6202 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6208 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6210 mono_array_setref (res, i, param);
6217 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6219 mono_metadata_free_marshal_spec (mspecs [i]);
6222 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6226 * mono_method_body_get_object:
6227 * @domain: an app domain
6230 * Return an System.Reflection.MethodBody object representing the method @method.
6232 MonoReflectionMethodBody*
6233 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6235 static MonoClass *System_Reflection_MethodBody = NULL;
6236 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6237 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6238 MonoReflectionMethodBody *ret;
6239 MonoMethodNormal *mn;
6240 MonoMethodHeader *header;
6241 guint32 method_rva, local_var_sig_token;
6243 unsigned char format, flags;
6246 if (!System_Reflection_MethodBody)
6247 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6248 if (!System_Reflection_LocalVariableInfo)
6249 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6250 if (!System_Reflection_ExceptionHandlingClause)
6251 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6253 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6255 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6256 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6257 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6258 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6260 mn = (MonoMethodNormal *)method;
6261 header = mono_method_get_header (method);
6263 /* Obtain local vars signature token */
6264 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6265 ptr = mono_image_rva_map (method->klass->image, method_rva);
6266 flags = *(const unsigned char *) ptr;
6267 format = flags & METHOD_HEADER_FORMAT_MASK;
6269 case METHOD_HEADER_TINY_FORMAT:
6270 case METHOD_HEADER_TINY_FORMAT1:
6271 local_var_sig_token = 0;
6273 case METHOD_HEADER_FAT_FORMAT:
6277 local_var_sig_token = read32 (ptr);
6280 g_assert_not_reached ();
6283 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6285 ret->init_locals = header->init_locals;
6286 ret->max_stack = header->max_stack;
6287 ret->local_var_sig_token = local_var_sig_token;
6288 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6289 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6292 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6293 for (i = 0; i < header->num_locals; ++i) {
6294 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6295 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6296 info->is_pinned = header->locals [i]->pinned;
6297 info->local_index = i;
6298 mono_array_setref (ret->locals, i, info);
6302 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6303 for (i = 0; i < header->num_clauses; ++i) {
6304 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6305 MonoExceptionClause *clause = &header->clauses [i];
6307 info->flags = clause->flags;
6308 info->try_offset = clause->try_offset;
6309 info->try_length = clause->try_len;
6310 info->handler_offset = clause->handler_offset;
6311 info->handler_length = clause->handler_len;
6312 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6313 info->filter_offset = clause->data.filter_offset;
6314 else if (clause->data.catch_class)
6315 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6317 mono_array_setref (ret->clauses, i, info);
6320 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6325 * mono_get_dbnull_object:
6326 * @domain: Domain where the object lives
6328 * Returns the System.DBNull.Value singleton object
6330 * Used as the value for ParameterInfo.DefaultValue
6333 mono_get_dbnull_object (MonoDomain *domain)
6336 static MonoClassField *dbnull_value_field = NULL;
6338 if (!dbnull_value_field) {
6339 MonoClass *dbnull_klass;
6340 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6341 mono_class_init (dbnull_klass);
6342 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6343 g_assert (dbnull_value_field);
6345 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6351 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6353 guint32 param_index, i, lastp, crow = 0;
6354 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6357 MonoClass *klass = method->klass;
6358 MonoImage *image = klass->image;
6359 MonoMethodSignature *methodsig = mono_method_signature (method);
6361 MonoTableInfo *constt;
6362 MonoTableInfo *methodt;
6363 MonoTableInfo *paramt;
6365 if (!methodsig->param_count)
6368 mono_class_init (klass);
6370 if (klass->image->dynamic) {
6371 MonoReflectionMethodAux *aux;
6372 if (method->is_inflated)
6373 method = ((MonoMethodInflated*)method)->declaring;
6374 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6375 if (aux && aux->param_defaults) {
6376 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6377 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6382 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6383 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6384 constt = &image->tables [MONO_TABLE_CONSTANT];
6386 idx = mono_method_get_index (method) - 1;
6387 g_assert (idx != -1);
6389 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6390 if (idx + 1 < methodt->rows)
6391 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6393 lastp = paramt->rows + 1;
6395 for (i = param_index; i < lastp; ++i) {
6398 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6399 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6401 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6404 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6409 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6410 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6411 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6418 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6423 MonoType *basetype = type;
6428 klass = mono_class_from_mono_type (type);
6429 if (klass->valuetype) {
6430 object = mono_object_new (domain, klass);
6431 retval = ((gchar *) object + sizeof (MonoObject));
6432 if (klass->enumtype)
6433 basetype = klass->enum_basetype;
6438 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6445 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6449 memset (assembly, 0, sizeof (MonoAssemblyName));
6451 assembly->culture = "";
6452 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6454 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6457 while (g_ascii_isspace (*p) || *p == ',') {
6466 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6468 assembly->major = strtoul (p, &s, 10);
6469 if (s == p || *s != '.')
6472 assembly->minor = strtoul (p, &s, 10);
6473 if (s == p || *s != '.')
6476 assembly->build = strtoul (p, &s, 10);
6477 if (s == p || *s != '.')
6480 assembly->revision = strtoul (p, &s, 10);
6484 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6486 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6487 assembly->culture = "";
6490 assembly->culture = p;
6491 while (*p && *p != ',') {
6495 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6497 if (strncmp (p, "null", 4) == 0) {
6502 while (*p && *p != ',') {
6505 len = (p - start + 1);
6506 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6507 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6508 g_strlcpy ((char*)assembly->public_key_token, start, len);
6511 while (*p && *p != ',')
6515 while (g_ascii_isspace (*p) || *p == ',') {
6529 * mono_reflection_parse_type:
6532 * Parse a type name as accepted by the GetType () method and output the info
6533 * extracted in the info structure.
6534 * the name param will be mangled, so, make a copy before passing it to this function.
6535 * The fields in info will be valid until the memory pointed to by name is valid.
6537 * See also mono_type_get_name () below.
6539 * Returns: 0 on parse error.
6542 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6543 MonoTypeNameParse *info)
6545 char *start, *p, *w, *temp, *last_point, *startn;
6546 int in_modifiers = 0;
6547 int isbyref = 0, rank, arity = 0, i;
6549 start = p = w = name;
6551 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6552 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6553 info->name = info->name_space = NULL;
6554 info->nested = NULL;
6555 info->modifiers = NULL;
6556 info->type_arguments = NULL;
6558 /* last_point separates the namespace from the name */
6564 *p = 0; /* NULL terminate the name */
6566 info->nested = g_list_append (info->nested, startn);
6567 /* we have parsed the nesting namespace + name */
6571 info->name_space = start;
6573 info->name = last_point + 1;
6575 info->name_space = (char *)"";
6594 i = strtol (p, &temp, 10);
6611 info->name_space = start;
6613 info->name = last_point + 1;
6615 info->name_space = (char *)"";
6622 if (isbyref) /* only one level allowed by the spec */
6625 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6629 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6635 info->type_arguments = g_ptr_array_new ();
6636 for (i = 0; i < arity; i++) {
6637 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6638 gboolean fqname = FALSE;
6640 g_ptr_array_add (info->type_arguments, subinfo);
6647 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6658 while (*p && (*p != ']'))
6666 if (g_ascii_isspace (*aname)) {
6673 !assembly_name_to_aname (&subinfo->assembly, aname))
6677 if (i + 1 < arity) {
6697 else if (*p == '*') /* '*' means unknown lower bound */
6698 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6705 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6716 if (g_ascii_isspace (*p)) {
6723 return 0; /* missing assembly name */
6724 if (!assembly_name_to_aname (&info->assembly, p))
6730 if (info->assembly.name)
6733 // *w = 0; /* terminate class name */
6735 if (!info->name || !*info->name)
6739 /* add other consistency checks */
6744 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6746 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6750 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6752 gboolean type_resolve = FALSE;
6754 MonoImage *rootimage = image;
6756 if (info->assembly.name) {
6757 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6759 /* then we must load the assembly ourselve - see #60439 */
6760 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6764 image = assembly->image;
6765 } else if (!image) {
6766 image = mono_defaults.corlib;
6769 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6770 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6771 image = mono_defaults.corlib;
6772 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6779 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6784 gboolean bounded = FALSE;
6787 image = mono_defaults.corlib;
6790 klass = mono_class_from_name_case (image, info->name_space, info->name);
6792 klass = mono_class_from_name (image, info->name_space, info->name);
6795 for (mod = info->nested; mod; mod = mod->next) {
6798 mono_class_init (klass);
6799 nested = klass->nested_classes;
6802 klass = nested->data;
6804 if (g_strcasecmp (klass->name, mod->data) == 0)
6807 if (strcmp (klass->name, mod->data) == 0)
6811 nested = nested->next;
6818 mono_class_init (klass);
6820 if (info->type_arguments) {
6821 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6822 MonoReflectionType *the_type;
6826 for (i = 0; i < info->type_arguments->len; i++) {
6827 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6829 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6830 if (!type_args [i]) {
6836 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6838 instance = mono_reflection_bind_generic_parameters (
6839 the_type, info->type_arguments->len, type_args);
6845 klass = mono_class_from_mono_type (instance);
6848 for (mod = info->modifiers; mod; mod = mod->next) {
6849 modval = GPOINTER_TO_UINT (mod->data);
6850 if (!modval) { /* byref: must be last modifier */
6851 return &klass->this_arg;
6852 } else if (modval == -1) {
6853 klass = mono_ptr_class_get (&klass->byval_arg);
6854 } else if (modval == -2) {
6856 } else { /* array rank */
6857 klass = mono_bounded_array_class_get (klass, modval, bounded);
6859 mono_class_init (klass);
6862 return &klass->byval_arg;
6866 * mono_reflection_get_type:
6867 * @image: a metadata context
6868 * @info: type description structure
6869 * @ignorecase: flag for case-insensitive string compares
6870 * @type_resolve: whenever type resolve was already tried
6872 * Build a MonoType from the type description in @info.
6877 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6878 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6882 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6884 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6888 g_assert (assembly->dynamic);
6890 /* Enumerate all modules */
6893 if (abuilder->modules) {
6894 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6895 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6896 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6902 if (!type && abuilder->loaded_modules) {
6903 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6904 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6905 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6915 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6918 MonoReflectionAssembly *assembly;
6922 if (image && image->dynamic)
6923 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6925 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6928 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6935 *type_resolve = TRUE;
6938 /* Reconstruct the type name */
6939 fullName = g_string_new ("");
6940 if (info->name_space && (info->name_space [0] != '\0'))
6941 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6943 g_string_printf (fullName, info->name);
6944 for (mod = info->nested; mod; mod = mod->next)
6945 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6947 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6949 if (assembly->assembly->dynamic)
6950 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6952 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6955 g_string_free (fullName, TRUE);
6960 mono_reflection_free_type_info (MonoTypeNameParse *info)
6962 g_list_free (info->modifiers);
6963 g_list_free (info->nested);
6965 if (info->type_arguments) {
6968 for (i = 0; i < info->type_arguments->len; i++) {
6969 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6971 mono_reflection_free_type_info (subinfo);
6972 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6976 g_ptr_array_free (info->type_arguments, TRUE);
6981 * mono_reflection_type_from_name:
6983 * @image: a metadata context (can be NULL).
6985 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6986 * it defaults to get the type from @image or, if @image is NULL or loading
6987 * from it fails, uses corlib.
6991 mono_reflection_type_from_name (char *name, MonoImage *image)
6993 MonoType *type = NULL;
6994 MonoTypeNameParse info;
6997 /* Make a copy since parse_type modifies its argument */
6998 tmp = g_strdup (name);
7000 /*g_print ("requested type %s\n", str);*/
7001 if (mono_reflection_parse_type (tmp, &info)) {
7002 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7006 mono_reflection_free_type_info (&info);
7011 * mono_reflection_get_token:
7013 * Return the metadata token of OBJ which should be an object
7014 * representing a metadata element.
7017 mono_reflection_get_token (MonoObject *obj)
7022 klass = obj->vtable->klass;
7024 if (strcmp (klass->name, "MethodBuilder") == 0) {
7025 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7027 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7028 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7029 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7031 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7032 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7033 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7035 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7036 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7037 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7038 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7039 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7040 } else if (strcmp (klass->name, "MonoType") == 0) {
7041 MonoReflectionType *tb = (MonoReflectionType *)obj;
7042 token = mono_class_from_mono_type (tb->type)->type_token;
7043 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7044 strcmp (klass->name, "MonoMethod") == 0 ||
7045 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7046 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7047 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7048 if (m->method->is_inflated) {
7049 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7050 return inflated->declaring->token;
7052 token = m->method->token;
7054 } else if (strcmp (klass->name, "MonoField") == 0) {
7055 MonoReflectionField *f = (MonoReflectionField*)obj;
7057 if (f->field->generic_info && f->field->generic_info->reflection_info)
7058 return mono_reflection_get_token (f->field->generic_info->reflection_info);
7060 token = mono_class_get_field_token (f->field);
7061 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7062 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7064 token = mono_class_get_property_token (p->property);
7065 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7066 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7068 token = mono_class_get_event_token (p->event);
7069 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7070 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7072 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7073 } else if (strcmp (klass->name, "Module") == 0) {
7074 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7077 } else if (strcmp (klass->name, "Assembly") == 0) {
7078 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7080 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7081 MonoException *ex = mono_get_exception_not_implemented (msg);
7083 mono_raise_exception (ex);
7090 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7092 int slen, type = t->type;
7093 MonoClass *tklass = t->data.klass;
7099 case MONO_TYPE_BOOLEAN: {
7100 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7105 case MONO_TYPE_CHAR:
7107 case MONO_TYPE_I2: {
7108 guint16 *val = g_malloc (sizeof (guint16));
7113 #if SIZEOF_VOID_P == 4
7119 case MONO_TYPE_I4: {
7120 guint32 *val = g_malloc (sizeof (guint32));
7125 #if SIZEOF_VOID_P == 8
7126 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7130 case MONO_TYPE_I8: {
7131 guint64 *val = g_malloc (sizeof (guint64));
7136 case MONO_TYPE_R8: {
7137 double *val = g_malloc (sizeof (double));
7142 case MONO_TYPE_VALUETYPE:
7143 if (t->data.klass->enumtype) {
7144 type = t->data.klass->enum_basetype->type;
7147 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7150 case MONO_TYPE_STRING:
7151 if (*p == (char)0xFF) {
7155 slen = mono_metadata_decode_value (p, &p);
7157 return mono_string_new_len (mono_domain_get (), p, slen);
7158 case MONO_TYPE_CLASS: {
7161 if (*p == (char)0xFF) {
7166 slen = mono_metadata_decode_value (p, &p);
7167 n = g_memdup (p, slen + 1);
7169 t = mono_reflection_type_from_name (n, image);
7171 g_warning ("Cannot load type '%s'", n);
7175 return mono_type_get_object (mono_domain_get (), t);
7179 case MONO_TYPE_OBJECT: {
7182 MonoClass *subc = NULL;
7187 } else if (subt == 0x0E) {
7188 type = MONO_TYPE_STRING;
7190 } else if (subt == 0x1D) {
7191 MonoType simple_type = {{0}};
7196 /* See Partition II, Appendix B3 */
7197 etype = MONO_TYPE_OBJECT;
7198 type = MONO_TYPE_SZARRAY;
7199 simple_type.type = etype;
7200 tklass = mono_class_from_mono_type (&simple_type);
7202 } else if (subt == 0x55) {
7205 slen = mono_metadata_decode_value (p, &p);
7206 n = g_memdup (p, slen + 1);
7208 t = mono_reflection_type_from_name (n, image);
7210 g_error ("Cannot load type '%s'", n);
7213 subc = mono_class_from_mono_type (t);
7214 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7215 MonoType simple_type = {{0}};
7216 simple_type.type = subt;
7217 subc = mono_class_from_mono_type (&simple_type);
7219 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7221 val = load_cattr_value (image, &subc->byval_arg, p, end);
7222 obj = mono_object_new (mono_domain_get (), subc);
7223 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7227 case MONO_TYPE_SZARRAY: {
7229 guint32 i, alen, basetype;
7232 if (alen == 0xffffffff) {
7236 arr = mono_array_new (mono_domain_get(), tklass, alen);
7237 basetype = tklass->byval_arg.type;
7238 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7239 basetype = tklass->enum_basetype->type;
7244 case MONO_TYPE_BOOLEAN:
7245 for (i = 0; i < alen; i++) {
7246 MonoBoolean val = *p++;
7247 mono_array_set (arr, MonoBoolean, i, val);
7250 case MONO_TYPE_CHAR:
7253 for (i = 0; i < alen; i++) {
7254 guint16 val = read16 (p);
7255 mono_array_set (arr, guint16, i, val);
7262 for (i = 0; i < alen; i++) {
7263 guint32 val = read32 (p);
7264 mono_array_set (arr, guint32, i, val);
7269 for (i = 0; i < alen; i++) {
7272 mono_array_set (arr, double, i, val);
7278 for (i = 0; i < alen; i++) {
7279 guint64 val = read64 (p);
7280 mono_array_set (arr, guint64, i, val);
7284 case MONO_TYPE_CLASS:
7285 case MONO_TYPE_OBJECT:
7286 case MONO_TYPE_STRING:
7287 for (i = 0; i < alen; i++) {
7288 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7289 mono_array_setref (arr, i, item);
7293 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7299 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7305 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7307 static MonoClass *klass;
7308 static MonoMethod *ctor;
7310 void *params [2], *unboxed;
7313 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7315 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7317 params [0] = mono_type_get_object (mono_domain_get (), t);
7319 retval = mono_object_new (mono_domain_get (), klass);
7320 unboxed = mono_object_unbox (retval);
7321 mono_runtime_invoke (ctor, unboxed, params, NULL);
7327 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7329 static MonoClass *klass;
7330 static MonoMethod *ctor;
7332 void *unboxed, *params [2];
7335 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7337 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7340 params [1] = typedarg;
7341 retval = mono_object_new (mono_domain_get (), klass);
7342 unboxed = mono_object_unbox (retval);
7343 mono_runtime_invoke (ctor, unboxed, params, NULL);
7349 type_is_reference (MonoType *type)
7351 switch (type->type) {
7352 case MONO_TYPE_BOOLEAN:
7353 case MONO_TYPE_CHAR:
7366 case MONO_TYPE_VALUETYPE:
7374 free_param_data (MonoMethodSignature *sig, void **params) {
7376 for (i = 0; i < sig->param_count; ++i) {
7377 if (!type_is_reference (sig->params [i]))
7378 g_free (params [i]);
7383 * Find the field index in the metadata FieldDef table.
7386 find_field_index (MonoClass *klass, MonoClassField *field) {
7389 for (i = 0; i < klass->field.count; ++i) {
7390 if (field == &klass->fields [i])
7391 return klass->field.first + 1 + i;
7397 * Find the property index in the metadata Property table.
7400 find_property_index (MonoClass *klass, MonoProperty *property) {
7403 for (i = 0; i < klass->property.count; ++i) {
7404 if (property == &klass->properties [i])
7405 return klass->property.first + 1 + i;
7411 * Find the event index in the metadata Event table.
7414 find_event_index (MonoClass *klass, MonoEvent *event) {
7417 for (i = 0; i < klass->event.count; ++i) {
7418 if (event == &klass->events [i])
7419 return klass->event.first + 1 + i;
7425 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7427 const char *p = (const char*)data;
7429 guint32 i, j, num_named;
7433 mono_class_init (method->klass);
7436 attr = mono_object_new (mono_domain_get (), method->klass);
7437 mono_runtime_invoke (method, attr, NULL, NULL);
7441 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7444 /*g_print ("got attr %s\n", method->klass->name);*/
7446 /* Allocate using alloca so it gets GC tracking */
7447 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7451 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7452 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7456 attr = mono_object_new (mono_domain_get (), method->klass);
7457 mono_runtime_invoke (method, attr, params, NULL);
7458 free_param_data (method->signature, params);
7459 num_named = read16 (named);
7461 for (j = 0; j < num_named; j++) {
7463 char *name, named_type, data_type;
7464 named_type = *named++;
7465 data_type = *named++; /* type of data */
7466 if (data_type == MONO_TYPE_SZARRAY)
7467 data_type = *named++;
7468 if (data_type == MONO_TYPE_ENUM) {
7471 type_len = mono_metadata_decode_blob_size (named, &named);
7472 type_name = g_malloc (type_len + 1);
7473 memcpy (type_name, named, type_len);
7474 type_name [type_len] = 0;
7476 /* FIXME: lookup the type and check type consistency */
7479 name_len = mono_metadata_decode_blob_size (named, &named);
7480 name = g_malloc (name_len + 1);
7481 memcpy (name, named, name_len);
7482 name [name_len] = 0;
7484 if (named_type == 0x53) {
7485 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7486 void *val = load_cattr_value (image, field->type, named, &named);
7487 mono_field_set_value (attr, field, val);
7488 if (!type_is_reference (field->type))
7490 } else if (named_type == 0x54) {
7493 MonoType *prop_type;
7495 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7496 /* can we have more that 1 arg in a custom attr named property? */
7497 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7498 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7499 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7500 mono_property_set_value (prop, attr, pparams, NULL);
7501 if (!type_is_reference (prop_type))
7502 g_free (pparams [0]);
7511 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7513 MonoArray *typedargs, *namedargs;
7514 MonoClass *attrklass;
7515 static MonoMethod *ctor;
7518 const char *p = (const char*)data;
7520 guint32 i, j, num_named;
7523 mono_class_init (method->klass);
7526 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7528 domain = mono_domain_get ();
7530 /* This is for Attributes with no parameters */
7531 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7532 params [0] = mono_method_get_object (domain, method, NULL);
7533 params [1] = params [2] = NULL;
7534 mono_runtime_invoke (method, attr, params, NULL);
7538 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7541 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7545 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7546 MonoObject *obj, *typedarg;
7549 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7550 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7551 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7552 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7553 mono_array_setref (typedargs, i, typedarg);
7555 if (!type_is_reference (mono_method_signature (method)->params [i]))
7560 num_named = read16 (named);
7561 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7563 attrklass = method->klass;
7564 for (j = 0; j < num_named; j++) {
7566 char *name, named_type, data_type;
7567 named_type = *named++;
7568 data_type = *named++; /* type of data */
7569 if (data_type == MONO_TYPE_SZARRAY)
7570 data_type = *named++;
7571 if (data_type == MONO_TYPE_ENUM) {
7574 type_len = mono_metadata_decode_blob_size (named, &named);
7575 type_name = g_malloc (type_len + 1);
7576 memcpy (type_name, named, type_len);
7577 type_name [type_len] = 0;
7579 /* FIXME: lookup the type and check type consistency */
7582 name_len = mono_metadata_decode_blob_size (named, &named);
7583 name = g_malloc (name_len + 1);
7584 memcpy (name, named, name_len);
7585 name [name_len] = 0;
7587 if (named_type == 0x53) {
7588 MonoObject *obj, *typedarg, *namedarg;
7589 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7590 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7592 minfo = mono_field_get_object (domain, NULL, field);
7593 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7594 typedarg = create_cattr_typed_arg (field->type, obj);
7595 namedarg = create_cattr_named_arg (minfo, typedarg);
7596 mono_array_setref (namedargs, j, namedarg);
7597 if (!type_is_reference (field->type))
7599 } else if (named_type == 0x54) {
7600 MonoObject *obj, *typedarg, *namedarg;
7601 MonoType *prop_type;
7603 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7605 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7606 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7607 minfo = mono_property_get_object (domain, NULL, prop);
7608 val = load_cattr_value (image, prop_type, named, &named);
7609 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7610 typedarg = create_cattr_typed_arg (prop_type, obj);
7611 namedarg = create_cattr_named_arg (minfo, typedarg);
7612 mono_array_setref (namedargs, j, namedarg);
7613 if (!type_is_reference (prop_type))
7618 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7619 params [0] = mono_method_get_object (domain, method, NULL);
7620 params [1] = typedargs;
7621 params [2] = namedargs;
7622 mono_runtime_invoke (ctor, attr, params, NULL);
7627 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7633 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7634 for (i = 0; i < cinfo->num_attrs; ++i) {
7635 if (!cinfo->attrs [i].ctor)
7636 /* The cattr type is not finished yet */
7637 /* We should include the type name but cinfo doesn't contain it */
7638 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7639 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7640 mono_array_setref (result, i, attr);
7646 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7653 for (i = 0; i < cinfo->num_attrs; ++i) {
7654 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7658 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7660 for (i = 0; i < cinfo->num_attrs; ++i) {
7661 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7662 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7663 mono_array_setref (result, n, attr);
7671 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7677 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7678 for (i = 0; i < cinfo->num_attrs; ++i) {
7679 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7680 mono_array_setref (result, i, attr);
7686 * mono_custom_attrs_from_index:
7688 * Returns: NULL if no attributes are found or if a loading error occurs.
7691 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7693 guint32 mtoken, i, len;
7694 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7696 MonoCustomAttrInfo *ainfo;
7697 GList *tmp, *list = NULL;
7700 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7702 i = mono_metadata_custom_attrs_from_index (image, idx);
7706 while (i < ca->rows) {
7707 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7709 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7712 len = g_list_length (list);
7715 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7716 ainfo->num_attrs = len;
7717 ainfo->image = image;
7718 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7719 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7720 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7721 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7722 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7723 mtoken |= MONO_TOKEN_METHOD_DEF;
7725 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7726 mtoken |= MONO_TOKEN_MEMBER_REF;
7729 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7732 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7733 if (!ainfo->attrs [i].ctor) {
7734 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7739 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7740 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7741 ainfo->attrs [i].data = (guchar*)data;
7749 mono_custom_attrs_from_method (MonoMethod *method)
7754 * An instantiated method has the same cattrs as the generic method definition.
7756 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7757 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7759 if (method->is_inflated)
7760 method = ((MonoMethodInflated *) method)->declaring;
7762 if (method->dynamic || method->klass->image->dynamic)
7763 return lookup_custom_attr (method->klass->image, method);
7765 idx = mono_method_get_index (method);
7766 idx <<= MONO_CUSTOM_ATTR_BITS;
7767 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7768 return mono_custom_attrs_from_index (method->klass->image, idx);
7772 mono_custom_attrs_from_class (MonoClass *klass)
7776 if (klass->generic_class)
7777 klass = klass->generic_class->container_class;
7779 if (klass->image->dynamic)
7780 return lookup_custom_attr (klass->image, klass);
7782 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7783 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7784 idx <<= MONO_CUSTOM_ATTR_BITS;
7785 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7787 idx = mono_metadata_token_index (klass->type_token);
7788 idx <<= MONO_CUSTOM_ATTR_BITS;
7789 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7791 return mono_custom_attrs_from_index (klass->image, idx);
7795 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7799 if (assembly->image->dynamic)
7800 return lookup_custom_attr (assembly->image, assembly);
7801 idx = 1; /* there is only one assembly */
7802 idx <<= MONO_CUSTOM_ATTR_BITS;
7803 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7804 return mono_custom_attrs_from_index (assembly->image, idx);
7807 static MonoCustomAttrInfo*
7808 mono_custom_attrs_from_module (MonoImage *image)
7813 return lookup_custom_attr (image, image);
7814 idx = 1; /* there is only one module */
7815 idx <<= MONO_CUSTOM_ATTR_BITS;
7816 idx |= MONO_CUSTOM_ATTR_MODULE;
7817 return mono_custom_attrs_from_index (image, idx);
7821 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7825 if (klass->image->dynamic) {
7826 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
7827 return lookup_custom_attr (klass->image, property);
7829 idx = find_property_index (klass, property);
7830 idx <<= MONO_CUSTOM_ATTR_BITS;
7831 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7832 return mono_custom_attrs_from_index (klass->image, idx);
7836 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7840 if (klass->image->dynamic) {
7841 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
7842 return lookup_custom_attr (klass->image, event);
7844 idx = find_event_index (klass, event);
7845 idx <<= MONO_CUSTOM_ATTR_BITS;
7846 idx |= MONO_CUSTOM_ATTR_EVENT;
7847 return mono_custom_attrs_from_index (klass->image, idx);
7851 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7854 if (klass->image->dynamic) {
7855 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
7856 return lookup_custom_attr (klass->image, field);
7858 idx = find_field_index (klass, field);
7859 idx <<= MONO_CUSTOM_ATTR_BITS;
7860 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7861 return mono_custom_attrs_from_index (klass->image, idx);
7865 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7868 guint32 i, idx, method_index;
7869 guint32 param_list, param_last, param_pos, found;
7871 MonoReflectionMethodAux *aux;
7874 * An instantiated method has the same cattrs as the generic method definition.
7876 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7877 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7879 if (method->is_inflated)
7880 method = ((MonoMethodInflated *) method)->declaring;
7882 if (method->klass->image->dynamic) {
7883 MonoCustomAttrInfo *res, *ainfo;
7886 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7887 if (!aux || !aux->param_cattr)
7890 /* Need to copy since it will be freed later */
7891 ainfo = aux->param_cattr [param];
7892 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7893 res = g_malloc0 (size);
7894 memcpy (res, ainfo, size);
7898 image = method->klass->image;
7899 method_index = mono_method_get_index (method);
7900 ca = &image->tables [MONO_TABLE_METHOD];
7902 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7903 if (method_index == ca->rows) {
7904 ca = &image->tables [MONO_TABLE_PARAM];
7905 param_last = ca->rows + 1;
7907 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7908 ca = &image->tables [MONO_TABLE_PARAM];
7911 for (i = param_list; i < param_last; ++i) {
7912 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7913 if (param_pos == param) {
7921 idx <<= MONO_CUSTOM_ATTR_BITS;
7922 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7923 return mono_custom_attrs_from_index (image, idx);
7927 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7931 for (i = 0; i < ainfo->num_attrs; ++i) {
7932 klass = ainfo->attrs [i].ctor->klass;
7933 if (mono_class_has_parent (klass, attr_klass))
7940 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7947 for (i = 0; i < ainfo->num_attrs; ++i) {
7948 klass = ainfo->attrs [i].ctor->klass;
7949 if (mono_class_has_parent (klass, attr_klass)) {
7954 if (attr_index == -1)
7957 attrs = mono_custom_attrs_construct (ainfo);
7959 return mono_array_get (attrs, MonoObject*, attr_index);
7965 * mono_reflection_get_custom_attrs_info:
7966 * @obj: a reflection object handle
7968 * Return the custom attribute info for attributes defined for the
7969 * reflection handle @obj. The objects.
7972 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7975 MonoCustomAttrInfo *cinfo = NULL;
7977 klass = obj->vtable->klass;
7978 if (klass == mono_defaults.monotype_class) {
7979 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7980 klass = mono_class_from_mono_type (rtype->type);
7981 cinfo = mono_custom_attrs_from_class (klass);
7982 } else if (strcmp ("Assembly", klass->name) == 0) {
7983 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7984 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7985 } else if (strcmp ("Module", klass->name) == 0) {
7986 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7987 cinfo = mono_custom_attrs_from_module (module->image);
7988 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7989 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7990 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7991 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7992 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7993 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7994 } else if (strcmp ("MonoField", klass->name) == 0) {
7995 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7996 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7997 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7998 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7999 cinfo = mono_custom_attrs_from_method (rmethod->method);
8000 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8001 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8002 cinfo = mono_custom_attrs_from_method (rmethod->method);
8003 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8004 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8005 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8006 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8007 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8008 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8009 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8010 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8011 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8012 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8013 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8014 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8015 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8016 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8017 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8018 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8019 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8020 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8021 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8022 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8023 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8024 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8025 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8026 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8027 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8028 } else { /* handle other types here... */
8029 g_error ("get custom attrs not yet supported for %s", klass->name);
8036 * mono_reflection_get_custom_attrs_by_type:
8037 * @obj: a reflection object handle
8039 * Return an array with all the custom attributes defined of the
8040 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8041 * of that type are returned. The objects are fully build. Return NULL if a loading error
8045 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8048 MonoCustomAttrInfo *cinfo;
8050 cinfo = mono_reflection_get_custom_attrs_info (obj);
8053 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8055 result = mono_custom_attrs_construct (cinfo);
8057 mono_custom_attrs_free (cinfo);
8059 if (mono_loader_get_last_error ())
8061 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8068 * mono_reflection_get_custom_attrs:
8069 * @obj: a reflection object handle
8071 * Return an array with all the custom attributes defined of the
8072 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8076 mono_reflection_get_custom_attrs (MonoObject *obj)
8078 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8082 * mono_reflection_get_custom_attrs_data:
8083 * @obj: a reflection obj handle
8085 * Returns an array of System.Reflection.CustomAttributeData,
8086 * which include information about attributes reflected on
8087 * types loaded using the Reflection Only methods
8090 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8093 MonoCustomAttrInfo *cinfo;
8095 cinfo = mono_reflection_get_custom_attrs_info (obj);
8097 result = mono_custom_attrs_data_construct (cinfo);
8099 mono_custom_attrs_free (cinfo);
8101 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8106 static MonoReflectionType*
8107 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8109 MonoMethod *method_get_underlying_system_type;
8111 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8112 mono_class_get_method_from_name (mono_object_class (t),
8113 "get_UnderlyingSystemType",
8115 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8119 mono_reflection_type_get_handle (MonoReflectionType* t)
8124 t = mono_reflection_type_get_underlying_system_type (t);
8132 * LOCKING: Assumes the loader lock is held.
8134 static MonoMethodSignature*
8135 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8136 MonoMethodSignature *sig;
8139 count = parameters? mono_array_length (parameters): 0;
8141 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8142 sig->param_count = count;
8143 sig->sentinelpos = -1; /* FIXME */
8144 for (i = 0; i < count; ++i) {
8145 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8146 sig->params [i] = mono_reflection_type_get_handle (pt);
8152 * LOCKING: Assumes the loader lock is held.
8154 static MonoMethodSignature*
8155 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8156 MonoMethodSignature *sig;
8158 sig = parameters_to_signature (mp, ctor->parameters);
8159 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8160 sig->ret = &mono_defaults.void_class->byval_arg;
8165 * LOCKING: Assumes the loader lock is held.
8167 static MonoMethodSignature*
8168 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8169 MonoMethodSignature *sig;
8171 sig = parameters_to_signature (mp, method->parameters);
8172 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8173 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8174 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8178 static MonoMethodSignature*
8179 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8180 MonoMethodSignature *sig;
8182 sig = parameters_to_signature (NULL, method->parameters);
8183 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8184 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8185 sig->generic_param_count = 0;
8190 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8192 MonoClass *klass = mono_object_class (prop);
8193 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8194 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8195 *name = mono_string_to_utf8 (pb->name);
8196 *type = pb->type->type;
8198 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8199 *name = g_strdup (p->property->name);
8200 if (p->property->get)
8201 *type = mono_method_signature (p->property->get)->ret;
8203 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8208 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8210 MonoClass *klass = mono_object_class (field);
8211 if (strcmp (klass->name, "FieldBuilder") == 0) {
8212 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8213 *name = mono_string_to_utf8 (fb->name);
8214 *type = fb->type->type;
8216 MonoReflectionField *f = (MonoReflectionField *)field;
8217 *name = g_strdup (f->field->name);
8218 *type = f->field->type;
8223 * Encode a value in a custom attribute stream of bytes.
8224 * The value to encode is either supplied as an object in argument val
8225 * (valuetypes are boxed), or as a pointer to the data in the
8227 * @type represents the type of the value
8228 * @buffer is the start of the buffer
8229 * @p the current position in the buffer
8230 * @buflen contains the size of the buffer and is used to return the new buffer size
8231 * if this needs to be realloced.
8232 * @retbuffer and @retp return the start and the position of the buffer
8235 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8237 MonoTypeEnum simple_type;
8239 if ((p-buffer) + 10 >= *buflen) {
8242 newbuf = g_realloc (buffer, *buflen);
8243 p = newbuf + (p-buffer);
8247 argval = ((char*)arg + sizeof (MonoObject));
8248 simple_type = type->type;
8250 switch (simple_type) {
8251 case MONO_TYPE_BOOLEAN:
8256 case MONO_TYPE_CHAR:
8259 swap_with_size (p, argval, 2, 1);
8265 swap_with_size (p, argval, 4, 1);
8269 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8279 swap_with_size (p, argval, 8, 1);
8285 swap_with_size (p, argval, 8, 1);
8288 case MONO_TYPE_VALUETYPE:
8289 if (type->data.klass->enumtype) {
8290 simple_type = type->data.klass->enum_basetype->type;
8293 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8296 case MONO_TYPE_STRING: {
8303 str = mono_string_to_utf8 ((MonoString*)arg);
8304 slen = strlen (str);
8305 if ((p-buffer) + 10 + slen >= *buflen) {
8309 newbuf = g_realloc (buffer, *buflen);
8310 p = newbuf + (p-buffer);
8313 mono_metadata_encode_value (slen, p, &p);
8314 memcpy (p, str, slen);
8319 case MONO_TYPE_CLASS: {
8327 k = mono_object_class (arg);
8328 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8329 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8330 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8333 if (rt && (rtc = mono_object_class (rt)) &&
8334 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8335 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8336 arg = (MonoObject *) rt;
8339 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8342 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8343 slen = strlen (str);
8344 if ((p-buffer) + 10 + slen >= *buflen) {
8348 newbuf = g_realloc (buffer, *buflen);
8349 p = newbuf + (p-buffer);
8352 mono_metadata_encode_value (slen, p, &p);
8353 memcpy (p, str, slen);
8358 case MONO_TYPE_SZARRAY: {
8360 MonoClass *eclass, *arg_eclass;
8363 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8366 len = mono_array_length ((MonoArray*)arg);
8368 *p++ = (len >> 8) & 0xff;
8369 *p++ = (len >> 16) & 0xff;
8370 *p++ = (len >> 24) & 0xff;
8372 *retbuffer = buffer;
8373 eclass = type->data.klass;
8374 arg_eclass = mono_object_class (arg)->element_class;
8377 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8378 eclass = mono_defaults.object_class;
8380 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8381 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8382 int elsize = mono_class_array_element_size (arg_eclass);
8383 for (i = 0; i < len; ++i) {
8384 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8387 } else if (eclass->valuetype && arg_eclass->valuetype) {
8388 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8389 int elsize = mono_class_array_element_size (eclass);
8390 for (i = 0; i < len; ++i) {
8391 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8395 for (i = 0; i < len; ++i) {
8396 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8401 case MONO_TYPE_OBJECT: {
8407 * The parameter type is 'object' but the type of the actual
8408 * argument is not. So we have to add type information to the blob
8409 * too. This is completely undocumented in the spec.
8413 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8418 klass = mono_object_class (arg);
8420 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8423 } else if (klass->enumtype) {
8425 } else if (klass == mono_defaults.string_class) {
8426 simple_type = MONO_TYPE_STRING;
8429 } else if (klass->rank == 1) {
8431 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8432 /* See Partition II, Appendix B3 */
8435 *p++ = klass->element_class->byval_arg.type;
8436 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8438 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8439 *p++ = simple_type = klass->byval_arg.type;
8442 g_error ("unhandled type in custom attr");
8444 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8445 slen = strlen (str);
8446 if ((p-buffer) + 10 + slen >= *buflen) {
8450 newbuf = g_realloc (buffer, *buflen);
8451 p = newbuf + (p-buffer);
8454 mono_metadata_encode_value (slen, p, &p);
8455 memcpy (p, str, slen);
8458 simple_type = klass->enum_basetype->type;
8462 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8465 *retbuffer = buffer;
8469 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8471 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8472 char *str = type_get_qualified_name (type, NULL);
8473 int slen = strlen (str);
8477 * This seems to be optional...
8480 mono_metadata_encode_value (slen, p, &p);
8481 memcpy (p, str, slen);
8484 } else if (type->type == MONO_TYPE_OBJECT) {
8486 } else if (type->type == MONO_TYPE_CLASS) {
8487 /* it should be a type: encode_cattr_value () has the check */
8490 mono_metadata_encode_value (type->type, p, &p);
8491 if (type->type == MONO_TYPE_SZARRAY)
8492 /* See the examples in Partition VI, Annex B */
8493 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8500 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8503 /* Preallocate a large enough buffer */
8504 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8505 char *str = type_get_qualified_name (type, NULL);
8508 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8509 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8515 len += strlen (name);
8517 if ((p-buffer) + 20 + len >= *buflen) {
8521 newbuf = g_realloc (buffer, *buflen);
8522 p = newbuf + (p-buffer);
8526 encode_field_or_prop_type (type, p, &p);
8528 len = strlen (name);
8529 mono_metadata_encode_value (len, p, &p);
8530 memcpy (p, name, len);
8532 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8534 *retbuffer = buffer;
8538 * mono_reflection_get_custom_attrs_blob:
8539 * @ctor: custom attribute constructor
8540 * @ctorArgs: arguments o the constructor
8546 * Creates the blob of data that needs to be saved in the metadata and that represents
8547 * the custom attributed described by @ctor, @ctorArgs etc.
8548 * Returns: a Byte array representing the blob of data.
8551 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8554 MonoMethodSignature *sig;
8559 MONO_ARCH_SAVE_REGS;
8561 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8562 /* sig is freed later so allocate it in the heap */
8563 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8565 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8568 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8570 p = buffer = g_malloc (buflen);
8571 /* write the prolog */
8574 for (i = 0; i < sig->param_count; ++i) {
8575 arg = mono_array_get (ctorArgs, MonoObject*, i);
8576 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8580 i += mono_array_length (properties);
8582 i += mono_array_length (fields);
8584 *p++ = (i >> 8) & 0xff;
8587 for (i = 0; i < mono_array_length (properties); ++i) {
8591 prop = mono_array_get (properties, gpointer, i);
8592 get_prop_name_and_type (prop, &pname, &ptype);
8593 *p++ = 0x54; /* PROPERTY signature */
8594 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8601 for (i = 0; i < mono_array_length (fields); ++i) {
8605 field = mono_array_get (fields, gpointer, i);
8606 get_field_name_and_type (field, &fname, &ftype);
8607 *p++ = 0x53; /* FIELD signature */
8608 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8613 g_assert (p - buffer <= buflen);
8614 buflen = p - buffer;
8615 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8616 p = mono_array_addr (result, char, 0);
8617 memcpy (p, buffer, buflen);
8619 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8625 static void* reflection_info_desc = NULL;
8626 #define MOVING_GC_REGISTER(addr) do { \
8627 if (!reflection_info_desc) { \
8629 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8631 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8634 #define MOVING_GC_REGISTER(addr)
8638 * mono_reflection_setup_internal_class:
8639 * @tb: a TypeBuilder object
8641 * Creates a MonoClass that represents the TypeBuilder.
8642 * This is a trick that lets us simplify a lot of reflection code
8643 * (and will allow us to support Build and Run assemblies easier).
8646 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8648 MonoClass *klass, *parent;
8650 MONO_ARCH_SAVE_REGS;
8652 mono_loader_lock ();
8655 /* check so we can compile corlib correctly */
8656 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8657 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8658 parent = tb->parent->type->data.klass;
8660 parent = my_mono_class_from_mono_type (tb->parent->type);
8666 /* the type has already being created: it means we just have to change the parent */
8667 if (tb->type.type) {
8668 klass = mono_class_from_mono_type (tb->type.type);
8669 klass->parent = NULL;
8670 /* fool mono_class_setup_parent */
8671 klass->supertypes = NULL;
8672 mono_class_setup_parent (klass, parent);
8673 mono_class_setup_mono_type (klass);
8674 mono_loader_unlock ();
8678 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8680 klass->image = &tb->module->dynamic_image->image;
8682 klass->inited = 1; /* we lie to the runtime */
8683 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8684 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8685 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8686 klass->flags = tb->attrs;
8688 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8690 klass->element_class = klass;
8692 MOVING_GC_REGISTER (&klass->reflection_info);
8693 klass->reflection_info = tb;
8695 /* Put into cache so mono_class_get () will find it */
8696 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8698 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8699 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8701 if (parent != NULL) {
8702 mono_class_setup_parent (klass, parent);
8703 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8704 const char *old_n = klass->name;
8705 /* trick to get relative numbering right when compiling corlib */
8706 klass->name = "BuildingObject";
8707 mono_class_setup_parent (klass, mono_defaults.object_class);
8708 klass->name = old_n;
8711 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8712 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8713 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8714 klass->instance_size = sizeof (MonoObject);
8715 klass->size_inited = 1;
8716 mono_class_setup_vtable_general (klass, NULL, 0);
8719 mono_class_setup_mono_type (klass);
8721 mono_class_setup_supertypes (klass);
8724 * FIXME: handle interfaces.
8727 tb->type.type = &klass->byval_arg;
8729 if (tb->nesting_type) {
8730 g_assert (tb->nesting_type->type);
8731 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8734 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8736 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8738 mono_loader_unlock ();
8742 * mono_reflection_setup_generic_class:
8743 * @tb: a TypeBuilder object
8745 * Setup the generic class before adding the first generic parameter.
8748 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8752 MONO_ARCH_SAVE_REGS;
8754 klass = my_mono_class_from_mono_type (tb->type.type);
8755 if (tb->generic_container)
8758 tb->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8759 tb->generic_container->owner.klass = klass;
8763 * mono_reflection_create_generic_class:
8764 * @tb: a TypeBuilder object
8766 * Creates the generic class after all generic parameters have been added.
8769 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8774 MONO_ARCH_SAVE_REGS;
8776 klass = my_mono_class_from_mono_type (tb->type.type);
8778 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8780 if (klass->generic_container || (count == 0))
8783 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8785 klass->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
8787 klass->generic_container->owner.klass = klass;
8788 klass->generic_container->type_argc = count;
8789 klass->generic_container->type_params = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericParam) * count);
8791 for (i = 0; i < count; i++) {
8792 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8793 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8794 /*Make sure we are a diferent type instance */
8795 klass->generic_container->type_params [i].owner = klass->generic_container;
8796 klass->generic_container->type_params [i].pklass = NULL;
8798 g_assert (klass->generic_container->type_params [i].owner);
8801 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8805 * mono_reflection_create_internal_class:
8806 * @tb: a TypeBuilder object
8808 * Actually create the MonoClass that is associated with the TypeBuilder.
8811 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8815 MONO_ARCH_SAVE_REGS;
8817 klass = my_mono_class_from_mono_type (tb->type.type);
8819 mono_loader_lock ();
8820 if (klass->enumtype && klass->enum_basetype == NULL) {
8821 MonoReflectionFieldBuilder *fb;
8824 g_assert (tb->fields != NULL);
8825 g_assert (mono_array_length (tb->fields) >= 1);
8827 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8829 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8830 mono_loader_unlock ();
8834 klass->enum_basetype = fb->type->type;
8835 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8836 if (!klass->element_class)
8837 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8840 * get the element_class from the current corlib.
8842 ec = default_class_from_mono_type (klass->enum_basetype);
8843 klass->instance_size = ec->instance_size;
8844 klass->size_inited = 1;
8846 * this is almost safe to do with enums and it's needed to be able
8847 * to create objects of the enum type (for use in SetConstant).
8849 /* FIXME: Does this mean enums can't have method overrides ? */
8850 mono_class_setup_vtable_general (klass, NULL, 0);
8852 mono_loader_unlock ();
8855 static MonoMarshalSpec*
8856 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
8857 MonoReflectionMarshal *minfo)
8859 MonoMarshalSpec *res;
8861 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
8862 res->native = minfo->type;
8864 switch (minfo->type) {
8865 case MONO_NATIVE_LPARRAY:
8866 res->data.array_data.elem_type = minfo->eltype;
8867 if (minfo->has_size) {
8868 res->data.array_data.param_num = minfo->param_num;
8869 res->data.array_data.num_elem = minfo->count;
8870 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8873 res->data.array_data.param_num = -1;
8874 res->data.array_data.num_elem = -1;
8875 res->data.array_data.elem_mult = -1;
8879 case MONO_NATIVE_BYVALTSTR:
8880 case MONO_NATIVE_BYVALARRAY:
8881 res->data.array_data.num_elem = minfo->count;
8884 case MONO_NATIVE_CUSTOM:
8885 if (minfo->marshaltyperef)
8886 res->data.custom_data.custom_name =
8887 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8889 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8899 MonoReflectionMarshal*
8900 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8901 MonoMarshalSpec *spec)
8903 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8904 MonoReflectionMarshal *minfo;
8907 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8908 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8909 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8910 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8913 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8914 minfo->type = spec->native;
8916 switch (minfo->type) {
8917 case MONO_NATIVE_LPARRAY:
8918 minfo->eltype = spec->data.array_data.elem_type;
8919 minfo->count = spec->data.array_data.num_elem;
8920 minfo->param_num = spec->data.array_data.param_num;
8923 case MONO_NATIVE_BYVALTSTR:
8924 case MONO_NATIVE_BYVALARRAY:
8925 minfo->count = spec->data.array_data.num_elem;
8928 case MONO_NATIVE_CUSTOM:
8929 if (spec->data.custom_data.custom_name) {
8930 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8932 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8934 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8936 if (spec->data.custom_data.cookie)
8937 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8948 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8949 ReflectionMethodBuilder *rmb,
8950 MonoMethodSignature *sig)
8953 MonoMethodNormal *pm;
8954 MonoMarshalSpec **specs;
8955 MonoReflectionMethodAux *method_aux;
8961 * Methods created using a MethodBuilder should have their memory allocated
8962 * inside the image mempool, while dynamic methods should have their memory
8965 dynamic = rmb->refs != NULL;
8966 mp = dynamic ? NULL : klass->image->mempool;
8969 g_assert (!klass->generic_class);
8971 mono_loader_lock ();
8973 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8974 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8975 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8977 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8979 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8981 pm = (MonoMethodNormal*)m;
8983 m->dynamic = dynamic;
8985 m->flags = rmb->attrs;
8986 m->iflags = rmb->iattrs;
8987 m->name = mp_string_to_utf8 (mp, rmb->name);
8990 m->skip_visibility = rmb->skip_visibility;
8992 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8994 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8995 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8998 m->signature->pinvoke = 1;
8999 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9000 m->signature->pinvoke = 1;
9002 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9004 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9005 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9007 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9009 if (klass->image->dynamic)
9010 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9012 mono_loader_unlock ();
9015 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9016 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9017 MonoMethodHeader *header;
9019 gint32 max_stack, i;
9020 gint32 num_locals = 0;
9021 gint32 num_clauses = 0;
9025 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9026 code_size = rmb->ilgen->code_len;
9027 max_stack = rmb->ilgen->max_stack;
9028 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9029 if (rmb->ilgen->ex_handlers)
9030 num_clauses = method_count_clauses (rmb->ilgen);
9033 code = mono_array_addr (rmb->code, guint8, 0);
9034 code_size = mono_array_length (rmb->code);
9035 /* we probably need to run a verifier on the code... */
9045 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9046 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9047 header->code_size = code_size;
9048 header->code = mp_g_malloc (mp, code_size);
9049 memcpy ((char*)header->code, code, code_size);
9050 header->max_stack = max_stack;
9051 header->init_locals = rmb->init_locals;
9052 header->num_locals = num_locals;
9054 for (i = 0; i < num_locals; ++i) {
9055 MonoReflectionLocalBuilder *lb =
9056 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9058 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9059 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9062 header->num_clauses = num_clauses;
9064 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9065 rmb->ilgen, num_clauses);
9068 pm->header = header;
9071 if (rmb->generic_params) {
9072 int count = mono_array_length (rmb->generic_params);
9073 MonoGenericContainer *container;
9075 container = rmb->generic_container;
9077 m->is_generic = TRUE;
9078 mono_method_set_generic_container (m, container);
9080 container->type_argc = count;
9081 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9082 container->owner.method = m;
9084 for (i = 0; i < count; i++) {
9085 MonoReflectionGenericParam *gp =
9086 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9088 container->type_params [i] = *gp->type.type->data.generic_param;
9091 if (klass->generic_container) {
9092 container->parent = klass->generic_container;
9093 container->context.class_inst = klass->generic_container->context.class_inst;
9095 container->context.method_inst = mono_get_shared_generic_inst (container);
9099 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9103 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9105 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9106 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9107 for (i = 0; i < rmb->nrefs; ++i)
9108 data [i + 1] = rmb->refs [i];
9113 /* Parameter info */
9116 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9117 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9118 for (i = 0; i <= m->signature->param_count; ++i) {
9119 MonoReflectionParamBuilder *pb;
9120 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9121 if ((i > 0) && (pb->attrs)) {
9122 /* Make a copy since it might point to a shared type structure */
9123 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9124 m->signature->params [i - 1]->attrs = pb->attrs;
9127 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9128 MonoDynamicImage *assembly;
9129 guint32 idx, def_type, len;
9133 if (!method_aux->param_defaults) {
9134 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9135 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9137 assembly = (MonoDynamicImage*)klass->image;
9138 idx = encode_constant (assembly, pb->def_value, &def_type);
9139 /* Copy the data from the blob since it might get realloc-ed */
9140 p = assembly->blob.data + idx;
9141 len = mono_metadata_decode_blob_size (p, &p2);
9143 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9144 method_aux->param_default_types [i] = def_type;
9145 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9149 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9151 if (!method_aux->param_cattr)
9152 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9153 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9159 /* Parameter marshalling */
9162 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9163 MonoReflectionParamBuilder *pb;
9164 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9165 if (pb->marshal_info) {
9167 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9168 specs [pb->position] =
9169 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9173 if (specs != NULL) {
9175 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9176 method_aux->param_marshall = specs;
9179 if (klass->image->dynamic && method_aux)
9180 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9182 mono_loader_unlock ();
9188 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9190 ReflectionMethodBuilder rmb;
9191 MonoMethodSignature *sig;
9193 mono_loader_lock ();
9194 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9195 mono_loader_unlock ();
9197 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9199 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9200 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9202 /* If we are in a generic class, we might be called multiple times from inflate_method */
9203 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9204 /* ilgen is no longer needed */
9212 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9214 ReflectionMethodBuilder rmb;
9215 MonoMethodSignature *sig;
9217 mono_loader_lock ();
9218 sig = method_builder_to_signature (klass->image->mempool, mb);
9219 mono_loader_unlock ();
9221 reflection_methodbuilder_from_method_builder (&rmb, mb);
9223 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9224 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9226 /* If we are in a generic class, we might be called multiple times from inflate_method */
9227 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9228 /* ilgen is no longer needed */
9234 static MonoClassField*
9235 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9237 MonoClassField *field;
9241 field = g_new0 (MonoClassField, 1);
9243 field->name = mono_string_to_utf8 (fb->name);
9245 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9246 field->type->attrs = fb->attrs;
9248 field->type = fb->type->type;
9250 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9251 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9252 if (fb->offset != -1)
9253 field->offset = fb->offset;
9254 field->parent = klass;
9255 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9257 if (fb->def_value) {
9258 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9259 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9260 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9261 /* Copy the data from the blob since it might get realloc-ed */
9262 p = assembly->blob.data + idx;
9263 len = mono_metadata_decode_blob_size (p, &p2);
9265 field->data = g_malloc (len);
9266 memcpy ((gpointer)field->data, p, len);
9273 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9276 MonoReflectionTypeBuilder *tb = NULL;
9277 gboolean is_dynamic = FALSE;
9281 mono_loader_lock ();
9283 domain = mono_object_domain (type);
9285 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9286 tb = (MonoReflectionTypeBuilder *) type;
9289 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9290 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9292 tb = rgi->generic_type;
9296 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9297 if (tb && tb->generic_container)
9298 mono_reflection_create_generic_class (tb);
9300 klass = mono_class_from_mono_type (type->type);
9301 if (!klass->generic_container) {
9302 mono_loader_unlock ();
9306 if (klass->wastypebuilder) {
9307 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9312 mono_loader_unlock ();
9314 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9316 return &geninst->byval_arg;
9320 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9322 MonoGenericClass *gclass;
9323 MonoGenericInst *inst;
9325 g_assert (klass->generic_container);
9327 inst = mono_metadata_get_generic_inst (type_argc, types);
9328 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9330 return mono_generic_class_get_class (gclass);
9333 MonoReflectionMethod*
9334 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9337 MonoMethod *method, *inflated;
9338 MonoMethodInflated *imethod;
9339 MonoReflectionMethodBuilder *mb = NULL;
9340 MonoGenericContext tmp_context;
9341 MonoGenericInst *ginst;
9342 MonoType **type_argv;
9345 MONO_ARCH_SAVE_REGS;
9346 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9347 MonoReflectionTypeBuilder *tb;
9350 mb = (MonoReflectionMethodBuilder *) rmethod;
9351 tb = (MonoReflectionTypeBuilder *) mb->type;
9352 klass = mono_class_from_mono_type (tb->type.type);
9354 method = methodbuilder_to_mono_method (klass, mb);
9356 method = rmethod->method;
9359 klass = method->klass;
9361 if (method->is_inflated)
9362 method = ((MonoMethodInflated *) method)->declaring;
9364 count = mono_method_signature (method)->generic_param_count;
9365 if (count != mono_array_length (types))
9368 type_argv = g_new0 (MonoType *, count);
9369 for (i = 0; i < count; i++) {
9370 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9371 type_argv [i] = garg->type;
9373 ginst = mono_metadata_get_generic_inst (count, type_argv);
9376 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9377 tmp_context.method_inst = ginst;
9379 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9380 imethod = (MonoMethodInflated *) inflated;
9382 if (method->klass->image->dynamic) {
9383 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9385 * This table maps metadata structures representing inflated methods/fields
9386 * to the reflection objects representing their generic definitions.
9388 mono_loader_lock ();
9389 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9390 mono_loader_unlock ();
9393 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9397 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9399 MonoMethodInflated *imethod;
9400 MonoGenericContext *context;
9403 g_assert (klass->generic_class);
9404 context = mono_class_get_context (klass);
9406 if (klass->method.count) {
9407 /* Find the already created inflated method */
9408 for (i = 0; i < klass->method.count; ++i) {
9409 g_assert (klass->methods [i]->is_inflated);
9410 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9413 g_assert (i < klass->method.count);
9414 imethod = (MonoMethodInflated*)klass->methods [i];
9416 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9419 if (method->is_generic && method->klass->image->dynamic) {
9420 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9422 mono_loader_lock ();
9423 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9424 mono_loader_unlock ();
9426 return (MonoMethod *) imethod;
9430 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9435 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9437 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9438 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9439 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9441 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9442 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9443 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9444 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9445 method = ((MonoReflectionMethod *) obj)->method;
9447 method = NULL; /* prevent compiler warning */
9448 g_assert_not_reached ();
9451 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9454 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9456 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9457 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9460 MonoGenericClass *gclass;
9461 MonoDynamicGenericClass *dgclass;
9462 MonoClass *klass, *gklass;
9465 MONO_ARCH_SAVE_REGS;
9467 klass = mono_class_from_mono_type (type->type.type);
9468 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9469 gclass = type->type.type->data.generic_class;
9471 g_assert (gclass->is_dynamic);
9472 dgclass = (MonoDynamicGenericClass *) gclass;
9474 if (dgclass->initialized)
9477 gklass = gclass->container_class;
9478 mono_class_init (gklass);
9480 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9481 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9482 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9483 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9484 dgclass->count_events = events ? mono_array_length (events) : 0;
9486 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9487 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9488 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9489 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9490 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9492 for (i = 0; i < dgclass->count_methods; i++) {
9493 MonoObject *obj = mono_array_get (methods, gpointer, i);
9495 dgclass->methods [i] = inflate_method (type, obj);
9498 for (i = 0; i < dgclass->count_ctors; i++) {
9499 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9501 dgclass->ctors [i] = inflate_method (type, obj);
9504 for (i = 0; i < dgclass->count_fields; i++) {
9505 MonoObject *obj = mono_array_get (fields, gpointer, i);
9506 MonoClassField *field, *inflated_field = NULL;
9507 MonoInflatedField *ifield;
9509 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9510 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9511 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9512 field = ((MonoReflectionField *) obj)->field;
9514 field = NULL; /* prevent compiler warning */
9515 g_assert_not_reached ();
9518 ifield = g_new0 (MonoInflatedField, 1);
9519 ifield->generic_type = field->type;
9520 MOVING_GC_REGISTER (&ifield->reflection_info);
9521 ifield->reflection_info = obj;
9523 dgclass->fields [i] = *field;
9524 dgclass->fields [i].parent = klass;
9525 dgclass->fields [i].generic_info = ifield;
9526 dgclass->fields [i].type = mono_class_inflate_generic_type (
9527 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9529 if (inflated_field) {
9530 g_free ((char*)inflated_field->data);
9531 g_free (inflated_field);
9533 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9537 for (i = 0; i < dgclass->count_properties; i++) {
9538 MonoObject *obj = mono_array_get (properties, gpointer, i);
9539 MonoProperty *property = &dgclass->properties [i];
9541 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9542 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9544 property->parent = klass;
9545 property->attrs = pb->attrs;
9546 property->name = mono_string_to_utf8 (pb->name);
9548 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9550 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9551 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9552 *property = *((MonoReflectionProperty *) obj)->property;
9553 property->name = g_strdup (property->name);
9556 property->get = inflate_mono_method (klass, property->get, NULL);
9558 property->set = inflate_mono_method (klass, property->set, NULL);
9560 g_assert_not_reached ();
9563 for (i = 0; i < dgclass->count_events; i++) {
9564 MonoObject *obj = mono_array_get (events, gpointer, i);
9565 MonoEvent *event = &dgclass->events [i];
9567 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9568 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9570 event->parent = klass;
9571 event->attrs = eb->attrs;
9572 event->name = mono_string_to_utf8 (eb->name);
9574 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9575 if (eb->remove_method)
9576 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9577 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9578 *event = *((MonoReflectionEvent *) obj)->event;
9579 event->name = g_strdup (event->name);
9582 event->add = inflate_mono_method (klass, event->add, NULL);
9584 event->remove = inflate_mono_method (klass, event->remove, NULL);
9586 g_assert_not_reached ();
9589 dgclass->initialized = TRUE;
9593 ensure_runtime_vtable (MonoClass *klass)
9595 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9598 if (!tb || klass->wastypebuilder)
9601 ensure_runtime_vtable (klass->parent);
9603 num = tb->ctors? mono_array_length (tb->ctors): 0;
9604 num += tb->num_methods;
9605 klass->method.count = num;
9606 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9607 num = tb->ctors? mono_array_length (tb->ctors): 0;
9608 for (i = 0; i < num; ++i)
9609 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9610 num = tb->num_methods;
9612 for (i = 0; i < num; ++i)
9613 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9615 if (tb->interfaces) {
9616 klass->interface_count = mono_array_length (tb->interfaces);
9617 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9618 for (i = 0; i < klass->interface_count; ++i) {
9619 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9620 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9624 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9625 for (i = 0; i < klass->method.count; ++i)
9626 klass->methods [i]->slot = i;
9628 mono_class_setup_interface_offsets (klass);
9632 * The generic vtable is needed even if image->run is not set since some
9633 * runtime code like ves_icall_Type_GetMethodsByName depends on
9634 * method->slot being defined.
9638 * tb->methods could not be freed since it is used for determining
9639 * overrides during dynamic vtable construction.
9644 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9646 MonoReflectionTypeBuilder *tb;
9652 g_assert (klass->image->dynamic);
9654 if (!klass->reflection_info)
9657 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9659 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9663 for (i = 0; i < tb->num_methods; ++i) {
9664 MonoReflectionMethodBuilder *mb =
9665 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9666 if (mb->override_method)
9672 *overrides = g_new0 (MonoMethod*, onum * 2);
9675 for (i = 0; i < tb->num_methods; ++i) {
9676 MonoReflectionMethodBuilder *mb =
9677 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9678 if (mb->override_method) {
9679 (*overrides) [onum * 2] =
9680 mb->override_method->method;
9681 (*overrides) [onum * 2 + 1] =
9684 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9685 g_assert (mb->override_method->method);
9686 g_assert (mb->mhandle);
9693 *num_overrides = onum;
9697 typebuilder_setup_fields (MonoClass *klass)
9699 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9700 MonoReflectionFieldBuilder *fb;
9701 MonoClassField *field;
9702 MonoMemPool *mp = klass->image->mempool;
9707 klass->field.count = tb->num_fields;
9708 klass->field.first = 0;
9710 if (!klass->field.count)
9713 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9715 for (i = 0; i < klass->field.count; ++i) {
9716 fb = mono_array_get (tb->fields, gpointer, i);
9717 field = &klass->fields [i];
9718 field->name = mp_string_to_utf8 (mp, fb->name);
9720 field->type = mono_metadata_type_dup (mp, fb->type->type);
9721 field->type->attrs = fb->attrs;
9723 field->type = fb->type->type;
9725 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9726 field->data = mono_array_addr (fb->rva_data, char, 0);
9727 if (fb->offset != -1)
9728 field->offset = fb->offset;
9729 field->parent = klass;
9731 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9733 if (fb->def_value) {
9734 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9735 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9736 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9737 /* Copy the data from the blob since it might get realloc-ed */
9738 p = assembly->blob.data + idx;
9739 len = mono_metadata_decode_blob_size (p, &p2);
9741 field->data = mono_mempool_alloc (mp, len);
9742 memcpy ((gpointer)field->data, p, len);
9745 mono_class_layout_fields (klass);
9749 typebuilder_setup_properties (MonoClass *klass)
9751 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9752 MonoReflectionPropertyBuilder *pb;
9753 MonoMemPool *mp = klass->image->mempool;
9756 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9757 klass->property.first = 0;
9759 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9760 for (i = 0; i < klass->property.count; ++i) {
9761 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9762 klass->properties [i].parent = klass;
9763 klass->properties [i].attrs = pb->attrs;
9764 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9766 klass->properties [i].get = pb->get_method->mhandle;
9768 klass->properties [i].set = pb->set_method->mhandle;
9770 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9774 MonoReflectionEvent *
9775 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9777 MonoEvent *event = g_new0 (MonoEvent, 1);
9781 klass = my_mono_class_from_mono_type (tb->type.type);
9783 event->parent = klass;
9784 event->attrs = eb->attrs;
9785 event->name = mono_string_to_utf8 (eb->name);
9787 event->add = eb->add_method->mhandle;
9788 if (eb->remove_method)
9789 event->remove = eb->remove_method->mhandle;
9790 if (eb->raise_method)
9791 event->raise = eb->raise_method->mhandle;
9793 if (eb->other_methods) {
9794 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9795 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9796 MonoReflectionMethodBuilder *mb =
9797 mono_array_get (eb->other_methods,
9798 MonoReflectionMethodBuilder*, j);
9799 event->other [j] = mb->mhandle;
9803 return mono_event_get_object (mono_object_domain (tb), klass, event);
9807 typebuilder_setup_events (MonoClass *klass)
9809 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9810 MonoReflectionEventBuilder *eb;
9811 MonoMemPool *mp = klass->image->mempool;
9814 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9815 klass->event.first = 0;
9817 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
9818 for (i = 0; i < klass->event.count; ++i) {
9819 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9820 klass->events [i].parent = klass;
9821 klass->events [i].attrs = eb->attrs;
9822 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
9824 klass->events [i].add = eb->add_method->mhandle;
9825 if (eb->remove_method)
9826 klass->events [i].remove = eb->remove_method->mhandle;
9827 if (eb->raise_method)
9828 klass->events [i].raise = eb->raise_method->mhandle;
9830 if (eb->other_methods) {
9831 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
9832 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9833 MonoReflectionMethodBuilder *mb =
9834 mono_array_get (eb->other_methods,
9835 MonoReflectionMethodBuilder*, j);
9836 klass->events [i].other [j] = mb->mhandle;
9839 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
9844 remove_instantiations_of (gpointer key,
9848 MonoType *type = (MonoType*)key;
9849 MonoClass *klass = (MonoClass*)user_data;
9851 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
9858 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9862 MonoReflectionType* res;
9865 MONO_ARCH_SAVE_REGS;
9867 domain = mono_object_domain (tb);
9868 klass = my_mono_class_from_mono_type (tb->type.type);
9870 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9873 * we need to lock the domain because the lock will be taken inside
9874 * So, we need to keep the locking order correct.
9876 mono_domain_lock (domain);
9877 mono_loader_lock ();
9878 if (klass->wastypebuilder) {
9879 mono_loader_unlock ();
9880 mono_domain_unlock (domain);
9881 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9884 * Fields to set in klass:
9885 * the various flags: delegate/unicode/contextbound etc.
9887 klass->flags = tb->attrs;
9888 klass->has_cctor = 1;
9889 klass->has_finalize = 1;
9892 if (!((MonoDynamicImage*)klass->image)->run) {
9893 if (klass->generic_container) {
9894 /* FIXME: The code below can't handle generic classes */
9895 klass->wastypebuilder = TRUE;
9896 mono_loader_unlock ();
9897 mono_domain_unlock (domain);
9898 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9903 /* enums are done right away */
9904 if (!klass->enumtype)
9905 ensure_runtime_vtable (klass);
9908 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9909 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9910 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9914 /* fields and object layout */
9915 if (klass->parent) {
9916 if (!klass->parent->size_inited)
9917 mono_class_init (klass->parent);
9918 klass->instance_size = klass->parent->instance_size;
9919 klass->sizes.class_size = 0;
9920 klass->min_align = klass->parent->min_align;
9921 /* if the type has no fields we won't call the field_setup
9922 * routine which sets up klass->has_references.
9924 klass->has_references |= klass->parent->has_references;
9926 klass->instance_size = sizeof (MonoObject);
9927 klass->min_align = 1;
9930 /* FIXME: handle packing_size and instance_size */
9931 typebuilder_setup_fields (klass);
9933 typebuilder_setup_properties (klass);
9935 typebuilder_setup_events (klass);
9937 klass->wastypebuilder = TRUE;
9940 * If we are a generic TypeBuilder, there might be instantiations in the type cache
9941 * which have type System.Reflection.MonoGenericClass, but after the type is created,
9942 * we want to return normal System.MonoType objects, so clear these out from the cache.
9944 if (domain->type_hash && klass->generic_container)
9945 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
9947 mono_loader_unlock ();
9948 mono_domain_unlock (domain);
9950 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9951 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9952 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9955 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9956 g_assert (res != (MonoReflectionType*)tb);
9962 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9964 MonoGenericParam *param;
9967 MONO_ARCH_SAVE_REGS;
9969 param = g_new0 (MonoGenericParam, 1);
9971 if (gparam->mbuilder) {
9972 if (!gparam->mbuilder->generic_container) {
9973 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
9974 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
9975 gparam->mbuilder->generic_container = mono_mempool_alloc0 (klass->image->mempool, sizeof (MonoGenericContainer));
9976 gparam->mbuilder->generic_container->is_method = TRUE;
9978 param->owner = gparam->mbuilder->generic_container;
9979 } else if (gparam->tbuilder) {
9980 g_assert (gparam->tbuilder->generic_container);
9981 param->owner = gparam->tbuilder->generic_container;
9984 param->name = mono_string_to_utf8 (gparam->name);
9985 param->num = gparam->index;
9987 image = &gparam->tbuilder->module->dynamic_image->image;
9988 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9990 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9991 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9993 gparam->type.type = g_new0 (MonoType, 1);
9994 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9995 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9996 gparam->type.type->data.generic_param = param;
10000 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10002 MonoDynamicImage *assembly = sig->module->dynamic_image;
10003 guint32 na = mono_array_length (sig->arguments);
10008 sigbuffer_init (&buf, 32);
10010 sigbuffer_add_value (&buf, 0x07);
10011 sigbuffer_add_value (&buf, na);
10012 for (i = 0; i < na; ++i) {
10013 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10014 encode_reflection_type (assembly, type, &buf);
10017 buflen = buf.p - buf.buf;
10018 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10019 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10020 sigbuffer_free (&buf);
10026 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10028 MonoDynamicImage *assembly = sig->module->dynamic_image;
10029 guint32 na = mono_array_length (sig->arguments);
10034 sigbuffer_init (&buf, 32);
10036 sigbuffer_add_value (&buf, 0x06);
10037 for (i = 0; i < na; ++i) {
10038 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10039 encode_reflection_type (assembly, type, &buf);
10042 buflen = buf.p - buf.buf;
10043 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10044 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10045 sigbuffer_free (&buf);
10051 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10053 ReflectionMethodBuilder rmb;
10054 MonoMethodSignature *sig;
10059 sig = dynamic_method_to_signature (mb);
10061 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10064 * Resolve references.
10067 * Every second entry in the refs array is reserved for storing handle_class,
10068 * which is needed by the ldtoken implementation in the JIT.
10070 rmb.nrefs = mb->nrefs;
10071 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10072 for (i = 0; i < mb->nrefs; i += 2) {
10073 MonoClass *handle_class;
10075 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10077 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10078 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10080 * The referenced DynamicMethod should already be created by the managed
10081 * code, except in the case of circular references. In that case, we store
10082 * method in the refs array, and fix it up later when the referenced
10083 * DynamicMethod is created.
10085 if (method->mhandle) {
10086 ref = method->mhandle;
10088 /* FIXME: GC object stored in unmanaged memory */
10091 /* FIXME: GC object stored in unmanaged memory */
10092 method->referenced_by = g_slist_append (method->referenced_by, mb);
10094 handle_class = mono_defaults.methodhandle_class;
10096 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10099 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10104 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10105 rmb.refs [i + 1] = handle_class;
10108 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10110 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10112 /* Fix up refs entries pointing at us */
10113 for (l = mb->referenced_by; l; l = l->next) {
10114 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10115 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10118 g_assert (method->mhandle);
10120 data = (gpointer*)wrapper->method_data;
10121 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10122 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10123 data [i + 1] = mb->mhandle;
10126 g_slist_free (mb->referenced_by);
10130 /* ilgen is no longer needed */
10135 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10140 mono_runtime_free_method (
10141 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10146 * mono_reflection_is_valid_dynamic_token:
10148 * Returns TRUE if token is valid.
10152 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10154 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10158 * mono_reflection_lookup_dynamic_token:
10160 * Finish the Builder object pointed to by TOKEN and return the corresponding
10161 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10162 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10166 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10168 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10172 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10175 g_assert_not_reached ();
10181 handle_class = &klass;
10182 return resolve_object (image, obj, handle_class, context);
10186 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10188 gpointer result = NULL;
10190 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10191 result = mono_string_intern ((MonoString*)obj);
10192 *handle_class = NULL;
10194 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10195 MonoReflectionType *tb = (MonoReflectionType*)obj;
10197 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10198 result = mono_class_from_mono_type (inflated);
10199 mono_metadata_free_type (inflated);
10201 result = mono_class_from_mono_type (tb->type);
10203 *handle_class = mono_defaults.typehandle_class;
10205 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10206 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10207 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10208 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10209 result = ((MonoReflectionMethod*)obj)->method;
10211 result = mono_class_inflate_generic_method (result, context);
10212 *handle_class = mono_defaults.methodhandle_class;
10214 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10215 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10216 result = mb->mhandle;
10218 /* Type is not yet created */
10219 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10221 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10224 * Hopefully this has been filled in by calling CreateType() on the
10228 * TODO: This won't work if the application finishes another
10229 * TypeBuilder instance instead of this one.
10231 result = mb->mhandle;
10234 result = mono_class_inflate_generic_method (result, context);
10235 *handle_class = mono_defaults.methodhandle_class;
10236 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10237 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10239 result = cb->mhandle;
10241 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10243 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10244 result = cb->mhandle;
10247 result = mono_class_inflate_generic_method (result, context);
10248 *handle_class = mono_defaults.methodhandle_class;
10249 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10250 result = ((MonoReflectionField*)obj)->field;
10251 *handle_class = mono_defaults.fieldhandle_class;
10253 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10254 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10255 result = fb->handle;
10258 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10260 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10261 result = fb->handle;
10264 if (fb->handle && fb->handle->parent->generic_container) {
10265 MonoClass *klass = fb->handle->parent;
10266 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10267 MonoClass *inflated = mono_class_from_mono_type (type);
10269 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10271 mono_metadata_free_type (type);
10273 *handle_class = mono_defaults.fieldhandle_class;
10274 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10275 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10278 klass = tb->type.type->data.klass;
10279 if (klass->wastypebuilder) {
10280 /* Already created */
10284 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10285 result = tb->type.type->data.klass;
10288 *handle_class = mono_defaults.typehandle_class;
10289 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10290 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10291 MonoMethodSignature *sig;
10294 if (helper->arguments)
10295 nargs = mono_array_length (helper->arguments);
10299 sig = mono_metadata_signature_alloc (image, nargs);
10300 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10301 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10303 if (helper->call_conv == 0) /* unmanaged */
10304 sig->call_convention = helper->unmanaged_call_conv - 1;
10306 if (helper->call_conv & 0x02)
10307 sig->call_convention = MONO_CALL_VARARG;
10309 sig->call_convention = MONO_CALL_DEFAULT;
10311 sig->param_count = nargs;
10312 /* TODO: Copy type ? */
10313 sig->ret = helper->return_type->type;
10314 for (i = 0; i < nargs; ++i) {
10315 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10316 sig->params [i] = rt->type;
10320 *handle_class = NULL;
10321 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10322 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10323 /* Already created by the managed code */
10324 g_assert (method->mhandle);
10325 result = method->mhandle;
10326 *handle_class = mono_defaults.methodhandle_class;
10327 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10328 MonoReflectionType *tb = (MonoReflectionType*)obj;
10329 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10330 result = mono_class_from_mono_type (type);
10331 *handle_class = mono_defaults.typehandle_class;
10333 mono_metadata_free_type (type);
10334 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10335 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10336 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10337 result = mono_class_from_mono_type (type);
10338 *handle_class = mono_defaults.typehandle_class;
10340 mono_metadata_free_type (type);
10341 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10342 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10343 MonoClass *inflated;
10346 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10347 inflated = mono_class_from_mono_type (type);
10349 g_assert (f->fb->handle);
10350 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10352 mono_metadata_free_type (type);
10353 *handle_class = mono_defaults.fieldhandle_class;
10354 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10355 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10356 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10357 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10358 g_assert (c->cb->mhandle);
10359 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10360 *handle_class = mono_defaults.methodhandle_class;
10361 mono_metadata_free_type (type);
10362 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10363 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10364 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10365 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10366 g_assert (m->mb->mhandle);
10367 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10368 *handle_class = mono_defaults.methodhandle_class;
10369 mono_metadata_free_type (type);
10371 g_print (obj->vtable->klass->name);
10372 g_assert_not_reached ();
10378 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10379 const static guint32 declsec_flags_map[] = {
10380 0x00000000, /* empty */
10381 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10382 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10383 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10384 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10385 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10386 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10387 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10388 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10389 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10390 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10391 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10392 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10393 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10394 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10395 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10396 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10397 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10398 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10402 * Returns flags that includes all available security action associated to the handle.
10403 * @token: metadata token (either for a class or a method)
10404 * @image: image where resides the metadata.
10407 mono_declsec_get_flags (MonoImage *image, guint32 token)
10409 int index = mono_metadata_declsec_from_index (image, token);
10410 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10411 guint32 result = 0;
10415 /* HasSecurity can be present for other, not specially encoded, attributes,
10416 e.g. SuppressUnmanagedCodeSecurityAttribute */
10420 for (i = index; i < t->rows; i++) {
10421 guint32 cols [MONO_DECL_SECURITY_SIZE];
10423 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10424 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10427 action = cols [MONO_DECL_SECURITY_ACTION];
10428 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10429 result |= declsec_flags_map [action];
10431 g_assert_not_reached ();
10438 * Get the security actions (in the form of flags) associated with the specified method.
10440 * @method: The method for which we want the declarative security flags.
10441 * Return the declarative security flags for the method (only).
10443 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10444 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10447 mono_declsec_flags_from_method (MonoMethod *method)
10449 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10450 /* FIXME: No cache (for the moment) */
10451 guint32 idx = mono_method_get_index (method);
10452 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10453 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10454 return mono_declsec_get_flags (method->klass->image, idx);
10460 * Get the security actions (in the form of flags) associated with the specified class.
10462 * @klass: The class for which we want the declarative security flags.
10463 * Return the declarative security flags for the class.
10465 * Note: We cache the flags inside the MonoClass structure as this will get
10466 * called very often (at least for each method).
10469 mono_declsec_flags_from_class (MonoClass *klass)
10471 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10472 if (!klass->declsec_flags) {
10473 guint32 idx = mono_metadata_token_index (klass->type_token);
10474 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10475 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10476 /* we cache the flags on classes */
10477 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10479 return klass->declsec_flags;
10485 * Get the security actions (in the form of flags) associated with the specified assembly.
10487 * @assembly: The assembly for which we want the declarative security flags.
10488 * Return the declarative security flags for the assembly.
10491 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10493 guint32 idx = 1; /* there is only one assembly */
10494 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10495 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10496 return mono_declsec_get_flags (assembly->image, idx);
10501 * Fill actions for the specific index (which may either be an encoded class token or
10502 * an encoded method token) from the metadata image.
10503 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10506 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10507 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10509 MonoBoolean result = FALSE;
10511 guint32 cols [MONO_DECL_SECURITY_SIZE];
10512 int index = mono_metadata_declsec_from_index (image, token);
10515 t = &image->tables [MONO_TABLE_DECLSECURITY];
10516 for (i = index; i < t->rows; i++) {
10517 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10519 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10522 /* if present only replace (class) permissions with method permissions */
10523 /* if empty accept either class or method permissions */
10524 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10525 if (!actions->demand.blob) {
10526 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10527 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10528 actions->demand.blob = (char*) (blob + 2);
10529 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10532 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10533 if (!actions->noncasdemand.blob) {
10534 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10535 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10536 actions->noncasdemand.blob = (char*) (blob + 2);
10537 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10540 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10541 if (!actions->demandchoice.blob) {
10542 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10543 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10544 actions->demandchoice.blob = (char*) (blob + 2);
10545 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10555 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10556 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10558 guint32 idx = mono_metadata_token_index (klass->type_token);
10559 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10560 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10561 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10565 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10566 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10568 guint32 idx = mono_method_get_index (method);
10569 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10570 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10571 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10575 * Collect all actions (that requires to generate code in mini) assigned for
10576 * the specified method.
10577 * Note: Don't use the content of actions if the function return FALSE.
10580 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10582 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10583 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10584 MonoBoolean result = FALSE;
10587 /* quick exit if no declarative security is present in the metadata */
10588 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10591 /* we want the original as the wrapper is "free" of the security informations */
10592 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10593 method = mono_marshal_method_from_wrapper (method);
10598 /* First we look for method-level attributes */
10599 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10600 mono_class_init (method->klass);
10601 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10603 result = mono_declsec_get_method_demands_params (method, demands,
10604 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10607 /* Here we use (or create) the class declarative cache to look for demands */
10608 flags = mono_declsec_flags_from_class (method->klass);
10609 if (flags & mask) {
10611 mono_class_init (method->klass);
10612 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10614 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10615 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10618 /* The boolean return value is used as a shortcut in case nothing needs to
10619 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10625 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10627 * Note: Don't use the content of actions if the function return FALSE.
10630 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10632 MonoBoolean result = FALSE;
10635 /* quick exit if no declarative security is present in the metadata */
10636 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10639 /* we want the original as the wrapper is "free" of the security informations */
10640 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10641 method = mono_marshal_method_from_wrapper (method);
10646 /* results are independant - zeroize both */
10647 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10648 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10650 /* First we look for method-level attributes */
10651 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10652 mono_class_init (method->klass);
10654 result = mono_declsec_get_method_demands_params (method, cmethod,
10655 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10658 /* Here we use (or create) the class declarative cache to look for demands */
10659 flags = mono_declsec_flags_from_class (method->klass);
10660 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10661 mono_class_init (method->klass);
10663 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10664 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10671 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10673 * @klass The inherited class - this is the class that provides the security check (attributes)
10675 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10677 * Note: Don't use the content of actions if the function return FALSE.
10680 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10682 MonoBoolean result = FALSE;
10685 /* quick exit if no declarative security is present in the metadata */
10686 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10689 /* Here we use (or create) the class declarative cache to look for demands */
10690 flags = mono_declsec_flags_from_class (klass);
10691 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10692 mono_class_init (klass);
10693 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10695 result |= mono_declsec_get_class_demands_params (klass, demands,
10696 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10703 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10705 * Note: Don't use the content of actions if the function return FALSE.
10708 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10710 /* quick exit if no declarative security is present in the metadata */
10711 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10714 /* we want the original as the wrapper is "free" of the security informations */
10715 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10716 method = mono_marshal_method_from_wrapper (method);
10721 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10722 mono_class_init (method->klass);
10723 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10725 return mono_declsec_get_method_demands_params (method, demands,
10726 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10733 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10735 guint32 cols [MONO_DECL_SECURITY_SIZE];
10739 int index = mono_metadata_declsec_from_index (image, token);
10743 t = &image->tables [MONO_TABLE_DECLSECURITY];
10744 for (i = index; i < t->rows; i++) {
10745 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10747 /* shortcut - index are ordered */
10748 if (token != cols [MONO_DECL_SECURITY_PARENT])
10751 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10752 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10753 entry->blob = (char*) (metadata + 2);
10754 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10763 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10765 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10766 guint32 idx = mono_method_get_index (method);
10767 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10768 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10769 return get_declsec_action (method->klass->image, idx, action, entry);
10775 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10778 guint32 flags = mono_declsec_flags_from_class (klass);
10779 if (declsec_flags_map [action] & flags) {
10780 guint32 idx = mono_metadata_token_index (klass->type_token);
10781 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10782 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10783 return get_declsec_action (klass->image, idx, action, entry);
10789 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10791 guint32 idx = 1; /* there is only one assembly */
10792 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10793 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10795 return get_declsec_action (assembly->image, idx, action, entry);
10799 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10801 MonoObject *res, *exc;
10803 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10804 static MonoMethod *method = NULL;
10806 if (!System_Reflection_Emit_TypeBuilder) {
10807 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10808 g_assert (System_Reflection_Emit_TypeBuilder);
10810 if (method == NULL) {
10811 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10816 * The result of mono_type_get_object () might be a System.MonoType but we
10817 * need a TypeBuilder so use klass->reflection_info.
10819 g_assert (klass->reflection_info);
10820 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10822 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10824 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10828 return *(MonoBoolean*)mono_object_unbox (res);