2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/gc-internal.h"
17 #include "mono/metadata/tokentype.h"
18 #include "mono/metadata/domain-internals.h"
19 #include "mono/metadata/opcodes.h"
20 #include "mono/metadata/assembly.h"
21 #include "mono/metadata/object-internals.h"
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/marshal.h>
24 #include <mono/metadata/security-manager.h>
33 #include "rawbuffer.h"
34 #include "mono-endian.h"
35 #include <mono/os/gc_wrapper.h>
43 #define TEXT_OFFSET 512
44 #define CLI_H_SIZE 136
45 #define FILE_ALIGN 512
46 #define VIRT_ALIGN 8192
47 #define START_TEXT_RVA 0x00002000
50 MonoReflectionILGen *ilgen;
51 MonoReflectionType *rtype;
52 MonoArray *parameters;
53 MonoArray *generic_params;
54 MonoGenericContainer *generic_container;
60 guint32 *table_idx; /* note: it's a pointer */
64 MonoBoolean init_locals;
65 MonoBoolean skip_visibility;
66 MonoArray *return_modreq;
67 MonoArray *return_modopt;
68 MonoArray *param_modreq;
69 MonoArray *param_modopt;
70 MonoArray *permissions;
75 int charset, extra_flags, native_cc;
76 MonoString *dll, *dllentry;
77 } ReflectionMethodBuilder;
81 MonoReflectionGenericParam *gparam;
82 } GenericParamTableEntry;
84 const unsigned char table_sizes [MONO_TABLE_NUM] = {
94 MONO_INTERFACEIMPL_SIZE,
95 MONO_MEMBERREF_SIZE, /* 0x0A */
97 MONO_CUSTOM_ATTR_SIZE,
98 MONO_FIELD_MARSHAL_SIZE,
99 MONO_DECL_SECURITY_SIZE,
100 MONO_CLASS_LAYOUT_SIZE,
101 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
102 MONO_STAND_ALONE_SIGNATURE_SIZE,
106 MONO_PROPERTY_MAP_SIZE,
109 MONO_METHOD_SEMA_SIZE,
110 MONO_METHODIMPL_SIZE,
111 MONO_MODULEREF_SIZE, /* 0x1A */
117 MONO_ASSEMBLY_SIZE, /* 0x20 */
118 MONO_ASSEMBLY_PROCESSOR_SIZE,
119 MONO_ASSEMBLYOS_SIZE,
120 MONO_ASSEMBLYREF_SIZE,
121 MONO_ASSEMBLYREFPROC_SIZE,
122 MONO_ASSEMBLYREFOS_SIZE,
126 MONO_NESTED_CLASS_SIZE,
128 MONO_GENERICPARAM_SIZE, /* 0x2A */
129 MONO_METHODSPEC_SIZE,
130 MONO_GENPARCONSTRAINT_SIZE
134 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
135 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
136 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
137 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
138 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
139 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
140 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
141 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
142 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
143 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
144 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
145 static void ensure_runtime_vtable (MonoClass *klass);
146 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
147 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
148 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
149 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
150 static inline MonoType *dup_type (const MonoType *original);
151 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
153 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
154 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
155 static CRITICAL_SECTION reflection_mutex;
158 mono_reflection_init (void)
160 InitializeCriticalSection (&reflection_mutex);
164 sigbuffer_init (SigBuffer *buf, int size)
166 buf->buf = g_malloc (size);
168 buf->end = buf->buf + size;
172 sigbuffer_make_room (SigBuffer *buf, int size)
174 if (buf->end - buf->p < size) {
175 int new_size = buf->end - buf->buf + size + 32;
176 char *p = g_realloc (buf->buf, new_size);
177 size = buf->p - buf->buf;
180 buf->end = buf->buf + new_size;
185 sigbuffer_add_value (SigBuffer *buf, guint32 val)
187 sigbuffer_make_room (buf, 6);
188 mono_metadata_encode_value (val, buf->p, &buf->p);
192 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
194 sigbuffer_make_room (buf, 1);
200 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
202 sigbuffer_make_room (buf, size);
203 memcpy (buf->p, p, size);
208 sigbuffer_free (SigBuffer *buf)
216 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
220 mp_g_malloc (MonoMemPool *mp, guint size)
223 return mono_mempool_alloc (mp, size);
225 return g_malloc (size);
231 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
235 mp_g_malloc0 (MonoMemPool *mp, guint size)
238 return mono_mempool_alloc0 (mp, size);
240 return g_malloc0 (size);
246 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
247 * memory from the C heap.
250 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
253 return mono_string_to_utf8_mp (mp, s);
255 return mono_string_to_utf8 (s);
258 #define mp_g_new(mp,struct_type, n_structs) \
259 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
261 #define mp_g_new0(mp,struct_type, n_structs) \
262 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
265 alloc_table (MonoDynamicTable *table, guint nrows)
268 g_assert (table->columns);
269 if (nrows + 1 >= table->alloc_rows) {
270 while (nrows + 1 >= table->alloc_rows) {
271 if (table->alloc_rows == 0)
272 table->alloc_rows = 16;
274 table->alloc_rows *= 2;
277 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
282 make_room_in_stream (MonoDynamicStream *stream, int size)
284 if (size <= stream->alloc_size)
287 while (stream->alloc_size <= size) {
288 if (stream->alloc_size < 4096)
289 stream->alloc_size = 4096;
291 stream->alloc_size *= 2;
294 stream->data = g_realloc (stream->data, stream->alloc_size);
298 string_heap_insert (MonoDynamicStream *sh, const char *str)
302 gpointer oldkey, oldval;
304 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
305 return GPOINTER_TO_UINT (oldval);
307 len = strlen (str) + 1;
310 make_room_in_stream (sh, idx + len);
313 * We strdup the string even if we already copy them in sh->data
314 * so that the string pointers in the hash remain valid even if
315 * we need to realloc sh->data. We may want to avoid that later.
317 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
318 memcpy (sh->data + idx, str, len);
324 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
326 char *name = mono_string_to_utf8 (str);
328 idx = string_heap_insert (sh, name);
334 string_heap_init (MonoDynamicStream *sh)
337 sh->alloc_size = 4096;
338 sh->data = g_malloc (4096);
339 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
340 string_heap_insert (sh, "");
344 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
348 make_room_in_stream (stream, stream->index + len);
349 memcpy (stream->data + stream->index, data, len);
351 stream->index += len;
353 * align index? Not without adding an additional param that controls it since
354 * we may store a blob value in pieces.
360 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
364 make_room_in_stream (stream, stream->index + len);
365 memset (stream->data + stream->index, 0, len);
367 stream->index += len;
372 stream_data_align (MonoDynamicStream *stream)
375 guint32 count = stream->index % 4;
377 /* we assume the stream data will be aligned */
379 mono_image_add_stream_data (stream, buf, 4 - count);
383 mono_blob_entry_hash (const char* str)
387 len = mono_metadata_decode_blob_size (str, &str);
391 for (str += 1; str < end; str++)
392 h = (h << 5) - h + *str;
400 mono_blob_entry_equal (const char *str1, const char *str2) {
404 len = mono_metadata_decode_blob_size (str1, &end1);
405 len2 = mono_metadata_decode_blob_size (str2, &end2);
408 return memcmp (end1, end2, len) == 0;
412 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
416 gpointer oldkey, oldval;
418 copy = g_malloc (s1+s2);
419 memcpy (copy, b1, s1);
420 memcpy (copy + s1, b2, s2);
421 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
423 idx = GPOINTER_TO_UINT (oldval);
425 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
426 mono_image_add_stream_data (&assembly->blob, b2, s2);
427 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
433 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
437 guint32 size = buf->p - buf->buf;
439 g_assert (size <= (buf->end - buf->buf));
440 mono_metadata_encode_value (size, b, &b);
441 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
445 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
446 * dest may be misaligned.
449 swap_with_size (char *dest, const char* val, int len, int nelem) {
450 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
453 for (elem = 0; elem < nelem; ++elem) {
479 g_assert_not_reached ();
485 memcpy (dest, val, len * nelem);
490 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
494 guint32 idx = 0, len;
496 len = str->length * 2;
497 mono_metadata_encode_value (len, b, &b);
498 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
500 char *swapped = g_malloc (2 * mono_string_length (str));
501 const char *p = (const char*)mono_string_chars (str);
503 swap_with_size (swapped, p, 2, mono_string_length (str));
504 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
508 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
513 /* modified version needed to handle building corlib */
515 my_mono_class_from_mono_type (MonoType *type) {
516 switch (type->type) {
517 case MONO_TYPE_ARRAY:
519 case MONO_TYPE_SZARRAY:
520 case MONO_TYPE_GENERICINST:
521 return mono_class_from_mono_type (type);
524 g_assert (type->data.generic_param->pklass);
525 return type->data.generic_param->pklass;
527 /* should be always valid when we reach this case... */
528 return type->data.klass;
533 default_class_from_mono_type (MonoType *type)
535 switch (type->type) {
536 case MONO_TYPE_OBJECT:
537 return mono_defaults.object_class;
539 return mono_defaults.void_class;
540 case MONO_TYPE_BOOLEAN:
541 return mono_defaults.boolean_class;
543 return mono_defaults.char_class;
545 return mono_defaults.sbyte_class;
547 return mono_defaults.byte_class;
549 return mono_defaults.int16_class;
551 return mono_defaults.uint16_class;
553 return mono_defaults.int32_class;
555 return mono_defaults.uint32_class;
557 return mono_defaults.int_class;
559 return mono_defaults.uint_class;
561 return mono_defaults.int64_class;
563 return mono_defaults.uint64_class;
565 return mono_defaults.single_class;
567 return mono_defaults.double_class;
568 case MONO_TYPE_STRING:
569 return mono_defaults.string_class;
571 g_warning ("implement me 0x%02x\n", type->type);
572 g_assert_not_reached ();
579 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
582 MonoGenericInst *class_inst;
586 class_inst = gclass->context.class_inst;
588 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
589 encode_type (assembly, &gclass->container_class->byval_arg, buf);
590 sigbuffer_add_value (buf, class_inst->type_argc);
591 for (i = 0; i < class_inst->type_argc; ++i)
592 encode_type (assembly, class_inst->type_argv [i], buf);
597 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
600 g_assert_not_reached ();
605 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
609 case MONO_TYPE_BOOLEAN:
623 case MONO_TYPE_STRING:
624 case MONO_TYPE_OBJECT:
625 case MONO_TYPE_TYPEDBYREF:
626 sigbuffer_add_value (buf, type->type);
629 sigbuffer_add_value (buf, type->type);
630 encode_type (assembly, type->data.type, buf);
632 case MONO_TYPE_SZARRAY:
633 sigbuffer_add_value (buf, type->type);
634 encode_type (assembly, &type->data.klass->byval_arg, buf);
636 case MONO_TYPE_VALUETYPE:
637 case MONO_TYPE_CLASS: {
638 MonoClass *k = mono_class_from_mono_type (type);
640 * Make sure we use the correct type.
642 sigbuffer_add_value (buf, k->byval_arg.type);
644 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
645 * otherwise two typerefs could point to the same type, leading to
646 * verification errors.
648 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
651 case MONO_TYPE_ARRAY:
652 sigbuffer_add_value (buf, type->type);
653 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
654 sigbuffer_add_value (buf, type->data.array->rank);
655 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
656 sigbuffer_add_value (buf, 0);
658 case MONO_TYPE_GENERICINST:
659 encode_generic_class (assembly, type->data.generic_class, buf);
663 sigbuffer_add_value (buf, type->type);
664 sigbuffer_add_value (buf, type->data.generic_param->num);
667 g_error ("need to encode type %x", type->type);
672 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
675 sigbuffer_add_value (buf, MONO_TYPE_VOID);
680 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
681 encode_type (assembly, type->type, buf);
685 g_assert_not_reached ();
690 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
695 for (i = 0; i < mono_array_length (modreq); ++i) {
696 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
697 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
698 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
702 for (i = 0; i < mono_array_length (modopt); ++i) {
703 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
704 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
705 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
711 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
715 guint32 nparams = sig->param_count;
721 sigbuffer_init (&buf, 32);
723 * FIXME: vararg, explicit_this, differenc call_conv values...
725 idx = sig->call_convention;
727 idx |= 0x20; /* hasthis */
728 if (sig->generic_param_count)
729 idx |= 0x10; /* generic */
730 sigbuffer_add_byte (&buf, idx);
731 if (sig->generic_param_count)
732 sigbuffer_add_value (&buf, sig->generic_param_count);
733 sigbuffer_add_value (&buf, nparams);
734 encode_type (assembly, sig->ret, &buf);
735 for (i = 0; i < nparams; ++i) {
736 if (i == sig->sentinelpos)
737 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
738 encode_type (assembly, sig->params [i], &buf);
740 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
741 sigbuffer_free (&buf);
746 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
749 * FIXME: reuse code from method_encode_signature().
753 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
754 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
755 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
758 sigbuffer_init (&buf, 32);
759 /* LAMESPEC: all the call conv spec is foobared */
760 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
761 if (mb->call_conv & 2)
762 idx |= 0x5; /* vararg */
763 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
764 idx |= 0x20; /* hasthis */
766 idx |= 0x10; /* generic */
767 sigbuffer_add_byte (&buf, idx);
769 sigbuffer_add_value (&buf, ngparams);
770 sigbuffer_add_value (&buf, nparams + notypes);
771 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
772 encode_reflection_type (assembly, mb->rtype, &buf);
773 for (i = 0; i < nparams; ++i) {
774 MonoArray *modreq = NULL;
775 MonoArray *modopt = NULL;
776 MonoReflectionType *pt;
778 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
779 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
780 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
781 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
782 encode_custom_modifiers (assembly, modreq, modopt, &buf);
783 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
784 encode_reflection_type (assembly, pt, &buf);
787 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
788 for (i = 0; i < notypes; ++i) {
789 MonoReflectionType *pt;
791 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
792 encode_reflection_type (assembly, pt, &buf);
795 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
796 sigbuffer_free (&buf);
801 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
803 MonoDynamicTable *table;
805 guint32 idx, sig_idx;
806 guint nl = mono_array_length (ilgen->locals);
810 sigbuffer_init (&buf, 32);
811 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
812 idx = table->next_idx ++;
814 alloc_table (table, table->rows);
815 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
817 sigbuffer_add_value (&buf, 0x07);
818 sigbuffer_add_value (&buf, nl);
819 for (i = 0; i < nl; ++i) {
820 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
823 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
825 encode_reflection_type (assembly, lb->type, &buf);
827 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
828 sigbuffer_free (&buf);
830 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
836 method_count_clauses (MonoReflectionILGen *ilgen)
838 guint32 num_clauses = 0;
841 MonoILExceptionInfo *ex_info;
842 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
843 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
844 if (ex_info->handlers)
845 num_clauses += mono_array_length (ex_info->handlers);
853 static MonoExceptionClause*
854 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
856 MonoExceptionClause *clauses;
857 MonoExceptionClause *clause;
858 MonoILExceptionInfo *ex_info;
859 MonoILExceptionBlock *ex_block;
860 guint32 finally_start;
861 int i, j, clause_index;;
863 clauses = g_new0 (MonoExceptionClause, num_clauses);
866 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
867 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
868 finally_start = ex_info->start + ex_info->len;
869 if (!ex_info->handlers)
871 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
872 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
873 clause = &(clauses [clause_index]);
875 clause->flags = ex_block->type;
876 clause->try_offset = ex_info->start;
878 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
879 clause->try_len = finally_start - ex_info->start;
881 clause->try_len = ex_info->len;
882 clause->handler_offset = ex_block->start;
883 clause->handler_len = ex_block->len;
884 if (ex_block->extype) {
885 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
887 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
888 clause->data.filter_offset = ex_block->filter_offset;
890 clause->data.filter_offset = 0;
892 finally_start = ex_block->start + ex_block->len;
902 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
908 gint32 num_locals = 0;
909 gint32 num_exception = 0;
912 char fat_header [12];
915 guint32 local_sig = 0;
916 guint32 header_size = 12;
919 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
920 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
924 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
926 code = mb->ilgen->code;
927 code_size = mb->ilgen->code_len;
928 max_stack = mb->ilgen->max_stack;
929 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
930 if (mb->ilgen->ex_handlers)
931 num_exception = method_count_clauses (mb->ilgen);
935 char *name = mono_string_to_utf8 (mb->name);
936 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
937 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
940 mono_raise_exception (exception);
943 code_size = mono_array_length (code);
944 max_stack = 8; /* we probably need to run a verifier on the code... */
947 stream_data_align (&assembly->code);
949 /* check for exceptions, maxstack, locals */
950 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
952 if (code_size < 64 && !(code_size & 1)) {
953 flags = (code_size << 2) | 0x2;
954 } else if (code_size < 32 && (code_size & 1)) {
955 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
959 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
960 /* add to the fixup todo list */
961 if (mb->ilgen && mb->ilgen->num_token_fixups)
962 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
963 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
964 return assembly->text_rva + idx;
968 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
970 * FIXME: need to set also the header size in fat_flags.
971 * (and more sects and init locals flags)
975 fat_flags |= METHOD_HEADER_MORE_SECTS;
977 fat_flags |= METHOD_HEADER_INIT_LOCALS;
978 fat_header [0] = fat_flags;
979 fat_header [1] = (header_size / 4 ) << 4;
980 short_value = GUINT16_TO_LE (max_stack);
981 memcpy (fat_header + 2, &short_value, 2);
982 int_value = GUINT32_TO_LE (code_size);
983 memcpy (fat_header + 4, &int_value, 4);
984 int_value = GUINT32_TO_LE (local_sig);
985 memcpy (fat_header + 8, &int_value, 4);
986 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
987 /* add to the fixup todo list */
988 if (mb->ilgen && mb->ilgen->num_token_fixups)
989 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
991 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
993 unsigned char sheader [4];
994 MonoILExceptionInfo * ex_info;
995 MonoILExceptionBlock * ex_block;
998 stream_data_align (&assembly->code);
999 /* always use fat format for now */
1000 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1001 num_exception *= 6 * sizeof (guint32);
1002 num_exception += 4; /* include the size of the header */
1003 sheader [1] = num_exception & 0xff;
1004 sheader [2] = (num_exception >> 8) & 0xff;
1005 sheader [3] = (num_exception >> 16) & 0xff;
1006 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1007 /* fat header, so we are already aligned */
1009 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1010 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1011 if (ex_info->handlers) {
1012 int finally_start = ex_info->start + ex_info->len;
1013 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1015 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1017 val = GUINT32_TO_LE (ex_block->type);
1018 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1020 val = GUINT32_TO_LE (ex_info->start);
1021 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1022 /* need fault, too, probably */
1023 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1024 val = GUINT32_TO_LE (finally_start - ex_info->start);
1026 val = GUINT32_TO_LE (ex_info->len);
1027 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1028 /* handler offset */
1029 val = GUINT32_TO_LE (ex_block->start);
1030 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1032 val = GUINT32_TO_LE (ex_block->len);
1033 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 finally_start = ex_block->start + ex_block->len;
1035 if (ex_block->extype) {
1036 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1038 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1039 val = ex_block->filter_offset;
1043 val = GUINT32_TO_LE (val);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1045 /*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",
1046 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);*/
1049 g_error ("No clauses for ex info block %d", i);
1053 return assembly->text_rva + idx;
1057 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1060 MonoDynamicTable *table;
1063 table = &assembly->tables [table_idx];
1065 g_assert (col < table->columns);
1067 values = table->values + table->columns;
1068 for (i = 1; i <= table->rows; ++i) {
1069 if (values [col] == token)
1071 values += table->columns;
1076 /* protected by reflection_mutex:
1077 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1079 static GHashTable *dynamic_custom_attrs = NULL;
1081 static MonoCustomAttrInfo*
1082 lookup_custom_attr (void *member)
1084 MonoCustomAttrInfo *ainfo, *res;
1087 mono_reflection_lock ();
1088 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1089 mono_reflection_unlock ();
1092 /* Need to copy since it will be freed later */
1093 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
1094 res = g_malloc0 (size);
1095 memcpy (res, ainfo, size);
1102 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1104 /* FIXME: Need to do more checks */
1105 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1106 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1108 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1115 static MonoCustomAttrInfo*
1116 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1118 int i, index, count, not_visible;
1119 MonoCustomAttrInfo *ainfo;
1120 MonoReflectionCustomAttr *cattr;
1124 /* FIXME: check in assembly the Run flag is set */
1126 count = mono_array_length (cattrs);
1128 /* Skip nonpublic attributes since MS.NET seems to do the same */
1129 /* FIXME: This needs to be done more globally */
1131 for (i = 0; i < count; ++i) {
1132 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1133 if (!custom_attr_visible (image, cattr))
1136 count -= not_visible;
1138 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1140 ainfo->image = image;
1141 ainfo->num_attrs = count;
1143 mono_loader_lock ();
1144 for (i = 0; i < count; ++i) {
1145 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1146 if (custom_attr_visible (image, cattr)) {
1147 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1148 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1149 ainfo->attrs [index].ctor = cattr->ctor->method;
1150 ainfo->attrs [index].data = saved;
1151 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1155 mono_loader_unlock ();
1161 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1163 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1168 mono_reflection_lock ();
1169 if (!dynamic_custom_attrs)
1170 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1172 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1173 ainfo->cached = TRUE;
1174 mono_reflection_unlock ();
1178 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1185 * idx is the table index of the object
1186 * type is one of MONO_CUSTOM_ATTR_*
1189 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1191 MonoDynamicTable *table;
1192 MonoReflectionCustomAttr *cattr;
1194 guint32 count, i, token;
1196 char *p = blob_size;
1198 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1201 count = mono_array_length (cattrs);
1202 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1203 table->rows += count;
1204 alloc_table (table, table->rows);
1205 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1206 idx <<= MONO_CUSTOM_ATTR_BITS;
1208 for (i = 0; i < count; ++i) {
1209 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1210 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1211 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1212 type = mono_metadata_token_index (token);
1213 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1214 switch (mono_metadata_token_table (token)) {
1215 case MONO_TABLE_METHOD:
1216 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1218 case MONO_TABLE_MEMBERREF:
1219 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1222 g_warning ("got wrong token in custom attr");
1225 values [MONO_CUSTOM_ATTR_TYPE] = type;
1227 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1228 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1229 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1230 values += MONO_CUSTOM_ATTR_SIZE;
1236 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1238 MonoDynamicTable *table;
1240 guint32 count, i, idx;
1241 MonoReflectionPermissionSet *perm;
1246 count = mono_array_length (permissions);
1247 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1248 table->rows += count;
1249 alloc_table (table, table->rows);
1251 for (i = 0; i < mono_array_length (permissions); ++i) {
1252 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1254 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1256 idx = mono_metadata_token_index (parent_token);
1257 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1258 switch (mono_metadata_token_table (parent_token)) {
1259 case MONO_TABLE_TYPEDEF:
1260 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1262 case MONO_TABLE_METHOD:
1263 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1265 case MONO_TABLE_ASSEMBLY:
1266 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1269 g_assert_not_reached ();
1272 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1273 values [MONO_DECL_SECURITY_PARENT] = idx;
1274 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1281 * Fill in the MethodDef and ParamDef tables for a method.
1282 * This is used for both normal methods and constructors.
1285 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1287 MonoDynamicTable *table;
1291 /* room in this table is already allocated */
1292 table = &assembly->tables [MONO_TABLE_METHOD];
1293 *mb->table_idx = table->next_idx ++;
1294 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1295 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1296 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1297 values [MONO_METHOD_FLAGS] = mb->attrs;
1298 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1299 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1300 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1302 table = &assembly->tables [MONO_TABLE_PARAM];
1303 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1305 mono_image_add_decl_security (assembly,
1306 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1309 MonoDynamicTable *mtable;
1312 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1313 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1316 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1317 if (mono_array_get (mb->pinfo, gpointer, i))
1320 table->rows += count;
1321 alloc_table (table, table->rows);
1322 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1323 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1324 MonoReflectionParamBuilder *pb;
1325 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1326 values [MONO_PARAM_FLAGS] = pb->attrs;
1327 values [MONO_PARAM_SEQUENCE] = i;
1328 if (pb->name != NULL) {
1329 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1331 values [MONO_PARAM_NAME] = 0;
1333 values += MONO_PARAM_SIZE;
1334 if (pb->marshal_info) {
1336 alloc_table (mtable, mtable->rows);
1337 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1338 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1339 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1341 pb->table_idx = table->next_idx++;
1342 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1343 guint32 field_type = 0;
1344 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1346 alloc_table (mtable, mtable->rows);
1347 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1348 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1349 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1350 mvalues [MONO_CONSTANT_TYPE] = field_type;
1351 mvalues [MONO_CONSTANT_PADDING] = 0;
1359 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1361 rmb->ilgen = mb->ilgen;
1362 rmb->rtype = mb->rtype;
1363 rmb->parameters = mb->parameters;
1364 rmb->generic_params = mb->generic_params;
1365 rmb->generic_container = mb->generic_container;
1366 rmb->opt_types = NULL;
1367 rmb->pinfo = mb->pinfo;
1368 rmb->attrs = mb->attrs;
1369 rmb->iattrs = mb->iattrs;
1370 rmb->call_conv = mb->call_conv;
1371 rmb->code = mb->code;
1372 rmb->type = mb->type;
1373 rmb->name = mb->name;
1374 rmb->table_idx = &mb->table_idx;
1375 rmb->init_locals = mb->init_locals;
1376 rmb->return_modreq = mb->return_modreq;
1377 rmb->return_modopt = mb->return_modopt;
1378 rmb->param_modreq = mb->param_modreq;
1379 rmb->param_modopt = mb->param_modopt;
1380 rmb->permissions = mb->permissions;
1381 rmb->mhandle = mb->mhandle;
1386 rmb->charset = mb->charset;
1387 rmb->extra_flags = mb->extra_flags;
1388 rmb->native_cc = mb->native_cc;
1389 rmb->dllentry = mb->dllentry;
1395 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1397 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1399 rmb->ilgen = mb->ilgen;
1400 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1401 rmb->parameters = mb->parameters;
1402 rmb->generic_params = NULL;
1403 rmb->generic_container = NULL;
1404 rmb->opt_types = NULL;
1405 rmb->pinfo = mb->pinfo;
1406 rmb->attrs = mb->attrs;
1407 rmb->iattrs = mb->iattrs;
1408 rmb->call_conv = mb->call_conv;
1410 rmb->type = mb->type;
1411 rmb->name = mono_string_new (mono_domain_get (), name);
1412 rmb->table_idx = &mb->table_idx;
1413 rmb->init_locals = mb->init_locals;
1414 rmb->return_modreq = NULL;
1415 rmb->return_modopt = NULL;
1416 rmb->param_modreq = mb->param_modreq;
1417 rmb->param_modopt = mb->param_modopt;
1418 rmb->permissions = mb->permissions;
1419 rmb->mhandle = mb->mhandle;
1425 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1427 rmb->ilgen = mb->ilgen;
1428 rmb->rtype = mb->rtype;
1429 rmb->parameters = mb->parameters;
1430 rmb->generic_params = NULL;
1431 rmb->generic_container = NULL;
1432 rmb->opt_types = NULL;
1434 rmb->attrs = mb->attrs;
1436 rmb->call_conv = mb->call_conv;
1439 rmb->name = mb->name;
1440 rmb->table_idx = NULL;
1441 rmb->init_locals = mb->init_locals;
1442 rmb->skip_visibility = mb->skip_visibility;
1443 rmb->return_modreq = NULL;
1444 rmb->return_modopt = NULL;
1445 rmb->param_modreq = NULL;
1446 rmb->param_modopt = NULL;
1447 rmb->permissions = NULL;
1448 rmb->mhandle = mb->mhandle;
1454 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1456 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1457 MonoDynamicTable *table;
1461 if (!mb->override_method)
1464 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1466 alloc_table (table, table->rows);
1467 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1468 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1469 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1471 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1472 switch (mono_metadata_token_table (tok)) {
1473 case MONO_TABLE_MEMBERREF:
1474 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1476 case MONO_TABLE_METHOD:
1477 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1480 g_assert_not_reached ();
1482 values [MONO_METHODIMPL_DECLARATION] = tok;
1486 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1488 MonoDynamicTable *table;
1490 ReflectionMethodBuilder rmb;
1493 reflection_methodbuilder_from_method_builder (&rmb, mb);
1495 mono_image_basic_method (&rmb, assembly);
1496 mb->table_idx = *rmb.table_idx;
1498 if (mb->dll) { /* It's a P/Invoke method */
1500 /* map CharSet values to on-disk values */
1501 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1502 int extra_flags = mb->extra_flags;
1503 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1505 alloc_table (table, table->rows);
1506 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1508 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1509 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1511 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1513 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1514 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1515 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1516 table = &assembly->tables [MONO_TABLE_MODULEREF];
1518 alloc_table (table, table->rows);
1519 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1520 values [MONO_IMPLMAP_SCOPE] = table->rows;
1524 if (mb->generic_params) {
1525 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1526 table->rows += mono_array_length (mb->generic_params);
1527 alloc_table (table, table->rows);
1528 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1529 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1531 mono_image_get_generic_param_info (
1532 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1539 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1541 ReflectionMethodBuilder rmb;
1543 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1545 mono_image_basic_method (&rmb, assembly);
1546 mb->table_idx = *rmb.table_idx;
1550 type_get_fully_qualified_name (MonoType *type)
1552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1556 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1560 klass = my_mono_class_from_mono_type (type);
1562 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1563 ta = klass->image->assembly;
1564 if (ta->dynamic || (ta == ass))
1565 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1567 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1571 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1576 if (!assembly->save)
1579 sigbuffer_init (&buf, 32);
1581 sigbuffer_add_value (&buf, 0x06);
1582 /* encode custom attributes before the type */
1583 encode_type (assembly, type, &buf);
1584 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1585 sigbuffer_free (&buf);
1590 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1595 sigbuffer_init (&buf, 32);
1597 sigbuffer_add_value (&buf, 0x06);
1598 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1599 /* encode custom attributes before the type */
1600 encode_reflection_type (assembly, fb->type, &buf);
1601 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1602 sigbuffer_free (&buf);
1607 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1608 char blob_size [64];
1609 char *b = blob_size;
1612 guint32 idx = 0, len = 0, dummy = 0;
1614 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1615 guint32 fpa_double [2];
1620 p = buf = g_malloc (64);
1622 *ret_type = MONO_TYPE_CLASS;
1624 box_val = (char*)&dummy;
1626 box_val = ((char*)val) + sizeof (MonoObject);
1627 *ret_type = val->vtable->klass->byval_arg.type;
1630 switch (*ret_type) {
1631 case MONO_TYPE_BOOLEAN:
1636 case MONO_TYPE_CHAR:
1653 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1654 fpa_p = (guint32*)box_val;
1655 fpa_double [0] = fpa_p [1];
1656 fpa_double [1] = fpa_p [0];
1657 box_val = (char*)fpa_double;
1661 case MONO_TYPE_VALUETYPE:
1662 if (val->vtable->klass->enumtype) {
1663 *ret_type = val->vtable->klass->enum_basetype->type;
1666 g_error ("we can't encode valuetypes");
1667 case MONO_TYPE_CLASS:
1669 case MONO_TYPE_STRING: {
1670 MonoString *str = (MonoString*)val;
1671 /* there is no signature */
1672 len = str->length * 2;
1673 mono_metadata_encode_value (len, b, &b);
1674 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1676 char *swapped = g_malloc (2 * mono_string_length (str));
1677 const char *p = (const char*)mono_string_chars (str);
1679 swap_with_size (swapped, p, 2, mono_string_length (str));
1680 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1684 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1690 case MONO_TYPE_GENERICINST:
1691 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1694 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1697 /* there is no signature */
1698 mono_metadata_encode_value (len, b, &b);
1699 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1700 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1701 swap_with_size (blob_size, box_val, len, 1);
1702 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1704 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1712 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1717 sigbuffer_init (&buf, 32);
1719 sigbuffer_add_value (&buf, minfo->type);
1721 switch (minfo->type) {
1722 case MONO_NATIVE_BYVALTSTR:
1723 case MONO_NATIVE_BYVALARRAY:
1724 sigbuffer_add_value (&buf, minfo->count);
1726 case MONO_NATIVE_LPARRAY:
1727 if (minfo->eltype || minfo->has_size) {
1728 sigbuffer_add_value (&buf, minfo->eltype);
1729 if (minfo->has_size) {
1730 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1731 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1733 /* LAMESPEC: ElemMult is undocumented */
1734 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1738 case MONO_NATIVE_CUSTOM:
1740 str = mono_string_to_utf8 (minfo->guid);
1742 sigbuffer_add_value (&buf, len);
1743 sigbuffer_add_mem (&buf, str, len);
1746 sigbuffer_add_value (&buf, 0);
1748 /* native type name */
1749 sigbuffer_add_value (&buf, 0);
1750 /* custom marshaler type name */
1751 if (minfo->marshaltype || minfo->marshaltyperef) {
1752 if (minfo->marshaltyperef)
1753 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1755 str = mono_string_to_utf8 (minfo->marshaltype);
1757 sigbuffer_add_value (&buf, len);
1758 sigbuffer_add_mem (&buf, str, len);
1761 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1762 sigbuffer_add_value (&buf, 0);
1764 if (minfo->mcookie) {
1765 str = mono_string_to_utf8 (minfo->mcookie);
1767 sigbuffer_add_value (&buf, len);
1768 sigbuffer_add_mem (&buf, str, len);
1771 sigbuffer_add_value (&buf, 0);
1777 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1778 sigbuffer_free (&buf);
1783 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1785 MonoDynamicTable *table;
1788 /* maybe this fixup should be done in the C# code */
1789 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1790 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1791 table = &assembly->tables [MONO_TABLE_FIELD];
1792 fb->table_idx = table->next_idx ++;
1793 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1794 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1795 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1796 values [MONO_FIELD_FLAGS] = fb->attrs;
1797 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1799 if (fb->offset != -1) {
1800 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1802 alloc_table (table, table->rows);
1803 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1804 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1805 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1807 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1808 guint32 field_type = 0;
1809 table = &assembly->tables [MONO_TABLE_CONSTANT];
1811 alloc_table (table, table->rows);
1812 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1813 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1814 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1815 values [MONO_CONSTANT_TYPE] = field_type;
1816 values [MONO_CONSTANT_PADDING] = 0;
1818 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1820 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1822 alloc_table (table, table->rows);
1823 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1824 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1826 * We store it in the code section because it's simpler for now.
1829 if (mono_array_length (fb->rva_data) >= 10)
1830 stream_data_align (&assembly->code);
1831 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1833 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1834 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1836 if (fb->marshal_info) {
1837 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1839 alloc_table (table, table->rows);
1840 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1841 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1842 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1847 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1850 guint32 nparams = 0;
1851 MonoReflectionMethodBuilder *mb = fb->get_method;
1852 MonoReflectionMethodBuilder *smb = fb->set_method;
1855 if (mb && mb->parameters)
1856 nparams = mono_array_length (mb->parameters);
1857 if (!mb && smb && smb->parameters)
1858 nparams = mono_array_length (smb->parameters) - 1;
1859 sigbuffer_init (&buf, 32);
1860 sigbuffer_add_byte (&buf, 0x08);
1861 sigbuffer_add_value (&buf, nparams);
1863 encode_reflection_type (assembly, mb->rtype, &buf);
1864 for (i = 0; i < nparams; ++i) {
1865 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1866 encode_reflection_type (assembly, pt, &buf);
1868 } else if (smb && smb->parameters) {
1869 /* the property type is the last param */
1870 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1871 for (i = 0; i < nparams; ++i) {
1872 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1873 encode_reflection_type (assembly, pt, &buf);
1876 encode_reflection_type (assembly, fb->type, &buf);
1879 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1880 sigbuffer_free (&buf);
1885 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1887 MonoDynamicTable *table;
1889 guint num_methods = 0;
1893 * we need to set things in the following tables:
1894 * PROPERTYMAP (info already filled in _get_type_info ())
1895 * PROPERTY (rows already preallocated in _get_type_info ())
1896 * METHOD (method info already done with the generic method code)
1899 table = &assembly->tables [MONO_TABLE_PROPERTY];
1900 pb->table_idx = table->next_idx ++;
1901 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1902 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1903 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1904 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1906 /* FIXME: we still don't handle 'other' methods */
1907 if (pb->get_method) num_methods ++;
1908 if (pb->set_method) num_methods ++;
1910 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1911 table->rows += num_methods;
1912 alloc_table (table, table->rows);
1914 if (pb->get_method) {
1915 semaidx = table->next_idx ++;
1916 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1917 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1918 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1919 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1921 if (pb->set_method) {
1922 semaidx = table->next_idx ++;
1923 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1924 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1925 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1926 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1931 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1933 MonoDynamicTable *table;
1935 guint num_methods = 0;
1939 * we need to set things in the following tables:
1940 * EVENTMAP (info already filled in _get_type_info ())
1941 * EVENT (rows already preallocated in _get_type_info ())
1942 * METHOD (method info already done with the generic method code)
1945 table = &assembly->tables [MONO_TABLE_EVENT];
1946 eb->table_idx = table->next_idx ++;
1947 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1948 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1949 values [MONO_EVENT_FLAGS] = eb->attrs;
1950 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1953 * FIXME: we still don't handle 'other' methods
1955 if (eb->add_method) num_methods ++;
1956 if (eb->remove_method) num_methods ++;
1957 if (eb->raise_method) num_methods ++;
1959 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1960 table->rows += num_methods;
1961 alloc_table (table, table->rows);
1963 if (eb->add_method) {
1964 semaidx = table->next_idx ++;
1965 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1966 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1967 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1968 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1970 if (eb->remove_method) {
1971 semaidx = table->next_idx ++;
1972 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1973 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1974 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1975 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1977 if (eb->raise_method) {
1978 semaidx = table->next_idx ++;
1979 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1980 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1981 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1982 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1987 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1989 MonoDynamicTable *table;
1990 guint32 num_constraints, i;
1994 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1995 num_constraints = gparam->iface_constraints ?
1996 mono_array_length (gparam->iface_constraints) : 0;
1997 table->rows += num_constraints;
1998 if (gparam->base_type)
2000 alloc_table (table, table->rows);
2002 if (gparam->base_type) {
2003 table_idx = table->next_idx ++;
2004 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2006 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2007 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2008 assembly, gparam->base_type->type);
2011 for (i = 0; i < num_constraints; i++) {
2012 MonoReflectionType *constraint = mono_array_get (
2013 gparam->iface_constraints, gpointer, i);
2015 table_idx = table->next_idx ++;
2016 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2018 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2019 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2020 assembly, constraint->type);
2025 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2027 GenericParamTableEntry *entry;
2030 * The GenericParam table must be sorted according to the `owner' field.
2031 * We need to do this sorting prior to writing the GenericParamConstraint
2032 * table, since we have to use the final GenericParam table indices there
2033 * and they must also be sorted.
2036 entry = g_new0 (GenericParamTableEntry, 1);
2037 entry->owner = owner;
2039 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2040 MONO_GC_REGISTER_ROOT (entry->gparam);
2042 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2044 g_ptr_array_add (assembly->gen_params, entry);
2048 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2050 MonoDynamicTable *table;
2051 MonoGenericParam *param;
2055 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2056 table_idx = table->next_idx ++;
2057 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2059 param = entry->gparam->type.type->data.generic_param;
2061 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2062 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2063 values [MONO_GENERICPARAM_NUMBER] = param->num;
2064 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2066 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2068 encode_constraints (entry->gparam, table_idx, assembly);
2072 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2074 MonoDynamicTable *table;
2077 guint32 cols [MONO_ASSEMBLY_SIZE];
2081 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2084 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2085 table = &assembly->tables [MONO_TABLE_MODULEREF];
2086 token = table->next_idx ++;
2088 alloc_table (table, table->rows);
2089 values = table->values + token * MONO_MODULEREF_SIZE;
2090 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2092 token <<= MONO_RESOLTION_SCOPE_BITS;
2093 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2094 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2099 if (image->assembly->dynamic)
2101 memset (cols, 0, sizeof (cols));
2103 /* image->assembly->image is the manifest module */
2104 image = image->assembly->image;
2105 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2108 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2109 token = table->next_idx ++;
2111 alloc_table (table, table->rows);
2112 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2113 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2114 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2115 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2116 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2117 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2118 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2119 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2120 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2122 if (strcmp ("", image->assembly->aname.culture)) {
2123 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2124 image->assembly->aname.culture);
2127 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2128 guchar pubtoken [9];
2130 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2131 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2133 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2135 token <<= MONO_RESOLTION_SCOPE_BITS;
2136 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2137 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2142 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2144 MonoDynamicTable *table;
2149 sigbuffer_init (&buf, 32);
2150 switch (type->type) {
2151 case MONO_TYPE_FNPTR:
2153 case MONO_TYPE_SZARRAY:
2154 case MONO_TYPE_ARRAY:
2156 case MONO_TYPE_MVAR:
2157 case MONO_TYPE_GENERICINST:
2158 encode_type (assembly, type, &buf);
2160 case MONO_TYPE_CLASS:
2161 case MONO_TYPE_VALUETYPE: {
2162 MonoClass *k = mono_class_from_mono_type (type);
2163 if (!k || !k->generic_class) {
2164 sigbuffer_free (&buf);
2167 encode_generic_class (assembly, k->generic_class, &buf);
2171 sigbuffer_free (&buf);
2175 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2176 if (assembly->save) {
2177 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2178 alloc_table (table, table->rows + 1);
2179 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2180 values [MONO_TYPESPEC_SIGNATURE] = token;
2182 sigbuffer_free (&buf);
2184 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2185 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2191 * Despite the name, we handle also TypeSpec (with the above helper).
2194 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2196 MonoDynamicTable *table;
2198 guint32 token, scope, enclosing;
2201 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2204 token = create_typespec (assembly, type);
2207 klass = my_mono_class_from_mono_type (type);
2209 klass = mono_class_from_mono_type (type);
2212 * If it's in the same module and not a generic type parameter:
2214 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2215 (type->type != MONO_TYPE_MVAR)) {
2216 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2217 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2218 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2222 if (klass->nested_in) {
2223 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2224 /* get the typeref idx of the enclosing type */
2225 enclosing >>= MONO_TYPEDEFORREF_BITS;
2226 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2228 scope = resolution_scope_from_image (assembly, klass->image);
2230 table = &assembly->tables [MONO_TABLE_TYPEREF];
2231 if (assembly->save) {
2232 alloc_table (table, table->rows + 1);
2233 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2234 values [MONO_TYPEREF_SCOPE] = scope;
2235 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2236 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2238 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2239 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2241 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 * Insert a memberef row into the metadata: the token that point to the memberref
2247 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2248 * mono_image_get_fieldref_token()).
2249 * The sig param is an index to an already built signature.
2252 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2254 MonoDynamicTable *table;
2256 guint32 token, pclass;
2259 parent = mono_image_typedef_or_ref (assembly, type);
2260 switch (parent & MONO_TYPEDEFORREF_MASK) {
2261 case MONO_TYPEDEFORREF_TYPEREF:
2262 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2264 case MONO_TYPEDEFORREF_TYPESPEC:
2265 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2267 case MONO_TYPEDEFORREF_TYPEDEF:
2268 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2271 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2274 /* extract the index */
2275 parent >>= MONO_TYPEDEFORREF_BITS;
2277 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2279 if (assembly->save) {
2280 alloc_table (table, table->rows + 1);
2281 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2282 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2283 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2284 values [MONO_MEMBERREF_SIGNATURE] = sig;
2287 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2294 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2297 MonoMethodSignature *sig;
2299 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2304 * A methodref signature can't contain an unmanaged calling convention.
2306 sig = mono_metadata_signature_dup (mono_method_signature (method));
2307 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2308 sig->call_convention = MONO_CALL_DEFAULT;
2309 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2310 method->name, method_encode_signature (assembly, sig));
2312 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2317 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2318 const gchar *name, guint32 sig)
2320 MonoDynamicTable *table;
2324 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2326 if (assembly->save) {
2327 alloc_table (table, table->rows + 1);
2328 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2329 values [MONO_MEMBERREF_CLASS] = original;
2330 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2331 values [MONO_MEMBERREF_SIGNATURE] = sig;
2334 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2341 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2344 ReflectionMethodBuilder rmb;
2346 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2350 reflection_methodbuilder_from_method_builder (&rmb, mb);
2352 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2353 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2354 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2359 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2362 ReflectionMethodBuilder rmb;
2364 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2368 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2370 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2371 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2372 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2377 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2382 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2385 g_assert (f->field->parent);
2386 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2387 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2388 f->field->name, fieldref_encode_signature (assembly, type));
2389 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2394 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2398 guint32 nparams = context->method_inst->type_argc;
2401 if (!assembly->save)
2404 sigbuffer_init (&buf, 32);
2406 * FIXME: vararg, explicit_this, differenc call_conv values...
2408 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2409 sigbuffer_add_value (&buf, nparams);
2411 for (i = 0; i < nparams; i++)
2412 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2414 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2415 sigbuffer_free (&buf);
2420 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2422 MonoDynamicTable *table;
2424 guint32 token, mtoken = 0, sig;
2425 MonoMethodInflated *imethod;
2426 MonoMethod *declaring;
2428 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2430 g_assert (method->is_inflated);
2431 g_assert (!method->klass->generic_container);
2432 imethod = (MonoMethodInflated *) method;
2433 declaring = imethod->declaring;
2435 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2436 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2438 if (!mono_method_signature (declaring)->generic_param_count)
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 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2454 if (assembly->save) {
2455 alloc_table (table, table->rows + 1);
2456 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2457 values [MONO_METHODSPEC_METHOD] = mtoken;
2458 values [MONO_METHODSPEC_SIGNATURE] = sig;
2461 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2468 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2470 MonoMethodInflated *imethod;
2471 MonoMethod *inflated;
2474 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478 g_assert (method->is_inflated);
2479 inflated = mono_get_inflated_method (method);
2480 imethod = (MonoMethodInflated *) inflated;
2482 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2483 token = method_encode_methodspec (assembly, inflated);
2485 guint32 sig = method_encode_signature (
2486 assembly, mono_method_signature (imethod->declaring));
2487 token = mono_image_get_memberref_token (
2488 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2491 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2496 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2498 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2501 m = mono_get_inflated_method (m);
2503 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2504 token = mono_image_get_memberref_token (
2505 assembly, &m->klass->byval_arg, m->name, sig);
2511 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2513 MonoDynamicTable *table;
2521 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2522 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2523 * Because of this, we must not insert it into the `typeref' hash table.
2526 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2530 sigbuffer_init (&buf, 32);
2532 g_assert (tb->generic_params);
2533 klass = mono_class_from_mono_type (tb->type.type);
2535 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2536 encode_type (assembly, &klass->byval_arg, &buf);
2538 count = mono_array_length (tb->generic_params);
2539 sigbuffer_add_value (&buf, count);
2540 for (i = 0; i < count; i++) {
2541 MonoReflectionGenericParam *gparam;
2543 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2545 encode_type (assembly, gparam->type.type, &buf);
2548 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2550 if (assembly->save) {
2551 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2552 alloc_table (table, table->rows + 1);
2553 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2554 values [MONO_TYPESPEC_SIGNATURE] = token;
2556 sigbuffer_free (&buf);
2558 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2559 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2565 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2567 MonoDynamicTable *table;
2570 guint32 token, pclass, parent, sig;
2573 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2577 klass = mono_class_from_mono_type (fb->typeb->type);
2578 name = mono_string_to_utf8 (fb->name);
2580 sig = fieldref_encode_signature (assembly, fb->type->type);
2582 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2583 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2585 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2586 parent >>= MONO_TYPEDEFORREF_BITS;
2588 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2590 if (assembly->save) {
2591 alloc_table (table, table->rows + 1);
2592 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2593 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2594 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2595 values [MONO_MEMBERREF_SIGNATURE] = sig;
2598 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2600 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2605 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2612 if (!assembly->save)
2616 g_assert (helper->type == 2);
2618 if (helper->arguments)
2619 nargs = mono_array_length (helper->arguments);
2623 size = 10 + (nargs * 10);
2625 sigbuffer_init (&buf, 32);
2627 /* Encode calling convention */
2628 /* Change Any to Standard */
2629 if ((helper->call_conv & 0x03) == 0x03)
2630 helper->call_conv = 0x01;
2631 /* explicit_this implies has_this */
2632 if (helper->call_conv & 0x40)
2633 helper->call_conv &= 0x20;
2635 if (helper->call_conv == 0) { /* Unmanaged */
2636 idx = helper->unmanaged_call_conv - 1;
2639 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2640 if (helper->call_conv & 0x02) /* varargs */
2644 sigbuffer_add_byte (&buf, idx);
2645 sigbuffer_add_value (&buf, nargs);
2646 encode_reflection_type (assembly, helper->return_type, &buf);
2647 for (i = 0; i < nargs; ++i) {
2648 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2649 encode_reflection_type (assembly, pt, &buf);
2651 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2652 sigbuffer_free (&buf);
2658 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2661 MonoDynamicTable *table;
2664 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2665 idx = table->next_idx ++;
2667 alloc_table (table, table->rows);
2668 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2670 values [MONO_STAND_ALONE_SIGNATURE] =
2671 mono_reflection_encode_sighelper (assembly, helper);
2677 reflection_cc_to_file (int call_conv) {
2678 switch (call_conv & 0x3) {
2680 case 1: return MONO_CALL_DEFAULT;
2681 case 2: return MONO_CALL_VARARG;
2683 g_assert_not_reached ();
2690 MonoMethodSignature *sig;
2696 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2701 MonoMethodSignature *sig;
2704 name = mono_string_to_utf8 (m->name);
2705 nparams = mono_array_length (m->parameters);
2706 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2708 sig->sentinelpos = -1;
2709 sig->call_convention = reflection_cc_to_file (m->call_conv);
2710 sig->param_count = nparams;
2711 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2712 for (i = 0; i < nparams; ++i) {
2713 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2714 sig->params [i] = t->type;
2717 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2719 if (strcmp (name, am->name) == 0 &&
2720 mono_metadata_type_equal (am->parent, m->parent->type) &&
2721 mono_metadata_signature_equal (am->sig, sig)) {
2724 m->table_idx = am->token & 0xffffff;
2728 am = g_new0 (ArrayMethod, 1);
2731 am->parent = m->parent->type;
2732 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2733 method_encode_signature (assembly, sig));
2734 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2735 m->table_idx = am->token & 0xffffff;
2740 * Insert into the metadata tables all the info about the TypeBuilder tb.
2741 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2744 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2746 MonoDynamicTable *table;
2748 int i, is_object = 0, is_system = 0;
2751 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2752 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2753 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2754 n = mono_string_to_utf8 (tb->name);
2755 if (strcmp (n, "Object") == 0)
2757 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2759 n = mono_string_to_utf8 (tb->nspace);
2760 if (strcmp (n, "System") == 0)
2762 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2764 if (tb->parent && !(is_system && is_object) &&
2765 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2766 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2768 values [MONO_TYPEDEF_EXTENDS] = 0;
2770 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2771 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2774 * if we have explicitlayout or sequentiallayouts, output data in the
2775 * ClassLayout table.
2777 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2778 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2779 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2781 alloc_table (table, table->rows);
2782 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2783 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2784 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2785 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2788 /* handle interfaces */
2789 if (tb->interfaces) {
2790 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2792 table->rows += mono_array_length (tb->interfaces);
2793 alloc_table (table, table->rows);
2794 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2795 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2796 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2797 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2798 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2799 values += MONO_INTERFACEIMPL_SIZE;
2805 table = &assembly->tables [MONO_TABLE_FIELD];
2806 table->rows += tb->num_fields;
2807 alloc_table (table, table->rows);
2808 for (i = 0; i < tb->num_fields; ++i)
2809 mono_image_get_field_info (
2810 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2813 /* handle constructors */
2815 table = &assembly->tables [MONO_TABLE_METHOD];
2816 table->rows += mono_array_length (tb->ctors);
2817 alloc_table (table, table->rows);
2818 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2819 mono_image_get_ctor_info (domain,
2820 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2823 /* handle methods */
2825 table = &assembly->tables [MONO_TABLE_METHOD];
2826 table->rows += tb->num_methods;
2827 alloc_table (table, table->rows);
2828 for (i = 0; i < tb->num_methods; ++i)
2829 mono_image_get_method_info (
2830 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2833 /* Do the same with properties etc.. */
2834 if (tb->events && mono_array_length (tb->events)) {
2835 table = &assembly->tables [MONO_TABLE_EVENT];
2836 table->rows += mono_array_length (tb->events);
2837 alloc_table (table, table->rows);
2838 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2840 alloc_table (table, table->rows);
2841 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2842 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2843 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2844 for (i = 0; i < mono_array_length (tb->events); ++i)
2845 mono_image_get_event_info (
2846 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2848 if (tb->properties && mono_array_length (tb->properties)) {
2849 table = &assembly->tables [MONO_TABLE_PROPERTY];
2850 table->rows += mono_array_length (tb->properties);
2851 alloc_table (table, table->rows);
2852 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2854 alloc_table (table, table->rows);
2855 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2856 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2857 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2858 for (i = 0; i < mono_array_length (tb->properties); ++i)
2859 mono_image_get_property_info (
2860 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2863 /* handle generic parameters */
2864 if (tb->generic_params) {
2865 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2866 table->rows += mono_array_length (tb->generic_params);
2867 alloc_table (table, table->rows);
2868 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2869 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2871 mono_image_get_generic_param_info (
2872 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2876 mono_image_add_decl_security (assembly,
2877 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2880 MonoDynamicTable *ntable;
2882 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2883 ntable->rows += mono_array_length (tb->subtypes);
2884 alloc_table (ntable, ntable->rows);
2885 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2887 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2888 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2890 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2891 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2892 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2893 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2894 mono_string_to_utf8 (tb->name), tb->table_idx,
2895 ntable->next_idx, ntable->rows);*/
2896 values += MONO_NESTED_CLASS_SIZE;
2903 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2907 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2909 if (!type->subtypes)
2912 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2913 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2914 collect_types (types, subtype);
2919 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2921 if ((*type1)->table_idx < (*type2)->table_idx)
2924 if ((*type1)->table_idx > (*type2)->table_idx)
2931 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2936 for (i = 0; i < mono_array_length (pinfo); ++i) {
2937 MonoReflectionParamBuilder *pb;
2938 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2941 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2946 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2949 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2951 for (i = 0; i < tb->num_fields; ++i) {
2952 MonoReflectionFieldBuilder* fb;
2953 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2954 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2958 for (i = 0; i < mono_array_length (tb->events); ++i) {
2959 MonoReflectionEventBuilder* eb;
2960 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2961 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2964 if (tb->properties) {
2965 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2966 MonoReflectionPropertyBuilder* pb;
2967 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2968 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2972 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2973 MonoReflectionCtorBuilder* cb;
2974 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2975 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2976 params_add_cattrs (assembly, cb->pinfo);
2981 for (i = 0; i < tb->num_methods; ++i) {
2982 MonoReflectionMethodBuilder* mb;
2983 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2984 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2985 params_add_cattrs (assembly, mb->pinfo);
2990 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2991 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2996 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3000 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3002 if (moduleb->global_methods) {
3003 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3004 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3005 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3006 params_add_cattrs (assembly, mb->pinfo);
3010 if (moduleb->global_fields) {
3011 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3012 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3013 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3017 if (moduleb->types) {
3018 for (i = 0; i < moduleb->num_types; ++i)
3019 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3024 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3026 MonoDynamicTable *table;
3030 char *b = blob_size;
3033 table = &assembly->tables [MONO_TABLE_FILE];
3035 alloc_table (table, table->rows);
3036 values = table->values + table->next_idx * MONO_FILE_SIZE;
3037 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3038 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3039 if (module->image->dynamic) {
3040 /* This depends on the fact that the main module is emitted last */
3041 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3042 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3045 path = g_strdup (module->image->name);
3047 mono_sha1_get_digest_from_file (path, hash);
3050 mono_metadata_encode_value (20, b, &b);
3051 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3052 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3057 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3059 MonoDynamicTable *table;
3062 table = &assembly->tables [MONO_TABLE_MODULE];
3063 mb->table_idx = table->next_idx ++;
3064 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3065 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3068 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3069 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3070 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3071 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3075 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3076 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3078 MonoDynamicTable *table;
3082 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3083 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3086 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3088 alloc_table (table, table->rows);
3089 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3091 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3092 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3093 if (klass->nested_in)
3094 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3096 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3097 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3098 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3100 res = table->next_idx;
3104 /* Emit nested types */
3105 if (klass->nested_classes) {
3108 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3109 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3116 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3117 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3122 klass = mono_class_from_mono_type (tb->type.type);
3124 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3126 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3127 parent_index, assembly);
3131 * We need to do this ourselves since klass->nested_classes is not set up.
3134 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3135 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3140 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3141 guint32 module_index, MonoDynamicImage *assembly)
3143 MonoImage *image = module->image;
3147 t = &image->tables [MONO_TABLE_TYPEDEF];
3149 for (i = 0; i < t->rows; ++i) {
3150 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3152 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3153 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3158 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3160 MonoDynamicTable *table;
3166 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3168 if (assemblyb->type_forwarders) {
3169 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3170 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3176 klass = mono_class_from_mono_type (t->type);
3178 scope = resolution_scope_from_image (assembly, klass->image);
3179 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3180 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3183 alloc_table (table, table->rows);
3184 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3186 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3187 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3188 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3189 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3190 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3195 #define align_pointer(base,p)\
3197 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3199 (p) += 4 - (__diff & 3);\
3203 compare_constants (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3207 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3211 compare_semantics (const void *a, const void *b)
3213 const guint32 *a_values = a;
3214 const guint32 *b_values = b;
3215 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3218 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3222 compare_custom_attrs (const void *a, const void *b)
3224 const guint32 *a_values = a;
3225 const guint32 *b_values = b;
3227 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3231 compare_field_marshal (const void *a, const void *b)
3233 const guint32 *a_values = a;
3234 const guint32 *b_values = b;
3236 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3240 compare_nested (const void *a, const void *b)
3242 const guint32 *a_values = a;
3243 const guint32 *b_values = b;
3245 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3249 compare_genericparam (const void *a, const void *b)
3251 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3252 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3254 if ((*b_entry)->owner == (*a_entry)->owner)
3256 (*a_entry)->gparam->type.type->data.generic_param->num -
3257 (*b_entry)->gparam->type.type->data.generic_param->num;
3259 return (*a_entry)->owner - (*b_entry)->owner;
3263 compare_declsecurity_attrs (const void *a, const void *b)
3265 const guint32 *a_values = a;
3266 const guint32 *b_values = b;
3268 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3272 pad_heap (MonoDynamicStream *sh)
3274 if (sh->index & 3) {
3275 int sz = 4 - (sh->index & 3);
3276 memset (sh->data + sh->index, 0, sz);
3283 MonoDynamicStream *stream;
3287 * build_compressed_metadata() fills in the blob of data that represents the
3288 * raw metadata as it will be saved in the PE file. The five streams are output
3289 * and the metadata tables are comnpressed from the guint32 array representation,
3290 * to the compressed on-disk format.
3293 build_compressed_metadata (MonoDynamicImage *assembly)
3295 MonoDynamicTable *table;
3297 guint64 valid_mask = 0;
3298 guint64 sorted_mask;
3299 guint32 heapt_size = 0;
3300 guint32 meta_size = 256; /* allow for header and other stuff */
3301 guint32 table_offset;
3302 guint32 ntables = 0;
3308 struct StreamDesc stream_desc [5];
3310 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3311 for (i = 0; i < assembly->gen_params->len; i++){
3312 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3313 write_generic_param_entry (assembly, entry);
3316 stream_desc [0].name = "#~";
3317 stream_desc [0].stream = &assembly->tstream;
3318 stream_desc [1].name = "#Strings";
3319 stream_desc [1].stream = &assembly->sheap;
3320 stream_desc [2].name = "#US";
3321 stream_desc [2].stream = &assembly->us;
3322 stream_desc [3].name = "#Blob";
3323 stream_desc [3].stream = &assembly->blob;
3324 stream_desc [4].name = "#GUID";
3325 stream_desc [4].stream = &assembly->guid;
3327 /* tables that are sorted */
3328 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3329 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3330 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3331 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3332 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3333 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3335 /* Compute table sizes */
3336 /* the MonoImage has already been created in mono_image_basic_init() */
3337 meta = &assembly->image;
3339 /* sizes should be multiple of 4 */
3340 pad_heap (&assembly->blob);
3341 pad_heap (&assembly->guid);
3342 pad_heap (&assembly->sheap);
3343 pad_heap (&assembly->us);
3345 /* Setup the info used by compute_sizes () */
3346 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3347 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3348 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3350 meta_size += assembly->blob.index;
3351 meta_size += assembly->guid.index;
3352 meta_size += assembly->sheap.index;
3353 meta_size += assembly->us.index;
3355 for (i=0; i < MONO_TABLE_NUM; ++i)
3356 meta->tables [i].rows = assembly->tables [i].rows;
3358 for (i = 0; i < MONO_TABLE_NUM; i++){
3359 if (meta->tables [i].rows == 0)
3361 valid_mask |= (guint64)1 << i;
3363 meta->tables [i].row_size = mono_metadata_compute_size (
3364 meta, i, &meta->tables [i].size_bitfield);
3365 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3367 heapt_size += 24; /* #~ header size */
3368 heapt_size += ntables * 4;
3369 /* make multiple of 4 */
3372 meta_size += heapt_size;
3373 meta->raw_metadata = g_malloc0 (meta_size);
3374 p = (unsigned char*)meta->raw_metadata;
3375 /* the metadata signature */
3376 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3377 /* version numbers and 4 bytes reserved */
3378 int16val = (guint16*)p;
3379 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3380 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3382 /* version string */
3383 int32val = (guint32*)p;
3384 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3386 memcpy (p, meta->version, strlen (meta->version));
3387 p += GUINT32_FROM_LE (*int32val);
3388 align_pointer (meta->raw_metadata, p);
3389 int16val = (guint16*)p;
3390 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3391 *int16val = GUINT16_TO_LE (5); /* number of streams */
3395 * write the stream info.
3397 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3398 table_offset += 3; table_offset &= ~3;
3400 assembly->tstream.index = heapt_size;
3401 for (i = 0; i < 5; ++i) {
3402 int32val = (guint32*)p;
3403 stream_desc [i].stream->offset = table_offset;
3404 *int32val++ = GUINT32_TO_LE (table_offset);
3405 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3406 table_offset += GUINT32_FROM_LE (*int32val);
3407 table_offset += 3; table_offset &= ~3;
3409 strcpy ((char*)p, stream_desc [i].name);
3410 p += strlen (stream_desc [i].name) + 1;
3411 align_pointer (meta->raw_metadata, p);
3414 * now copy the data, the table stream header and contents goes first.
3416 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3417 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3418 int32val = (guint32*)p;
3419 *int32val = GUINT32_TO_LE (0); /* reserved */
3422 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3423 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3424 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3425 *p++ = 2; /* version */
3428 *p++ = 1; /* version */
3432 if (meta->idx_string_wide)
3434 if (meta->idx_guid_wide)
3436 if (meta->idx_blob_wide)
3439 *p++ = 1; /* reserved */
3440 int64val = (guint64*)p;
3441 *int64val++ = GUINT64_TO_LE (valid_mask);
3442 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3444 int32val = (guint32*)p;
3445 for (i = 0; i < MONO_TABLE_NUM; i++){
3446 if (meta->tables [i].rows == 0)
3448 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3450 p = (unsigned char*)int32val;
3452 /* sort the tables that still need sorting */
3453 table = &assembly->tables [MONO_TABLE_CONSTANT];
3455 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3456 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3458 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3459 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3461 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3462 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3464 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3465 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3467 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3468 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3469 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3471 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3473 /* compress the tables */
3474 for (i = 0; i < MONO_TABLE_NUM; i++){
3477 guint32 bitfield = meta->tables [i].size_bitfield;
3478 if (!meta->tables [i].rows)
3480 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3481 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3482 meta->tables [i].base = (char*)p;
3483 for (row = 1; row <= meta->tables [i].rows; ++row) {
3484 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3485 for (col = 0; col < assembly->tables [i].columns; ++col) {
3486 switch (mono_metadata_table_size (bitfield, col)) {
3488 *p++ = values [col];
3491 *p++ = values [col] & 0xff;
3492 *p++ = (values [col] >> 8) & 0xff;
3495 *p++ = values [col] & 0xff;
3496 *p++ = (values [col] >> 8) & 0xff;
3497 *p++ = (values [col] >> 16) & 0xff;
3498 *p++ = (values [col] >> 24) & 0xff;
3501 g_assert_not_reached ();
3505 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3508 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3509 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3510 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3511 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3512 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3514 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3518 * Some tables in metadata need to be sorted according to some criteria, but
3519 * when methods and fields are first created with reflection, they may be assigned a token
3520 * that doesn't correspond to the final token they will get assigned after the sorting.
3521 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3522 * with the reflection objects that represent them. Once all the tables are set up, the
3523 * reflection objects will contains the correct table index. fixup_method() will fixup the
3524 * tokens for the method with ILGenerator @ilgen.
3527 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3528 guint32 code_idx = GPOINTER_TO_UINT (value);
3529 MonoReflectionILTokenInfo *iltoken;
3530 MonoReflectionFieldBuilder *field;
3531 MonoReflectionCtorBuilder *ctor;
3532 MonoReflectionMethodBuilder *method;
3533 MonoReflectionTypeBuilder *tb;
3534 MonoReflectionArrayMethod *am;
3536 unsigned char *target;
3538 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3539 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3540 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3541 switch (target [3]) {
3542 case MONO_TABLE_FIELD:
3543 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3544 field = (MonoReflectionFieldBuilder *)iltoken->member;
3545 idx = field->table_idx;
3546 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3547 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3548 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3550 g_assert_not_reached ();
3553 case MONO_TABLE_METHOD:
3554 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3555 method = (MonoReflectionMethodBuilder *)iltoken->member;
3556 idx = method->table_idx;
3557 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3558 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3559 idx = ctor->table_idx;
3560 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3561 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3562 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3563 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3565 g_assert_not_reached ();
3568 case MONO_TABLE_TYPEDEF:
3569 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3570 g_assert_not_reached ();
3571 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3572 idx = tb->table_idx;
3574 case MONO_TABLE_MEMBERREF:
3575 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3576 am = (MonoReflectionArrayMethod*)iltoken->member;
3577 idx = am->table_idx;
3578 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3579 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3580 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3581 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3582 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3583 g_assert (m->klass->generic_class || m->klass->generic_container);
3585 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3587 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3588 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3589 g_assert (f->generic_info);
3591 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3594 g_assert_not_reached ();
3597 case MONO_TABLE_METHODSPEC:
3598 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3599 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3600 g_assert (mono_method_signature (m)->generic_param_count);
3603 g_assert_not_reached ();
3607 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3609 target [0] = idx & 0xff;
3610 target [1] = (idx >> 8) & 0xff;
3611 target [2] = (idx >> 16) & 0xff;
3618 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3619 * value is not known when the table is emitted.
3622 fixup_cattrs (MonoDynamicImage *assembly)
3624 MonoDynamicTable *table;
3626 guint32 type, i, idx, token;
3629 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3631 for (i = 0; i < table->rows; ++i) {
3632 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3634 type = values [MONO_CUSTOM_ATTR_TYPE];
3635 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3636 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3637 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3638 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3641 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3642 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3643 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3644 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3651 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3653 MonoDynamicTable *table;
3656 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3658 alloc_table (table, table->rows);
3659 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3660 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3661 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3662 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3663 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3668 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3670 MonoDynamicTable *table;
3674 char *b = blob_size;
3676 guint32 idx, offset;
3678 if (rsrc->filename) {
3679 name = mono_string_to_utf8 (rsrc->filename);
3680 sname = g_path_get_basename (name);
3682 table = &assembly->tables [MONO_TABLE_FILE];
3684 alloc_table (table, table->rows);
3685 values = table->values + table->next_idx * MONO_FILE_SIZE;
3686 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3687 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3690 mono_sha1_get_digest_from_file (name, hash);
3691 mono_metadata_encode_value (20, b, &b);
3692 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3693 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3695 idx = table->next_idx++;
3697 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3703 data = mono_array_addr (rsrc->data, char, 0);
3704 len = mono_array_length (rsrc->data);
3710 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3711 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3712 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3713 mono_image_add_stream_data (&assembly->resources, data, len);
3717 * The entry should be emitted into the MANIFESTRESOURCE table of
3718 * the main module, but that needs to reference the FILE table
3719 * which isn't emitted yet.
3726 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3730 set_version_from_string (MonoString *version, guint32 *values)
3732 gchar *ver, *p, *str;
3735 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3736 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3737 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3738 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3741 ver = str = mono_string_to_utf8 (version);
3742 for (i = 0; i < 4; ++i) {
3743 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3749 /* handle Revision and Build */
3759 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3763 char *b = blob_size;
3768 len = mono_array_length (pkey);
3769 mono_metadata_encode_value (len, b, &b);
3770 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3771 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3773 /* Special case: check for ECMA key (16 bytes) */
3774 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3775 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3776 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3777 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3778 /* minimum key size (in 2.0) is 384 bits */
3779 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3781 /* FIXME - verifier */
3782 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3783 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3785 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3791 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3793 MonoDynamicTable *table;
3794 MonoDynamicImage *assembly;
3795 MonoReflectionAssemblyBuilder *assemblyb;
3799 guint32 module_index;
3801 assemblyb = moduleb->assemblyb;
3802 assembly = moduleb->dynamic_image;
3803 domain = mono_object_domain (assemblyb);
3805 /* Emit ASSEMBLY table */
3806 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3807 alloc_table (table, 1);
3808 values = table->values + MONO_ASSEMBLY_SIZE;
3809 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3810 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3811 if (assemblyb->culture) {
3812 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3814 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3816 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3817 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3818 set_version_from_string (assemblyb->version, values);
3820 /* Emit FILE + EXPORTED_TYPE table */
3822 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3824 MonoReflectionModuleBuilder *file_module =
3825 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3826 if (file_module != moduleb) {
3827 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3829 if (file_module->types) {
3830 for (j = 0; j < file_module->num_types; ++j) {
3831 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3832 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3837 if (assemblyb->loaded_modules) {
3838 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3839 MonoReflectionModule *file_module =
3840 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3841 mono_image_fill_file_table (domain, file_module, assembly);
3843 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3846 if (assemblyb->type_forwarders)
3847 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3849 /* Emit MANIFESTRESOURCE table */
3851 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3853 MonoReflectionModuleBuilder *file_module =
3854 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3855 /* The table for the main module is emitted later */
3856 if (file_module != moduleb) {
3858 if (file_module->resources) {
3859 int len = mono_array_length (file_module->resources);
3860 for (j = 0; j < len; ++j) {
3861 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3862 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3870 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3871 * for the modulebuilder @moduleb.
3872 * At the end of the process, method and field tokens are fixed up and the
3873 * on-disk compressed metadata representation is created.
3876 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3878 MonoDynamicTable *table;
3879 MonoDynamicImage *assembly;
3880 MonoReflectionAssemblyBuilder *assemblyb;
3886 assemblyb = moduleb->assemblyb;
3887 assembly = moduleb->dynamic_image;
3888 domain = mono_object_domain (assemblyb);
3890 if (assembly->text_rva)
3893 assembly->text_rva = START_TEXT_RVA;
3895 if (moduleb->is_main) {
3896 mono_image_emit_manifest (moduleb);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows = 1; /* .<Module> */
3902 alloc_table (table, table->rows);
3904 * Set the first entry.
3906 values = table->values + table->columns;
3907 values [MONO_TYPEDEF_FLAGS] = 0;
3908 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3909 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3910 values [MONO_TYPEDEF_EXTENDS] = 0;
3911 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3912 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3915 * handle global methods
3916 * FIXME: test what to do when global methods are defined in multiple modules.
3918 if (moduleb->global_methods) {
3919 table = &assembly->tables [MONO_TABLE_METHOD];
3920 table->rows += mono_array_length (moduleb->global_methods);
3921 alloc_table (table, table->rows);
3922 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3923 mono_image_get_method_info (
3924 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3926 if (moduleb->global_fields) {
3927 table = &assembly->tables [MONO_TABLE_FIELD];
3928 table->rows += mono_array_length (moduleb->global_fields);
3929 alloc_table (table, table->rows);
3930 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3931 mono_image_get_field_info (
3932 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3935 table = &assembly->tables [MONO_TABLE_MODULE];
3936 alloc_table (table, 1);
3937 mono_image_fill_module_table (domain, moduleb, assembly);
3939 /* Collect all types into a list sorted by their table_idx */
3940 types = g_ptr_array_new ();
3943 for (i = 0; i < moduleb->num_types; ++i) {
3944 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3945 collect_types (types, type);
3948 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3949 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3950 table->rows += types->len;
3951 alloc_table (table, table->rows);
3954 * Emit type names + namespaces at one place inside the string heap,
3955 * so load_class_names () needs to touch fewer pages.
3957 for (i = 0; i < types->len; ++i) {
3958 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3959 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3961 for (i = 0; i < types->len; ++i) {
3962 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3963 string_heap_insert_mstring (&assembly->sheap, tb->name);
3966 for (i = 0; i < types->len; ++i) {
3967 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3968 mono_image_get_type_info (domain, type, assembly);
3972 * table->rows is already set above and in mono_image_fill_module_table.
3974 /* add all the custom attributes at the end, once all the indexes are stable */
3975 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3977 /* CAS assembly permissions */
3978 if (assemblyb->permissions_minimum)
3979 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3980 if (assemblyb->permissions_optional)
3981 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3982 if (assemblyb->permissions_refused)
3983 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3985 module_add_cattrs (assembly, moduleb);
3988 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3990 /* Create the MethodImpl table. We do this after emitting all methods so we already know
3991 * the final tokens and don't need another fixup pass. */
3993 if (moduleb->global_methods) {
3994 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3995 MonoReflectionMethodBuilder *mb = mono_array_get (
3996 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3997 mono_image_add_methodimpl (assembly, mb);
4001 for (i = 0; i < types->len; ++i) {
4002 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4003 if (type->methods) {
4004 for (j = 0; j < type->num_methods; ++j) {
4005 MonoReflectionMethodBuilder *mb = mono_array_get (
4006 type->methods, MonoReflectionMethodBuilder*, j);
4008 mono_image_add_methodimpl (assembly, mb);
4013 g_ptr_array_free (types, TRUE);
4015 fixup_cattrs (assembly);
4019 * mono_image_insert_string:
4020 * @module: module builder object
4023 * Insert @str into the user string stream of @module.
4026 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4028 MonoDynamicImage *assembly;
4033 MONO_ARCH_SAVE_REGS;
4035 if (!module->dynamic_image)
4036 mono_image_module_basic_init (module);
4038 assembly = module->dynamic_image;
4040 if (assembly->save) {
4041 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4042 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4043 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4045 char *swapped = g_malloc (2 * mono_string_length (str));
4046 const char *p = (const char*)mono_string_chars (str);
4048 swap_with_size (swapped, p, 2, mono_string_length (str));
4049 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4053 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4055 mono_image_add_stream_data (&assembly->us, "", 1);
4057 idx = assembly->us.index ++;
4060 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4062 return MONO_TOKEN_STRING | idx;
4066 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4071 klass = obj->vtable->klass;
4072 if (strcmp (klass->name, "MonoMethod") == 0) {
4073 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4074 MonoMethodSignature *sig, *old;
4075 guint32 sig_token, parent;
4078 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4080 nargs = mono_array_length (opt_param_types);
4081 old = mono_method_signature (method);
4082 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4084 sig->hasthis = old->hasthis;
4085 sig->explicit_this = old->explicit_this;
4086 sig->call_convention = old->call_convention;
4087 sig->generic_param_count = old->generic_param_count;
4088 sig->param_count = old->param_count + nargs;
4089 sig->sentinelpos = old->param_count;
4090 sig->ret = old->ret;
4092 for (i = 0; i < old->param_count; i++)
4093 sig->params [i] = old->params [i];
4095 for (i = 0; i < nargs; i++) {
4096 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4097 sig->params [old->param_count + i] = rt->type;
4100 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4101 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4102 parent >>= MONO_TYPEDEFORREF_BITS;
4104 parent <<= MONO_MEMBERREF_PARENT_BITS;
4105 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4107 sig_token = method_encode_signature (assembly, sig);
4108 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4109 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4110 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4111 ReflectionMethodBuilder rmb;
4112 guint32 parent, sig;
4114 reflection_methodbuilder_from_method_builder (&rmb, mb);
4115 rmb.opt_types = opt_param_types;
4117 sig = method_builder_encode_signature (assembly, &rmb);
4119 parent = mono_image_create_token (assembly, obj, TRUE);
4120 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4122 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4123 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4125 token = mono_image_get_varargs_method_token (
4126 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4128 g_error ("requested method token for %s\n", klass->name);
4135 * mono_image_create_token:
4136 * @assembly: a dynamic assembly
4139 * Get a token to insert in the IL code stream for the given MemberInfo.
4140 * @obj can be one of:
4141 * ConstructorBuilder
4151 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4156 klass = obj->vtable->klass;
4157 if (strcmp (klass->name, "MethodBuilder") == 0) {
4158 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4160 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4161 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4163 token = mono_image_get_methodbuilder_token (assembly, mb);
4164 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4165 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4166 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4168 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4169 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4171 token = mono_image_get_ctorbuilder_token (assembly, mb);
4172 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4173 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4174 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4175 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4176 if (tb->generic_params) {
4177 token = mono_image_get_generic_field_token (assembly, fb);
4179 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4181 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4182 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4183 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4184 } else if (strcmp (klass->name, "MonoType") == 0 ||
4185 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4186 MonoReflectionType *tb = (MonoReflectionType *)obj;
4187 token = mono_metadata_token_from_dor (
4188 mono_image_typedef_or_ref (assembly, tb->type));
4189 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4190 MonoReflectionType *tb = (MonoReflectionType *)obj;
4191 token = mono_metadata_token_from_dor (
4192 mono_image_typedef_or_ref (assembly, tb->type));
4193 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4194 strcmp (klass->name, "MonoMethod") == 0 ||
4195 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4196 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4197 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4198 if (m->method->is_inflated) {
4199 if (create_methodspec)
4200 token = mono_image_get_methodspec_token (assembly, m->method);
4202 token = mono_image_get_inflated_method_token (assembly, m->method);
4203 } else if ((m->method->klass->image == &assembly->image) &&
4204 !m->method->klass->generic_class) {
4205 static guint32 method_table_idx = 0xffffff;
4206 if (m->method->klass->wastypebuilder) {
4207 /* we use the same token as the one that was assigned
4208 * to the Methodbuilder.
4209 * FIXME: do the equivalent for Fields.
4211 token = m->method->token;
4214 * Each token should have a unique index, but the indexes are
4215 * assigned by managed code, so we don't know about them. An
4216 * easy solution is to count backwards...
4218 method_table_idx --;
4219 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4222 token = mono_image_get_methodref_token (assembly, m->method);
4224 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4225 } else if (strcmp (klass->name, "MonoField") == 0) {
4226 MonoReflectionField *f = (MonoReflectionField *)obj;
4227 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4228 static guint32 field_table_idx = 0xffffff;
4230 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4232 token = mono_image_get_fieldref_token (assembly, f);
4234 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4235 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4236 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4237 token = mono_image_get_array_token (assembly, m);
4238 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4239 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4240 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4241 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4242 MonoReflectionType *tb = (MonoReflectionType *)obj;
4243 token = mono_metadata_token_from_dor (
4244 mono_image_typedef_or_ref (assembly, tb->type));
4246 g_error ("requested token for %s\n", klass->name);
4249 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4255 guint32 import_lookup_table;
4259 guint32 import_address_table_rva;
4267 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4269 static MonoDynamicImage*
4270 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4272 static const guchar entrycode [16] = {0xff, 0x25, 0};
4273 MonoDynamicImage *image;
4276 const char *version = mono_get_runtime_info ()->runtime_version;
4279 image = GC_MALLOC (sizeof (MonoDynamicImage));
4281 image = g_new0 (MonoDynamicImage, 1);
4284 /*g_print ("created image %p\n", image);*/
4285 /* keep in sync with image.c */
4286 image->image.name = assembly_name;
4287 image->image.assembly_name = image->image.name; /* they may be different */
4288 image->image.module_name = module_name;
4289 image->image.version = g_strdup (version);
4290 image->image.md_version_major = 1;
4291 image->image.md_version_minor = 1;
4292 image->image.dynamic = TRUE;
4294 image->image.references = g_new0 (MonoAssembly*, 1);
4295 image->image.references [0] = NULL;
4297 mono_image_init (&image->image);
4299 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4300 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4301 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4302 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4303 image->handleref = g_hash_table_new (NULL, NULL);
4304 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4305 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4306 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4307 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4308 image->gen_params = g_ptr_array_new ();
4310 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4311 string_heap_init (&image->sheap);
4312 mono_image_add_stream_data (&image->us, "", 1);
4313 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4314 /* import tables... */
4315 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4316 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4317 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4318 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4319 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4320 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4321 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4322 stream_data_align (&image->code);
4324 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4326 for (i=0; i < MONO_TABLE_NUM; ++i) {
4327 image->tables [i].next_idx = 1;
4328 image->tables [i].columns = table_sizes [i];
4331 image->image.assembly = (MonoAssembly*)assembly;
4332 image->run = assembly->run;
4333 image->save = assembly->save;
4334 image->pe_kind = 0x1; /* ILOnly */
4335 image->machine = 0x14c; /* I386 */
4341 * mono_image_basic_init:
4342 * @assembly: an assembly builder object
4344 * Create the MonoImage that represents the assembly builder and setup some
4345 * of the helper hash table and the basic metadata streams.
4348 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4350 MonoDynamicAssembly *assembly;
4351 MonoDynamicImage *image;
4352 MonoDomain *domain = mono_object_domain (assemblyb);
4354 MONO_ARCH_SAVE_REGS;
4356 if (assemblyb->dynamic_assembly)
4360 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4362 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4365 assembly->assembly.ref_count = 1;
4366 assembly->assembly.dynamic = TRUE;
4367 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4368 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4369 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4370 if (assemblyb->culture)
4371 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4373 assembly->assembly.aname.culture = g_strdup ("");
4375 if (assemblyb->version) {
4376 char *vstr = mono_string_to_utf8 (assemblyb->version);
4377 char **version = g_strsplit (vstr, ".", 4);
4378 char **parts = version;
4379 assembly->assembly.aname.major = atoi (*parts++);
4380 assembly->assembly.aname.minor = atoi (*parts++);
4381 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4382 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4384 g_strfreev (version);
4387 assembly->assembly.aname.major = 0;
4388 assembly->assembly.aname.minor = 0;
4389 assembly->assembly.aname.build = 0;
4390 assembly->assembly.aname.revision = 0;
4393 assembly->run = assemblyb->access != 2;
4394 assembly->save = assemblyb->access != 1;
4396 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4397 image->initial_image = TRUE;
4398 assembly->assembly.aname.name = image->image.name;
4399 assembly->assembly.image = &image->image;
4401 mono_domain_assemblies_lock (domain);
4402 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4403 mono_domain_assemblies_unlock (domain);
4405 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4406 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4410 calc_section_size (MonoDynamicImage *assembly)
4414 /* alignment constraints */
4415 assembly->code.index += 3;
4416 assembly->code.index &= ~3;
4417 assembly->meta_size += 3;
4418 assembly->meta_size &= ~3;
4419 assembly->resources.index += 3;
4420 assembly->resources.index &= ~3;
4422 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4423 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4426 if (assembly->win32_res) {
4427 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4429 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4430 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4434 assembly->sections [MONO_SECTION_RELOC].size = 12;
4435 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4445 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4449 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4451 ResTreeNode *t1 = (ResTreeNode*)a;
4452 ResTreeNode *t2 = (ResTreeNode*)b;
4454 return t1->id - t2->id;
4458 * resource_tree_create:
4460 * Organize the resources into a resource tree.
4462 static ResTreeNode *
4463 resource_tree_create (MonoArray *win32_resources)
4465 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4469 tree = g_new0 (ResTreeNode, 1);
4471 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4472 MonoReflectionWin32Resource *win32_res =
4473 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4477 /* FIXME: BUG: this stores managed references in unmanaged memory */
4478 lang_node = g_new0 (ResTreeNode, 1);
4479 lang_node->id = win32_res->lang_id;
4480 lang_node->win32_res = win32_res;
4482 /* Create type node if neccesary */
4484 for (l = tree->children; l; l = l->next)
4485 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4486 type_node = (ResTreeNode*)l->data;
4491 type_node = g_new0 (ResTreeNode, 1);
4492 type_node->id = win32_res->res_type;
4495 * The resource types have to be sorted otherwise
4496 * Windows Explorer can't display the version information.
4498 tree->children = g_slist_insert_sorted (tree->children,
4499 type_node, resource_tree_compare_by_id);
4502 /* Create res node if neccesary */
4504 for (l = type_node->children; l; l = l->next)
4505 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4506 res_node = (ResTreeNode*)l->data;
4511 res_node = g_new0 (ResTreeNode, 1);
4512 res_node->id = win32_res->res_id;
4513 type_node->children = g_slist_append (type_node->children, res_node);
4516 res_node->children = g_slist_append (res_node->children, lang_node);
4523 * resource_tree_encode:
4525 * Encode the resource tree into the format used in the PE file.
4528 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4531 MonoPEResourceDir dir;
4532 MonoPEResourceDirEntry dir_entry;
4533 MonoPEResourceDataEntry data_entry;
4537 * For the format of the resource directory, see the article
4538 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4542 memset (&dir, 0, sizeof (dir));
4543 memset (&dir_entry, 0, sizeof (dir_entry));
4544 memset (&data_entry, 0, sizeof (data_entry));
4546 g_assert (sizeof (dir) == 16);
4547 g_assert (sizeof (dir_entry) == 8);
4548 g_assert (sizeof (data_entry) == 16);
4550 node->offset = p - begin;
4552 /* IMAGE_RESOURCE_DIRECTORY */
4553 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4555 memcpy (p, &dir, sizeof (dir));
4558 /* Reserve space for entries */
4560 p += sizeof (dir_entry) * dir.res_id_entries;
4562 /* Write children */
4563 for (l = node->children; l; l = l->next) {
4564 ResTreeNode *child = (ResTreeNode*)l->data;
4566 if (child->win32_res) {
4568 child->offset = p - begin;
4570 /* IMAGE_RESOURCE_DATA_ENTRY */
4571 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4572 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4574 memcpy (p, &data_entry, sizeof (data_entry));
4575 p += sizeof (data_entry);
4577 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4578 p += data_entry.rde_size;
4580 resource_tree_encode (child, begin, p, &p);
4584 /* IMAGE_RESOURCE_ENTRY */
4585 for (l = node->children; l; l = l->next) {
4586 ResTreeNode *child = (ResTreeNode*)l->data;
4587 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4589 dir_entry.is_dir = child->win32_res ? 0 : 1;
4590 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4592 memcpy (entries, &dir_entry, sizeof (dir_entry));
4593 entries += sizeof (dir_entry);
4600 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4605 MonoReflectionWin32Resource *win32_res;
4608 if (!assemblyb->win32_resources)
4612 * Resources are stored in a three level tree inside the PE file.
4613 * - level one contains a node for each type of resource
4614 * - level two contains a node for each resource
4615 * - level three contains a node for each instance of a resource for a
4616 * specific language.
4619 tree = resource_tree_create (assemblyb->win32_resources);
4621 /* Estimate the size of the encoded tree */
4623 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4624 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4625 size += mono_array_length (win32_res->res_data);
4627 /* Directory structure */
4628 size += mono_array_length (assemblyb->win32_resources) * 256;
4629 p = buf = g_malloc (size);
4631 resource_tree_encode (tree, p, p, &p);
4633 g_assert (p - buf <= size);
4635 assembly->win32_res = g_malloc (p - buf);
4636 assembly->win32_res_size = p - buf;
4637 memcpy (assembly->win32_res, buf, p - buf);
4643 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4645 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4648 p += sizeof (MonoPEResourceDir);
4649 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4650 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4651 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4652 if (dir_entry->is_dir) {
4653 fixup_resource_directory (res_section, child, rva);
4655 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4656 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4659 p += sizeof (MonoPEResourceDirEntry);
4664 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4667 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4668 g_error ("WriteFile returned %d\n", GetLastError ());
4672 * mono_image_create_pefile:
4673 * @mb: a module builder object
4675 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4676 * assembly->pefile where it can be easily retrieved later in chunks.
4679 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4680 MonoMSDOSHeader *msdos;
4681 MonoDotNetHeader *header;
4682 MonoSectionTable *section;
4683 MonoCLIHeader *cli_header;
4684 guint32 size, image_size, virtual_base, text_offset;
4685 guint32 header_start, section_start, file_offset, virtual_offset;
4686 MonoDynamicImage *assembly;
4687 MonoReflectionAssemblyBuilder *assemblyb;
4688 MonoDynamicStream pefile_stream = {0};
4689 MonoDynamicStream *pefile = &pefile_stream;
4691 guint32 *rva, value;
4693 static const unsigned char msheader[] = {
4694 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4695 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4698 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4699 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4700 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4701 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4704 assemblyb = mb->assemblyb;
4706 mono_image_basic_init (assemblyb);
4707 assembly = mb->dynamic_image;
4709 assembly->pe_kind = assemblyb->pe_kind;
4710 assembly->machine = assemblyb->machine;
4711 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4712 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4714 mono_image_build_metadata (mb);
4716 if (mb->is_main && assemblyb->resources) {
4717 int len = mono_array_length (assemblyb->resources);
4718 for (i = 0; i < len; ++i)
4719 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4722 if (mb->resources) {
4723 int len = mono_array_length (mb->resources);
4724 for (i = 0; i < len; ++i)
4725 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4728 build_compressed_metadata (assembly);
4731 assembly_add_win32_resources (assembly, assemblyb);
4733 nsections = calc_section_size (assembly);
4735 /* The DOS header and stub */
4736 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4737 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4739 /* the dotnet header */
4740 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4742 /* the section tables */
4743 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4745 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4746 virtual_offset = VIRT_ALIGN;
4749 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4750 if (!assembly->sections [i].size)
4753 file_offset += FILE_ALIGN - 1;
4754 file_offset &= ~(FILE_ALIGN - 1);
4755 virtual_offset += VIRT_ALIGN - 1;
4756 virtual_offset &= ~(VIRT_ALIGN - 1);
4758 assembly->sections [i].offset = file_offset;
4759 assembly->sections [i].rva = virtual_offset;
4761 file_offset += assembly->sections [i].size;
4762 virtual_offset += assembly->sections [i].size;
4763 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4766 file_offset += FILE_ALIGN - 1;
4767 file_offset &= ~(FILE_ALIGN - 1);
4769 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4771 /* back-patch info */
4772 msdos = (MonoMSDOSHeader*)pefile->data;
4773 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4775 header = (MonoDotNetHeader*)(pefile->data + header_start);
4776 header->pesig [0] = 'P';
4777 header->pesig [1] = 'E';
4779 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4780 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4781 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4782 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4783 if (assemblyb->pekind == 1) {
4785 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4788 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4791 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4793 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4794 header->pe.pe_major = 6;
4795 header->pe.pe_minor = 0;
4796 size = assembly->sections [MONO_SECTION_TEXT].size;
4797 size += FILE_ALIGN - 1;
4798 size &= ~(FILE_ALIGN - 1);
4799 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4800 size = assembly->sections [MONO_SECTION_RSRC].size;
4801 size += FILE_ALIGN - 1;
4802 size &= ~(FILE_ALIGN - 1);
4803 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4804 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4805 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4806 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4807 /* pe_rva_entry_point always at the beginning of the text section */
4808 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4810 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4811 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4812 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4813 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4814 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4815 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4816 size = section_start;
4817 size += FILE_ALIGN - 1;
4818 size &= ~(FILE_ALIGN - 1);
4819 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4821 size += VIRT_ALIGN - 1;
4822 size &= ~(VIRT_ALIGN - 1);
4823 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4826 // Translate the PEFileKind value to the value expected by the Windows loader
4832 // PEFileKinds.Dll == 1
4833 // PEFileKinds.ConsoleApplication == 2
4834 // PEFileKinds.WindowApplication == 3
4837 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4838 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4840 if (assemblyb->pekind == 3)
4845 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4847 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4848 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4849 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4850 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4851 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4852 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4854 /* fill data directory entries */
4856 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4857 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4859 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4860 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4862 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4863 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4864 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4865 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4866 /* patch entrypoint name */
4867 if (assemblyb->pekind == 1)
4868 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4870 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4871 /* patch imported function RVA name */
4872 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4873 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4875 /* the import table */
4876 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4877 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4878 /* patch imported dll RVA name and other entries in the dir */
4879 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4880 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4881 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4882 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4883 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4884 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4886 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4887 value = (assembly->text_rva + assembly->imp_names_offset);
4888 *p++ = (value) & 0xff;
4889 *p++ = (value >> 8) & (0xff);
4890 *p++ = (value >> 16) & (0xff);
4891 *p++ = (value >> 24) & (0xff);
4893 /* the CLI header info */
4894 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4895 cli_header->ch_size = GUINT32_FROM_LE (72);
4896 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4897 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4898 if (assemblyb->entry_point) {
4899 guint32 table_idx = 0;
4900 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4901 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4902 table_idx = methodb->table_idx;
4904 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4906 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4908 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4910 /* The embedded managed resources */
4911 text_offset = assembly->text_rva + assembly->code.index;
4912 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4913 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4914 text_offset += assembly->resources.index;
4915 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4916 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4917 text_offset += assembly->meta_size;
4918 if (assembly->strong_name_size) {
4919 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4920 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4921 text_offset += assembly->strong_name_size;
4924 /* write the section tables and section content */
4925 section = (MonoSectionTable*)(pefile->data + section_start);
4926 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4927 static const char section_names [][7] = {
4928 ".text", ".rsrc", ".reloc"
4930 if (!assembly->sections [i].size)
4932 strcpy (section->st_name, section_names [i]);
4933 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4934 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4935 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4936 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4937 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4938 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4939 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4943 checked_write_file (file, pefile->data, pefile->index);
4945 mono_dynamic_stream_reset (pefile);
4947 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4948 if (!assembly->sections [i].size)
4951 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4952 g_error ("SetFilePointer returned %d\n", GetLastError ());
4955 case MONO_SECTION_TEXT:
4956 /* patch entry point */
4957 p = (guchar*)(assembly->code.data + 2);
4958 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4959 *p++ = (value) & 0xff;
4960 *p++ = (value >> 8) & 0xff;
4961 *p++ = (value >> 16) & 0xff;
4962 *p++ = (value >> 24) & 0xff;
4964 checked_write_file (file, assembly->code.data, assembly->code.index);
4965 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4966 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4967 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4970 g_free (assembly->image.raw_metadata);
4972 case MONO_SECTION_RELOC: {
4976 guint16 type_and_offset;
4980 g_assert (sizeof (reloc) == 12);
4982 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4983 reloc.block_size = GUINT32_FROM_LE (12);
4986 * the entrypoint is always at the start of the text section
4987 * 3 is IMAGE_REL_BASED_HIGHLOW
4988 * 2 is patch_size_rva - text_rva
4990 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4993 checked_write_file (file, &reloc, sizeof (reloc));
4997 case MONO_SECTION_RSRC:
4998 if (assembly->win32_res) {
5000 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5001 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5002 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5006 g_assert_not_reached ();
5010 /* check that the file is properly padded */
5011 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5012 g_error ("SetFilePointer returned %d\n", GetLastError ());
5013 if (! SetEndOfFile (file))
5014 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5016 mono_dynamic_stream_reset (&assembly->code);
5017 mono_dynamic_stream_reset (&assembly->us);
5018 mono_dynamic_stream_reset (&assembly->blob);
5019 mono_dynamic_stream_reset (&assembly->guid);
5020 mono_dynamic_stream_reset (&assembly->sheap);
5022 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5023 g_hash_table_destroy (assembly->blob_cache);
5024 assembly->blob_cache = NULL;
5027 MonoReflectionModule *
5028 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5032 MonoImageOpenStatus status;
5033 MonoDynamicAssembly *assembly;
5034 guint32 module_count;
5035 MonoImage **new_modules;
5036 gboolean *new_modules_loaded;
5038 name = mono_string_to_utf8 (fileName);
5040 image = mono_image_open (name, &status);
5043 if (status == MONO_IMAGE_ERROR_ERRNO)
5044 exc = mono_get_exception_file_not_found (fileName);
5046 exc = mono_get_exception_bad_image_format (name);
5048 mono_raise_exception (exc);
5053 assembly = ab->dynamic_assembly;
5054 image->assembly = (MonoAssembly*)assembly;
5056 module_count = image->assembly->image->module_count;
5057 new_modules = g_new0 (MonoImage *, module_count + 1);
5058 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5060 if (image->assembly->image->modules)
5061 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5062 if (image->assembly->image->modules_loaded)
5063 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5064 new_modules [module_count] = image;
5065 new_modules_loaded [module_count] = TRUE;
5066 mono_image_addref (image);
5068 g_free (image->assembly->image->modules);
5069 image->assembly->image->modules = new_modules;
5070 image->assembly->image->modules_loaded = new_modules_loaded;
5071 image->assembly->image->module_count ++;
5073 mono_assembly_load_references (image, &status);
5075 mono_image_close (image);
5076 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5079 return mono_module_get_object (mono_domain_get (), image);
5083 * We need to return always the same object for MethodInfo, FieldInfo etc..
5084 * but we need to consider the reflected type.
5085 * type uses a different hash, since it uses custom hash/equal functions.
5090 MonoClass *refclass;
5094 reflected_equal (gconstpointer a, gconstpointer b) {
5095 const ReflectedEntry *ea = a;
5096 const ReflectedEntry *eb = b;
5098 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5102 reflected_hash (gconstpointer a) {
5103 const ReflectedEntry *ea = a;
5104 return mono_aligned_addr_hash (ea->item);
5107 #define CHECK_OBJECT(t,p,k) \
5113 mono_domain_lock (domain); \
5114 if (!domain->refobject_hash) \
5115 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5116 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5117 mono_domain_unlock (domain); \
5120 mono_domain_unlock (domain); \
5124 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5126 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5128 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5131 #define CACHE_OBJECT(t,p,o,k) \
5134 ReflectedEntry pe; \
5136 pe.refclass = (k); \
5137 mono_domain_lock (domain); \
5138 if (!domain->refobject_hash) \
5139 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5140 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5142 ReflectedEntry *e = ALLOC_REFENTRY; \
5144 e->refclass = (k); \
5145 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5148 mono_domain_unlock (domain); \
5153 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5155 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5159 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5161 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5165 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5167 MonoDynamicImage *image = moduleb->dynamic_image;
5168 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5171 MonoImage **new_modules;
5174 * FIXME: we already created an image in mono_image_basic_init (), but
5175 * we don't know which module it belongs to, since that is only
5176 * determined at assembly save time.
5178 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5179 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5181 moduleb->module.image = &image->image;
5182 moduleb->dynamic_image = image;
5183 register_module (mono_object_domain (moduleb), moduleb, image);
5185 /* register the module with the assembly */
5186 ass = ab->dynamic_assembly->assembly.image;
5187 module_count = ass->module_count;
5188 new_modules = g_new0 (MonoImage *, module_count + 1);
5191 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5192 new_modules [module_count] = &image->image;
5193 mono_image_addref (&image->image);
5195 g_free (ass->modules);
5196 ass->modules = new_modules;
5197 ass->module_count ++;
5202 * mono_assembly_get_object:
5203 * @domain: an app domain
5204 * @assembly: an assembly
5206 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5208 MonoReflectionAssembly*
5209 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5211 static MonoClass *System_Reflection_Assembly;
5212 MonoReflectionAssembly *res;
5214 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5215 if (!System_Reflection_Assembly)
5216 System_Reflection_Assembly = mono_class_from_name (
5217 mono_defaults.corlib, "System.Reflection", "Assembly");
5218 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5219 res->assembly = assembly;
5221 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5226 MonoReflectionModule*
5227 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5229 static MonoClass *System_Reflection_Module;
5230 MonoReflectionModule *res;
5233 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5234 if (!System_Reflection_Module)
5235 System_Reflection_Module = mono_class_from_name (
5236 mono_defaults.corlib, "System.Reflection", "Module");
5237 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5240 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5242 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5243 basename = g_path_get_basename (image->name);
5244 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5245 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5249 if (image->assembly->image == image) {
5250 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5254 if (image->assembly->image->modules) {
5255 for (i = 0; i < image->assembly->image->module_count; i++) {
5256 if (image->assembly->image->modules [i] == image)
5257 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5259 g_assert (res->token);
5263 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5266 MonoReflectionModule*
5267 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5269 static MonoClass *System_Reflection_Module;
5270 MonoReflectionModule *res;
5271 MonoTableInfo *table;
5272 guint32 cols [MONO_FILE_SIZE];
5274 guint32 i, name_idx;
5277 if (!System_Reflection_Module)
5278 System_Reflection_Module = mono_class_from_name (
5279 mono_defaults.corlib, "System.Reflection", "Module");
5280 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5282 table = &image->tables [MONO_TABLE_FILE];
5283 g_assert (table_index < table->rows);
5284 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5287 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5288 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5290 /* Check whenever the row has a corresponding row in the moduleref table */
5291 table = &image->tables [MONO_TABLE_MODULEREF];
5292 for (i = 0; i < table->rows; ++i) {
5293 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5294 val = mono_metadata_string_heap (image, name_idx);
5295 if (strcmp (val, name) == 0)
5296 res->image = image->modules [i];
5299 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5300 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5301 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5302 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5303 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5309 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5311 if ((t1->type != t2->type) ||
5312 (t1->byref != t2->byref))
5316 case MONO_TYPE_VOID:
5317 case MONO_TYPE_BOOLEAN:
5318 case MONO_TYPE_CHAR:
5329 case MONO_TYPE_STRING:
5332 case MONO_TYPE_OBJECT:
5333 case MONO_TYPE_TYPEDBYREF:
5335 case MONO_TYPE_VALUETYPE:
5336 case MONO_TYPE_CLASS:
5337 case MONO_TYPE_SZARRAY:
5338 return t1->data.klass == t2->data.klass;
5340 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5341 case MONO_TYPE_ARRAY:
5342 if (t1->data.array->rank != t2->data.array->rank)
5344 return t1->data.array->eklass == t2->data.array->eklass;
5345 case MONO_TYPE_GENERICINST: {
5347 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5348 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5349 if (i1->type_argc != i2->type_argc)
5351 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5352 &t2->data.generic_class->container_class->byval_arg))
5354 /* FIXME: we should probably just compare the instance pointers directly. */
5355 for (i = 0; i < i1->type_argc; ++i) {
5356 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5362 case MONO_TYPE_MVAR:
5363 return t1->data.generic_param == t2->data.generic_param;
5365 g_error ("implement type compare for %0x!", t1->type);
5373 mymono_metadata_type_hash (MonoType *t1)
5379 hash |= t1->byref << 6; /* do not collide with t1->type values */
5381 case MONO_TYPE_VALUETYPE:
5382 case MONO_TYPE_CLASS:
5383 case MONO_TYPE_SZARRAY:
5384 /* check if the distribution is good enough */
5385 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5387 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5388 case MONO_TYPE_GENERICINST: {
5390 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5391 hash += g_str_hash (t1->data.generic_class->container_class->name);
5393 for (i = 0; i < inst->type_argc; ++i) {
5394 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5403 static MonoReflectionGenericClass*
5404 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5406 static MonoClass *System_Reflection_MonoGenericClass;
5407 MonoReflectionGenericClass *res;
5408 MonoClass *klass, *gklass;
5410 if (!System_Reflection_MonoGenericClass) {
5411 System_Reflection_MonoGenericClass = mono_class_from_name (
5412 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5413 g_assert (System_Reflection_MonoGenericClass);
5416 klass = mono_class_from_mono_type (geninst);
5417 gklass = klass->generic_class->container_class;
5419 mono_class_init (klass);
5422 /* FIXME: allow unpinned later */
5423 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5425 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5428 res->type.type = geninst;
5429 if (gklass->wastypebuilder && gklass->reflection_info)
5430 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5432 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5438 verify_safe_for_managed_space (MonoType *type)
5440 switch (type->type) {
5442 case MONO_TYPE_ARRAY:
5443 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5445 return verify_safe_for_managed_space (type->data.type);
5446 case MONO_TYPE_SZARRAY:
5447 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5448 case MONO_TYPE_GENERICINST: {
5449 MonoGenericInst *inst = type->data.generic_class->inst;
5453 for (i = 0; i < inst->type_argc; ++i)
5454 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5460 case MONO_TYPE_MVAR:
5467 * mono_type_get_object:
5468 * @domain: an app domain
5471 * Return an System.MonoType object representing the type @type.
5474 mono_type_get_object (MonoDomain *domain, MonoType *type)
5476 MonoReflectionType *res;
5477 MonoClass *klass = mono_class_from_mono_type (type);
5479 mono_domain_lock (domain);
5480 if (!domain->type_hash)
5481 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5482 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5483 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5484 mono_domain_unlock (domain);
5487 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5488 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5489 mono_g_hash_table_insert (domain->type_hash, type, res);
5490 mono_domain_unlock (domain);
5494 if (!verify_safe_for_managed_space (type)) {
5495 mono_domain_unlock (domain);
5496 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5499 if (klass->reflection_info && !klass->wastypebuilder) {
5500 /* g_assert_not_reached (); */
5501 /* should this be considered an error condition? */
5503 mono_domain_unlock (domain);
5504 return klass->reflection_info;
5507 mono_class_init (klass);
5509 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5511 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5514 mono_g_hash_table_insert (domain->type_hash, type, res);
5515 mono_domain_unlock (domain);
5520 * mono_method_get_object:
5521 * @domain: an app domain
5523 * @refclass: the reflected type (can be NULL)
5525 * Return an System.Reflection.MonoMethod object representing the method @method.
5527 MonoReflectionMethod*
5528 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5531 * We use the same C representation for methods and constructors, but the type
5532 * name in C# is different.
5534 static MonoClass *System_Reflection_MonoMethod = NULL;
5535 static MonoClass *System_Reflection_MonoCMethod = NULL;
5536 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5537 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5539 MonoReflectionMethod *ret;
5541 if (method->is_inflated) {
5542 MonoReflectionGenericMethod *gret;
5544 method = mono_get_inflated_method (method);
5545 refclass = method->klass;
5546 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5547 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5548 if (!System_Reflection_MonoGenericCMethod)
5549 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5550 klass = System_Reflection_MonoGenericCMethod;
5552 if (!System_Reflection_MonoGenericMethod)
5553 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5554 klass = System_Reflection_MonoGenericMethod;
5556 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5557 gret->method.method = method;
5558 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5559 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5560 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5564 refclass = method->klass;
5566 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5567 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5568 if (!System_Reflection_MonoCMethod)
5569 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5570 klass = System_Reflection_MonoCMethod;
5573 if (!System_Reflection_MonoMethod)
5574 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5575 klass = System_Reflection_MonoMethod;
5577 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5578 ret->method = method;
5579 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5580 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5581 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5585 * mono_field_get_object:
5586 * @domain: an app domain
5590 * Return an System.Reflection.MonoField object representing the field @field
5593 MonoReflectionField*
5594 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5596 MonoReflectionField *res;
5597 static MonoClass *monofield_klass;
5599 CHECK_OBJECT (MonoReflectionField *, field, klass);
5600 if (!monofield_klass)
5601 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5602 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5605 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5606 if (field->generic_info)
5607 res->attrs = field->generic_info->generic_type->attrs;
5609 res->attrs = field->type->attrs;
5610 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5611 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5615 * mono_property_get_object:
5616 * @domain: an app domain
5618 * @property: a property
5620 * Return an System.Reflection.MonoProperty object representing the property @property
5623 MonoReflectionProperty*
5624 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5626 MonoReflectionProperty *res;
5627 static MonoClass *monoproperty_klass;
5629 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5630 if (!monoproperty_klass)
5631 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5632 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5634 res->property = property;
5635 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5639 * mono_event_get_object:
5640 * @domain: an app domain
5644 * Return an System.Reflection.MonoEvent object representing the event @event
5647 MonoReflectionEvent*
5648 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5650 MonoReflectionEvent *res;
5651 static MonoClass *monoevent_klass;
5653 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5654 if (!monoevent_klass)
5655 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5656 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5659 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5663 * mono_param_get_objects:
5664 * @domain: an app domain
5667 * Return an System.Reflection.ParameterInfo array object representing the parameters
5668 * in the method @method.
5671 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5673 static MonoClass *System_Reflection_ParameterInfo;
5674 MonoArray *res = NULL;
5675 MonoReflectionMethod *member = NULL;
5676 MonoReflectionParameter *param = NULL;
5677 char **names, **blobs = NULL;
5678 guint32 *types = NULL;
5679 MonoType *type = NULL;
5680 MonoObject *dbnull = mono_get_dbnull_object (domain);
5681 MonoMarshalSpec **mspecs;
5682 MonoMethodSignature *sig;
5685 if (!System_Reflection_ParameterInfo)
5686 System_Reflection_ParameterInfo = mono_class_from_name (
5687 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5689 if (!mono_method_signature (method)->param_count)
5690 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5692 /* Note: the cache is based on the address of the signature into the method
5693 * since we already cache MethodInfos with the method as keys.
5695 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5697 sig = mono_method_signature (method);
5698 member = mono_method_get_object (domain, method, NULL);
5699 names = g_new (char *, sig->param_count);
5700 mono_method_get_param_names (method, (const char **) names);
5702 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5703 mono_method_get_marshal_info (method, mspecs);
5705 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5706 for (i = 0; i < sig->param_count; ++i) {
5707 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5708 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5709 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5710 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5711 param->PositionImpl = i;
5712 param->AttrsImpl = sig->params [i]->attrs;
5714 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5715 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5719 blobs = g_new0 (char *, sig->param_count);
5720 types = g_new0 (guint32, sig->param_count);
5721 get_default_param_value_blobs (method, blobs, types);
5724 /* Build MonoType for the type from the Constant Table */
5726 type = g_new0 (MonoType, 1);
5727 type->type = types [i];
5728 type->data.klass = NULL;
5729 if (types [i] == MONO_TYPE_CLASS)
5730 type->data.klass = mono_defaults.object_class;
5731 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5732 /* For enums, types [i] contains the base type */
5734 type->type = MONO_TYPE_VALUETYPE;
5735 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5737 type->data.klass = mono_class_from_mono_type (type);
5739 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5741 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5742 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5743 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5748 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5750 mono_array_setref (res, i, param);
5757 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5759 mono_metadata_free_marshal_spec (mspecs [i]);
5762 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5766 * mono_method_body_get_object:
5767 * @domain: an app domain
5770 * Return an System.Reflection.MethodBody object representing the method @method.
5772 MonoReflectionMethodBody*
5773 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5775 static MonoClass *System_Reflection_MethodBody = NULL;
5776 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5777 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5778 MonoReflectionMethodBody *ret;
5779 MonoMethodNormal *mn;
5780 MonoMethodHeader *header;
5781 guint32 method_rva, local_var_sig_token;
5783 unsigned char format, flags;
5786 if (!System_Reflection_MethodBody)
5787 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5788 if (!System_Reflection_LocalVariableInfo)
5789 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5790 if (!System_Reflection_ExceptionHandlingClause)
5791 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5793 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5795 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5796 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5797 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5798 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5800 mn = (MonoMethodNormal *)method;
5801 header = mono_method_get_header (method);
5803 /* Obtain local vars signature token */
5804 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5805 ptr = mono_image_rva_map (method->klass->image, method_rva);
5806 flags = *(const unsigned char *) ptr;
5807 format = flags & METHOD_HEADER_FORMAT_MASK;
5809 case METHOD_HEADER_TINY_FORMAT:
5810 case METHOD_HEADER_TINY_FORMAT1:
5811 local_var_sig_token = 0;
5813 case METHOD_HEADER_FAT_FORMAT:
5817 local_var_sig_token = read32 (ptr);
5820 g_assert_not_reached ();
5823 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5825 ret->init_locals = header->init_locals;
5826 ret->max_stack = header->max_stack;
5827 ret->local_var_sig_token = local_var_sig_token;
5828 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5829 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5832 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5833 for (i = 0; i < header->num_locals; ++i) {
5834 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5835 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5836 info->is_pinned = header->locals [i]->pinned;
5837 info->local_index = i;
5838 mono_array_setref (ret->locals, i, info);
5842 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5843 for (i = 0; i < header->num_clauses; ++i) {
5844 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5845 MonoExceptionClause *clause = &header->clauses [i];
5847 info->flags = clause->flags;
5848 info->try_offset = clause->try_offset;
5849 info->try_length = clause->try_len;
5850 info->handler_offset = clause->handler_offset;
5851 info->handler_length = clause->handler_len;
5852 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5853 info->filter_offset = clause->data.filter_offset;
5854 else if (clause->data.catch_class)
5855 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5857 mono_array_setref (ret->clauses, i, info);
5860 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5865 mono_get_dbnull_object (MonoDomain *domain)
5868 static MonoClassField *dbnull_value_field = NULL;
5870 if (!dbnull_value_field) {
5871 MonoClass *dbnull_klass;
5872 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5873 mono_class_init (dbnull_klass);
5874 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5875 g_assert (dbnull_value_field);
5877 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5884 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5886 guint32 param_index, i, lastp, crow = 0;
5887 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5890 MonoClass *klass = method->klass;
5891 MonoImage *image = klass->image;
5892 MonoMethodSignature *methodsig = mono_method_signature (method);
5894 MonoTableInfo *constt;
5895 MonoTableInfo *methodt;
5896 MonoTableInfo *paramt;
5898 if (!methodsig->param_count)
5901 mono_class_init (klass);
5903 if (klass->image->dynamic) {
5904 MonoReflectionMethodAux *aux;
5905 if (method->is_inflated)
5906 method = ((MonoMethodInflated*)method)->declaring;
5907 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5908 if (aux && aux->param_defaults) {
5909 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5910 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5915 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5916 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5917 constt = &image->tables [MONO_TABLE_CONSTANT];
5919 idx = mono_method_get_index (method) - 1;
5920 g_assert (idx != -1);
5922 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5923 if (idx + 1 < methodt->rows)
5924 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5926 lastp = paramt->rows + 1;
5928 for (i = param_index; i < lastp; ++i) {
5931 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5932 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5934 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5937 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5942 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5943 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5944 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5951 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5956 MonoType *basetype = type;
5961 klass = mono_class_from_mono_type (type);
5962 if (klass->valuetype) {
5963 object = mono_object_new (domain, klass);
5964 retval = ((gchar *) object + sizeof (MonoObject));
5965 if (klass->enumtype)
5966 basetype = klass->enum_basetype;
5971 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5978 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5982 memset (assembly, 0, sizeof (MonoAssemblyName));
5984 assembly->culture = "";
5985 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5987 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5990 while (g_ascii_isspace (*p) || *p == ',') {
5999 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6001 assembly->major = strtoul (p, &s, 10);
6002 if (s == p || *s != '.')
6005 assembly->minor = strtoul (p, &s, 10);
6006 if (s == p || *s != '.')
6009 assembly->build = strtoul (p, &s, 10);
6010 if (s == p || *s != '.')
6013 assembly->revision = strtoul (p, &s, 10);
6017 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6019 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6020 assembly->culture = "";
6023 assembly->culture = p;
6024 while (*p && *p != ',') {
6028 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6030 if (strncmp (p, "null", 4) == 0) {
6035 while (*p && *p != ',') {
6038 len = (p - start + 1);
6039 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6040 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6041 g_strlcpy ((char*)assembly->public_key_token, start, len);
6044 while (*p && *p != ',')
6048 while (g_ascii_isspace (*p) || *p == ',') {
6062 * mono_reflection_parse_type:
6065 * Parse a type name as accepted by the GetType () method and output the info
6066 * extracted in the info structure.
6067 * the name param will be mangled, so, make a copy before passing it to this function.
6068 * The fields in info will be valid until the memory pointed to by name is valid.
6070 * See also mono_type_get_name () below.
6072 * Returns: 0 on parse error.
6075 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6076 MonoTypeNameParse *info)
6078 char *start, *p, *w, *temp, *last_point, *startn;
6079 int in_modifiers = 0;
6080 int isbyref = 0, rank, arity = 0, i;
6082 start = p = w = name;
6084 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6085 info->name = info->name_space = NULL;
6086 info->nested = NULL;
6087 info->modifiers = NULL;
6088 info->type_arguments = NULL;
6090 /* last_point separates the namespace from the name */
6096 *p = 0; /* NULL terminate the name */
6098 info->nested = g_list_append (info->nested, startn);
6099 /* we have parsed the nesting namespace + name */
6103 info->name_space = start;
6105 info->name = last_point + 1;
6107 info->name_space = (char *)"";
6126 i = strtol (p, &temp, 10);
6143 info->name_space = start;
6145 info->name = last_point + 1;
6147 info->name_space = (char *)"";
6154 if (isbyref) /* only one level allowed by the spec */
6157 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6161 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6167 info->type_arguments = g_ptr_array_new ();
6168 for (i = 0; i < arity; i++) {
6169 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6170 gboolean fqname = FALSE;
6172 g_ptr_array_add (info->type_arguments, subinfo);
6179 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6190 while (*p && (*p != ']'))
6198 if (g_ascii_isspace (*aname)) {
6205 !assembly_name_to_aname (&subinfo->assembly, aname))
6209 if (i + 1 < arity) {
6229 else if (*p != '*') /* '*' means unknown lower bound */
6235 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6246 if (g_ascii_isspace (*p)) {
6253 return 0; /* missing assembly name */
6254 if (!assembly_name_to_aname (&info->assembly, p))
6260 if (info->assembly.name)
6263 // *w = 0; /* terminate class name */
6265 if (!info->name || !*info->name)
6269 /* add other consistency checks */
6274 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6276 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6280 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6282 gboolean type_resolve = FALSE;
6285 if (info->assembly.name) {
6286 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6288 /* then we must load the assembly ourselve - see #60439 */
6289 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6293 image = assembly->image;
6294 } else if (!image) {
6295 image = mono_defaults.corlib;
6298 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6299 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6300 image = mono_defaults.corlib;
6301 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6308 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6315 image = mono_defaults.corlib;
6318 klass = mono_class_from_name_case (image, info->name_space, info->name);
6320 klass = mono_class_from_name (image, info->name_space, info->name);
6323 for (mod = info->nested; mod; mod = mod->next) {
6326 mono_class_init (klass);
6327 nested = klass->nested_classes;
6330 klass = nested->data;
6332 if (g_strcasecmp (klass->name, mod->data) == 0)
6335 if (strcmp (klass->name, mod->data) == 0)
6339 nested = nested->next;
6346 mono_class_init (klass);
6348 if (info->type_arguments) {
6349 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6350 MonoReflectionType *the_type;
6354 for (i = 0; i < info->type_arguments->len; i++) {
6355 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6357 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6358 if (!type_args [i]) {
6364 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6366 instance = mono_reflection_bind_generic_parameters (
6367 the_type, info->type_arguments->len, type_args);
6374 klass = mono_class_from_mono_type (instance);
6377 for (mod = info->modifiers; mod; mod = mod->next) {
6378 modval = GPOINTER_TO_UINT (mod->data);
6379 if (!modval) { /* byref: must be last modifier */
6380 return &klass->this_arg;
6381 } else if (modval == -1) {
6382 klass = mono_ptr_class_get (&klass->byval_arg);
6383 } else { /* array rank */
6384 klass = mono_array_class_get (klass, modval);
6386 mono_class_init (klass);
6389 return &klass->byval_arg;
6393 * mono_reflection_get_type:
6394 * @image: a metadata context
6395 * @info: type description structure
6396 * @ignorecase: flag for case-insensitive string compares
6397 * @type_resolve: whenever type resolve was already tried
6399 * Build a MonoType from the type description in @info.
6404 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6407 MonoReflectionAssembly *assembly;
6411 type = mono_reflection_get_type_internal (image, info, ignorecase);
6414 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6421 *type_resolve = TRUE;
6424 /* Reconstruct the type name */
6425 fullName = g_string_new ("");
6426 if (info->name_space && (info->name_space [0] != '\0'))
6427 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6429 g_string_printf (fullName, info->name);
6430 for (mod = info->nested; mod; mod = mod->next)
6431 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6433 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6435 if (assembly->assembly->dynamic) {
6436 /* Enumerate all modules */
6437 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6441 if (abuilder->modules) {
6442 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6443 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6444 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6450 if (!type && abuilder->loaded_modules) {
6451 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6452 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6453 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6460 type = mono_reflection_get_type_internal (assembly->assembly->image,
6463 g_string_free (fullName, TRUE);
6468 free_type_info (MonoTypeNameParse *info)
6470 g_list_free (info->modifiers);
6471 g_list_free (info->nested);
6473 if (info->type_arguments) {
6476 for (i = 0; i < info->type_arguments->len; i++) {
6477 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6479 free_type_info (subinfo);
6482 g_ptr_array_free (info->type_arguments, TRUE);
6487 * mono_reflection_type_from_name:
6489 * @image: a metadata context (can be NULL).
6491 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6492 * it defaults to get the type from @image or, if @image is NULL or loading
6493 * from it fails, uses corlib.
6497 mono_reflection_type_from_name (char *name, MonoImage *image)
6499 MonoType *type = NULL;
6500 MonoTypeNameParse info;
6503 /* Make a copy since parse_type modifies its argument */
6504 tmp = g_strdup (name);
6506 /*g_print ("requested type %s\n", str);*/
6507 if (mono_reflection_parse_type (tmp, &info)) {
6508 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6512 free_type_info (&info);
6517 * mono_reflection_get_token:
6519 * Return the metadata token of OBJ which should be an object
6520 * representing a metadata element.
6523 mono_reflection_get_token (MonoObject *obj)
6528 klass = obj->vtable->klass;
6530 if (strcmp (klass->name, "MethodBuilder") == 0) {
6531 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6533 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6534 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6535 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6537 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6538 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6539 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6540 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6541 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6542 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6543 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6544 } else if (strcmp (klass->name, "MonoType") == 0) {
6545 MonoReflectionType *tb = (MonoReflectionType *)obj;
6546 token = mono_class_from_mono_type (tb->type)->type_token;
6547 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6548 strcmp (klass->name, "MonoMethod") == 0 ||
6549 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6550 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6551 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6552 if (m->method->is_inflated) {
6553 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6554 return inflated->declaring->token;
6556 token = m->method->token;
6558 } else if (strcmp (klass->name, "MonoField") == 0) {
6559 MonoReflectionField *f = (MonoReflectionField*)obj;
6561 if (f->field->generic_info && f->field->generic_info->reflection_info)
6562 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6564 token = mono_class_get_field_token (f->field);
6565 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6566 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6568 token = mono_class_get_property_token (p->property);
6569 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6570 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6572 token = mono_class_get_event_token (p->event);
6573 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6574 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6576 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6577 } else if (strcmp (klass->name, "Module") == 0) {
6578 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6581 } else if (strcmp (klass->name, "Assembly") == 0) {
6582 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6584 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6585 MonoException *ex = mono_get_exception_not_implemented (msg);
6587 mono_raise_exception (ex);
6594 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6596 int slen, type = t->type;
6597 MonoClass *tklass = t->data.klass;
6603 case MONO_TYPE_BOOLEAN: {
6604 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6609 case MONO_TYPE_CHAR:
6611 case MONO_TYPE_I2: {
6612 guint16 *val = g_malloc (sizeof (guint16));
6617 #if SIZEOF_VOID_P == 4
6623 case MONO_TYPE_I4: {
6624 guint32 *val = g_malloc (sizeof (guint32));
6629 #if SIZEOF_VOID_P == 8
6630 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6634 case MONO_TYPE_I8: {
6635 guint64 *val = g_malloc (sizeof (guint64));
6640 case MONO_TYPE_R8: {
6641 double *val = g_malloc (sizeof (double));
6646 case MONO_TYPE_VALUETYPE:
6647 if (t->data.klass->enumtype) {
6648 type = t->data.klass->enum_basetype->type;
6651 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6654 case MONO_TYPE_STRING:
6655 if (*p == (char)0xFF) {
6659 slen = mono_metadata_decode_value (p, &p);
6661 return mono_string_new_len (mono_domain_get (), p, slen);
6662 case MONO_TYPE_CLASS: {
6665 if (*p == (char)0xFF) {
6670 slen = mono_metadata_decode_value (p, &p);
6671 n = g_memdup (p, slen + 1);
6673 t = mono_reflection_type_from_name (n, image);
6675 g_warning ("Cannot load type '%s'", n);
6679 return mono_type_get_object (mono_domain_get (), t);
6683 case MONO_TYPE_OBJECT: {
6686 MonoClass *subc = NULL;
6691 } else if (subt == 0x0E) {
6692 type = MONO_TYPE_STRING;
6694 } else if (subt == 0x1D) {
6695 MonoType simple_type = {{0}};
6700 /* See Partition II, Appendix B3 */
6701 etype = MONO_TYPE_OBJECT;
6702 type = MONO_TYPE_SZARRAY;
6703 simple_type.type = etype;
6704 tklass = mono_class_from_mono_type (&simple_type);
6706 } else if (subt == 0x55) {
6709 slen = mono_metadata_decode_value (p, &p);
6710 n = g_memdup (p, slen + 1);
6712 t = mono_reflection_type_from_name (n, image);
6714 g_error ("Cannot load type '%s'", n);
6717 subc = mono_class_from_mono_type (t);
6718 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6719 MonoType simple_type = {{0}};
6720 simple_type.type = subt;
6721 subc = mono_class_from_mono_type (&simple_type);
6723 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6725 val = load_cattr_value (image, &subc->byval_arg, p, end);
6726 obj = mono_object_new (mono_domain_get (), subc);
6727 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6731 case MONO_TYPE_SZARRAY: {
6733 guint32 i, alen, basetype;
6736 if (alen == 0xffffffff) {
6740 arr = mono_array_new (mono_domain_get(), tklass, alen);
6741 basetype = tklass->byval_arg.type;
6742 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6743 basetype = tklass->enum_basetype->type;
6748 case MONO_TYPE_BOOLEAN:
6749 for (i = 0; i < alen; i++) {
6750 MonoBoolean val = *p++;
6751 mono_array_set (arr, MonoBoolean, i, val);
6754 case MONO_TYPE_CHAR:
6757 for (i = 0; i < alen; i++) {
6758 guint16 val = read16 (p);
6759 mono_array_set (arr, guint16, i, val);
6766 for (i = 0; i < alen; i++) {
6767 guint32 val = read32 (p);
6768 mono_array_set (arr, guint32, i, val);
6773 for (i = 0; i < alen; i++) {
6776 mono_array_set (arr, double, i, val);
6782 for (i = 0; i < alen; i++) {
6783 guint64 val = read64 (p);
6784 mono_array_set (arr, guint64, i, val);
6788 case MONO_TYPE_CLASS:
6789 case MONO_TYPE_OBJECT:
6790 case MONO_TYPE_STRING:
6791 for (i = 0; i < alen; i++) {
6792 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6793 mono_array_setref (arr, i, item);
6797 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6803 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6809 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6811 static MonoClass *klass;
6812 static MonoMethod *ctor;
6814 void *params [2], *unboxed;
6817 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6819 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6821 params [0] = mono_type_get_object (mono_domain_get (), t);
6823 retval = mono_object_new (mono_domain_get (), klass);
6824 unboxed = mono_object_unbox (retval);
6825 mono_runtime_invoke (ctor, unboxed, params, NULL);
6831 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6833 static MonoClass *klass;
6834 static MonoMethod *ctor;
6836 void *unboxed, *params [2];
6839 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6841 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6844 params [1] = typedarg;
6845 retval = mono_object_new (mono_domain_get (), klass);
6846 unboxed = mono_object_unbox (retval);
6847 mono_runtime_invoke (ctor, unboxed, params, NULL);
6853 type_is_reference (MonoType *type)
6855 switch (type->type) {
6856 case MONO_TYPE_BOOLEAN:
6857 case MONO_TYPE_CHAR:
6870 case MONO_TYPE_VALUETYPE:
6878 free_param_data (MonoMethodSignature *sig, void **params) {
6880 for (i = 0; i < sig->param_count; ++i) {
6881 if (!type_is_reference (sig->params [i]))
6882 g_free (params [i]);
6887 * Find the field index in the metadata FieldDef table.
6890 find_field_index (MonoClass *klass, MonoClassField *field) {
6893 for (i = 0; i < klass->field.count; ++i) {
6894 if (field == &klass->fields [i])
6895 return klass->field.first + 1 + i;
6901 * Find the property index in the metadata Property table.
6904 find_property_index (MonoClass *klass, MonoProperty *property) {
6907 for (i = 0; i < klass->property.count; ++i) {
6908 if (property == &klass->properties [i])
6909 return klass->property.first + 1 + i;
6915 * Find the event index in the metadata Event table.
6918 find_event_index (MonoClass *klass, MonoEvent *event) {
6921 for (i = 0; i < klass->event.count; ++i) {
6922 if (event == &klass->events [i])
6923 return klass->event.first + 1 + i;
6929 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6931 const char *p = (const char*)data;
6933 guint32 i, j, num_named;
6937 mono_class_init (method->klass);
6940 attr = mono_object_new (mono_domain_get (), method->klass);
6941 mono_runtime_invoke (method, attr, NULL, NULL);
6945 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6948 /*g_print ("got attr %s\n", method->klass->name);*/
6950 /* Allocate using alloca so it gets GC tracking */
6951 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6955 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6956 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6960 attr = mono_object_new (mono_domain_get (), method->klass);
6961 mono_runtime_invoke (method, attr, params, NULL);
6962 free_param_data (method->signature, params);
6963 num_named = read16 (named);
6965 for (j = 0; j < num_named; j++) {
6967 char *name, named_type, data_type;
6968 named_type = *named++;
6969 data_type = *named++; /* type of data */
6970 if (data_type == MONO_TYPE_SZARRAY)
6971 data_type = *named++;
6972 if (data_type == MONO_TYPE_ENUM) {
6975 type_len = mono_metadata_decode_blob_size (named, &named);
6976 type_name = g_malloc (type_len + 1);
6977 memcpy (type_name, named, type_len);
6978 type_name [type_len] = 0;
6980 /* FIXME: lookup the type and check type consistency */
6983 name_len = mono_metadata_decode_blob_size (named, &named);
6984 name = g_malloc (name_len + 1);
6985 memcpy (name, named, name_len);
6986 name [name_len] = 0;
6988 if (named_type == 0x53) {
6989 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6990 void *val = load_cattr_value (image, field->type, named, &named);
6991 mono_field_set_value (attr, field, val);
6992 if (!type_is_reference (field->type))
6994 } else if (named_type == 0x54) {
6997 MonoType *prop_type;
6999 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7000 /* can we have more that 1 arg in a custom attr named property? */
7001 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7002 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7003 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7004 mono_property_set_value (prop, attr, pparams, NULL);
7005 if (!type_is_reference (prop_type))
7006 g_free (pparams [0]);
7015 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7017 MonoArray *typedargs, *namedargs;
7018 MonoClass *attrklass;
7019 static MonoMethod *ctor;
7022 const char *p = (const char*)data;
7024 guint32 i, j, num_named;
7027 mono_class_init (method->klass);
7030 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7032 domain = mono_domain_get ();
7034 /* This is for Attributes with no parameters */
7035 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7036 params [0] = mono_method_get_object (domain, method, NULL);
7037 params [1] = params [2] = NULL;
7038 mono_runtime_invoke (method, attr, params, NULL);
7042 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7045 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7049 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7050 MonoObject *obj, *typedarg;
7053 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7054 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7055 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7056 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7057 mono_array_setref (typedargs, i, typedarg);
7059 if (!type_is_reference (mono_method_signature (method)->params [i]))
7064 num_named = read16 (named);
7065 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7067 attrklass = method->klass;
7068 for (j = 0; j < num_named; j++) {
7070 char *name, named_type, data_type;
7071 named_type = *named++;
7072 data_type = *named++; /* type of data */
7073 if (data_type == MONO_TYPE_SZARRAY)
7074 data_type = *named++;
7075 if (data_type == MONO_TYPE_ENUM) {
7078 type_len = mono_metadata_decode_blob_size (named, &named);
7079 type_name = g_malloc (type_len + 1);
7080 memcpy (type_name, named, type_len);
7081 type_name [type_len] = 0;
7083 /* FIXME: lookup the type and check type consistency */
7086 name_len = mono_metadata_decode_blob_size (named, &named);
7087 name = g_malloc (name_len + 1);
7088 memcpy (name, named, name_len);
7089 name [name_len] = 0;
7091 if (named_type == 0x53) {
7092 MonoObject *obj, *typedarg, *namedarg;
7093 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7094 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7096 minfo = mono_field_get_object (domain, NULL, field);
7097 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7098 typedarg = create_cattr_typed_arg (field->type, obj);
7099 namedarg = create_cattr_named_arg (minfo, typedarg);
7100 mono_array_setref (namedargs, j, namedarg);
7101 if (!type_is_reference (field->type))
7103 } else if (named_type == 0x54) {
7104 MonoObject *obj, *typedarg, *namedarg;
7105 MonoType *prop_type;
7107 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7109 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7110 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7111 minfo = mono_property_get_object (domain, NULL, prop);
7112 val = load_cattr_value (image, prop_type, named, &named);
7113 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7114 typedarg = create_cattr_typed_arg (prop_type, obj);
7115 namedarg = create_cattr_named_arg (minfo, typedarg);
7116 mono_array_setref (namedargs, j, namedarg);
7117 if (!type_is_reference (prop_type))
7122 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7123 params [0] = mono_method_get_object (domain, method, NULL);
7124 params [1] = typedargs;
7125 params [2] = namedargs;
7126 mono_runtime_invoke (ctor, attr, params, NULL);
7131 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7137 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7138 for (i = 0; i < cinfo->num_attrs; ++i) {
7139 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7140 mono_array_setref (result, i, attr);
7146 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7153 for (i = 0; i < cinfo->num_attrs; ++i) {
7154 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7158 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7160 for (i = 0; i < cinfo->num_attrs; ++i) {
7161 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7162 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7163 mono_array_setref (result, n, attr);
7171 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7177 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7178 for (i = 0; i < cinfo->num_attrs; ++i) {
7179 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7180 mono_array_setref (result, i, attr);
7186 * mono_custom_attrs_from_index:
7188 * Returns: NULL if no attributes are found or if a loading error occurs.
7191 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7193 guint32 mtoken, i, len;
7194 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7196 MonoCustomAttrInfo *ainfo;
7197 GList *tmp, *list = NULL;
7200 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7202 i = mono_metadata_custom_attrs_from_index (image, idx);
7206 while (i < ca->rows) {
7207 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7209 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7212 len = g_list_length (list);
7215 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7216 ainfo->num_attrs = len;
7217 ainfo->image = image;
7218 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7219 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7220 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7221 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7222 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7223 mtoken |= MONO_TOKEN_METHOD_DEF;
7225 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7226 mtoken |= MONO_TOKEN_MEMBER_REF;
7229 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7232 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7233 if (!ainfo->attrs [i].ctor) {
7234 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7239 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7240 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7241 ainfo->attrs [i].data = (guchar*)data;
7249 mono_custom_attrs_from_method (MonoMethod *method)
7251 MonoCustomAttrInfo *cinfo;
7254 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7256 idx = mono_method_get_index (method);
7257 idx <<= MONO_CUSTOM_ATTR_BITS;
7258 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7259 return mono_custom_attrs_from_index (method->klass->image, idx);
7263 mono_custom_attrs_from_class (MonoClass *klass)
7265 MonoCustomAttrInfo *cinfo;
7268 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7270 idx = mono_metadata_token_index (klass->type_token);
7271 idx <<= MONO_CUSTOM_ATTR_BITS;
7272 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7273 return mono_custom_attrs_from_index (klass->image, idx);
7277 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7279 MonoCustomAttrInfo *cinfo;
7282 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7284 idx = 1; /* there is only one assembly */
7285 idx <<= MONO_CUSTOM_ATTR_BITS;
7286 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7287 return mono_custom_attrs_from_index (assembly->image, idx);
7290 static MonoCustomAttrInfo*
7291 mono_custom_attrs_from_module (MonoImage *image)
7293 MonoCustomAttrInfo *cinfo;
7296 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7298 idx = 1; /* there is only one module */
7299 idx <<= MONO_CUSTOM_ATTR_BITS;
7300 idx |= MONO_CUSTOM_ATTR_MODULE;
7301 return mono_custom_attrs_from_index (image, idx);
7305 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7307 MonoCustomAttrInfo *cinfo;
7310 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7312 idx = find_property_index (klass, property);
7313 idx <<= MONO_CUSTOM_ATTR_BITS;
7314 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7315 return mono_custom_attrs_from_index (klass->image, idx);
7319 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7321 MonoCustomAttrInfo *cinfo;
7324 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7326 idx = find_event_index (klass, event);
7327 idx <<= MONO_CUSTOM_ATTR_BITS;
7328 idx |= MONO_CUSTOM_ATTR_EVENT;
7329 return mono_custom_attrs_from_index (klass->image, idx);
7333 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7335 MonoCustomAttrInfo *cinfo;
7338 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7340 idx = find_field_index (klass, field);
7341 idx <<= MONO_CUSTOM_ATTR_BITS;
7342 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7343 return mono_custom_attrs_from_index (klass->image, idx);
7347 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7350 guint32 i, idx, method_index;
7351 guint32 param_list, param_last, param_pos, found;
7353 MonoReflectionMethodAux *aux;
7355 if (method->klass->image->dynamic) {
7356 MonoCustomAttrInfo *res, *ainfo;
7359 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7360 if (!aux || !aux->param_cattr)
7363 /* Need to copy since it will be freed later */
7364 ainfo = aux->param_cattr [param];
7365 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7366 res = g_malloc0 (size);
7367 memcpy (res, ainfo, size);
7371 image = method->klass->image;
7372 method_index = mono_method_get_index (method);
7373 ca = &image->tables [MONO_TABLE_METHOD];
7375 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7376 if (method_index == ca->rows) {
7377 ca = &image->tables [MONO_TABLE_PARAM];
7378 param_last = ca->rows + 1;
7380 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7381 ca = &image->tables [MONO_TABLE_PARAM];
7384 for (i = param_list; i < param_last; ++i) {
7385 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7386 if (param_pos == param) {
7394 idx <<= MONO_CUSTOM_ATTR_BITS;
7395 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7396 return mono_custom_attrs_from_index (image, idx);
7400 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7404 for (i = 0; i < ainfo->num_attrs; ++i) {
7405 klass = ainfo->attrs [i].ctor->klass;
7406 if (mono_class_has_parent (klass, attr_klass))
7413 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7420 for (i = 0; i < ainfo->num_attrs; ++i) {
7421 klass = ainfo->attrs [i].ctor->klass;
7422 if (mono_class_has_parent (klass, attr_klass)) {
7427 if (attr_index == -1)
7430 attrs = mono_custom_attrs_construct (ainfo);
7432 return mono_array_get (attrs, MonoObject*, attr_index);
7438 * mono_reflection_get_custom_attrs_info:
7439 * @obj: a reflection object handle
7441 * Return the custom attribute info for attributes defined for the
7442 * reflection handle @obj. The objects.
7445 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7448 MonoCustomAttrInfo *cinfo = NULL;
7450 klass = obj->vtable->klass;
7451 if (klass == mono_defaults.monotype_class) {
7452 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7453 klass = mono_class_from_mono_type (rtype->type);
7454 cinfo = mono_custom_attrs_from_class (klass);
7455 } else if (strcmp ("Assembly", klass->name) == 0) {
7456 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7457 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7458 } else if (strcmp ("Module", klass->name) == 0) {
7459 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7460 cinfo = mono_custom_attrs_from_module (module->image);
7461 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7462 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7463 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7464 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7465 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7466 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7467 } else if (strcmp ("MonoField", klass->name) == 0) {
7468 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7469 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7470 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7471 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7472 cinfo = mono_custom_attrs_from_method (rmethod->method);
7473 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7474 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7475 cinfo = mono_custom_attrs_from_method (method);
7476 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7477 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7478 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7479 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7480 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7481 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7482 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7483 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7484 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7485 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7486 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7487 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7488 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7489 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7490 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7491 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7492 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7493 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7494 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7495 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7496 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7497 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7498 } else { /* handle other types here... */
7499 g_error ("get custom attrs not yet supported for %s", klass->name);
7506 * mono_reflection_get_custom_attrs_by_type:
7507 * @obj: a reflection object handle
7509 * Return an array with all the custom attributes defined of the
7510 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7511 * of that type are returned. The objects are fully build. Return NULL if a loading error
7515 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7518 MonoCustomAttrInfo *cinfo;
7520 cinfo = mono_reflection_get_custom_attrs_info (obj);
7523 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7525 result = mono_custom_attrs_construct (cinfo);
7527 mono_custom_attrs_free (cinfo);
7529 if (mono_loader_get_last_error ())
7531 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7538 * mono_reflection_get_custom_attrs:
7539 * @obj: a reflection object handle
7541 * Return an array with all the custom attributes defined of the
7542 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7546 mono_reflection_get_custom_attrs (MonoObject *obj)
7548 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7552 * mono_reflection_get_custom_attrs_data:
7553 * @obj: a reflection obj handle
7555 * Returns an array of System.Reflection.CustomAttributeData,
7556 * which include information about attributes reflected on
7557 * types loaded using the Reflection Only methods
7560 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7563 MonoCustomAttrInfo *cinfo;
7565 cinfo = mono_reflection_get_custom_attrs_info (obj);
7567 result = mono_custom_attrs_data_construct (cinfo);
7569 mono_custom_attrs_free (cinfo);
7571 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7576 static MonoReflectionType*
7577 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7579 MonoMethod *method_get_underlying_system_type;
7581 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7582 mono_class_get_method_from_name (mono_object_class (t),
7583 "get_UnderlyingSystemType",
7585 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7589 mono_reflection_type_get_handle (MonoReflectionType* t)
7594 t = mono_reflection_type_get_underlying_system_type (t);
7602 * LOCKING: Assumes the loader lock is held.
7604 static MonoMethodSignature*
7605 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7606 MonoMethodSignature *sig;
7609 count = parameters? mono_array_length (parameters): 0;
7611 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7612 sig->param_count = count;
7613 sig->sentinelpos = -1; /* FIXME */
7614 for (i = 0; i < count; ++i) {
7615 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7616 sig->params [i] = mono_reflection_type_get_handle (pt);
7622 * LOCKING: Assumes the loader lock is held.
7624 static MonoMethodSignature*
7625 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7626 MonoMethodSignature *sig;
7628 sig = parameters_to_signature (mp, ctor->parameters);
7629 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7630 sig->ret = &mono_defaults.void_class->byval_arg;
7635 * LOCKING: Assumes the loader lock is held.
7637 static MonoMethodSignature*
7638 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7639 MonoMethodSignature *sig;
7641 sig = parameters_to_signature (mp, method->parameters);
7642 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7643 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7644 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7648 static MonoMethodSignature*
7649 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7650 MonoMethodSignature *sig;
7652 sig = parameters_to_signature (NULL, method->parameters);
7653 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7654 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7655 sig->generic_param_count = 0;
7660 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7662 MonoClass *klass = mono_object_class (prop);
7663 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7664 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7665 *name = mono_string_to_utf8 (pb->name);
7666 *type = pb->type->type;
7668 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7669 *name = g_strdup (p->property->name);
7670 if (p->property->get)
7671 *type = mono_method_signature (p->property->get)->ret;
7673 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7678 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7680 MonoClass *klass = mono_object_class (field);
7681 if (strcmp (klass->name, "FieldBuilder") == 0) {
7682 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7683 *name = mono_string_to_utf8 (fb->name);
7684 *type = fb->type->type;
7686 MonoReflectionField *f = (MonoReflectionField *)field;
7687 *name = g_strdup (f->field->name);
7688 *type = f->field->type;
7693 * Encode a value in a custom attribute stream of bytes.
7694 * The value to encode is either supplied as an object in argument val
7695 * (valuetypes are boxed), or as a pointer to the data in the
7697 * @type represents the type of the value
7698 * @buffer is the start of the buffer
7699 * @p the current position in the buffer
7700 * @buflen contains the size of the buffer and is used to return the new buffer size
7701 * if this needs to be realloced.
7702 * @retbuffer and @retp return the start and the position of the buffer
7705 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7707 MonoTypeEnum simple_type;
7709 if ((p-buffer) + 10 >= *buflen) {
7712 newbuf = g_realloc (buffer, *buflen);
7713 p = newbuf + (p-buffer);
7717 argval = ((char*)arg + sizeof (MonoObject));
7718 simple_type = type->type;
7720 switch (simple_type) {
7721 case MONO_TYPE_BOOLEAN:
7726 case MONO_TYPE_CHAR:
7729 swap_with_size (p, argval, 2, 1);
7735 swap_with_size (p, argval, 4, 1);
7739 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7749 swap_with_size (p, argval, 8, 1);
7755 swap_with_size (p, argval, 8, 1);
7758 case MONO_TYPE_VALUETYPE:
7759 if (type->data.klass->enumtype) {
7760 simple_type = type->data.klass->enum_basetype->type;
7763 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7766 case MONO_TYPE_STRING: {
7773 str = mono_string_to_utf8 ((MonoString*)arg);
7774 slen = strlen (str);
7775 if ((p-buffer) + 10 + slen >= *buflen) {
7779 newbuf = g_realloc (buffer, *buflen);
7780 p = newbuf + (p-buffer);
7783 mono_metadata_encode_value (slen, p, &p);
7784 memcpy (p, str, slen);
7789 case MONO_TYPE_CLASS: {
7797 k = mono_object_class (arg);
7798 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7799 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7800 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7803 if (rt && (rtc = mono_object_class (rt)) &&
7804 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7805 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7806 arg = (MonoObject *) rt;
7809 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7812 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7813 slen = strlen (str);
7814 if ((p-buffer) + 10 + slen >= *buflen) {
7818 newbuf = g_realloc (buffer, *buflen);
7819 p = newbuf + (p-buffer);
7822 mono_metadata_encode_value (slen, p, &p);
7823 memcpy (p, str, slen);
7828 case MONO_TYPE_SZARRAY: {
7830 MonoClass *eclass, *arg_eclass;
7833 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7836 len = mono_array_length ((MonoArray*)arg);
7838 *p++ = (len >> 8) & 0xff;
7839 *p++ = (len >> 16) & 0xff;
7840 *p++ = (len >> 24) & 0xff;
7842 *retbuffer = buffer;
7843 eclass = type->data.klass;
7844 arg_eclass = mono_object_class (arg)->element_class;
7847 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7848 eclass = mono_defaults.object_class;
7850 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7851 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7852 int elsize = mono_class_array_element_size (arg_eclass);
7853 for (i = 0; i < len; ++i) {
7854 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7857 } else if (eclass->valuetype && arg_eclass->valuetype) {
7858 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7859 int elsize = mono_class_array_element_size (eclass);
7860 for (i = 0; i < len; ++i) {
7861 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7865 for (i = 0; i < len; ++i) {
7866 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7871 case MONO_TYPE_OBJECT: {
7877 * The parameter type is 'object' but the type of the actual
7878 * argument is not. So we have to add type information to the blob
7879 * too. This is completely undocumented in the spec.
7883 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7888 klass = mono_object_class (arg);
7890 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7893 } else if (klass->enumtype) {
7895 } else if (klass == mono_defaults.string_class) {
7896 simple_type = MONO_TYPE_STRING;
7899 } else if (klass->rank == 1) {
7901 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7902 /* See Partition II, Appendix B3 */
7905 *p++ = klass->element_class->byval_arg.type;
7906 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7908 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7909 *p++ = simple_type = klass->byval_arg.type;
7912 g_error ("unhandled type in custom attr");
7914 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7915 slen = strlen (str);
7916 if ((p-buffer) + 10 + slen >= *buflen) {
7920 newbuf = g_realloc (buffer, *buflen);
7921 p = newbuf + (p-buffer);
7924 mono_metadata_encode_value (slen, p, &p);
7925 memcpy (p, str, slen);
7928 simple_type = klass->enum_basetype->type;
7932 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7935 *retbuffer = buffer;
7939 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7941 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7942 char *str = type_get_qualified_name (type, NULL);
7943 int slen = strlen (str);
7947 * This seems to be optional...
7950 mono_metadata_encode_value (slen, p, &p);
7951 memcpy (p, str, slen);
7954 } else if (type->type == MONO_TYPE_OBJECT) {
7956 } else if (type->type == MONO_TYPE_CLASS) {
7957 /* it should be a type: encode_cattr_value () has the check */
7960 mono_metadata_encode_value (type->type, p, &p);
7961 if (type->type == MONO_TYPE_SZARRAY)
7962 /* See the examples in Partition VI, Annex B */
7963 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7970 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7973 /* Preallocate a large enough buffer */
7974 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7975 char *str = type_get_qualified_name (type, NULL);
7978 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7979 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7985 len += strlen (name);
7987 if ((p-buffer) + 20 + len >= *buflen) {
7991 newbuf = g_realloc (buffer, *buflen);
7992 p = newbuf + (p-buffer);
7996 encode_field_or_prop_type (type, p, &p);
7998 len = strlen (name);
7999 mono_metadata_encode_value (len, p, &p);
8000 memcpy (p, name, len);
8002 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8004 *retbuffer = buffer;
8008 * mono_reflection_get_custom_attrs_blob:
8009 * @ctor: custom attribute constructor
8010 * @ctorArgs: arguments o the constructor
8016 * Creates the blob of data that needs to be saved in the metadata and that represents
8017 * the custom attributed described by @ctor, @ctorArgs etc.
8018 * Returns: a Byte array representing the blob of data.
8021 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8024 MonoMethodSignature *sig;
8029 MONO_ARCH_SAVE_REGS;
8031 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8032 /* sig is freed later so allocate it in the heap */
8033 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8035 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8038 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8040 p = buffer = g_malloc (buflen);
8041 /* write the prolog */
8044 for (i = 0; i < sig->param_count; ++i) {
8045 arg = mono_array_get (ctorArgs, MonoObject*, i);
8046 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8050 i += mono_array_length (properties);
8052 i += mono_array_length (fields);
8054 *p++ = (i >> 8) & 0xff;
8057 for (i = 0; i < mono_array_length (properties); ++i) {
8061 prop = mono_array_get (properties, gpointer, i);
8062 get_prop_name_and_type (prop, &pname, &ptype);
8063 *p++ = 0x54; /* PROPERTY signature */
8064 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8071 for (i = 0; i < mono_array_length (fields); ++i) {
8075 field = mono_array_get (fields, gpointer, i);
8076 get_field_name_and_type (field, &fname, &ftype);
8077 *p++ = 0x53; /* FIELD signature */
8078 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8083 g_assert (p - buffer <= buflen);
8084 buflen = p - buffer;
8085 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8086 p = mono_array_addr (result, char, 0);
8087 memcpy (p, buffer, buflen);
8089 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8095 static void* reflection_info_desc = NULL;
8096 #define MOVING_GC_REGISTER(addr) do { \
8097 if (!reflection_info_desc) { \
8099 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8101 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8104 #define MOVING_GC_REGISTER(addr)
8108 * mono_reflection_setup_internal_class:
8109 * @tb: a TypeBuilder object
8111 * Creates a MonoClass that represents the TypeBuilder.
8112 * This is a trick that lets us simplify a lot of reflection code
8113 * (and will allow us to support Build and Run assemblies easier).
8116 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8118 MonoClass *klass, *parent;
8120 MONO_ARCH_SAVE_REGS;
8122 mono_loader_lock ();
8125 /* check so we can compile corlib correctly */
8126 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8127 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8128 parent = tb->parent->type->data.klass;
8130 parent = my_mono_class_from_mono_type (tb->parent->type);
8136 /* the type has already being created: it means we just have to change the parent */
8137 if (tb->type.type) {
8138 klass = mono_class_from_mono_type (tb->type.type);
8139 klass->parent = NULL;
8140 /* fool mono_class_setup_parent */
8141 klass->supertypes = NULL;
8142 mono_class_setup_parent (klass, parent);
8143 mono_class_setup_mono_type (klass);
8144 mono_loader_unlock ();
8148 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8150 klass->image = &tb->module->dynamic_image->image;
8152 klass->inited = 1; /* we lie to the runtime */
8153 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8154 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8155 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8156 klass->flags = tb->attrs;
8158 klass->element_class = klass;
8160 MOVING_GC_REGISTER (&klass->reflection_info);
8161 klass->reflection_info = tb;
8163 /* Put into cache so mono_class_get () will find it */
8164 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8166 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8167 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8169 if (parent != NULL) {
8170 mono_class_setup_parent (klass, parent);
8171 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8172 const char *old_n = klass->name;
8173 /* trick to get relative numbering right when compiling corlib */
8174 klass->name = "BuildingObject";
8175 mono_class_setup_parent (klass, mono_defaults.object_class);
8176 klass->name = old_n;
8179 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8180 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8181 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8182 klass->instance_size = sizeof (MonoObject);
8183 klass->size_inited = 1;
8184 mono_class_setup_vtable_general (klass, NULL, 0);
8187 mono_class_setup_mono_type (klass);
8189 mono_class_setup_supertypes (klass);
8192 * FIXME: handle interfaces.
8195 tb->type.type = &klass->byval_arg;
8197 if (tb->nesting_type) {
8198 g_assert (tb->nesting_type->type);
8199 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8202 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8204 mono_loader_unlock ();
8208 * mono_reflection_setup_generic_class:
8209 * @tb: a TypeBuilder object
8211 * Setup the generic class before adding the first generic parameter.
8214 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8218 MONO_ARCH_SAVE_REGS;
8220 klass = my_mono_class_from_mono_type (tb->type.type);
8221 if (tb->generic_container)
8224 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8225 tb->generic_container->owner.klass = klass;
8229 * mono_reflection_create_generic_class:
8230 * @tb: a TypeBuilder object
8232 * Creates the generic class after all generic parameters have been added.
8235 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8240 MONO_ARCH_SAVE_REGS;
8242 klass = my_mono_class_from_mono_type (tb->type.type);
8244 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8246 if (klass->generic_container || (count == 0))
8249 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8251 klass->generic_container = tb->generic_container;
8253 klass->generic_container->type_argc = count;
8254 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8256 for (i = 0; i < count; i++) {
8257 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8258 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8259 g_assert (klass->generic_container->type_params [i].owner);
8262 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8266 * mono_reflection_create_internal_class:
8267 * @tb: a TypeBuilder object
8269 * Actually create the MonoClass that is associated with the TypeBuilder.
8272 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8276 MONO_ARCH_SAVE_REGS;
8278 klass = my_mono_class_from_mono_type (tb->type.type);
8280 mono_loader_lock ();
8281 if (klass->enumtype && klass->enum_basetype == NULL) {
8282 MonoReflectionFieldBuilder *fb;
8285 g_assert (tb->fields != NULL);
8286 g_assert (mono_array_length (tb->fields) >= 1);
8288 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8290 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8291 mono_loader_unlock ();
8295 klass->enum_basetype = fb->type->type;
8296 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8297 if (!klass->element_class)
8298 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8301 * get the element_class from the current corlib.
8303 ec = default_class_from_mono_type (klass->enum_basetype);
8304 klass->instance_size = ec->instance_size;
8305 klass->size_inited = 1;
8307 * this is almost safe to do with enums and it's needed to be able
8308 * to create objects of the enum type (for use in SetConstant).
8310 /* FIXME: Does this mean enums can't have method overrides ? */
8311 mono_class_setup_vtable_general (klass, NULL, 0);
8313 mono_loader_unlock ();
8316 static MonoMarshalSpec*
8317 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8318 MonoReflectionMarshal *minfo)
8320 MonoMarshalSpec *res;
8322 res = g_new0 (MonoMarshalSpec, 1);
8323 res->native = minfo->type;
8325 switch (minfo->type) {
8326 case MONO_NATIVE_LPARRAY:
8327 res->data.array_data.elem_type = minfo->eltype;
8328 if (minfo->has_size) {
8329 res->data.array_data.param_num = minfo->param_num;
8330 res->data.array_data.num_elem = minfo->count;
8331 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8334 res->data.array_data.param_num = -1;
8335 res->data.array_data.num_elem = -1;
8336 res->data.array_data.elem_mult = -1;
8340 case MONO_NATIVE_BYVALTSTR:
8341 case MONO_NATIVE_BYVALARRAY:
8342 res->data.array_data.num_elem = minfo->count;
8345 case MONO_NATIVE_CUSTOM:
8346 if (minfo->marshaltyperef)
8347 res->data.custom_data.custom_name =
8348 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8350 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8360 MonoReflectionMarshal*
8361 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8362 MonoMarshalSpec *spec)
8364 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8365 MonoReflectionMarshal *minfo;
8368 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8369 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8370 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8371 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8374 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8375 minfo->type = spec->native;
8377 switch (minfo->type) {
8378 case MONO_NATIVE_LPARRAY:
8379 minfo->eltype = spec->data.array_data.elem_type;
8380 minfo->count = spec->data.array_data.num_elem;
8381 minfo->param_num = spec->data.array_data.param_num;
8384 case MONO_NATIVE_BYVALTSTR:
8385 case MONO_NATIVE_BYVALARRAY:
8386 minfo->count = spec->data.array_data.num_elem;
8389 case MONO_NATIVE_CUSTOM:
8390 if (spec->data.custom_data.custom_name) {
8391 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8393 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8395 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8397 if (spec->data.custom_data.cookie)
8398 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8409 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8410 ReflectionMethodBuilder *rmb,
8411 MonoMethodSignature *sig)
8414 MonoMethodNormal *pm;
8415 MonoMarshalSpec **specs;
8416 MonoReflectionMethodAux *method_aux;
8421 g_assert (!klass->generic_class);
8424 * Methods created using a MethodBuilder should have their memory allocated
8425 * inside the image mempool, while dynamic methods should have their memory
8428 dynamic = rmb->refs != NULL;
8429 mp = dynamic ? NULL : klass->image->mempool;
8431 mono_loader_lock ();
8433 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8434 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8435 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8437 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8439 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8441 pm = (MonoMethodNormal*)m;
8443 m->dynamic = dynamic;
8445 m->flags = rmb->attrs;
8446 m->iflags = rmb->iattrs;
8447 m->name = mp_string_to_utf8 (mp, rmb->name);
8450 m->skip_visibility = rmb->skip_visibility;
8452 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8454 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8455 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8458 m->signature->pinvoke = 1;
8459 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8460 m->signature->pinvoke = 1;
8462 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8464 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8465 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8467 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8469 if (klass->image->dynamic)
8470 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8472 mono_loader_unlock ();
8475 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8476 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8477 MonoMethodHeader *header;
8479 gint32 max_stack, i;
8480 gint32 num_locals = 0;
8481 gint32 num_clauses = 0;
8485 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8486 code_size = rmb->ilgen->code_len;
8487 max_stack = rmb->ilgen->max_stack;
8488 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8489 if (rmb->ilgen->ex_handlers)
8490 num_clauses = method_count_clauses (rmb->ilgen);
8493 code = mono_array_addr (rmb->code, guint8, 0);
8494 code_size = mono_array_length (rmb->code);
8495 /* we probably need to run a verifier on the code... */
8505 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8506 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8507 header->code_size = code_size;
8508 header->code = mp_g_malloc (mp, code_size);
8509 memcpy ((char*)header->code, code, code_size);
8510 header->max_stack = max_stack;
8511 header->init_locals = rmb->init_locals;
8512 header->num_locals = num_locals;
8514 for (i = 0; i < num_locals; ++i) {
8515 MonoReflectionLocalBuilder *lb =
8516 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8518 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8519 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8522 header->num_clauses = num_clauses;
8524 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8525 rmb->ilgen, num_clauses);
8528 pm->header = header;
8531 if (rmb->generic_params) {
8532 int count = mono_array_length (rmb->generic_params);
8533 MonoGenericContainer *container;
8535 m->generic_container = container = rmb->generic_container;
8536 container->type_argc = count;
8537 container->type_params = g_new0 (MonoGenericParam, count);
8538 container->owner.method = m;
8540 for (i = 0; i < count; i++) {
8541 MonoReflectionGenericParam *gp =
8542 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8544 container->type_params [i] = *gp->type.type->data.generic_param;
8547 if (klass->generic_container) {
8548 container->parent = klass->generic_container;
8549 container->context.class_inst = klass->generic_container->context.class_inst;
8551 container->context.method_inst = mono_get_shared_generic_inst (container);
8555 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8559 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8561 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8562 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8563 for (i = 0; i < rmb->nrefs; ++i)
8564 data [i + 1] = rmb->refs [i];
8569 /* Parameter info */
8572 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8573 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8574 for (i = 0; i <= m->signature->param_count; ++i) {
8575 MonoReflectionParamBuilder *pb;
8576 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8577 if ((i > 0) && (pb->attrs)) {
8578 /* Make a copy since it might point to a shared type structure */
8579 /* FIXME: Alloc this from a mempool */
8580 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8581 m->signature->params [i - 1]->attrs = pb->attrs;
8584 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8585 MonoDynamicImage *assembly;
8586 guint32 idx, def_type, len;
8590 if (!method_aux->param_defaults) {
8591 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8592 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8594 assembly = (MonoDynamicImage*)klass->image;
8595 idx = encode_constant (assembly, pb->def_value, &def_type);
8596 /* Copy the data from the blob since it might get realloc-ed */
8597 p = assembly->blob.data + idx;
8598 len = mono_metadata_decode_blob_size (p, &p2);
8600 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8601 method_aux->param_default_types [i] = def_type;
8602 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8606 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8608 if (!method_aux->param_cattr)
8609 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8610 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8616 /* Parameter marshalling */
8619 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8620 MonoReflectionParamBuilder *pb;
8621 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8622 if (pb->marshal_info) {
8624 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8625 specs [pb->position] =
8626 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8630 if (specs != NULL) {
8632 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8633 method_aux->param_marshall = specs;
8636 if (klass->image->dynamic && method_aux)
8637 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8639 mono_loader_unlock ();
8645 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8647 ReflectionMethodBuilder rmb;
8648 MonoMethodSignature *sig;
8650 mono_loader_lock ();
8651 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8652 mono_loader_unlock ();
8654 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8656 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8657 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8659 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8660 /* ilgen is no longer needed */
8668 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8670 ReflectionMethodBuilder rmb;
8671 MonoMethodSignature *sig;
8673 mono_loader_lock ();
8674 sig = method_builder_to_signature (klass->image->mempool, mb);
8675 mono_loader_unlock ();
8677 reflection_methodbuilder_from_method_builder (&rmb, mb);
8679 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8680 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8682 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8683 /* ilgen is no longer needed */
8689 static MonoClassField*
8690 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8692 MonoClassField *field;
8696 field = g_new0 (MonoClassField, 1);
8698 field->name = mono_string_to_utf8 (fb->name);
8700 /* FIXME: handle type modifiers */
8701 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8702 field->type->attrs = fb->attrs;
8704 field->type = fb->type->type;
8706 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8707 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8708 if (fb->offset != -1)
8709 field->offset = fb->offset;
8710 field->parent = klass;
8711 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8713 if (fb->def_value) {
8714 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8715 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8716 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8717 /* Copy the data from the blob since it might get realloc-ed */
8718 p = assembly->blob.data + idx;
8719 len = mono_metadata_decode_blob_size (p, &p2);
8721 field->data = g_malloc (len);
8722 memcpy ((gpointer)field->data, p, len);
8729 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8732 MonoReflectionTypeBuilder *tb = NULL;
8733 gboolean is_dynamic = FALSE;
8737 mono_loader_lock ();
8739 domain = mono_object_domain (type);
8741 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8742 tb = (MonoReflectionTypeBuilder *) type;
8745 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8746 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8747 MonoReflectionType *rgt = rgi->generic_type;
8749 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8750 tb = (MonoReflectionTypeBuilder *) rgt;
8755 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8756 if (tb && tb->generic_container)
8757 mono_reflection_create_generic_class (tb);
8759 klass = mono_class_from_mono_type (type->type);
8760 if (!klass->generic_container) {
8761 mono_loader_unlock ();
8765 if (klass->wastypebuilder) {
8766 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8771 mono_loader_unlock ();
8773 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8775 return &geninst->byval_arg;
8779 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8781 MonoGenericClass *gclass;
8782 MonoGenericInst *inst;
8785 g_assert (klass->generic_container);
8787 inst = g_new0 (MonoGenericInst, 1);
8788 inst->type_argc = type_argc;
8789 inst->type_argv = g_new0 (MonoType *, inst->type_argc);
8791 for (i = 0; i < inst->type_argc; ++i) {
8792 MonoType *t = dup_type (types [i]);
8795 inst->is_open = mono_class_is_open_constructed_type (t);
8797 inst->type_argv [i] = t;
8800 inst = mono_metadata_lookup_generic_inst (inst);
8801 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8803 return mono_generic_class_get_class (gclass);
8806 static inline MonoType*
8807 dup_type (const MonoType *original)
8809 MonoType *r = g_new0 (MonoType, 1);
8811 r->attrs = original->attrs;
8812 r->byref = original->byref;
8813 if (original->type == MONO_TYPE_PTR)
8814 r->data.type = dup_type (original->data.type);
8815 else if (original->type == MONO_TYPE_ARRAY)
8816 r->data.array = mono_dup_array_type (original->data.array);
8817 else if (original->type == MONO_TYPE_FNPTR)
8818 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8819 mono_stats.generics_metadata_size += sizeof (MonoType);
8823 MonoReflectionMethod*
8824 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8827 MonoMethod *method, *inflated;
8828 MonoMethodInflated *imethod;
8829 MonoReflectionMethodBuilder *mb = NULL;
8830 MonoGenericContainer *container;
8831 MonoGenericContext tmp_context;
8832 MonoGenericInst *ginst;
8835 MONO_ARCH_SAVE_REGS;
8836 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8837 MonoReflectionTypeBuilder *tb;
8840 mb = (MonoReflectionMethodBuilder *) rmethod;
8841 tb = (MonoReflectionTypeBuilder *) mb->type;
8842 klass = mono_class_from_mono_type (tb->type.type);
8844 method = methodbuilder_to_mono_method (klass, mb);
8846 method = rmethod->method;
8849 klass = method->klass;
8851 if (method->is_inflated)
8852 method = ((MonoMethodInflated *) method)->declaring;
8854 count = mono_method_signature (method)->generic_param_count;
8855 if (count != mono_array_length (types))
8858 container = method->generic_container;
8859 g_assert (container);
8861 if (!container->method_hash)
8862 container->method_hash = g_hash_table_new (
8863 (GHashFunc) mono_metadata_generic_context_hash,
8864 (GCompareFunc) mono_metadata_generic_context_equal);
8866 ginst = g_new0 (MonoGenericInst,1 );
8867 ginst->type_argc = count;
8868 ginst->type_argv = g_new0 (MonoType *, count);
8869 for (i = 0; i < count; i++) {
8870 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8871 ginst->type_argv [i] = dup_type (garg->type);
8873 if (!ginst->is_open)
8874 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8876 ginst = mono_metadata_lookup_generic_inst (ginst);
8878 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8879 tmp_context.method_inst = ginst;
8881 inflated = g_hash_table_lookup (container->method_hash, &tmp_context);
8883 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8885 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8886 imethod = (MonoMethodInflated *) inflated;
8888 MOVING_GC_REGISTER (&imethod->reflection_info);
8889 imethod->reflection_info = rmethod;
8891 g_hash_table_insert (container->method_hash, mono_method_get_context (inflated), inflated);
8893 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8897 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8899 MonoMethodInflated *imethod;
8900 MonoGenericContext tmp_context;
8901 MonoGenericContext *context;
8904 klass = mono_class_from_mono_type (type->type.type);
8905 g_assert (klass->generic_class);
8906 context = mono_class_get_context (klass);
8908 if (method->generic_container) {
8909 g_assert (method->klass == klass->generic_class->container_class);
8911 tmp_context.class_inst = klass->generic_class->context.class_inst;
8912 tmp_context.method_inst = method->generic_container->context.method_inst;
8913 context = &tmp_context;
8916 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8917 if (method->generic_container) {
8918 MOVING_GC_REGISTER (&imethod->reflection_info);
8919 imethod->reflection_info = obj;
8921 return (MonoMethod *) imethod;
8925 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8930 gklass = mono_class_from_mono_type (type->generic_type->type);
8932 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8933 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8934 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8935 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8936 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8937 method = ((MonoReflectionMethod *) obj)->method;
8939 method = NULL; /* prevent compiler warning */
8940 g_assert_not_reached ();
8943 return inflate_mono_method (type, method, obj);
8947 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8948 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8951 MonoGenericClass *gclass;
8952 MonoDynamicGenericClass *dgclass;
8953 MonoClass *klass, *gklass;
8956 MONO_ARCH_SAVE_REGS;
8958 klass = mono_class_from_mono_type (type->type.type);
8959 gclass = type->type.type->data.generic_class;
8961 g_assert (gclass->is_dynamic);
8962 dgclass = (MonoDynamicGenericClass *) gclass;
8964 if (dgclass->initialized)
8967 gklass = gclass->container_class;
8968 mono_class_init (gklass);
8970 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8971 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8972 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8973 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8974 dgclass->count_events = events ? mono_array_length (events) : 0;
8976 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8977 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8978 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8979 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8980 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8982 for (i = 0; i < dgclass->count_methods; i++) {
8983 MonoObject *obj = mono_array_get (methods, gpointer, i);
8985 dgclass->methods [i] = inflate_method (type, obj);
8988 for (i = 0; i < dgclass->count_ctors; i++) {
8989 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8991 dgclass->ctors [i] = inflate_method (type, obj);
8994 for (i = 0; i < dgclass->count_fields; i++) {
8995 MonoObject *obj = mono_array_get (fields, gpointer, i);
8996 MonoClassField *field;
8997 MonoInflatedField *ifield;
8999 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9000 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9001 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9002 field = ((MonoReflectionField *) obj)->field;
9004 field = NULL; /* prevent compiler warning */
9005 g_assert_not_reached ();
9008 ifield = g_new0 (MonoInflatedField, 1);
9009 ifield->generic_type = field->type;
9010 MOVING_GC_REGISTER (&ifield->reflection_info);
9011 ifield->reflection_info = obj;
9013 dgclass->fields [i] = *field;
9014 dgclass->fields [i].parent = klass;
9015 dgclass->fields [i].generic_info = ifield;
9016 dgclass->fields [i].type = mono_class_inflate_generic_type (
9017 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9020 for (i = 0; i < dgclass->count_properties; i++) {
9021 MonoObject *obj = mono_array_get (properties, gpointer, i);
9022 MonoProperty *property = &dgclass->properties [i];
9024 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9025 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9027 property->parent = klass;
9028 property->attrs = pb->attrs;
9029 property->name = mono_string_to_utf8 (pb->name);
9031 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9033 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9034 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9035 *property = *((MonoReflectionProperty *) obj)->property;
9038 property->get = inflate_mono_method (type, property->get, NULL);
9040 property->set = inflate_mono_method (type, property->set, NULL);
9042 g_assert_not_reached ();
9045 for (i = 0; i < dgclass->count_events; i++) {
9046 MonoObject *obj = mono_array_get (events, gpointer, i);
9047 MonoEvent *event = &dgclass->events [i];
9049 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9050 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9052 event->parent = klass;
9053 event->attrs = eb->attrs;
9054 event->name = mono_string_to_utf8 (eb->name);
9056 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9057 if (eb->remove_method)
9058 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9059 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9060 *event = *((MonoReflectionEvent *) obj)->event;
9063 event->add = inflate_mono_method (type, event->add, NULL);
9065 event->remove = inflate_mono_method (type, event->remove, NULL);
9067 g_assert_not_reached ();
9070 dgclass->initialized = TRUE;
9074 ensure_runtime_vtable (MonoClass *klass)
9076 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9079 if (!tb || klass->wastypebuilder)
9082 ensure_runtime_vtable (klass->parent);
9084 num = tb->ctors? mono_array_length (tb->ctors): 0;
9085 num += tb->num_methods;
9086 klass->method.count = num;
9087 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9088 num = tb->ctors? mono_array_length (tb->ctors): 0;
9089 for (i = 0; i < num; ++i)
9090 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9091 num = tb->num_methods;
9093 for (i = 0; i < num; ++i)
9094 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9096 if (tb->interfaces) {
9097 klass->interface_count = mono_array_length (tb->interfaces);
9098 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9099 for (i = 0; i < klass->interface_count; ++i) {
9100 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9101 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9105 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9106 for (i = 0; i < klass->method.count; ++i)
9107 klass->methods [i]->slot = i;
9109 mono_class_setup_interface_offsets (klass);
9113 * The generic vtable is needed even if image->run is not set since some
9114 * runtime code like ves_icall_Type_GetMethodsByName depends on
9115 * method->slot being defined.
9119 * tb->methods could not be freed since it is used for determining
9120 * overrides during dynamic vtable construction.
9125 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9127 MonoReflectionTypeBuilder *tb;
9133 g_assert (klass->image->dynamic);
9135 if (!klass->reflection_info)
9138 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9140 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9144 for (i = 0; i < tb->num_methods; ++i) {
9145 MonoReflectionMethodBuilder *mb =
9146 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9147 if (mb->override_method)
9153 *overrides = g_new0 (MonoMethod*, onum * 2);
9156 for (i = 0; i < tb->num_methods; ++i) {
9157 MonoReflectionMethodBuilder *mb =
9158 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9159 if (mb->override_method) {
9160 (*overrides) [onum * 2] =
9161 mb->override_method->method;
9162 (*overrides) [onum * 2 + 1] =
9165 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9166 g_assert (mb->override_method->method);
9167 g_assert (mb->mhandle);
9174 *num_overrides = onum;
9178 typebuilder_setup_fields (MonoClass *klass)
9180 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9181 MonoReflectionFieldBuilder *fb;
9182 MonoClassField *field;
9187 klass->field.count = tb->num_fields;
9188 klass->field.first = 0;
9190 if (!klass->field.count)
9193 klass->fields = g_new0 (MonoClassField, klass->field.count);
9195 for (i = 0; i < klass->field.count; ++i) {
9196 fb = mono_array_get (tb->fields, gpointer, i);
9197 field = &klass->fields [i];
9198 field->name = mono_string_to_utf8 (fb->name);
9200 /* FIXME: handle type modifiers */
9201 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9202 field->type->attrs = fb->attrs;
9204 field->type = fb->type->type;
9206 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9207 field->data = mono_array_addr (fb->rva_data, char, 0);
9208 if (fb->offset != -1)
9209 field->offset = fb->offset;
9210 field->parent = klass;
9212 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9214 if (fb->def_value) {
9215 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9216 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9217 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9218 /* Copy the data from the blob since it might get realloc-ed */
9219 p = assembly->blob.data + idx;
9220 len = mono_metadata_decode_blob_size (p, &p2);
9222 field->data = g_malloc (len);
9223 memcpy ((gpointer)field->data, p, len);
9226 mono_class_layout_fields (klass);
9230 typebuilder_setup_properties (MonoClass *klass)
9232 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9233 MonoReflectionPropertyBuilder *pb;
9236 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9237 klass->property.first = 0;
9239 klass->properties = g_new0 (MonoProperty, klass->property.count);
9240 for (i = 0; i < klass->property.count; ++i) {
9241 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9242 klass->properties [i].parent = klass;
9243 klass->properties [i].attrs = pb->attrs;
9244 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9246 klass->properties [i].get = pb->get_method->mhandle;
9248 klass->properties [i].set = pb->set_method->mhandle;
9250 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9254 MonoReflectionEvent *
9255 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9257 MonoEvent *event = g_new0 (MonoEvent, 1);
9261 klass = my_mono_class_from_mono_type (tb->type.type);
9263 event->parent = klass;
9264 event->attrs = eb->attrs;
9265 event->name = mono_string_to_utf8 (eb->name);
9267 event->add = eb->add_method->mhandle;
9268 if (eb->remove_method)
9269 event->remove = eb->remove_method->mhandle;
9270 if (eb->raise_method)
9271 event->raise = eb->raise_method->mhandle;
9273 if (eb->other_methods) {
9274 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9275 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9276 MonoReflectionMethodBuilder *mb =
9277 mono_array_get (eb->other_methods,
9278 MonoReflectionMethodBuilder*, j);
9279 event->other [j] = mb->mhandle;
9283 return mono_event_get_object (mono_object_domain (tb), klass, event);
9287 typebuilder_setup_events (MonoClass *klass)
9289 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9290 MonoReflectionEventBuilder *eb;
9293 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9294 klass->event.first = 0;
9296 klass->events = g_new0 (MonoEvent, klass->event.count);
9297 for (i = 0; i < klass->event.count; ++i) {
9298 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9299 klass->events [i].parent = klass;
9300 klass->events [i].attrs = eb->attrs;
9301 klass->events [i].name = mono_string_to_utf8 (eb->name);
9303 klass->events [i].add = eb->add_method->mhandle;
9304 if (eb->remove_method)
9305 klass->events [i].remove = eb->remove_method->mhandle;
9306 if (eb->raise_method)
9307 klass->events [i].raise = eb->raise_method->mhandle;
9309 if (eb->other_methods) {
9310 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9311 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9312 MonoReflectionMethodBuilder *mb =
9313 mono_array_get (eb->other_methods,
9314 MonoReflectionMethodBuilder*, j);
9315 klass->events [i].other [j] = mb->mhandle;
9322 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9326 MonoReflectionType* res;
9329 MONO_ARCH_SAVE_REGS;
9331 domain = mono_object_domain (tb);
9332 klass = my_mono_class_from_mono_type (tb->type.type);
9334 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9337 * we need to lock the domain because the lock will be taken inside
9338 * So, we need to keep the locking order correct.
9340 mono_domain_lock (domain);
9341 mono_loader_lock ();
9342 if (klass->wastypebuilder) {
9343 mono_loader_unlock ();
9344 mono_domain_unlock (domain);
9345 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9348 * Fields to set in klass:
9349 * the various flags: delegate/unicode/contextbound etc.
9351 klass->flags = tb->attrs;
9352 klass->has_cctor = 1;
9353 klass->has_finalize = 1;
9356 if (!((MonoDynamicImage*)klass->image)->run) {
9357 if (klass->generic_container) {
9358 /* FIXME: The code below can't handle generic classes */
9359 klass->wastypebuilder = TRUE;
9360 mono_loader_unlock ();
9361 mono_domain_unlock (domain);
9362 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9367 /* enums are done right away */
9368 if (!klass->enumtype)
9369 ensure_runtime_vtable (klass);
9372 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9373 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9374 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9378 /* fields and object layout */
9379 if (klass->parent) {
9380 if (!klass->parent->size_inited)
9381 mono_class_init (klass->parent);
9382 klass->instance_size = klass->parent->instance_size;
9383 klass->sizes.class_size = 0;
9384 klass->min_align = klass->parent->min_align;
9385 /* if the type has no fields we won't call the field_setup
9386 * routine which sets up klass->has_references.
9388 klass->has_references |= klass->parent->has_references;
9390 klass->instance_size = sizeof (MonoObject);
9391 klass->min_align = 1;
9394 /* FIXME: handle packing_size and instance_size */
9395 typebuilder_setup_fields (klass);
9397 typebuilder_setup_properties (klass);
9399 typebuilder_setup_events (klass);
9401 klass->wastypebuilder = TRUE;
9402 mono_loader_unlock ();
9403 mono_domain_unlock (domain);
9405 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9406 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9407 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9410 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9411 g_assert (res != (MonoReflectionType*)tb);
9417 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9419 MonoGenericParam *param;
9422 MONO_ARCH_SAVE_REGS;
9424 param = g_new0 (MonoGenericParam, 1);
9426 if (gparam->mbuilder) {
9427 if (!gparam->mbuilder->generic_container)
9428 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9429 param->owner = gparam->mbuilder->generic_container;
9430 } else if (gparam->tbuilder) {
9431 g_assert (gparam->tbuilder->generic_container);
9432 param->owner = gparam->tbuilder->generic_container;
9435 param->name = mono_string_to_utf8 (gparam->name);
9436 param->num = gparam->index;
9438 image = &gparam->tbuilder->module->dynamic_image->image;
9439 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9441 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9442 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9444 gparam->type.type = g_new0 (MonoType, 1);
9445 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9446 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9447 gparam->type.type->data.generic_param = param;
9451 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9453 MonoDynamicImage *assembly = sig->module->dynamic_image;
9454 guint32 na = mono_array_length (sig->arguments);
9459 sigbuffer_init (&buf, 32);
9461 sigbuffer_add_value (&buf, 0x07);
9462 sigbuffer_add_value (&buf, na);
9463 for (i = 0; i < na; ++i) {
9464 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9465 encode_reflection_type (assembly, type, &buf);
9468 buflen = buf.p - buf.buf;
9469 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9470 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9471 sigbuffer_free (&buf);
9477 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9479 MonoDynamicImage *assembly = sig->module->dynamic_image;
9480 guint32 na = mono_array_length (sig->arguments);
9485 sigbuffer_init (&buf, 32);
9487 sigbuffer_add_value (&buf, 0x06);
9488 for (i = 0; i < na; ++i) {
9489 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9490 encode_reflection_type (assembly, type, &buf);
9493 buflen = buf.p - buf.buf;
9494 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9495 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9496 sigbuffer_free (&buf);
9502 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9504 ReflectionMethodBuilder rmb;
9505 MonoMethodSignature *sig;
9509 sig = dynamic_method_to_signature (mb);
9511 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9514 * Resolve references.
9517 * Every second entry in the refs array is reserved for storing handle_class,
9518 * which is needed by the ldtoken implementation in the JIT.
9520 rmb.nrefs = mb->nrefs;
9521 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9522 for (i = 0; i < mb->nrefs; i += 2) {
9523 MonoClass *handle_class;
9525 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9527 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9528 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9530 * The referenced DynamicMethod should already be created by the managed
9531 * code, except in the case of circular references. In that case, we store
9532 * method in the refs array, and fix it up later when the referenced
9533 * DynamicMethod is created.
9535 if (method->mhandle) {
9536 ref = method->mhandle;
9538 /* FIXME: GC object stored in unmanaged memory */
9541 /* FIXME: GC object stored in unmanaged memory */
9542 method->referenced_by = g_slist_append (method->referenced_by, mb);
9544 handle_class = mono_defaults.methodhandle_class;
9546 ref = resolve_object (mb->module->image, obj, &handle_class);
9549 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9554 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9555 rmb.refs [i + 1] = handle_class;
9559 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9561 /* Fix up refs entries pointing at us */
9562 for (l = mb->referenced_by; l; l = l->next) {
9563 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9564 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9567 g_assert (method->mhandle);
9569 data = (gpointer*)wrapper->method_data;
9570 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9571 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9572 data [i + 1] = mb->mhandle;
9575 g_slist_free (mb->referenced_by);
9579 /* ilgen is no longer needed */
9584 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9589 mono_runtime_free_method (
9590 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9594 * mono_reflection_lookup_dynamic_token:
9596 * Finish the Builder object pointed to by TOKEN and return the corresponding
9597 * runtime structure. HANDLE_CLASS is set to the class required by
9601 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9603 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9606 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9609 return resolve_object (image, obj, handle_class);
9613 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9615 gpointer result = NULL;
9617 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9618 result = mono_string_intern ((MonoString*)obj);
9619 *handle_class = NULL;
9621 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9622 MonoReflectionType *tb = (MonoReflectionType*)obj;
9623 result = mono_class_from_mono_type (tb->type);
9624 *handle_class = mono_defaults.typehandle_class;
9626 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9627 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9628 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9629 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9630 result = ((MonoReflectionMethod*)obj)->method;
9631 *handle_class = mono_defaults.methodhandle_class;
9633 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9634 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9635 result = mb->mhandle;
9637 /* Type is not yet created */
9638 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9640 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9643 * Hopefully this has been filled in by calling CreateType() on the
9647 * TODO: This won't work if the application finishes another
9648 * TypeBuilder instance instead of this one.
9650 result = mb->mhandle;
9652 *handle_class = mono_defaults.methodhandle_class;
9653 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9654 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9656 result = cb->mhandle;
9658 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9660 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9661 result = cb->mhandle;
9663 *handle_class = mono_defaults.methodhandle_class;
9664 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9665 result = ((MonoReflectionField*)obj)->field;
9666 *handle_class = mono_defaults.fieldhandle_class;
9668 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9669 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9670 result = fb->handle;
9673 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9675 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9676 result = fb->handle;
9678 *handle_class = mono_defaults.fieldhandle_class;
9679 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9680 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9683 klass = tb->type.type->data.klass;
9684 if (klass->wastypebuilder) {
9685 /* Already created */
9689 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9690 result = tb->type.type->data.klass;
9693 *handle_class = mono_defaults.typehandle_class;
9694 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9695 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9696 MonoMethodSignature *sig;
9699 if (helper->arguments)
9700 nargs = mono_array_length (helper->arguments);
9704 sig = mono_metadata_signature_alloc (image, nargs);
9705 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9706 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9708 if (helper->call_conv == 0) /* unmanaged */
9709 sig->call_convention = helper->unmanaged_call_conv - 1;
9711 if (helper->call_conv & 0x02)
9712 sig->call_convention = MONO_CALL_VARARG;
9714 sig->call_convention = MONO_CALL_DEFAULT;
9716 sig->param_count = nargs;
9717 /* TODO: Copy type ? */
9718 sig->ret = helper->return_type->type;
9719 for (i = 0; i < nargs; ++i) {
9720 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9721 sig->params [i] = rt->type;
9725 *handle_class = NULL;
9726 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9727 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9728 /* Already created by the managed code */
9729 g_assert (method->mhandle);
9730 result = method->mhandle;
9731 *handle_class = mono_defaults.methodhandle_class;
9733 g_print (obj->vtable->klass->name);
9734 g_assert_not_reached ();
9740 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9741 const static guint32 declsec_flags_map[] = {
9742 0x00000000, /* empty */
9743 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9744 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9745 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9746 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9747 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9748 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9749 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9750 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9751 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9752 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9753 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9754 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9755 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9756 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9757 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9758 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9759 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9760 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9764 * Returns flags that includes all available security action associated to the handle.
9765 * @token: metadata token (either for a class or a method)
9766 * @image: image where resides the metadata.
9769 mono_declsec_get_flags (MonoImage *image, guint32 token)
9771 int index = mono_metadata_declsec_from_index (image, token);
9772 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9777 /* HasSecurity can be present for other, not specially encoded, attributes,
9778 e.g. SuppressUnmanagedCodeSecurityAttribute */
9782 for (i = index; i < t->rows; i++) {
9783 guint32 cols [MONO_DECL_SECURITY_SIZE];
9785 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9786 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9789 action = cols [MONO_DECL_SECURITY_ACTION];
9790 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9791 result |= declsec_flags_map [action];
9793 g_assert_not_reached ();
9800 * Get the security actions (in the form of flags) associated with the specified method.
9802 * @method: The method for which we want the declarative security flags.
9803 * Return the declarative security flags for the method (only).
9805 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9806 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9809 mono_declsec_flags_from_method (MonoMethod *method)
9811 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9812 /* FIXME: No cache (for the moment) */
9813 guint32 idx = mono_method_get_index (method);
9814 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9815 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9816 return mono_declsec_get_flags (method->klass->image, idx);
9822 * Get the security actions (in the form of flags) associated with the specified class.
9824 * @klass: The class for which we want the declarative security flags.
9825 * Return the declarative security flags for the class.
9827 * Note: We cache the flags inside the MonoClass structure as this will get
9828 * called very often (at least for each method).
9831 mono_declsec_flags_from_class (MonoClass *klass)
9833 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9834 if (!klass->declsec_flags) {
9835 guint32 idx = mono_metadata_token_index (klass->type_token);
9836 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9837 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9838 /* we cache the flags on classes */
9839 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9841 return klass->declsec_flags;
9847 * Get the security actions (in the form of flags) associated with the specified assembly.
9849 * @assembly: The assembly for which we want the declarative security flags.
9850 * Return the declarative security flags for the assembly.
9853 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9855 guint32 idx = 1; /* there is only one assembly */
9856 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9857 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9858 return mono_declsec_get_flags (assembly->image, idx);
9863 * Fill actions for the specific index (which may either be an encoded class token or
9864 * an encoded method token) from the metadata image.
9865 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9868 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9869 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9871 MonoBoolean result = FALSE;
9873 guint32 cols [MONO_DECL_SECURITY_SIZE];
9874 int index = mono_metadata_declsec_from_index (image, token);
9877 t = &image->tables [MONO_TABLE_DECLSECURITY];
9878 for (i = index; i < t->rows; i++) {
9879 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9881 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9884 /* if present only replace (class) permissions with method permissions */
9885 /* if empty accept either class or method permissions */
9886 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9887 if (!actions->demand.blob) {
9888 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9889 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9890 actions->demand.blob = (char*) (blob + 2);
9891 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9894 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9895 if (!actions->noncasdemand.blob) {
9896 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9897 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9898 actions->noncasdemand.blob = (char*) (blob + 2);
9899 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9902 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9903 if (!actions->demandchoice.blob) {
9904 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9905 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9906 actions->demandchoice.blob = (char*) (blob + 2);
9907 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9917 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9918 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9920 guint32 idx = mono_metadata_token_index (klass->type_token);
9921 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9922 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9923 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9927 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9928 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9930 guint32 idx = mono_method_get_index (method);
9931 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9932 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9933 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9937 * Collect all actions (that requires to generate code in mini) assigned for
9938 * the specified method.
9939 * Note: Don't use the content of actions if the function return FALSE.
9942 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9944 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9945 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9946 MonoBoolean result = FALSE;
9949 /* quick exit if no declarative security is present in the metadata */
9950 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9953 /* we want the original as the wrapper is "free" of the security informations */
9954 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9955 method = mono_marshal_method_from_wrapper (method);
9960 /* First we look for method-level attributes */
9961 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9962 mono_class_init (method->klass);
9963 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9965 result = mono_declsec_get_method_demands_params (method, demands,
9966 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9969 /* Here we use (or create) the class declarative cache to look for demands */
9970 flags = mono_declsec_flags_from_class (method->klass);
9973 mono_class_init (method->klass);
9974 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9976 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9977 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9980 /* The boolean return value is used as a shortcut in case nothing needs to
9981 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9987 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9989 * Note: Don't use the content of actions if the function return FALSE.
9992 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9994 MonoBoolean result = FALSE;
9997 /* quick exit if no declarative security is present in the metadata */
9998 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10001 /* we want the original as the wrapper is "free" of the security informations */
10002 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10003 method = mono_marshal_method_from_wrapper (method);
10008 /* results are independant - zeroize both */
10009 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10010 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10012 /* First we look for method-level attributes */
10013 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10014 mono_class_init (method->klass);
10016 result = mono_declsec_get_method_demands_params (method, cmethod,
10017 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10020 /* Here we use (or create) the class declarative cache to look for demands */
10021 flags = mono_declsec_flags_from_class (method->klass);
10022 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10023 mono_class_init (method->klass);
10025 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10026 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10033 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10035 * @klass The inherited class - this is the class that provides the security check (attributes)
10037 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10039 * Note: Don't use the content of actions if the function return FALSE.
10042 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10044 MonoBoolean result = FALSE;
10047 /* quick exit if no declarative security is present in the metadata */
10048 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10051 /* Here we use (or create) the class declarative cache to look for demands */
10052 flags = mono_declsec_flags_from_class (klass);
10053 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10054 mono_class_init (klass);
10055 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10057 result |= mono_declsec_get_class_demands_params (klass, demands,
10058 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10065 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10067 * Note: Don't use the content of actions if the function return FALSE.
10070 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10072 /* quick exit if no declarative security is present in the metadata */
10073 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10076 /* we want the original as the wrapper is "free" of the security informations */
10077 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10078 method = mono_marshal_method_from_wrapper (method);
10083 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10084 mono_class_init (method->klass);
10085 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10087 return mono_declsec_get_method_demands_params (method, demands,
10088 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10095 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10097 guint32 cols [MONO_DECL_SECURITY_SIZE];
10101 int index = mono_metadata_declsec_from_index (image, token);
10105 t = &image->tables [MONO_TABLE_DECLSECURITY];
10106 for (i = index; i < t->rows; i++) {
10107 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10109 /* shortcut - index are ordered */
10110 if (token != cols [MONO_DECL_SECURITY_PARENT])
10113 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10114 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10115 entry->blob = (char*) (metadata + 2);
10116 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10125 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10127 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10128 guint32 idx = mono_method_get_index (method);
10129 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10130 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10131 return get_declsec_action (method->klass->image, idx, action, entry);
10137 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10140 guint32 flags = mono_declsec_flags_from_class (klass);
10141 if (declsec_flags_map [action] & flags) {
10142 guint32 idx = mono_metadata_token_index (klass->type_token);
10143 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10144 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10145 return get_declsec_action (klass->image, idx, action, entry);
10151 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10153 guint32 idx = 1; /* there is only one assembly */
10154 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10155 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10157 return get_declsec_action (assembly->image, idx, action, entry);
10161 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10163 MonoObject *res, *exc;
10165 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10166 static MonoMethod *method = NULL;
10168 if (!System_Reflection_Emit_TypeBuilder) {
10169 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10170 g_assert (System_Reflection_Emit_TypeBuilder);
10172 if (method == NULL) {
10173 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10178 * The result of mono_type_get_object () might be a System.MonoType but we
10179 * need a TypeBuilder so use klass->reflection_info.
10181 g_assert (klass->reflection_info);
10182 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10184 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10186 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10190 return *(MonoBoolean*)mono_object_unbox (res);