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, MonoGenericContext *context);
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 MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
151 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
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 ("default_class_from_mono_type: 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;
1438 rmb->type = (MonoObject *) mb->owner;
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 imethod = (MonoMethodInflated *) method;
2432 declaring = imethod->declaring;
2434 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2435 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2437 if (!mono_method_signature (declaring)->generic_param_count)
2440 switch (mono_metadata_token_table (mtoken)) {
2441 case MONO_TABLE_MEMBERREF:
2442 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2444 case MONO_TABLE_METHOD:
2445 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2448 g_assert_not_reached ();
2451 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2453 if (assembly->save) {
2454 alloc_table (table, table->rows + 1);
2455 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2456 values [MONO_METHODSPEC_METHOD] = mtoken;
2457 values [MONO_METHODSPEC_SIGNATURE] = sig;
2460 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2467 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2469 MonoMethodInflated *imethod;
2472 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2476 g_assert (method->is_inflated);
2477 imethod = (MonoMethodInflated *) method;
2479 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2480 token = method_encode_methodspec (assembly, method);
2482 guint32 sig = method_encode_signature (
2483 assembly, mono_method_signature (imethod->declaring));
2484 token = mono_image_get_memberref_token (
2485 assembly, &method->klass->byval_arg, method->name, sig);
2488 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2493 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2495 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2498 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2499 token = mono_image_get_memberref_token (
2500 assembly, &m->klass->byval_arg, m->name, sig);
2506 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2508 MonoDynamicTable *table;
2516 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2517 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2518 * Because of this, we must not insert it into the `typeref' hash table.
2521 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2525 sigbuffer_init (&buf, 32);
2527 g_assert (tb->generic_params);
2528 klass = mono_class_from_mono_type (tb->type.type);
2530 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2531 encode_type (assembly, &klass->byval_arg, &buf);
2533 count = mono_array_length (tb->generic_params);
2534 sigbuffer_add_value (&buf, count);
2535 for (i = 0; i < count; i++) {
2536 MonoReflectionGenericParam *gparam;
2538 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2540 encode_type (assembly, gparam->type.type, &buf);
2543 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2545 if (assembly->save) {
2546 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2547 alloc_table (table, table->rows + 1);
2548 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2549 values [MONO_TYPESPEC_SIGNATURE] = token;
2551 sigbuffer_free (&buf);
2553 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2554 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2560 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2562 MonoDynamicTable *table;
2565 guint32 token, pclass, parent, sig;
2568 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2572 klass = mono_class_from_mono_type (fb->typeb->type);
2573 name = mono_string_to_utf8 (fb->name);
2575 sig = fieldref_encode_signature (assembly, fb->type->type);
2577 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2578 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2580 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2581 parent >>= MONO_TYPEDEFORREF_BITS;
2583 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2585 if (assembly->save) {
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2588 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2589 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2590 values [MONO_MEMBERREF_SIGNATURE] = sig;
2593 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2595 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2600 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2607 if (!assembly->save)
2611 g_assert (helper->type == 2);
2613 if (helper->arguments)
2614 nargs = mono_array_length (helper->arguments);
2618 size = 10 + (nargs * 10);
2620 sigbuffer_init (&buf, 32);
2622 /* Encode calling convention */
2623 /* Change Any to Standard */
2624 if ((helper->call_conv & 0x03) == 0x03)
2625 helper->call_conv = 0x01;
2626 /* explicit_this implies has_this */
2627 if (helper->call_conv & 0x40)
2628 helper->call_conv &= 0x20;
2630 if (helper->call_conv == 0) { /* Unmanaged */
2631 idx = helper->unmanaged_call_conv - 1;
2634 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2635 if (helper->call_conv & 0x02) /* varargs */
2639 sigbuffer_add_byte (&buf, idx);
2640 sigbuffer_add_value (&buf, nargs);
2641 encode_reflection_type (assembly, helper->return_type, &buf);
2642 for (i = 0; i < nargs; ++i) {
2643 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2644 encode_reflection_type (assembly, pt, &buf);
2646 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2647 sigbuffer_free (&buf);
2653 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2656 MonoDynamicTable *table;
2659 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2660 idx = table->next_idx ++;
2662 alloc_table (table, table->rows);
2663 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2665 values [MONO_STAND_ALONE_SIGNATURE] =
2666 mono_reflection_encode_sighelper (assembly, helper);
2672 reflection_cc_to_file (int call_conv) {
2673 switch (call_conv & 0x3) {
2675 case 1: return MONO_CALL_DEFAULT;
2676 case 2: return MONO_CALL_VARARG;
2678 g_assert_not_reached ();
2685 MonoMethodSignature *sig;
2691 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2696 MonoMethodSignature *sig;
2699 name = mono_string_to_utf8 (m->name);
2700 nparams = mono_array_length (m->parameters);
2701 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2703 sig->sentinelpos = -1;
2704 sig->call_convention = reflection_cc_to_file (m->call_conv);
2705 sig->param_count = nparams;
2706 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2707 for (i = 0; i < nparams; ++i) {
2708 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2709 sig->params [i] = t->type;
2712 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2714 if (strcmp (name, am->name) == 0 &&
2715 mono_metadata_type_equal (am->parent, m->parent->type) &&
2716 mono_metadata_signature_equal (am->sig, sig)) {
2719 m->table_idx = am->token & 0xffffff;
2723 am = g_new0 (ArrayMethod, 1);
2726 am->parent = m->parent->type;
2727 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2728 method_encode_signature (assembly, sig));
2729 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2730 m->table_idx = am->token & 0xffffff;
2735 * Insert into the metadata tables all the info about the TypeBuilder tb.
2736 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2739 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2741 MonoDynamicTable *table;
2743 int i, is_object = 0, is_system = 0;
2746 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2747 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2748 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2749 n = mono_string_to_utf8 (tb->name);
2750 if (strcmp (n, "Object") == 0)
2752 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2754 n = mono_string_to_utf8 (tb->nspace);
2755 if (strcmp (n, "System") == 0)
2757 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2759 if (tb->parent && !(is_system && is_object) &&
2760 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2761 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2763 values [MONO_TYPEDEF_EXTENDS] = 0;
2765 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2766 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2769 * if we have explicitlayout or sequentiallayouts, output data in the
2770 * ClassLayout table.
2772 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2773 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2774 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2776 alloc_table (table, table->rows);
2777 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2778 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2779 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2780 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2783 /* handle interfaces */
2784 if (tb->interfaces) {
2785 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2787 table->rows += mono_array_length (tb->interfaces);
2788 alloc_table (table, table->rows);
2789 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2790 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2791 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2792 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2793 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2794 values += MONO_INTERFACEIMPL_SIZE;
2800 table = &assembly->tables [MONO_TABLE_FIELD];
2801 table->rows += tb->num_fields;
2802 alloc_table (table, table->rows);
2803 for (i = 0; i < tb->num_fields; ++i)
2804 mono_image_get_field_info (
2805 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2808 /* handle constructors */
2810 table = &assembly->tables [MONO_TABLE_METHOD];
2811 table->rows += mono_array_length (tb->ctors);
2812 alloc_table (table, table->rows);
2813 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2814 mono_image_get_ctor_info (domain,
2815 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2818 /* handle methods */
2820 table = &assembly->tables [MONO_TABLE_METHOD];
2821 table->rows += tb->num_methods;
2822 alloc_table (table, table->rows);
2823 for (i = 0; i < tb->num_methods; ++i)
2824 mono_image_get_method_info (
2825 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2828 /* Do the same with properties etc.. */
2829 if (tb->events && mono_array_length (tb->events)) {
2830 table = &assembly->tables [MONO_TABLE_EVENT];
2831 table->rows += mono_array_length (tb->events);
2832 alloc_table (table, table->rows);
2833 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2835 alloc_table (table, table->rows);
2836 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2837 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2838 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2839 for (i = 0; i < mono_array_length (tb->events); ++i)
2840 mono_image_get_event_info (
2841 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2843 if (tb->properties && mono_array_length (tb->properties)) {
2844 table = &assembly->tables [MONO_TABLE_PROPERTY];
2845 table->rows += mono_array_length (tb->properties);
2846 alloc_table (table, table->rows);
2847 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2849 alloc_table (table, table->rows);
2850 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2851 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2852 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2853 for (i = 0; i < mono_array_length (tb->properties); ++i)
2854 mono_image_get_property_info (
2855 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2858 /* handle generic parameters */
2859 if (tb->generic_params) {
2860 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2861 table->rows += mono_array_length (tb->generic_params);
2862 alloc_table (table, table->rows);
2863 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2864 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2866 mono_image_get_generic_param_info (
2867 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2871 mono_image_add_decl_security (assembly,
2872 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2875 MonoDynamicTable *ntable;
2877 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2878 ntable->rows += mono_array_length (tb->subtypes);
2879 alloc_table (ntable, ntable->rows);
2880 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2882 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2883 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2885 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2886 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2887 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2888 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2889 mono_string_to_utf8 (tb->name), tb->table_idx,
2890 ntable->next_idx, ntable->rows);*/
2891 values += MONO_NESTED_CLASS_SIZE;
2898 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2902 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2904 if (!type->subtypes)
2907 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2908 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2909 collect_types (types, subtype);
2914 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2916 if ((*type1)->table_idx < (*type2)->table_idx)
2919 if ((*type1)->table_idx > (*type2)->table_idx)
2926 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2931 for (i = 0; i < mono_array_length (pinfo); ++i) {
2932 MonoReflectionParamBuilder *pb;
2933 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2936 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2941 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2944 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2946 for (i = 0; i < tb->num_fields; ++i) {
2947 MonoReflectionFieldBuilder* fb;
2948 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2949 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2953 for (i = 0; i < mono_array_length (tb->events); ++i) {
2954 MonoReflectionEventBuilder* eb;
2955 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2956 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2959 if (tb->properties) {
2960 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2961 MonoReflectionPropertyBuilder* pb;
2962 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2963 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2967 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2968 MonoReflectionCtorBuilder* cb;
2969 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2970 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2971 params_add_cattrs (assembly, cb->pinfo);
2976 for (i = 0; i < tb->num_methods; ++i) {
2977 MonoReflectionMethodBuilder* mb;
2978 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2979 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2980 params_add_cattrs (assembly, mb->pinfo);
2985 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2986 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2991 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
2995 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
2997 if (moduleb->global_methods) {
2998 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2999 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3000 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3001 params_add_cattrs (assembly, mb->pinfo);
3005 if (moduleb->global_fields) {
3006 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3007 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3008 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3012 if (moduleb->types) {
3013 for (i = 0; i < moduleb->num_types; ++i)
3014 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3019 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3021 MonoDynamicTable *table;
3025 char *b = blob_size;
3028 table = &assembly->tables [MONO_TABLE_FILE];
3030 alloc_table (table, table->rows);
3031 values = table->values + table->next_idx * MONO_FILE_SIZE;
3032 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3033 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3034 if (module->image->dynamic) {
3035 /* This depends on the fact that the main module is emitted last */
3036 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3037 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3040 path = g_strdup (module->image->name);
3042 mono_sha1_get_digest_from_file (path, hash);
3045 mono_metadata_encode_value (20, b, &b);
3046 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3047 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3052 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3054 MonoDynamicTable *table;
3057 table = &assembly->tables [MONO_TABLE_MODULE];
3058 mb->table_idx = table->next_idx ++;
3059 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3060 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3063 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3064 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3065 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3066 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3070 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3071 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3073 MonoDynamicTable *table;
3077 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3078 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3081 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3083 alloc_table (table, table->rows);
3084 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3086 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3087 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3088 if (klass->nested_in)
3089 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3091 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3092 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3093 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3095 res = table->next_idx;
3099 /* Emit nested types */
3100 if (klass->nested_classes) {
3103 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3104 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3111 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3112 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3117 klass = mono_class_from_mono_type (tb->type.type);
3119 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3121 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3122 parent_index, assembly);
3126 * We need to do this ourselves since klass->nested_classes is not set up.
3129 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3130 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3135 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3136 guint32 module_index, MonoDynamicImage *assembly)
3138 MonoImage *image = module->image;
3142 t = &image->tables [MONO_TABLE_TYPEDEF];
3144 for (i = 0; i < t->rows; ++i) {
3145 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3147 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3148 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3153 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3155 MonoDynamicTable *table;
3161 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3163 if (assemblyb->type_forwarders) {
3164 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3165 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3171 klass = mono_class_from_mono_type (t->type);
3173 scope = resolution_scope_from_image (assembly, klass->image);
3174 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3175 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3178 alloc_table (table, table->rows);
3179 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3181 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3182 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3183 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3184 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3185 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3190 #define align_pointer(base,p)\
3192 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3194 (p) += 4 - (__diff & 3);\
3198 compare_constants (const void *a, const void *b)
3200 const guint32 *a_values = a;
3201 const guint32 *b_values = b;
3202 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3206 compare_semantics (const void *a, const void *b)
3208 const guint32 *a_values = a;
3209 const guint32 *b_values = b;
3210 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3213 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3217 compare_custom_attrs (const void *a, const void *b)
3219 const guint32 *a_values = a;
3220 const guint32 *b_values = b;
3222 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3226 compare_field_marshal (const void *a, const void *b)
3228 const guint32 *a_values = a;
3229 const guint32 *b_values = b;
3231 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3235 compare_nested (const void *a, const void *b)
3237 const guint32 *a_values = a;
3238 const guint32 *b_values = b;
3240 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3244 compare_genericparam (const void *a, const void *b)
3246 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3247 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3249 if ((*b_entry)->owner == (*a_entry)->owner)
3251 (*a_entry)->gparam->type.type->data.generic_param->num -
3252 (*b_entry)->gparam->type.type->data.generic_param->num;
3254 return (*a_entry)->owner - (*b_entry)->owner;
3258 compare_declsecurity_attrs (const void *a, const void *b)
3260 const guint32 *a_values = a;
3261 const guint32 *b_values = b;
3263 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3267 pad_heap (MonoDynamicStream *sh)
3269 if (sh->index & 3) {
3270 int sz = 4 - (sh->index & 3);
3271 memset (sh->data + sh->index, 0, sz);
3278 MonoDynamicStream *stream;
3282 * build_compressed_metadata() fills in the blob of data that represents the
3283 * raw metadata as it will be saved in the PE file. The five streams are output
3284 * and the metadata tables are comnpressed from the guint32 array representation,
3285 * to the compressed on-disk format.
3288 build_compressed_metadata (MonoDynamicImage *assembly)
3290 MonoDynamicTable *table;
3292 guint64 valid_mask = 0;
3293 guint64 sorted_mask;
3294 guint32 heapt_size = 0;
3295 guint32 meta_size = 256; /* allow for header and other stuff */
3296 guint32 table_offset;
3297 guint32 ntables = 0;
3303 struct StreamDesc stream_desc [5];
3305 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3306 for (i = 0; i < assembly->gen_params->len; i++){
3307 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3308 write_generic_param_entry (assembly, entry);
3311 stream_desc [0].name = "#~";
3312 stream_desc [0].stream = &assembly->tstream;
3313 stream_desc [1].name = "#Strings";
3314 stream_desc [1].stream = &assembly->sheap;
3315 stream_desc [2].name = "#US";
3316 stream_desc [2].stream = &assembly->us;
3317 stream_desc [3].name = "#Blob";
3318 stream_desc [3].stream = &assembly->blob;
3319 stream_desc [4].name = "#GUID";
3320 stream_desc [4].stream = &assembly->guid;
3322 /* tables that are sorted */
3323 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3324 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3325 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3326 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3327 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3328 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3330 /* Compute table sizes */
3331 /* the MonoImage has already been created in mono_image_basic_init() */
3332 meta = &assembly->image;
3334 /* sizes should be multiple of 4 */
3335 pad_heap (&assembly->blob);
3336 pad_heap (&assembly->guid);
3337 pad_heap (&assembly->sheap);
3338 pad_heap (&assembly->us);
3340 /* Setup the info used by compute_sizes () */
3341 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3342 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3343 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3345 meta_size += assembly->blob.index;
3346 meta_size += assembly->guid.index;
3347 meta_size += assembly->sheap.index;
3348 meta_size += assembly->us.index;
3350 for (i=0; i < MONO_TABLE_NUM; ++i)
3351 meta->tables [i].rows = assembly->tables [i].rows;
3353 for (i = 0; i < MONO_TABLE_NUM; i++){
3354 if (meta->tables [i].rows == 0)
3356 valid_mask |= (guint64)1 << i;
3358 meta->tables [i].row_size = mono_metadata_compute_size (
3359 meta, i, &meta->tables [i].size_bitfield);
3360 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3362 heapt_size += 24; /* #~ header size */
3363 heapt_size += ntables * 4;
3364 /* make multiple of 4 */
3367 meta_size += heapt_size;
3368 meta->raw_metadata = g_malloc0 (meta_size);
3369 p = (unsigned char*)meta->raw_metadata;
3370 /* the metadata signature */
3371 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3372 /* version numbers and 4 bytes reserved */
3373 int16val = (guint16*)p;
3374 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3375 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3377 /* version string */
3378 int32val = (guint32*)p;
3379 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3381 memcpy (p, meta->version, strlen (meta->version));
3382 p += GUINT32_FROM_LE (*int32val);
3383 align_pointer (meta->raw_metadata, p);
3384 int16val = (guint16*)p;
3385 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3386 *int16val = GUINT16_TO_LE (5); /* number of streams */
3390 * write the stream info.
3392 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3393 table_offset += 3; table_offset &= ~3;
3395 assembly->tstream.index = heapt_size;
3396 for (i = 0; i < 5; ++i) {
3397 int32val = (guint32*)p;
3398 stream_desc [i].stream->offset = table_offset;
3399 *int32val++ = GUINT32_TO_LE (table_offset);
3400 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3401 table_offset += GUINT32_FROM_LE (*int32val);
3402 table_offset += 3; table_offset &= ~3;
3404 strcpy ((char*)p, stream_desc [i].name);
3405 p += strlen (stream_desc [i].name) + 1;
3406 align_pointer (meta->raw_metadata, p);
3409 * now copy the data, the table stream header and contents goes first.
3411 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3412 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3413 int32val = (guint32*)p;
3414 *int32val = GUINT32_TO_LE (0); /* reserved */
3417 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3418 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3419 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3420 *p++ = 2; /* version */
3423 *p++ = 1; /* version */
3427 if (meta->idx_string_wide)
3429 if (meta->idx_guid_wide)
3431 if (meta->idx_blob_wide)
3434 *p++ = 1; /* reserved */
3435 int64val = (guint64*)p;
3436 *int64val++ = GUINT64_TO_LE (valid_mask);
3437 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3439 int32val = (guint32*)p;
3440 for (i = 0; i < MONO_TABLE_NUM; i++){
3441 if (meta->tables [i].rows == 0)
3443 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3445 p = (unsigned char*)int32val;
3447 /* sort the tables that still need sorting */
3448 table = &assembly->tables [MONO_TABLE_CONSTANT];
3450 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3451 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3453 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3454 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3456 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3457 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3459 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3460 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3462 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3463 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3464 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3466 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3468 /* compress the tables */
3469 for (i = 0; i < MONO_TABLE_NUM; i++){
3472 guint32 bitfield = meta->tables [i].size_bitfield;
3473 if (!meta->tables [i].rows)
3475 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3476 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3477 meta->tables [i].base = (char*)p;
3478 for (row = 1; row <= meta->tables [i].rows; ++row) {
3479 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3480 for (col = 0; col < assembly->tables [i].columns; ++col) {
3481 switch (mono_metadata_table_size (bitfield, col)) {
3483 *p++ = values [col];
3486 *p++ = values [col] & 0xff;
3487 *p++ = (values [col] >> 8) & 0xff;
3490 *p++ = values [col] & 0xff;
3491 *p++ = (values [col] >> 8) & 0xff;
3492 *p++ = (values [col] >> 16) & 0xff;
3493 *p++ = (values [col] >> 24) & 0xff;
3496 g_assert_not_reached ();
3500 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3503 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3504 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3505 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3506 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3507 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3509 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3513 * Some tables in metadata need to be sorted according to some criteria, but
3514 * when methods and fields are first created with reflection, they may be assigned a token
3515 * that doesn't correspond to the final token they will get assigned after the sorting.
3516 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3517 * with the reflection objects that represent them. Once all the tables are set up, the
3518 * reflection objects will contains the correct table index. fixup_method() will fixup the
3519 * tokens for the method with ILGenerator @ilgen.
3522 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3523 guint32 code_idx = GPOINTER_TO_UINT (value);
3524 MonoReflectionILTokenInfo *iltoken;
3525 MonoReflectionFieldBuilder *field;
3526 MonoReflectionCtorBuilder *ctor;
3527 MonoReflectionMethodBuilder *method;
3528 MonoReflectionTypeBuilder *tb;
3529 MonoReflectionArrayMethod *am;
3531 unsigned char *target;
3533 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3534 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3535 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3536 switch (target [3]) {
3537 case MONO_TABLE_FIELD:
3538 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3539 field = (MonoReflectionFieldBuilder *)iltoken->member;
3540 idx = field->table_idx;
3541 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3542 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3543 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3545 g_assert_not_reached ();
3548 case MONO_TABLE_METHOD:
3549 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3550 method = (MonoReflectionMethodBuilder *)iltoken->member;
3551 idx = method->table_idx;
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3553 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3554 idx = ctor->table_idx;
3555 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3556 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3557 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3558 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3560 g_assert_not_reached ();
3563 case MONO_TABLE_TYPEDEF:
3564 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3565 g_assert_not_reached ();
3566 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3567 idx = tb->table_idx;
3569 case MONO_TABLE_MEMBERREF:
3570 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3571 am = (MonoReflectionArrayMethod*)iltoken->member;
3572 idx = am->table_idx;
3573 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3574 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3575 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3576 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3577 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3578 g_assert (m->klass->generic_class || m->klass->generic_container);
3580 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3582 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3583 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3584 g_assert (f->generic_info);
3586 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3589 g_assert_not_reached ();
3592 case MONO_TABLE_METHODSPEC:
3593 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3594 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3595 g_assert (mono_method_signature (m)->generic_param_count);
3598 g_assert_not_reached ();
3602 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3604 target [0] = idx & 0xff;
3605 target [1] = (idx >> 8) & 0xff;
3606 target [2] = (idx >> 16) & 0xff;
3613 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3614 * value is not known when the table is emitted.
3617 fixup_cattrs (MonoDynamicImage *assembly)
3619 MonoDynamicTable *table;
3621 guint32 type, i, idx, token;
3624 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3626 for (i = 0; i < table->rows; ++i) {
3627 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3629 type = values [MONO_CUSTOM_ATTR_TYPE];
3630 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3631 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3632 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3633 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3636 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3637 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3638 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3639 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3646 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3648 MonoDynamicTable *table;
3651 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3653 alloc_table (table, table->rows);
3654 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3655 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3656 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3657 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3658 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3663 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3665 MonoDynamicTable *table;
3669 char *b = blob_size;
3671 guint32 idx, offset;
3673 if (rsrc->filename) {
3674 name = mono_string_to_utf8 (rsrc->filename);
3675 sname = g_path_get_basename (name);
3677 table = &assembly->tables [MONO_TABLE_FILE];
3679 alloc_table (table, table->rows);
3680 values = table->values + table->next_idx * MONO_FILE_SIZE;
3681 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3682 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3685 mono_sha1_get_digest_from_file (name, hash);
3686 mono_metadata_encode_value (20, b, &b);
3687 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3688 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3690 idx = table->next_idx++;
3692 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3698 data = mono_array_addr (rsrc->data, char, 0);
3699 len = mono_array_length (rsrc->data);
3705 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3706 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3707 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3708 mono_image_add_stream_data (&assembly->resources, data, len);
3712 * The entry should be emitted into the MANIFESTRESOURCE table of
3713 * the main module, but that needs to reference the FILE table
3714 * which isn't emitted yet.
3721 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3725 set_version_from_string (MonoString *version, guint32 *values)
3727 gchar *ver, *p, *str;
3730 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3731 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3732 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3733 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3736 ver = str = mono_string_to_utf8 (version);
3737 for (i = 0; i < 4; ++i) {
3738 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3744 /* handle Revision and Build */
3754 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3758 char *b = blob_size;
3763 len = mono_array_length (pkey);
3764 mono_metadata_encode_value (len, b, &b);
3765 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3766 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3768 /* Special case: check for ECMA key (16 bytes) */
3769 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3770 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3771 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3772 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3773 /* minimum key size (in 2.0) is 384 bits */
3774 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3776 /* FIXME - verifier */
3777 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3778 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3780 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3786 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3788 MonoDynamicTable *table;
3789 MonoDynamicImage *assembly;
3790 MonoReflectionAssemblyBuilder *assemblyb;
3794 guint32 module_index;
3796 assemblyb = moduleb->assemblyb;
3797 assembly = moduleb->dynamic_image;
3798 domain = mono_object_domain (assemblyb);
3800 /* Emit ASSEMBLY table */
3801 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3802 alloc_table (table, 1);
3803 values = table->values + MONO_ASSEMBLY_SIZE;
3804 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3805 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3806 if (assemblyb->culture) {
3807 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3809 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3811 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3812 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3813 set_version_from_string (assemblyb->version, values);
3815 /* Emit FILE + EXPORTED_TYPE table */
3817 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3819 MonoReflectionModuleBuilder *file_module =
3820 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3821 if (file_module != moduleb) {
3822 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3824 if (file_module->types) {
3825 for (j = 0; j < file_module->num_types; ++j) {
3826 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3827 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3832 if (assemblyb->loaded_modules) {
3833 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3834 MonoReflectionModule *file_module =
3835 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3836 mono_image_fill_file_table (domain, file_module, assembly);
3838 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3841 if (assemblyb->type_forwarders)
3842 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3844 /* Emit MANIFESTRESOURCE table */
3846 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3848 MonoReflectionModuleBuilder *file_module =
3849 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3850 /* The table for the main module is emitted later */
3851 if (file_module != moduleb) {
3853 if (file_module->resources) {
3854 int len = mono_array_length (file_module->resources);
3855 for (j = 0; j < len; ++j) {
3856 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3857 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3865 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3866 * for the modulebuilder @moduleb.
3867 * At the end of the process, method and field tokens are fixed up and the
3868 * on-disk compressed metadata representation is created.
3871 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3873 MonoDynamicTable *table;
3874 MonoDynamicImage *assembly;
3875 MonoReflectionAssemblyBuilder *assemblyb;
3881 assemblyb = moduleb->assemblyb;
3882 assembly = moduleb->dynamic_image;
3883 domain = mono_object_domain (assemblyb);
3885 if (assembly->text_rva)
3888 assembly->text_rva = START_TEXT_RVA;
3890 if (moduleb->is_main) {
3891 mono_image_emit_manifest (moduleb);
3894 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3895 table->rows = 1; /* .<Module> */
3897 alloc_table (table, table->rows);
3899 * Set the first entry.
3901 values = table->values + table->columns;
3902 values [MONO_TYPEDEF_FLAGS] = 0;
3903 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3904 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3905 values [MONO_TYPEDEF_EXTENDS] = 0;
3906 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3907 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3910 * handle global methods
3911 * FIXME: test what to do when global methods are defined in multiple modules.
3913 if (moduleb->global_methods) {
3914 table = &assembly->tables [MONO_TABLE_METHOD];
3915 table->rows += mono_array_length (moduleb->global_methods);
3916 alloc_table (table, table->rows);
3917 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3918 mono_image_get_method_info (
3919 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3921 if (moduleb->global_fields) {
3922 table = &assembly->tables [MONO_TABLE_FIELD];
3923 table->rows += mono_array_length (moduleb->global_fields);
3924 alloc_table (table, table->rows);
3925 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3926 mono_image_get_field_info (
3927 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3930 table = &assembly->tables [MONO_TABLE_MODULE];
3931 alloc_table (table, 1);
3932 mono_image_fill_module_table (domain, moduleb, assembly);
3934 /* Collect all types into a list sorted by their table_idx */
3935 types = g_ptr_array_new ();
3938 for (i = 0; i < moduleb->num_types; ++i) {
3939 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3940 collect_types (types, type);
3943 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3944 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3945 table->rows += types->len;
3946 alloc_table (table, table->rows);
3949 * Emit type names + namespaces at one place inside the string heap,
3950 * so load_class_names () needs to touch fewer pages.
3952 for (i = 0; i < types->len; ++i) {
3953 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3954 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3956 for (i = 0; i < types->len; ++i) {
3957 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3958 string_heap_insert_mstring (&assembly->sheap, tb->name);
3961 for (i = 0; i < types->len; ++i) {
3962 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3963 mono_image_get_type_info (domain, type, assembly);
3967 * table->rows is already set above and in mono_image_fill_module_table.
3969 /* add all the custom attributes at the end, once all the indexes are stable */
3970 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3972 /* CAS assembly permissions */
3973 if (assemblyb->permissions_minimum)
3974 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3975 if (assemblyb->permissions_optional)
3976 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3977 if (assemblyb->permissions_refused)
3978 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3980 module_add_cattrs (assembly, moduleb);
3983 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3985 /* Create the MethodImpl table. We do this after emitting all methods so we already know
3986 * the final tokens and don't need another fixup pass. */
3988 if (moduleb->global_methods) {
3989 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3990 MonoReflectionMethodBuilder *mb = mono_array_get (
3991 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3992 mono_image_add_methodimpl (assembly, mb);
3996 for (i = 0; i < types->len; ++i) {
3997 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3998 if (type->methods) {
3999 for (j = 0; j < type->num_methods; ++j) {
4000 MonoReflectionMethodBuilder *mb = mono_array_get (
4001 type->methods, MonoReflectionMethodBuilder*, j);
4003 mono_image_add_methodimpl (assembly, mb);
4008 g_ptr_array_free (types, TRUE);
4010 fixup_cattrs (assembly);
4014 * mono_image_insert_string:
4015 * @module: module builder object
4018 * Insert @str into the user string stream of @module.
4021 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4023 MonoDynamicImage *assembly;
4028 MONO_ARCH_SAVE_REGS;
4030 if (!module->dynamic_image)
4031 mono_image_module_basic_init (module);
4033 assembly = module->dynamic_image;
4035 if (assembly->save) {
4036 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4037 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4038 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4040 char *swapped = g_malloc (2 * mono_string_length (str));
4041 const char *p = (const char*)mono_string_chars (str);
4043 swap_with_size (swapped, p, 2, mono_string_length (str));
4044 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4048 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4050 mono_image_add_stream_data (&assembly->us, "", 1);
4052 idx = assembly->us.index ++;
4055 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4057 return MONO_TOKEN_STRING | idx;
4061 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4066 klass = obj->vtable->klass;
4067 if (strcmp (klass->name, "MonoMethod") == 0) {
4068 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4069 MonoMethodSignature *sig, *old;
4070 guint32 sig_token, parent;
4073 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4075 nargs = mono_array_length (opt_param_types);
4076 old = mono_method_signature (method);
4077 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4079 sig->hasthis = old->hasthis;
4080 sig->explicit_this = old->explicit_this;
4081 sig->call_convention = old->call_convention;
4082 sig->generic_param_count = old->generic_param_count;
4083 sig->param_count = old->param_count + nargs;
4084 sig->sentinelpos = old->param_count;
4085 sig->ret = old->ret;
4087 for (i = 0; i < old->param_count; i++)
4088 sig->params [i] = old->params [i];
4090 for (i = 0; i < nargs; i++) {
4091 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4092 sig->params [old->param_count + i] = rt->type;
4095 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4096 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4097 parent >>= MONO_TYPEDEFORREF_BITS;
4099 parent <<= MONO_MEMBERREF_PARENT_BITS;
4100 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4102 sig_token = method_encode_signature (assembly, sig);
4103 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4104 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4105 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4106 ReflectionMethodBuilder rmb;
4107 guint32 parent, sig;
4109 reflection_methodbuilder_from_method_builder (&rmb, mb);
4110 rmb.opt_types = opt_param_types;
4112 sig = method_builder_encode_signature (assembly, &rmb);
4114 parent = mono_image_create_token (assembly, obj, TRUE);
4115 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4117 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4118 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4120 token = mono_image_get_varargs_method_token (
4121 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4123 g_error ("requested method token for %s\n", klass->name);
4130 * mono_image_create_token:
4131 * @assembly: a dynamic assembly
4134 * Get a token to insert in the IL code stream for the given MemberInfo.
4135 * @obj can be one of:
4136 * ConstructorBuilder
4146 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4151 klass = obj->vtable->klass;
4152 if (strcmp (klass->name, "MethodBuilder") == 0) {
4153 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4155 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4156 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4158 token = mono_image_get_methodbuilder_token (assembly, mb);
4159 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4160 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4161 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4163 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4164 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4166 token = mono_image_get_ctorbuilder_token (assembly, mb);
4167 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4168 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4169 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4170 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4171 if (tb->generic_params) {
4172 token = mono_image_get_generic_field_token (assembly, fb);
4174 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4176 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4177 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4178 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4179 } else if (strcmp (klass->name, "MonoType") == 0 ||
4180 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4181 MonoReflectionType *tb = (MonoReflectionType *)obj;
4182 token = mono_metadata_token_from_dor (
4183 mono_image_typedef_or_ref (assembly, tb->type));
4184 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4185 MonoReflectionType *tb = (MonoReflectionType *)obj;
4186 token = mono_metadata_token_from_dor (
4187 mono_image_typedef_or_ref (assembly, tb->type));
4188 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4189 strcmp (klass->name, "MonoMethod") == 0 ||
4190 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4191 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4192 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4193 if (m->method->is_inflated) {
4194 if (create_methodspec)
4195 token = mono_image_get_methodspec_token (assembly, m->method);
4197 token = mono_image_get_inflated_method_token (assembly, m->method);
4198 } else if ((m->method->klass->image == &assembly->image) &&
4199 !m->method->klass->generic_class) {
4200 static guint32 method_table_idx = 0xffffff;
4201 if (m->method->klass->wastypebuilder) {
4202 /* we use the same token as the one that was assigned
4203 * to the Methodbuilder.
4204 * FIXME: do the equivalent for Fields.
4206 token = m->method->token;
4209 * Each token should have a unique index, but the indexes are
4210 * assigned by managed code, so we don't know about them. An
4211 * easy solution is to count backwards...
4213 method_table_idx --;
4214 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4217 token = mono_image_get_methodref_token (assembly, m->method);
4219 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4220 } else if (strcmp (klass->name, "MonoField") == 0) {
4221 MonoReflectionField *f = (MonoReflectionField *)obj;
4222 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4223 static guint32 field_table_idx = 0xffffff;
4225 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4227 token = mono_image_get_fieldref_token (assembly, f);
4229 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4230 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4231 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4232 token = mono_image_get_array_token (assembly, m);
4233 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4234 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4235 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4236 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4237 MonoReflectionType *tb = (MonoReflectionType *)obj;
4238 token = mono_metadata_token_from_dor (
4239 mono_image_typedef_or_ref (assembly, tb->type));
4241 g_error ("requested token for %s\n", klass->name);
4244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4250 guint32 import_lookup_table;
4254 guint32 import_address_table_rva;
4262 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4264 static MonoDynamicImage*
4265 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4267 static const guchar entrycode [16] = {0xff, 0x25, 0};
4268 MonoDynamicImage *image;
4271 const char *version = mono_get_runtime_info ()->runtime_version;
4274 image = GC_MALLOC (sizeof (MonoDynamicImage));
4276 image = g_new0 (MonoDynamicImage, 1);
4279 /*g_print ("created image %p\n", image);*/
4280 /* keep in sync with image.c */
4281 image->image.name = assembly_name;
4282 image->image.assembly_name = image->image.name; /* they may be different */
4283 image->image.module_name = module_name;
4284 image->image.version = g_strdup (version);
4285 image->image.md_version_major = 1;
4286 image->image.md_version_minor = 1;
4287 image->image.dynamic = TRUE;
4289 image->image.references = g_new0 (MonoAssembly*, 1);
4290 image->image.references [0] = NULL;
4292 mono_image_init (&image->image);
4294 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4295 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4296 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4297 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4298 image->handleref = g_hash_table_new (NULL, NULL);
4299 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4300 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4301 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4302 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4303 image->gen_params = g_ptr_array_new ();
4305 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4306 string_heap_init (&image->sheap);
4307 mono_image_add_stream_data (&image->us, "", 1);
4308 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4309 /* import tables... */
4310 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4311 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4312 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4313 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4314 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4315 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4316 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4317 stream_data_align (&image->code);
4319 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4321 for (i=0; i < MONO_TABLE_NUM; ++i) {
4322 image->tables [i].next_idx = 1;
4323 image->tables [i].columns = table_sizes [i];
4326 image->image.assembly = (MonoAssembly*)assembly;
4327 image->run = assembly->run;
4328 image->save = assembly->save;
4329 image->pe_kind = 0x1; /* ILOnly */
4330 image->machine = 0x14c; /* I386 */
4336 * mono_image_basic_init:
4337 * @assembly: an assembly builder object
4339 * Create the MonoImage that represents the assembly builder and setup some
4340 * of the helper hash table and the basic metadata streams.
4343 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4345 MonoDynamicAssembly *assembly;
4346 MonoDynamicImage *image;
4347 MonoDomain *domain = mono_object_domain (assemblyb);
4349 MONO_ARCH_SAVE_REGS;
4351 if (assemblyb->dynamic_assembly)
4355 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4357 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4360 assembly->assembly.ref_count = 1;
4361 assembly->assembly.dynamic = TRUE;
4362 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4363 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4364 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4365 if (assemblyb->culture)
4366 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4368 assembly->assembly.aname.culture = g_strdup ("");
4370 if (assemblyb->version) {
4371 char *vstr = mono_string_to_utf8 (assemblyb->version);
4372 char **version = g_strsplit (vstr, ".", 4);
4373 char **parts = version;
4374 assembly->assembly.aname.major = atoi (*parts++);
4375 assembly->assembly.aname.minor = atoi (*parts++);
4376 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4377 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4379 g_strfreev (version);
4382 assembly->assembly.aname.major = 0;
4383 assembly->assembly.aname.minor = 0;
4384 assembly->assembly.aname.build = 0;
4385 assembly->assembly.aname.revision = 0;
4388 assembly->run = assemblyb->access != 2;
4389 assembly->save = assemblyb->access != 1;
4391 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4392 image->initial_image = TRUE;
4393 assembly->assembly.aname.name = image->image.name;
4394 assembly->assembly.image = &image->image;
4396 mono_domain_assemblies_lock (domain);
4397 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4398 mono_domain_assemblies_unlock (domain);
4400 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4401 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4405 calc_section_size (MonoDynamicImage *assembly)
4409 /* alignment constraints */
4410 assembly->code.index += 3;
4411 assembly->code.index &= ~3;
4412 assembly->meta_size += 3;
4413 assembly->meta_size &= ~3;
4414 assembly->resources.index += 3;
4415 assembly->resources.index &= ~3;
4417 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4418 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4421 if (assembly->win32_res) {
4422 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4424 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4425 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4429 assembly->sections [MONO_SECTION_RELOC].size = 12;
4430 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4440 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4444 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4446 ResTreeNode *t1 = (ResTreeNode*)a;
4447 ResTreeNode *t2 = (ResTreeNode*)b;
4449 return t1->id - t2->id;
4453 * resource_tree_create:
4455 * Organize the resources into a resource tree.
4457 static ResTreeNode *
4458 resource_tree_create (MonoArray *win32_resources)
4460 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4464 tree = g_new0 (ResTreeNode, 1);
4466 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4467 MonoReflectionWin32Resource *win32_res =
4468 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4472 /* FIXME: BUG: this stores managed references in unmanaged memory */
4473 lang_node = g_new0 (ResTreeNode, 1);
4474 lang_node->id = win32_res->lang_id;
4475 lang_node->win32_res = win32_res;
4477 /* Create type node if neccesary */
4479 for (l = tree->children; l; l = l->next)
4480 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4481 type_node = (ResTreeNode*)l->data;
4486 type_node = g_new0 (ResTreeNode, 1);
4487 type_node->id = win32_res->res_type;
4490 * The resource types have to be sorted otherwise
4491 * Windows Explorer can't display the version information.
4493 tree->children = g_slist_insert_sorted (tree->children,
4494 type_node, resource_tree_compare_by_id);
4497 /* Create res node if neccesary */
4499 for (l = type_node->children; l; l = l->next)
4500 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4501 res_node = (ResTreeNode*)l->data;
4506 res_node = g_new0 (ResTreeNode, 1);
4507 res_node->id = win32_res->res_id;
4508 type_node->children = g_slist_append (type_node->children, res_node);
4511 res_node->children = g_slist_append (res_node->children, lang_node);
4518 * resource_tree_encode:
4520 * Encode the resource tree into the format used in the PE file.
4523 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4526 MonoPEResourceDir dir;
4527 MonoPEResourceDirEntry dir_entry;
4528 MonoPEResourceDataEntry data_entry;
4532 * For the format of the resource directory, see the article
4533 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4537 memset (&dir, 0, sizeof (dir));
4538 memset (&dir_entry, 0, sizeof (dir_entry));
4539 memset (&data_entry, 0, sizeof (data_entry));
4541 g_assert (sizeof (dir) == 16);
4542 g_assert (sizeof (dir_entry) == 8);
4543 g_assert (sizeof (data_entry) == 16);
4545 node->offset = p - begin;
4547 /* IMAGE_RESOURCE_DIRECTORY */
4548 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4550 memcpy (p, &dir, sizeof (dir));
4553 /* Reserve space for entries */
4555 p += sizeof (dir_entry) * dir.res_id_entries;
4557 /* Write children */
4558 for (l = node->children; l; l = l->next) {
4559 ResTreeNode *child = (ResTreeNode*)l->data;
4561 if (child->win32_res) {
4563 child->offset = p - begin;
4565 /* IMAGE_RESOURCE_DATA_ENTRY */
4566 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4567 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4569 memcpy (p, &data_entry, sizeof (data_entry));
4570 p += sizeof (data_entry);
4572 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4573 p += data_entry.rde_size;
4575 resource_tree_encode (child, begin, p, &p);
4579 /* IMAGE_RESOURCE_ENTRY */
4580 for (l = node->children; l; l = l->next) {
4581 ResTreeNode *child = (ResTreeNode*)l->data;
4582 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4584 dir_entry.is_dir = child->win32_res ? 0 : 1;
4585 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4587 memcpy (entries, &dir_entry, sizeof (dir_entry));
4588 entries += sizeof (dir_entry);
4595 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4600 MonoReflectionWin32Resource *win32_res;
4603 if (!assemblyb->win32_resources)
4607 * Resources are stored in a three level tree inside the PE file.
4608 * - level one contains a node for each type of resource
4609 * - level two contains a node for each resource
4610 * - level three contains a node for each instance of a resource for a
4611 * specific language.
4614 tree = resource_tree_create (assemblyb->win32_resources);
4616 /* Estimate the size of the encoded tree */
4618 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4619 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4620 size += mono_array_length (win32_res->res_data);
4622 /* Directory structure */
4623 size += mono_array_length (assemblyb->win32_resources) * 256;
4624 p = buf = g_malloc (size);
4626 resource_tree_encode (tree, p, p, &p);
4628 g_assert (p - buf <= size);
4630 assembly->win32_res = g_malloc (p - buf);
4631 assembly->win32_res_size = p - buf;
4632 memcpy (assembly->win32_res, buf, p - buf);
4638 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4640 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4643 p += sizeof (MonoPEResourceDir);
4644 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4645 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4646 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4647 if (dir_entry->is_dir) {
4648 fixup_resource_directory (res_section, child, rva);
4650 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4651 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4654 p += sizeof (MonoPEResourceDirEntry);
4659 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4662 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4663 g_error ("WriteFile returned %d\n", GetLastError ());
4667 * mono_image_create_pefile:
4668 * @mb: a module builder object
4670 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4671 * assembly->pefile where it can be easily retrieved later in chunks.
4674 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4675 MonoMSDOSHeader *msdos;
4676 MonoDotNetHeader *header;
4677 MonoSectionTable *section;
4678 MonoCLIHeader *cli_header;
4679 guint32 size, image_size, virtual_base, text_offset;
4680 guint32 header_start, section_start, file_offset, virtual_offset;
4681 MonoDynamicImage *assembly;
4682 MonoReflectionAssemblyBuilder *assemblyb;
4683 MonoDynamicStream pefile_stream = {0};
4684 MonoDynamicStream *pefile = &pefile_stream;
4686 guint32 *rva, value;
4688 static const unsigned char msheader[] = {
4689 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4690 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4691 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4693 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4694 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4695 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4696 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4699 assemblyb = mb->assemblyb;
4701 mono_image_basic_init (assemblyb);
4702 assembly = mb->dynamic_image;
4704 assembly->pe_kind = assemblyb->pe_kind;
4705 assembly->machine = assemblyb->machine;
4706 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4707 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4709 mono_image_build_metadata (mb);
4711 if (mb->is_main && assemblyb->resources) {
4712 int len = mono_array_length (assemblyb->resources);
4713 for (i = 0; i < len; ++i)
4714 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4717 if (mb->resources) {
4718 int len = mono_array_length (mb->resources);
4719 for (i = 0; i < len; ++i)
4720 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4723 build_compressed_metadata (assembly);
4726 assembly_add_win32_resources (assembly, assemblyb);
4728 nsections = calc_section_size (assembly);
4730 /* The DOS header and stub */
4731 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4732 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4734 /* the dotnet header */
4735 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4737 /* the section tables */
4738 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4740 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4741 virtual_offset = VIRT_ALIGN;
4744 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4745 if (!assembly->sections [i].size)
4748 file_offset += FILE_ALIGN - 1;
4749 file_offset &= ~(FILE_ALIGN - 1);
4750 virtual_offset += VIRT_ALIGN - 1;
4751 virtual_offset &= ~(VIRT_ALIGN - 1);
4753 assembly->sections [i].offset = file_offset;
4754 assembly->sections [i].rva = virtual_offset;
4756 file_offset += assembly->sections [i].size;
4757 virtual_offset += assembly->sections [i].size;
4758 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4761 file_offset += FILE_ALIGN - 1;
4762 file_offset &= ~(FILE_ALIGN - 1);
4764 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4766 /* back-patch info */
4767 msdos = (MonoMSDOSHeader*)pefile->data;
4768 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4770 header = (MonoDotNetHeader*)(pefile->data + header_start);
4771 header->pesig [0] = 'P';
4772 header->pesig [1] = 'E';
4774 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4775 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4776 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4777 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4778 if (assemblyb->pekind == 1) {
4780 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4783 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4786 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4788 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4789 header->pe.pe_major = 6;
4790 header->pe.pe_minor = 0;
4791 size = assembly->sections [MONO_SECTION_TEXT].size;
4792 size += FILE_ALIGN - 1;
4793 size &= ~(FILE_ALIGN - 1);
4794 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4795 size = assembly->sections [MONO_SECTION_RSRC].size;
4796 size += FILE_ALIGN - 1;
4797 size &= ~(FILE_ALIGN - 1);
4798 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4799 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4800 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4801 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4802 /* pe_rva_entry_point always at the beginning of the text section */
4803 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4805 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4806 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4807 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4808 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4809 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4810 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4811 size = section_start;
4812 size += FILE_ALIGN - 1;
4813 size &= ~(FILE_ALIGN - 1);
4814 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4816 size += VIRT_ALIGN - 1;
4817 size &= ~(VIRT_ALIGN - 1);
4818 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4821 // Translate the PEFileKind value to the value expected by the Windows loader
4827 // PEFileKinds.Dll == 1
4828 // PEFileKinds.ConsoleApplication == 2
4829 // PEFileKinds.WindowApplication == 3
4832 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4833 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4835 if (assemblyb->pekind == 3)
4840 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4842 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4843 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4844 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4845 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4846 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4847 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4849 /* fill data directory entries */
4851 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4852 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4854 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4855 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4857 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4858 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4859 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4860 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4861 /* patch entrypoint name */
4862 if (assemblyb->pekind == 1)
4863 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4865 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4866 /* patch imported function RVA name */
4867 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4868 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4870 /* the import table */
4871 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4872 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4873 /* patch imported dll RVA name and other entries in the dir */
4874 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4875 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4876 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4877 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4878 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4879 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4881 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4882 value = (assembly->text_rva + assembly->imp_names_offset);
4883 *p++ = (value) & 0xff;
4884 *p++ = (value >> 8) & (0xff);
4885 *p++ = (value >> 16) & (0xff);
4886 *p++ = (value >> 24) & (0xff);
4888 /* the CLI header info */
4889 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4890 cli_header->ch_size = GUINT32_FROM_LE (72);
4891 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4892 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4893 if (assemblyb->entry_point) {
4894 guint32 table_idx = 0;
4895 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4896 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4897 table_idx = methodb->table_idx;
4899 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4901 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4903 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4905 /* The embedded managed resources */
4906 text_offset = assembly->text_rva + assembly->code.index;
4907 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4908 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4909 text_offset += assembly->resources.index;
4910 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4911 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4912 text_offset += assembly->meta_size;
4913 if (assembly->strong_name_size) {
4914 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4915 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4916 text_offset += assembly->strong_name_size;
4919 /* write the section tables and section content */
4920 section = (MonoSectionTable*)(pefile->data + section_start);
4921 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4922 static const char section_names [][7] = {
4923 ".text", ".rsrc", ".reloc"
4925 if (!assembly->sections [i].size)
4927 strcpy (section->st_name, section_names [i]);
4928 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4929 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4930 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4931 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4932 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4933 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4934 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4938 checked_write_file (file, pefile->data, pefile->index);
4940 mono_dynamic_stream_reset (pefile);
4942 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4943 if (!assembly->sections [i].size)
4946 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4947 g_error ("SetFilePointer returned %d\n", GetLastError ());
4950 case MONO_SECTION_TEXT:
4951 /* patch entry point */
4952 p = (guchar*)(assembly->code.data + 2);
4953 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4954 *p++ = (value) & 0xff;
4955 *p++ = (value >> 8) & 0xff;
4956 *p++ = (value >> 16) & 0xff;
4957 *p++ = (value >> 24) & 0xff;
4959 checked_write_file (file, assembly->code.data, assembly->code.index);
4960 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4961 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4962 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4965 g_free (assembly->image.raw_metadata);
4967 case MONO_SECTION_RELOC: {
4971 guint16 type_and_offset;
4975 g_assert (sizeof (reloc) == 12);
4977 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4978 reloc.block_size = GUINT32_FROM_LE (12);
4981 * the entrypoint is always at the start of the text section
4982 * 3 is IMAGE_REL_BASED_HIGHLOW
4983 * 2 is patch_size_rva - text_rva
4985 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4988 checked_write_file (file, &reloc, sizeof (reloc));
4992 case MONO_SECTION_RSRC:
4993 if (assembly->win32_res) {
4995 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4996 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4997 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5001 g_assert_not_reached ();
5005 /* check that the file is properly padded */
5006 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5007 g_error ("SetFilePointer returned %d\n", GetLastError ());
5008 if (! SetEndOfFile (file))
5009 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5011 mono_dynamic_stream_reset (&assembly->code);
5012 mono_dynamic_stream_reset (&assembly->us);
5013 mono_dynamic_stream_reset (&assembly->blob);
5014 mono_dynamic_stream_reset (&assembly->guid);
5015 mono_dynamic_stream_reset (&assembly->sheap);
5017 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5018 g_hash_table_destroy (assembly->blob_cache);
5019 assembly->blob_cache = NULL;
5022 MonoReflectionModule *
5023 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5027 MonoImageOpenStatus status;
5028 MonoDynamicAssembly *assembly;
5029 guint32 module_count;
5030 MonoImage **new_modules;
5031 gboolean *new_modules_loaded;
5033 name = mono_string_to_utf8 (fileName);
5035 image = mono_image_open (name, &status);
5038 if (status == MONO_IMAGE_ERROR_ERRNO)
5039 exc = mono_get_exception_file_not_found (fileName);
5041 exc = mono_get_exception_bad_image_format (name);
5043 mono_raise_exception (exc);
5048 assembly = ab->dynamic_assembly;
5049 image->assembly = (MonoAssembly*)assembly;
5051 module_count = image->assembly->image->module_count;
5052 new_modules = g_new0 (MonoImage *, module_count + 1);
5053 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5055 if (image->assembly->image->modules)
5056 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5057 if (image->assembly->image->modules_loaded)
5058 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5059 new_modules [module_count] = image;
5060 new_modules_loaded [module_count] = TRUE;
5061 mono_image_addref (image);
5063 g_free (image->assembly->image->modules);
5064 image->assembly->image->modules = new_modules;
5065 image->assembly->image->modules_loaded = new_modules_loaded;
5066 image->assembly->image->module_count ++;
5068 mono_assembly_load_references (image, &status);
5070 mono_image_close (image);
5071 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5074 return mono_module_get_object (mono_domain_get (), image);
5078 * We need to return always the same object for MethodInfo, FieldInfo etc..
5079 * but we need to consider the reflected type.
5080 * type uses a different hash, since it uses custom hash/equal functions.
5085 MonoClass *refclass;
5089 reflected_equal (gconstpointer a, gconstpointer b) {
5090 const ReflectedEntry *ea = a;
5091 const ReflectedEntry *eb = b;
5093 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5097 reflected_hash (gconstpointer a) {
5098 const ReflectedEntry *ea = a;
5099 return mono_aligned_addr_hash (ea->item);
5102 #define CHECK_OBJECT(t,p,k) \
5108 mono_domain_lock (domain); \
5109 if (!domain->refobject_hash) \
5110 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5111 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5112 mono_domain_unlock (domain); \
5115 mono_domain_unlock (domain); \
5119 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5121 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5123 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5126 #define CACHE_OBJECT(t,p,o,k) \
5129 ReflectedEntry pe; \
5131 pe.refclass = (k); \
5132 mono_domain_lock (domain); \
5133 if (!domain->refobject_hash) \
5134 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5135 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5137 ReflectedEntry *e = ALLOC_REFENTRY; \
5139 e->refclass = (k); \
5140 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5143 mono_domain_unlock (domain); \
5148 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5150 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5154 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5156 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5160 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5162 MonoDynamicImage *image = moduleb->dynamic_image;
5163 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5166 MonoImage **new_modules;
5169 * FIXME: we already created an image in mono_image_basic_init (), but
5170 * we don't know which module it belongs to, since that is only
5171 * determined at assembly save time.
5173 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5174 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5176 moduleb->module.image = &image->image;
5177 moduleb->dynamic_image = image;
5178 register_module (mono_object_domain (moduleb), moduleb, image);
5180 /* register the module with the assembly */
5181 ass = ab->dynamic_assembly->assembly.image;
5182 module_count = ass->module_count;
5183 new_modules = g_new0 (MonoImage *, module_count + 1);
5186 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5187 new_modules [module_count] = &image->image;
5188 mono_image_addref (&image->image);
5190 g_free (ass->modules);
5191 ass->modules = new_modules;
5192 ass->module_count ++;
5197 * mono_assembly_get_object:
5198 * @domain: an app domain
5199 * @assembly: an assembly
5201 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5203 MonoReflectionAssembly*
5204 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5206 static MonoClass *System_Reflection_Assembly;
5207 MonoReflectionAssembly *res;
5209 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5210 if (!System_Reflection_Assembly)
5211 System_Reflection_Assembly = mono_class_from_name (
5212 mono_defaults.corlib, "System.Reflection", "Assembly");
5213 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5214 res->assembly = assembly;
5216 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5221 MonoReflectionModule*
5222 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5224 static MonoClass *System_Reflection_Module;
5225 MonoReflectionModule *res;
5228 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5229 if (!System_Reflection_Module)
5230 System_Reflection_Module = mono_class_from_name (
5231 mono_defaults.corlib, "System.Reflection", "Module");
5232 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5235 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5237 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5238 basename = g_path_get_basename (image->name);
5239 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5240 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5244 if (image->assembly->image == image) {
5245 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5249 if (image->assembly->image->modules) {
5250 for (i = 0; i < image->assembly->image->module_count; i++) {
5251 if (image->assembly->image->modules [i] == image)
5252 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5254 g_assert (res->token);
5258 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5261 MonoReflectionModule*
5262 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5264 static MonoClass *System_Reflection_Module;
5265 MonoReflectionModule *res;
5266 MonoTableInfo *table;
5267 guint32 cols [MONO_FILE_SIZE];
5269 guint32 i, name_idx;
5272 if (!System_Reflection_Module)
5273 System_Reflection_Module = mono_class_from_name (
5274 mono_defaults.corlib, "System.Reflection", "Module");
5275 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5277 table = &image->tables [MONO_TABLE_FILE];
5278 g_assert (table_index < table->rows);
5279 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5282 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5283 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5285 /* Check whenever the row has a corresponding row in the moduleref table */
5286 table = &image->tables [MONO_TABLE_MODULEREF];
5287 for (i = 0; i < table->rows; ++i) {
5288 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5289 val = mono_metadata_string_heap (image, name_idx);
5290 if (strcmp (val, name) == 0)
5291 res->image = image->modules [i];
5294 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5295 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5296 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5297 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5298 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5304 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5306 if ((t1->type != t2->type) ||
5307 (t1->byref != t2->byref))
5311 case MONO_TYPE_VOID:
5312 case MONO_TYPE_BOOLEAN:
5313 case MONO_TYPE_CHAR:
5324 case MONO_TYPE_STRING:
5327 case MONO_TYPE_OBJECT:
5328 case MONO_TYPE_TYPEDBYREF:
5330 case MONO_TYPE_VALUETYPE:
5331 case MONO_TYPE_CLASS:
5332 case MONO_TYPE_SZARRAY:
5333 return t1->data.klass == t2->data.klass;
5335 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5336 case MONO_TYPE_ARRAY:
5337 if (t1->data.array->rank != t2->data.array->rank)
5339 return t1->data.array->eklass == t2->data.array->eklass;
5340 case MONO_TYPE_GENERICINST: {
5342 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5343 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5344 if (i1->type_argc != i2->type_argc)
5346 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5347 &t2->data.generic_class->container_class->byval_arg))
5349 /* FIXME: we should probably just compare the instance pointers directly. */
5350 for (i = 0; i < i1->type_argc; ++i) {
5351 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5357 case MONO_TYPE_MVAR:
5358 return t1->data.generic_param == t2->data.generic_param;
5360 g_error ("implement type compare for %0x!", t1->type);
5368 mymono_metadata_type_hash (MonoType *t1)
5374 hash |= t1->byref << 6; /* do not collide with t1->type values */
5376 case MONO_TYPE_VALUETYPE:
5377 case MONO_TYPE_CLASS:
5378 case MONO_TYPE_SZARRAY:
5379 /* check if the distribution is good enough */
5380 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5382 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5383 case MONO_TYPE_GENERICINST: {
5385 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5386 hash += g_str_hash (t1->data.generic_class->container_class->name);
5388 for (i = 0; i < inst->type_argc; ++i) {
5389 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5398 static MonoReflectionGenericClass*
5399 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5401 static MonoClass *System_Reflection_MonoGenericClass;
5402 MonoReflectionGenericClass *res;
5403 MonoClass *klass, *gklass;
5405 if (!System_Reflection_MonoGenericClass) {
5406 System_Reflection_MonoGenericClass = mono_class_from_name (
5407 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5408 g_assert (System_Reflection_MonoGenericClass);
5411 klass = mono_class_from_mono_type (geninst);
5412 gklass = klass->generic_class->container_class;
5414 mono_class_init (klass);
5417 /* FIXME: allow unpinned later */
5418 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5420 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5423 res->type.type = geninst;
5424 if (gklass->wastypebuilder && gklass->reflection_info)
5425 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5427 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5433 verify_safe_for_managed_space (MonoType *type)
5435 switch (type->type) {
5437 case MONO_TYPE_ARRAY:
5438 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5440 return verify_safe_for_managed_space (type->data.type);
5441 case MONO_TYPE_SZARRAY:
5442 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5443 case MONO_TYPE_GENERICINST: {
5444 MonoGenericInst *inst = type->data.generic_class->inst;
5448 for (i = 0; i < inst->type_argc; ++i)
5449 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5455 case MONO_TYPE_MVAR:
5462 * mono_type_get_object:
5463 * @domain: an app domain
5466 * Return an System.MonoType object representing the type @type.
5469 mono_type_get_object (MonoDomain *domain, MonoType *type)
5471 MonoReflectionType *res;
5472 MonoClass *klass = mono_class_from_mono_type (type);
5474 mono_domain_lock (domain);
5475 if (!domain->type_hash)
5476 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5477 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5478 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5479 mono_domain_unlock (domain);
5482 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5483 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5484 mono_g_hash_table_insert (domain->type_hash, type, res);
5485 mono_domain_unlock (domain);
5489 if (!verify_safe_for_managed_space (type)) {
5490 mono_domain_unlock (domain);
5491 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5494 if (klass->reflection_info && !klass->wastypebuilder) {
5495 /* g_assert_not_reached (); */
5496 /* should this be considered an error condition? */
5498 mono_domain_unlock (domain);
5499 return klass->reflection_info;
5502 mono_class_init (klass);
5504 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5506 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5509 mono_g_hash_table_insert (domain->type_hash, type, res);
5510 mono_domain_unlock (domain);
5515 * mono_method_get_object:
5516 * @domain: an app domain
5518 * @refclass: the reflected type (can be NULL)
5520 * Return an System.Reflection.MonoMethod object representing the method @method.
5522 MonoReflectionMethod*
5523 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5526 * We use the same C representation for methods and constructors, but the type
5527 * name in C# is different.
5529 static MonoClass *System_Reflection_MonoMethod = NULL;
5530 static MonoClass *System_Reflection_MonoCMethod = NULL;
5531 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5532 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5534 MonoReflectionMethod *ret;
5536 if (method->is_inflated) {
5537 MonoReflectionGenericMethod *gret;
5539 refclass = method->klass;
5540 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5541 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5542 if (!System_Reflection_MonoGenericCMethod)
5543 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5544 klass = System_Reflection_MonoGenericCMethod;
5546 if (!System_Reflection_MonoGenericMethod)
5547 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5548 klass = System_Reflection_MonoGenericMethod;
5550 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5551 gret->method.method = method;
5552 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5553 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5554 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5558 refclass = method->klass;
5560 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5561 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5562 if (!System_Reflection_MonoCMethod)
5563 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5564 klass = System_Reflection_MonoCMethod;
5567 if (!System_Reflection_MonoMethod)
5568 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5569 klass = System_Reflection_MonoMethod;
5571 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5572 ret->method = method;
5573 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5574 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5578 * mono_field_get_object:
5579 * @domain: an app domain
5583 * Return an System.Reflection.MonoField object representing the field @field
5586 MonoReflectionField*
5587 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5589 MonoReflectionField *res;
5590 static MonoClass *monofield_klass;
5592 CHECK_OBJECT (MonoReflectionField *, field, klass);
5593 if (!monofield_klass)
5594 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5595 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5598 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5599 if (field->generic_info)
5600 res->attrs = field->generic_info->generic_type->attrs;
5602 res->attrs = field->type->attrs;
5603 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5604 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5608 * mono_property_get_object:
5609 * @domain: an app domain
5611 * @property: a property
5613 * Return an System.Reflection.MonoProperty object representing the property @property
5616 MonoReflectionProperty*
5617 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5619 MonoReflectionProperty *res;
5620 static MonoClass *monoproperty_klass;
5622 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5623 if (!monoproperty_klass)
5624 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5625 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5627 res->property = property;
5628 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5632 * mono_event_get_object:
5633 * @domain: an app domain
5637 * Return an System.Reflection.MonoEvent object representing the event @event
5640 MonoReflectionEvent*
5641 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5643 MonoReflectionEvent *res;
5644 static MonoClass *monoevent_klass;
5646 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5647 if (!monoevent_klass)
5648 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5649 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5652 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5656 * mono_param_get_objects:
5657 * @domain: an app domain
5660 * Return an System.Reflection.ParameterInfo array object representing the parameters
5661 * in the method @method.
5664 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5666 static MonoClass *System_Reflection_ParameterInfo;
5667 MonoArray *res = NULL;
5668 MonoReflectionMethod *member = NULL;
5669 MonoReflectionParameter *param = NULL;
5670 char **names, **blobs = NULL;
5671 guint32 *types = NULL;
5672 MonoType *type = NULL;
5673 MonoObject *dbnull = mono_get_dbnull_object (domain);
5674 MonoMarshalSpec **mspecs;
5675 MonoMethodSignature *sig;
5678 if (!System_Reflection_ParameterInfo)
5679 System_Reflection_ParameterInfo = mono_class_from_name (
5680 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5682 if (!mono_method_signature (method)->param_count)
5683 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5685 /* Note: the cache is based on the address of the signature into the method
5686 * since we already cache MethodInfos with the method as keys.
5688 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5690 sig = mono_method_signature (method);
5691 member = mono_method_get_object (domain, method, NULL);
5692 names = g_new (char *, sig->param_count);
5693 mono_method_get_param_names (method, (const char **) names);
5695 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5696 mono_method_get_marshal_info (method, mspecs);
5698 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5699 for (i = 0; i < sig->param_count; ++i) {
5700 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5701 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5702 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5703 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5704 param->PositionImpl = i;
5705 param->AttrsImpl = sig->params [i]->attrs;
5707 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5708 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5712 blobs = g_new0 (char *, sig->param_count);
5713 types = g_new0 (guint32, sig->param_count);
5714 get_default_param_value_blobs (method, blobs, types);
5717 /* Build MonoType for the type from the Constant Table */
5719 type = g_new0 (MonoType, 1);
5720 type->type = types [i];
5721 type->data.klass = NULL;
5722 if (types [i] == MONO_TYPE_CLASS)
5723 type->data.klass = mono_defaults.object_class;
5724 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5725 /* For enums, types [i] contains the base type */
5727 type->type = MONO_TYPE_VALUETYPE;
5728 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5730 type->data.klass = mono_class_from_mono_type (type);
5732 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5734 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5735 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5736 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5741 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5743 mono_array_setref (res, i, param);
5750 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5752 mono_metadata_free_marshal_spec (mspecs [i]);
5755 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5759 * mono_method_body_get_object:
5760 * @domain: an app domain
5763 * Return an System.Reflection.MethodBody object representing the method @method.
5765 MonoReflectionMethodBody*
5766 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5768 static MonoClass *System_Reflection_MethodBody = NULL;
5769 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5770 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5771 MonoReflectionMethodBody *ret;
5772 MonoMethodNormal *mn;
5773 MonoMethodHeader *header;
5774 guint32 method_rva, local_var_sig_token;
5776 unsigned char format, flags;
5779 if (!System_Reflection_MethodBody)
5780 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5781 if (!System_Reflection_LocalVariableInfo)
5782 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5783 if (!System_Reflection_ExceptionHandlingClause)
5784 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5786 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5788 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5789 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5790 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5791 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5793 mn = (MonoMethodNormal *)method;
5794 header = mono_method_get_header (method);
5796 /* Obtain local vars signature token */
5797 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5798 ptr = mono_image_rva_map (method->klass->image, method_rva);
5799 flags = *(const unsigned char *) ptr;
5800 format = flags & METHOD_HEADER_FORMAT_MASK;
5802 case METHOD_HEADER_TINY_FORMAT:
5803 case METHOD_HEADER_TINY_FORMAT1:
5804 local_var_sig_token = 0;
5806 case METHOD_HEADER_FAT_FORMAT:
5810 local_var_sig_token = read32 (ptr);
5813 g_assert_not_reached ();
5816 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5818 ret->init_locals = header->init_locals;
5819 ret->max_stack = header->max_stack;
5820 ret->local_var_sig_token = local_var_sig_token;
5821 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5822 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5825 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5826 for (i = 0; i < header->num_locals; ++i) {
5827 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5828 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5829 info->is_pinned = header->locals [i]->pinned;
5830 info->local_index = i;
5831 mono_array_setref (ret->locals, i, info);
5835 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5836 for (i = 0; i < header->num_clauses; ++i) {
5837 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5838 MonoExceptionClause *clause = &header->clauses [i];
5840 info->flags = clause->flags;
5841 info->try_offset = clause->try_offset;
5842 info->try_length = clause->try_len;
5843 info->handler_offset = clause->handler_offset;
5844 info->handler_length = clause->handler_len;
5845 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5846 info->filter_offset = clause->data.filter_offset;
5847 else if (clause->data.catch_class)
5848 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5850 mono_array_setref (ret->clauses, i, info);
5853 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5858 mono_get_dbnull_object (MonoDomain *domain)
5861 static MonoClassField *dbnull_value_field = NULL;
5863 if (!dbnull_value_field) {
5864 MonoClass *dbnull_klass;
5865 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5866 mono_class_init (dbnull_klass);
5867 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5868 g_assert (dbnull_value_field);
5870 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5877 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5879 guint32 param_index, i, lastp, crow = 0;
5880 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5883 MonoClass *klass = method->klass;
5884 MonoImage *image = klass->image;
5885 MonoMethodSignature *methodsig = mono_method_signature (method);
5887 MonoTableInfo *constt;
5888 MonoTableInfo *methodt;
5889 MonoTableInfo *paramt;
5891 if (!methodsig->param_count)
5894 mono_class_init (klass);
5896 if (klass->image->dynamic) {
5897 MonoReflectionMethodAux *aux;
5898 if (method->is_inflated)
5899 method = ((MonoMethodInflated*)method)->declaring;
5900 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5901 if (aux && aux->param_defaults) {
5902 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5903 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5908 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5909 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5910 constt = &image->tables [MONO_TABLE_CONSTANT];
5912 idx = mono_method_get_index (method) - 1;
5913 g_assert (idx != -1);
5915 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5916 if (idx + 1 < methodt->rows)
5917 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5919 lastp = paramt->rows + 1;
5921 for (i = param_index; i < lastp; ++i) {
5924 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5925 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5927 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5930 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5935 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5936 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5937 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5944 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5949 MonoType *basetype = type;
5954 klass = mono_class_from_mono_type (type);
5955 if (klass->valuetype) {
5956 object = mono_object_new (domain, klass);
5957 retval = ((gchar *) object + sizeof (MonoObject));
5958 if (klass->enumtype)
5959 basetype = klass->enum_basetype;
5964 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5971 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5975 memset (assembly, 0, sizeof (MonoAssemblyName));
5977 assembly->culture = "";
5978 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5980 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5983 while (g_ascii_isspace (*p) || *p == ',') {
5992 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5994 assembly->major = strtoul (p, &s, 10);
5995 if (s == p || *s != '.')
5998 assembly->minor = strtoul (p, &s, 10);
5999 if (s == p || *s != '.')
6002 assembly->build = strtoul (p, &s, 10);
6003 if (s == p || *s != '.')
6006 assembly->revision = strtoul (p, &s, 10);
6010 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6012 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6013 assembly->culture = "";
6016 assembly->culture = p;
6017 while (*p && *p != ',') {
6021 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6023 if (strncmp (p, "null", 4) == 0) {
6028 while (*p && *p != ',') {
6031 len = (p - start + 1);
6032 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6033 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6034 g_strlcpy ((char*)assembly->public_key_token, start, len);
6037 while (*p && *p != ',')
6041 while (g_ascii_isspace (*p) || *p == ',') {
6055 * mono_reflection_parse_type:
6058 * Parse a type name as accepted by the GetType () method and output the info
6059 * extracted in the info structure.
6060 * the name param will be mangled, so, make a copy before passing it to this function.
6061 * The fields in info will be valid until the memory pointed to by name is valid.
6063 * See also mono_type_get_name () below.
6065 * Returns: 0 on parse error.
6068 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6069 MonoTypeNameParse *info)
6071 char *start, *p, *w, *temp, *last_point, *startn;
6072 int in_modifiers = 0;
6073 int isbyref = 0, rank, arity = 0, i;
6075 start = p = w = name;
6077 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6078 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6079 info->name = info->name_space = NULL;
6080 info->nested = NULL;
6081 info->modifiers = NULL;
6082 info->type_arguments = NULL;
6084 /* last_point separates the namespace from the name */
6090 *p = 0; /* NULL terminate the name */
6092 info->nested = g_list_append (info->nested, startn);
6093 /* we have parsed the nesting namespace + name */
6097 info->name_space = start;
6099 info->name = last_point + 1;
6101 info->name_space = (char *)"";
6120 i = strtol (p, &temp, 10);
6137 info->name_space = start;
6139 info->name = last_point + 1;
6141 info->name_space = (char *)"";
6148 if (isbyref) /* only one level allowed by the spec */
6151 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6155 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6161 info->type_arguments = g_ptr_array_new ();
6162 for (i = 0; i < arity; i++) {
6163 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6164 gboolean fqname = FALSE;
6166 g_ptr_array_add (info->type_arguments, subinfo);
6173 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6184 while (*p && (*p != ']'))
6192 if (g_ascii_isspace (*aname)) {
6199 !assembly_name_to_aname (&subinfo->assembly, aname))
6203 if (i + 1 < arity) {
6223 else if (*p != '*') /* '*' means unknown lower bound */
6229 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6240 if (g_ascii_isspace (*p)) {
6247 return 0; /* missing assembly name */
6248 if (!assembly_name_to_aname (&info->assembly, p))
6254 if (info->assembly.name)
6257 // *w = 0; /* terminate class name */
6259 if (!info->name || !*info->name)
6263 /* add other consistency checks */
6268 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6270 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6274 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6276 gboolean type_resolve = FALSE;
6278 MonoImage *rootimage = image;
6280 if (info->assembly.name) {
6281 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6283 /* then we must load the assembly ourselve - see #60439 */
6284 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6288 image = assembly->image;
6289 } else if (!image) {
6290 image = mono_defaults.corlib;
6293 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6294 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6295 image = mono_defaults.corlib;
6296 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6303 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6310 image = mono_defaults.corlib;
6313 klass = mono_class_from_name_case (image, info->name_space, info->name);
6315 klass = mono_class_from_name (image, info->name_space, info->name);
6318 for (mod = info->nested; mod; mod = mod->next) {
6321 mono_class_init (klass);
6322 nested = klass->nested_classes;
6325 klass = nested->data;
6327 if (g_strcasecmp (klass->name, mod->data) == 0)
6330 if (strcmp (klass->name, mod->data) == 0)
6334 nested = nested->next;
6341 mono_class_init (klass);
6343 if (info->type_arguments) {
6344 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6345 MonoReflectionType *the_type;
6349 for (i = 0; i < info->type_arguments->len; i++) {
6350 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6352 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6353 if (!type_args [i]) {
6359 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6361 instance = mono_reflection_bind_generic_parameters (
6362 the_type, info->type_arguments->len, type_args);
6368 klass = mono_class_from_mono_type (instance);
6371 for (mod = info->modifiers; mod; mod = mod->next) {
6372 modval = GPOINTER_TO_UINT (mod->data);
6373 if (!modval) { /* byref: must be last modifier */
6374 return &klass->this_arg;
6375 } else if (modval == -1) {
6376 klass = mono_ptr_class_get (&klass->byval_arg);
6377 } else { /* array rank */
6378 klass = mono_array_class_get (klass, modval);
6380 mono_class_init (klass);
6383 return &klass->byval_arg;
6387 * mono_reflection_get_type:
6388 * @image: a metadata context
6389 * @info: type description structure
6390 * @ignorecase: flag for case-insensitive string compares
6391 * @type_resolve: whenever type resolve was already tried
6393 * Build a MonoType from the type description in @info.
6398 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6399 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6403 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6406 MonoReflectionAssembly *assembly;
6410 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6413 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6420 *type_resolve = TRUE;
6423 /* Reconstruct the type name */
6424 fullName = g_string_new ("");
6425 if (info->name_space && (info->name_space [0] != '\0'))
6426 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6428 g_string_printf (fullName, info->name);
6429 for (mod = info->nested; mod; mod = mod->next)
6430 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6432 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6434 if (assembly->assembly->dynamic) {
6435 /* Enumerate all modules */
6436 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6440 if (abuilder->modules) {
6441 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6442 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6443 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6449 if (!type && abuilder->loaded_modules) {
6450 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6451 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6452 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6459 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6462 g_string_free (fullName, TRUE);
6467 mono_reflection_free_type_info (MonoTypeNameParse *info)
6469 g_list_free (info->modifiers);
6470 g_list_free (info->nested);
6472 if (info->type_arguments) {
6475 for (i = 0; i < info->type_arguments->len; i++) {
6476 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6478 mono_reflection_free_type_info (subinfo);
6479 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6483 g_ptr_array_free (info->type_arguments, TRUE);
6488 * mono_reflection_type_from_name:
6490 * @image: a metadata context (can be NULL).
6492 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6493 * it defaults to get the type from @image or, if @image is NULL or loading
6494 * from it fails, uses corlib.
6498 mono_reflection_type_from_name (char *name, MonoImage *image)
6500 MonoType *type = NULL;
6501 MonoTypeNameParse info;
6504 /* Make a copy since parse_type modifies its argument */
6505 tmp = g_strdup (name);
6507 /*g_print ("requested type %s\n", str);*/
6508 if (mono_reflection_parse_type (tmp, &info)) {
6509 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6513 mono_reflection_free_type_info (&info);
6518 * mono_reflection_get_token:
6520 * Return the metadata token of OBJ which should be an object
6521 * representing a metadata element.
6524 mono_reflection_get_token (MonoObject *obj)
6529 klass = obj->vtable->klass;
6531 if (strcmp (klass->name, "MethodBuilder") == 0) {
6532 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6534 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6535 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6536 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6538 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6539 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6540 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6541 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6542 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6543 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6544 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6545 } else if (strcmp (klass->name, "MonoType") == 0) {
6546 MonoReflectionType *tb = (MonoReflectionType *)obj;
6547 token = mono_class_from_mono_type (tb->type)->type_token;
6548 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6549 strcmp (klass->name, "MonoMethod") == 0 ||
6550 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6551 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6552 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6553 if (m->method->is_inflated) {
6554 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6555 return inflated->declaring->token;
6557 token = m->method->token;
6559 } else if (strcmp (klass->name, "MonoField") == 0) {
6560 MonoReflectionField *f = (MonoReflectionField*)obj;
6562 if (f->field->generic_info && f->field->generic_info->reflection_info)
6563 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6565 token = mono_class_get_field_token (f->field);
6566 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6567 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6569 token = mono_class_get_property_token (p->property);
6570 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6571 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6573 token = mono_class_get_event_token (p->event);
6574 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6575 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6577 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6578 } else if (strcmp (klass->name, "Module") == 0) {
6579 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6582 } else if (strcmp (klass->name, "Assembly") == 0) {
6583 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6585 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6586 MonoException *ex = mono_get_exception_not_implemented (msg);
6588 mono_raise_exception (ex);
6595 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6597 int slen, type = t->type;
6598 MonoClass *tklass = t->data.klass;
6604 case MONO_TYPE_BOOLEAN: {
6605 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6610 case MONO_TYPE_CHAR:
6612 case MONO_TYPE_I2: {
6613 guint16 *val = g_malloc (sizeof (guint16));
6618 #if SIZEOF_VOID_P == 4
6624 case MONO_TYPE_I4: {
6625 guint32 *val = g_malloc (sizeof (guint32));
6630 #if SIZEOF_VOID_P == 8
6631 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6635 case MONO_TYPE_I8: {
6636 guint64 *val = g_malloc (sizeof (guint64));
6641 case MONO_TYPE_R8: {
6642 double *val = g_malloc (sizeof (double));
6647 case MONO_TYPE_VALUETYPE:
6648 if (t->data.klass->enumtype) {
6649 type = t->data.klass->enum_basetype->type;
6652 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6655 case MONO_TYPE_STRING:
6656 if (*p == (char)0xFF) {
6660 slen = mono_metadata_decode_value (p, &p);
6662 return mono_string_new_len (mono_domain_get (), p, slen);
6663 case MONO_TYPE_CLASS: {
6666 if (*p == (char)0xFF) {
6671 slen = mono_metadata_decode_value (p, &p);
6672 n = g_memdup (p, slen + 1);
6674 t = mono_reflection_type_from_name (n, image);
6676 g_warning ("Cannot load type '%s'", n);
6680 return mono_type_get_object (mono_domain_get (), t);
6684 case MONO_TYPE_OBJECT: {
6687 MonoClass *subc = NULL;
6692 } else if (subt == 0x0E) {
6693 type = MONO_TYPE_STRING;
6695 } else if (subt == 0x1D) {
6696 MonoType simple_type = {{0}};
6701 /* See Partition II, Appendix B3 */
6702 etype = MONO_TYPE_OBJECT;
6703 type = MONO_TYPE_SZARRAY;
6704 simple_type.type = etype;
6705 tklass = mono_class_from_mono_type (&simple_type);
6707 } else if (subt == 0x55) {
6710 slen = mono_metadata_decode_value (p, &p);
6711 n = g_memdup (p, slen + 1);
6713 t = mono_reflection_type_from_name (n, image);
6715 g_error ("Cannot load type '%s'", n);
6718 subc = mono_class_from_mono_type (t);
6719 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6720 MonoType simple_type = {{0}};
6721 simple_type.type = subt;
6722 subc = mono_class_from_mono_type (&simple_type);
6724 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6726 val = load_cattr_value (image, &subc->byval_arg, p, end);
6727 obj = mono_object_new (mono_domain_get (), subc);
6728 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6732 case MONO_TYPE_SZARRAY: {
6734 guint32 i, alen, basetype;
6737 if (alen == 0xffffffff) {
6741 arr = mono_array_new (mono_domain_get(), tklass, alen);
6742 basetype = tklass->byval_arg.type;
6743 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6744 basetype = tklass->enum_basetype->type;
6749 case MONO_TYPE_BOOLEAN:
6750 for (i = 0; i < alen; i++) {
6751 MonoBoolean val = *p++;
6752 mono_array_set (arr, MonoBoolean, i, val);
6755 case MONO_TYPE_CHAR:
6758 for (i = 0; i < alen; i++) {
6759 guint16 val = read16 (p);
6760 mono_array_set (arr, guint16, i, val);
6767 for (i = 0; i < alen; i++) {
6768 guint32 val = read32 (p);
6769 mono_array_set (arr, guint32, i, val);
6774 for (i = 0; i < alen; i++) {
6777 mono_array_set (arr, double, i, val);
6783 for (i = 0; i < alen; i++) {
6784 guint64 val = read64 (p);
6785 mono_array_set (arr, guint64, i, val);
6789 case MONO_TYPE_CLASS:
6790 case MONO_TYPE_OBJECT:
6791 case MONO_TYPE_STRING:
6792 for (i = 0; i < alen; i++) {
6793 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6794 mono_array_setref (arr, i, item);
6798 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6804 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6810 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6812 static MonoClass *klass;
6813 static MonoMethod *ctor;
6815 void *params [2], *unboxed;
6818 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6820 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6822 params [0] = mono_type_get_object (mono_domain_get (), t);
6824 retval = mono_object_new (mono_domain_get (), klass);
6825 unboxed = mono_object_unbox (retval);
6826 mono_runtime_invoke (ctor, unboxed, params, NULL);
6832 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6834 static MonoClass *klass;
6835 static MonoMethod *ctor;
6837 void *unboxed, *params [2];
6840 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6842 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6845 params [1] = typedarg;
6846 retval = mono_object_new (mono_domain_get (), klass);
6847 unboxed = mono_object_unbox (retval);
6848 mono_runtime_invoke (ctor, unboxed, params, NULL);
6854 type_is_reference (MonoType *type)
6856 switch (type->type) {
6857 case MONO_TYPE_BOOLEAN:
6858 case MONO_TYPE_CHAR:
6871 case MONO_TYPE_VALUETYPE:
6879 free_param_data (MonoMethodSignature *sig, void **params) {
6881 for (i = 0; i < sig->param_count; ++i) {
6882 if (!type_is_reference (sig->params [i]))
6883 g_free (params [i]);
6888 * Find the field index in the metadata FieldDef table.
6891 find_field_index (MonoClass *klass, MonoClassField *field) {
6894 for (i = 0; i < klass->field.count; ++i) {
6895 if (field == &klass->fields [i])
6896 return klass->field.first + 1 + i;
6902 * Find the property index in the metadata Property table.
6905 find_property_index (MonoClass *klass, MonoProperty *property) {
6908 for (i = 0; i < klass->property.count; ++i) {
6909 if (property == &klass->properties [i])
6910 return klass->property.first + 1 + i;
6916 * Find the event index in the metadata Event table.
6919 find_event_index (MonoClass *klass, MonoEvent *event) {
6922 for (i = 0; i < klass->event.count; ++i) {
6923 if (event == &klass->events [i])
6924 return klass->event.first + 1 + i;
6930 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6932 const char *p = (const char*)data;
6934 guint32 i, j, num_named;
6938 mono_class_init (method->klass);
6941 attr = mono_object_new (mono_domain_get (), method->klass);
6942 mono_runtime_invoke (method, attr, NULL, NULL);
6946 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6949 /*g_print ("got attr %s\n", method->klass->name);*/
6951 /* Allocate using alloca so it gets GC tracking */
6952 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6956 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6957 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6961 attr = mono_object_new (mono_domain_get (), method->klass);
6962 mono_runtime_invoke (method, attr, params, NULL);
6963 free_param_data (method->signature, params);
6964 num_named = read16 (named);
6966 for (j = 0; j < num_named; j++) {
6968 char *name, named_type, data_type;
6969 named_type = *named++;
6970 data_type = *named++; /* type of data */
6971 if (data_type == MONO_TYPE_SZARRAY)
6972 data_type = *named++;
6973 if (data_type == MONO_TYPE_ENUM) {
6976 type_len = mono_metadata_decode_blob_size (named, &named);
6977 type_name = g_malloc (type_len + 1);
6978 memcpy (type_name, named, type_len);
6979 type_name [type_len] = 0;
6981 /* FIXME: lookup the type and check type consistency */
6984 name_len = mono_metadata_decode_blob_size (named, &named);
6985 name = g_malloc (name_len + 1);
6986 memcpy (name, named, name_len);
6987 name [name_len] = 0;
6989 if (named_type == 0x53) {
6990 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6991 void *val = load_cattr_value (image, field->type, named, &named);
6992 mono_field_set_value (attr, field, val);
6993 if (!type_is_reference (field->type))
6995 } else if (named_type == 0x54) {
6998 MonoType *prop_type;
7000 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7001 /* can we have more that 1 arg in a custom attr named property? */
7002 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7003 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7004 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7005 mono_property_set_value (prop, attr, pparams, NULL);
7006 if (!type_is_reference (prop_type))
7007 g_free (pparams [0]);
7016 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7018 MonoArray *typedargs, *namedargs;
7019 MonoClass *attrklass;
7020 static MonoMethod *ctor;
7023 const char *p = (const char*)data;
7025 guint32 i, j, num_named;
7028 mono_class_init (method->klass);
7031 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7033 domain = mono_domain_get ();
7035 /* This is for Attributes with no parameters */
7036 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7037 params [0] = mono_method_get_object (domain, method, NULL);
7038 params [1] = params [2] = NULL;
7039 mono_runtime_invoke (method, attr, params, NULL);
7043 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7046 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7050 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7051 MonoObject *obj, *typedarg;
7054 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7055 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7056 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7057 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7058 mono_array_setref (typedargs, i, typedarg);
7060 if (!type_is_reference (mono_method_signature (method)->params [i]))
7065 num_named = read16 (named);
7066 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7068 attrklass = method->klass;
7069 for (j = 0; j < num_named; j++) {
7071 char *name, named_type, data_type;
7072 named_type = *named++;
7073 data_type = *named++; /* type of data */
7074 if (data_type == MONO_TYPE_SZARRAY)
7075 data_type = *named++;
7076 if (data_type == MONO_TYPE_ENUM) {
7079 type_len = mono_metadata_decode_blob_size (named, &named);
7080 type_name = g_malloc (type_len + 1);
7081 memcpy (type_name, named, type_len);
7082 type_name [type_len] = 0;
7084 /* FIXME: lookup the type and check type consistency */
7087 name_len = mono_metadata_decode_blob_size (named, &named);
7088 name = g_malloc (name_len + 1);
7089 memcpy (name, named, name_len);
7090 name [name_len] = 0;
7092 if (named_type == 0x53) {
7093 MonoObject *obj, *typedarg, *namedarg;
7094 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7095 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7097 minfo = mono_field_get_object (domain, NULL, field);
7098 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7099 typedarg = create_cattr_typed_arg (field->type, obj);
7100 namedarg = create_cattr_named_arg (minfo, typedarg);
7101 mono_array_setref (namedargs, j, namedarg);
7102 if (!type_is_reference (field->type))
7104 } else if (named_type == 0x54) {
7105 MonoObject *obj, *typedarg, *namedarg;
7106 MonoType *prop_type;
7108 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7110 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7111 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7112 minfo = mono_property_get_object (domain, NULL, prop);
7113 val = load_cattr_value (image, prop_type, named, &named);
7114 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7115 typedarg = create_cattr_typed_arg (prop_type, obj);
7116 namedarg = create_cattr_named_arg (minfo, typedarg);
7117 mono_array_setref (namedargs, j, namedarg);
7118 if (!type_is_reference (prop_type))
7123 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7124 params [0] = mono_method_get_object (domain, method, NULL);
7125 params [1] = typedargs;
7126 params [2] = namedargs;
7127 mono_runtime_invoke (ctor, attr, params, NULL);
7132 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7138 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7139 for (i = 0; i < cinfo->num_attrs; ++i) {
7140 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7141 mono_array_setref (result, i, attr);
7147 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7154 for (i = 0; i < cinfo->num_attrs; ++i) {
7155 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7159 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7161 for (i = 0; i < cinfo->num_attrs; ++i) {
7162 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7163 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7164 mono_array_setref (result, n, attr);
7172 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7178 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7179 for (i = 0; i < cinfo->num_attrs; ++i) {
7180 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7181 mono_array_setref (result, i, attr);
7187 * mono_custom_attrs_from_index:
7189 * Returns: NULL if no attributes are found or if a loading error occurs.
7192 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7194 guint32 mtoken, i, len;
7195 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7197 MonoCustomAttrInfo *ainfo;
7198 GList *tmp, *list = NULL;
7201 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7203 i = mono_metadata_custom_attrs_from_index (image, idx);
7207 while (i < ca->rows) {
7208 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7210 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7213 len = g_list_length (list);
7216 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7217 ainfo->num_attrs = len;
7218 ainfo->image = image;
7219 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7220 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7221 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7222 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7223 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7224 mtoken |= MONO_TOKEN_METHOD_DEF;
7226 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7227 mtoken |= MONO_TOKEN_MEMBER_REF;
7230 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7233 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7234 if (!ainfo->attrs [i].ctor) {
7235 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7240 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7241 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7242 ainfo->attrs [i].data = (guchar*)data;
7250 mono_custom_attrs_from_method (MonoMethod *method)
7252 MonoCustomAttrInfo *cinfo;
7255 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7257 idx = mono_method_get_index (method);
7258 idx <<= MONO_CUSTOM_ATTR_BITS;
7259 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7260 return mono_custom_attrs_from_index (method->klass->image, idx);
7264 mono_custom_attrs_from_class (MonoClass *klass)
7266 MonoCustomAttrInfo *cinfo;
7269 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7271 idx = mono_metadata_token_index (klass->type_token);
7272 idx <<= MONO_CUSTOM_ATTR_BITS;
7273 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7274 return mono_custom_attrs_from_index (klass->image, idx);
7278 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7280 MonoCustomAttrInfo *cinfo;
7283 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7285 idx = 1; /* there is only one assembly */
7286 idx <<= MONO_CUSTOM_ATTR_BITS;
7287 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7288 return mono_custom_attrs_from_index (assembly->image, idx);
7291 static MonoCustomAttrInfo*
7292 mono_custom_attrs_from_module (MonoImage *image)
7294 MonoCustomAttrInfo *cinfo;
7297 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7299 idx = 1; /* there is only one module */
7300 idx <<= MONO_CUSTOM_ATTR_BITS;
7301 idx |= MONO_CUSTOM_ATTR_MODULE;
7302 return mono_custom_attrs_from_index (image, idx);
7306 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7308 MonoCustomAttrInfo *cinfo;
7311 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7313 idx = find_property_index (klass, property);
7314 idx <<= MONO_CUSTOM_ATTR_BITS;
7315 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7316 return mono_custom_attrs_from_index (klass->image, idx);
7320 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7322 MonoCustomAttrInfo *cinfo;
7325 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7327 idx = find_event_index (klass, event);
7328 idx <<= MONO_CUSTOM_ATTR_BITS;
7329 idx |= MONO_CUSTOM_ATTR_EVENT;
7330 return mono_custom_attrs_from_index (klass->image, idx);
7334 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7336 MonoCustomAttrInfo *cinfo;
7339 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7341 idx = find_field_index (klass, field);
7342 idx <<= MONO_CUSTOM_ATTR_BITS;
7343 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7344 return mono_custom_attrs_from_index (klass->image, idx);
7348 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7351 guint32 i, idx, method_index;
7352 guint32 param_list, param_last, param_pos, found;
7354 MonoReflectionMethodAux *aux;
7356 if (method->klass->image->dynamic) {
7357 MonoCustomAttrInfo *res, *ainfo;
7360 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7361 if (!aux || !aux->param_cattr)
7364 /* Need to copy since it will be freed later */
7365 ainfo = aux->param_cattr [param];
7366 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7367 res = g_malloc0 (size);
7368 memcpy (res, ainfo, size);
7372 image = method->klass->image;
7373 method_index = mono_method_get_index (method);
7374 ca = &image->tables [MONO_TABLE_METHOD];
7376 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7377 if (method_index == ca->rows) {
7378 ca = &image->tables [MONO_TABLE_PARAM];
7379 param_last = ca->rows + 1;
7381 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7382 ca = &image->tables [MONO_TABLE_PARAM];
7385 for (i = param_list; i < param_last; ++i) {
7386 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7387 if (param_pos == param) {
7395 idx <<= MONO_CUSTOM_ATTR_BITS;
7396 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7397 return mono_custom_attrs_from_index (image, idx);
7401 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7405 for (i = 0; i < ainfo->num_attrs; ++i) {
7406 klass = ainfo->attrs [i].ctor->klass;
7407 if (mono_class_has_parent (klass, attr_klass))
7414 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7421 for (i = 0; i < ainfo->num_attrs; ++i) {
7422 klass = ainfo->attrs [i].ctor->klass;
7423 if (mono_class_has_parent (klass, attr_klass)) {
7428 if (attr_index == -1)
7431 attrs = mono_custom_attrs_construct (ainfo);
7433 return mono_array_get (attrs, MonoObject*, attr_index);
7439 * mono_reflection_get_custom_attrs_info:
7440 * @obj: a reflection object handle
7442 * Return the custom attribute info for attributes defined for the
7443 * reflection handle @obj. The objects.
7446 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7449 MonoCustomAttrInfo *cinfo = NULL;
7451 klass = obj->vtable->klass;
7452 if (klass == mono_defaults.monotype_class) {
7453 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7454 klass = mono_class_from_mono_type (rtype->type);
7455 cinfo = mono_custom_attrs_from_class (klass);
7456 } else if (strcmp ("Assembly", klass->name) == 0) {
7457 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7458 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7459 } else if (strcmp ("Module", klass->name) == 0) {
7460 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7461 cinfo = mono_custom_attrs_from_module (module->image);
7462 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7463 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7464 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7465 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7466 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7467 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7468 } else if (strcmp ("MonoField", klass->name) == 0) {
7469 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7470 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7471 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7472 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7473 cinfo = mono_custom_attrs_from_method (rmethod->method);
7474 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7475 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7476 cinfo = mono_custom_attrs_from_method (rmethod->method);
7477 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7478 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7479 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7480 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7481 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7482 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7483 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7484 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7485 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7486 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7487 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7488 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7489 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7490 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7491 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7492 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7493 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7494 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7495 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7496 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7497 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7498 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7499 } else { /* handle other types here... */
7500 g_error ("get custom attrs not yet supported for %s", klass->name);
7507 * mono_reflection_get_custom_attrs_by_type:
7508 * @obj: a reflection object handle
7510 * Return an array with all the custom attributes defined of the
7511 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7512 * of that type are returned. The objects are fully build. Return NULL if a loading error
7516 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7519 MonoCustomAttrInfo *cinfo;
7521 cinfo = mono_reflection_get_custom_attrs_info (obj);
7524 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7526 result = mono_custom_attrs_construct (cinfo);
7528 mono_custom_attrs_free (cinfo);
7530 if (mono_loader_get_last_error ())
7532 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7539 * mono_reflection_get_custom_attrs:
7540 * @obj: a reflection object handle
7542 * Return an array with all the custom attributes defined of the
7543 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7547 mono_reflection_get_custom_attrs (MonoObject *obj)
7549 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7553 * mono_reflection_get_custom_attrs_data:
7554 * @obj: a reflection obj handle
7556 * Returns an array of System.Reflection.CustomAttributeData,
7557 * which include information about attributes reflected on
7558 * types loaded using the Reflection Only methods
7561 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7564 MonoCustomAttrInfo *cinfo;
7566 cinfo = mono_reflection_get_custom_attrs_info (obj);
7568 result = mono_custom_attrs_data_construct (cinfo);
7570 mono_custom_attrs_free (cinfo);
7572 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7577 static MonoReflectionType*
7578 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7580 MonoMethod *method_get_underlying_system_type;
7582 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7583 mono_class_get_method_from_name (mono_object_class (t),
7584 "get_UnderlyingSystemType",
7586 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7590 mono_reflection_type_get_handle (MonoReflectionType* t)
7595 t = mono_reflection_type_get_underlying_system_type (t);
7603 * LOCKING: Assumes the loader lock is held.
7605 static MonoMethodSignature*
7606 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7607 MonoMethodSignature *sig;
7610 count = parameters? mono_array_length (parameters): 0;
7612 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7613 sig->param_count = count;
7614 sig->sentinelpos = -1; /* FIXME */
7615 for (i = 0; i < count; ++i) {
7616 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7617 sig->params [i] = mono_reflection_type_get_handle (pt);
7623 * LOCKING: Assumes the loader lock is held.
7625 static MonoMethodSignature*
7626 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7627 MonoMethodSignature *sig;
7629 sig = parameters_to_signature (mp, ctor->parameters);
7630 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7631 sig->ret = &mono_defaults.void_class->byval_arg;
7636 * LOCKING: Assumes the loader lock is held.
7638 static MonoMethodSignature*
7639 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7640 MonoMethodSignature *sig;
7642 sig = parameters_to_signature (mp, method->parameters);
7643 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7644 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7645 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7649 static MonoMethodSignature*
7650 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7651 MonoMethodSignature *sig;
7653 sig = parameters_to_signature (NULL, method->parameters);
7654 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7655 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7656 sig->generic_param_count = 0;
7661 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7663 MonoClass *klass = mono_object_class (prop);
7664 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7665 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7666 *name = mono_string_to_utf8 (pb->name);
7667 *type = pb->type->type;
7669 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7670 *name = g_strdup (p->property->name);
7671 if (p->property->get)
7672 *type = mono_method_signature (p->property->get)->ret;
7674 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7679 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7681 MonoClass *klass = mono_object_class (field);
7682 if (strcmp (klass->name, "FieldBuilder") == 0) {
7683 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7684 *name = mono_string_to_utf8 (fb->name);
7685 *type = fb->type->type;
7687 MonoReflectionField *f = (MonoReflectionField *)field;
7688 *name = g_strdup (f->field->name);
7689 *type = f->field->type;
7694 * Encode a value in a custom attribute stream of bytes.
7695 * The value to encode is either supplied as an object in argument val
7696 * (valuetypes are boxed), or as a pointer to the data in the
7698 * @type represents the type of the value
7699 * @buffer is the start of the buffer
7700 * @p the current position in the buffer
7701 * @buflen contains the size of the buffer and is used to return the new buffer size
7702 * if this needs to be realloced.
7703 * @retbuffer and @retp return the start and the position of the buffer
7706 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7708 MonoTypeEnum simple_type;
7710 if ((p-buffer) + 10 >= *buflen) {
7713 newbuf = g_realloc (buffer, *buflen);
7714 p = newbuf + (p-buffer);
7718 argval = ((char*)arg + sizeof (MonoObject));
7719 simple_type = type->type;
7721 switch (simple_type) {
7722 case MONO_TYPE_BOOLEAN:
7727 case MONO_TYPE_CHAR:
7730 swap_with_size (p, argval, 2, 1);
7736 swap_with_size (p, argval, 4, 1);
7740 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7750 swap_with_size (p, argval, 8, 1);
7756 swap_with_size (p, argval, 8, 1);
7759 case MONO_TYPE_VALUETYPE:
7760 if (type->data.klass->enumtype) {
7761 simple_type = type->data.klass->enum_basetype->type;
7764 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7767 case MONO_TYPE_STRING: {
7774 str = mono_string_to_utf8 ((MonoString*)arg);
7775 slen = strlen (str);
7776 if ((p-buffer) + 10 + slen >= *buflen) {
7780 newbuf = g_realloc (buffer, *buflen);
7781 p = newbuf + (p-buffer);
7784 mono_metadata_encode_value (slen, p, &p);
7785 memcpy (p, str, slen);
7790 case MONO_TYPE_CLASS: {
7798 k = mono_object_class (arg);
7799 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7800 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7801 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7804 if (rt && (rtc = mono_object_class (rt)) &&
7805 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7806 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7807 arg = (MonoObject *) rt;
7810 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7813 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7814 slen = strlen (str);
7815 if ((p-buffer) + 10 + slen >= *buflen) {
7819 newbuf = g_realloc (buffer, *buflen);
7820 p = newbuf + (p-buffer);
7823 mono_metadata_encode_value (slen, p, &p);
7824 memcpy (p, str, slen);
7829 case MONO_TYPE_SZARRAY: {
7831 MonoClass *eclass, *arg_eclass;
7834 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7837 len = mono_array_length ((MonoArray*)arg);
7839 *p++ = (len >> 8) & 0xff;
7840 *p++ = (len >> 16) & 0xff;
7841 *p++ = (len >> 24) & 0xff;
7843 *retbuffer = buffer;
7844 eclass = type->data.klass;
7845 arg_eclass = mono_object_class (arg)->element_class;
7848 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7849 eclass = mono_defaults.object_class;
7851 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7852 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7853 int elsize = mono_class_array_element_size (arg_eclass);
7854 for (i = 0; i < len; ++i) {
7855 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7858 } else if (eclass->valuetype && arg_eclass->valuetype) {
7859 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7860 int elsize = mono_class_array_element_size (eclass);
7861 for (i = 0; i < len; ++i) {
7862 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7866 for (i = 0; i < len; ++i) {
7867 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7872 case MONO_TYPE_OBJECT: {
7878 * The parameter type is 'object' but the type of the actual
7879 * argument is not. So we have to add type information to the blob
7880 * too. This is completely undocumented in the spec.
7884 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7889 klass = mono_object_class (arg);
7891 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7894 } else if (klass->enumtype) {
7896 } else if (klass == mono_defaults.string_class) {
7897 simple_type = MONO_TYPE_STRING;
7900 } else if (klass->rank == 1) {
7902 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7903 /* See Partition II, Appendix B3 */
7906 *p++ = klass->element_class->byval_arg.type;
7907 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7909 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7910 *p++ = simple_type = klass->byval_arg.type;
7913 g_error ("unhandled type in custom attr");
7915 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7916 slen = strlen (str);
7917 if ((p-buffer) + 10 + slen >= *buflen) {
7921 newbuf = g_realloc (buffer, *buflen);
7922 p = newbuf + (p-buffer);
7925 mono_metadata_encode_value (slen, p, &p);
7926 memcpy (p, str, slen);
7929 simple_type = klass->enum_basetype->type;
7933 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7936 *retbuffer = buffer;
7940 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7942 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7943 char *str = type_get_qualified_name (type, NULL);
7944 int slen = strlen (str);
7948 * This seems to be optional...
7951 mono_metadata_encode_value (slen, p, &p);
7952 memcpy (p, str, slen);
7955 } else if (type->type == MONO_TYPE_OBJECT) {
7957 } else if (type->type == MONO_TYPE_CLASS) {
7958 /* it should be a type: encode_cattr_value () has the check */
7961 mono_metadata_encode_value (type->type, p, &p);
7962 if (type->type == MONO_TYPE_SZARRAY)
7963 /* See the examples in Partition VI, Annex B */
7964 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7971 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7974 /* Preallocate a large enough buffer */
7975 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7976 char *str = type_get_qualified_name (type, NULL);
7979 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7980 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7986 len += strlen (name);
7988 if ((p-buffer) + 20 + len >= *buflen) {
7992 newbuf = g_realloc (buffer, *buflen);
7993 p = newbuf + (p-buffer);
7997 encode_field_or_prop_type (type, p, &p);
7999 len = strlen (name);
8000 mono_metadata_encode_value (len, p, &p);
8001 memcpy (p, name, len);
8003 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8005 *retbuffer = buffer;
8009 * mono_reflection_get_custom_attrs_blob:
8010 * @ctor: custom attribute constructor
8011 * @ctorArgs: arguments o the constructor
8017 * Creates the blob of data that needs to be saved in the metadata and that represents
8018 * the custom attributed described by @ctor, @ctorArgs etc.
8019 * Returns: a Byte array representing the blob of data.
8022 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8025 MonoMethodSignature *sig;
8030 MONO_ARCH_SAVE_REGS;
8032 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8033 /* sig is freed later so allocate it in the heap */
8034 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8036 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8039 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8041 p = buffer = g_malloc (buflen);
8042 /* write the prolog */
8045 for (i = 0; i < sig->param_count; ++i) {
8046 arg = mono_array_get (ctorArgs, MonoObject*, i);
8047 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8051 i += mono_array_length (properties);
8053 i += mono_array_length (fields);
8055 *p++ = (i >> 8) & 0xff;
8058 for (i = 0; i < mono_array_length (properties); ++i) {
8062 prop = mono_array_get (properties, gpointer, i);
8063 get_prop_name_and_type (prop, &pname, &ptype);
8064 *p++ = 0x54; /* PROPERTY signature */
8065 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8072 for (i = 0; i < mono_array_length (fields); ++i) {
8076 field = mono_array_get (fields, gpointer, i);
8077 get_field_name_and_type (field, &fname, &ftype);
8078 *p++ = 0x53; /* FIELD signature */
8079 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8084 g_assert (p - buffer <= buflen);
8085 buflen = p - buffer;
8086 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8087 p = mono_array_addr (result, char, 0);
8088 memcpy (p, buffer, buflen);
8090 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8096 static void* reflection_info_desc = NULL;
8097 #define MOVING_GC_REGISTER(addr) do { \
8098 if (!reflection_info_desc) { \
8100 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8102 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8105 #define MOVING_GC_REGISTER(addr)
8109 * mono_reflection_setup_internal_class:
8110 * @tb: a TypeBuilder object
8112 * Creates a MonoClass that represents the TypeBuilder.
8113 * This is a trick that lets us simplify a lot of reflection code
8114 * (and will allow us to support Build and Run assemblies easier).
8117 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8119 MonoClass *klass, *parent;
8121 MONO_ARCH_SAVE_REGS;
8123 mono_loader_lock ();
8126 /* check so we can compile corlib correctly */
8127 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8128 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8129 parent = tb->parent->type->data.klass;
8131 parent = my_mono_class_from_mono_type (tb->parent->type);
8137 /* the type has already being created: it means we just have to change the parent */
8138 if (tb->type.type) {
8139 klass = mono_class_from_mono_type (tb->type.type);
8140 klass->parent = NULL;
8141 /* fool mono_class_setup_parent */
8142 klass->supertypes = NULL;
8143 mono_class_setup_parent (klass, parent);
8144 mono_class_setup_mono_type (klass);
8145 mono_loader_unlock ();
8149 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8151 klass->image = &tb->module->dynamic_image->image;
8153 klass->inited = 1; /* we lie to the runtime */
8154 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8155 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8156 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8157 klass->flags = tb->attrs;
8159 klass->element_class = klass;
8161 MOVING_GC_REGISTER (&klass->reflection_info);
8162 klass->reflection_info = tb;
8164 /* Put into cache so mono_class_get () will find it */
8165 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8167 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8168 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8170 if (parent != NULL) {
8171 mono_class_setup_parent (klass, parent);
8172 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8173 const char *old_n = klass->name;
8174 /* trick to get relative numbering right when compiling corlib */
8175 klass->name = "BuildingObject";
8176 mono_class_setup_parent (klass, mono_defaults.object_class);
8177 klass->name = old_n;
8180 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8181 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8182 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8183 klass->instance_size = sizeof (MonoObject);
8184 klass->size_inited = 1;
8185 mono_class_setup_vtable_general (klass, NULL, 0);
8188 mono_class_setup_mono_type (klass);
8190 mono_class_setup_supertypes (klass);
8193 * FIXME: handle interfaces.
8196 tb->type.type = &klass->byval_arg;
8198 if (tb->nesting_type) {
8199 g_assert (tb->nesting_type->type);
8200 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8203 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8205 mono_loader_unlock ();
8209 * mono_reflection_setup_generic_class:
8210 * @tb: a TypeBuilder object
8212 * Setup the generic class before adding the first generic parameter.
8215 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8219 MONO_ARCH_SAVE_REGS;
8221 klass = my_mono_class_from_mono_type (tb->type.type);
8222 if (tb->generic_container)
8225 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8226 tb->generic_container->owner.klass = klass;
8230 * mono_reflection_create_generic_class:
8231 * @tb: a TypeBuilder object
8233 * Creates the generic class after all generic parameters have been added.
8236 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8241 MONO_ARCH_SAVE_REGS;
8243 klass = my_mono_class_from_mono_type (tb->type.type);
8245 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8247 if (klass->generic_container || (count == 0))
8250 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8252 klass->generic_container = tb->generic_container;
8254 klass->generic_container->type_argc = count;
8255 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8257 for (i = 0; i < count; i++) {
8258 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8259 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8260 g_assert (klass->generic_container->type_params [i].owner);
8263 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8267 * mono_reflection_create_internal_class:
8268 * @tb: a TypeBuilder object
8270 * Actually create the MonoClass that is associated with the TypeBuilder.
8273 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8277 MONO_ARCH_SAVE_REGS;
8279 klass = my_mono_class_from_mono_type (tb->type.type);
8281 mono_loader_lock ();
8282 if (klass->enumtype && klass->enum_basetype == NULL) {
8283 MonoReflectionFieldBuilder *fb;
8286 g_assert (tb->fields != NULL);
8287 g_assert (mono_array_length (tb->fields) >= 1);
8289 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8291 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8292 mono_loader_unlock ();
8296 klass->enum_basetype = fb->type->type;
8297 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8298 if (!klass->element_class)
8299 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8302 * get the element_class from the current corlib.
8304 ec = default_class_from_mono_type (klass->enum_basetype);
8305 klass->instance_size = ec->instance_size;
8306 klass->size_inited = 1;
8308 * this is almost safe to do with enums and it's needed to be able
8309 * to create objects of the enum type (for use in SetConstant).
8311 /* FIXME: Does this mean enums can't have method overrides ? */
8312 mono_class_setup_vtable_general (klass, NULL, 0);
8314 mono_loader_unlock ();
8317 static MonoMarshalSpec*
8318 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8319 MonoReflectionMarshal *minfo)
8321 MonoMarshalSpec *res;
8323 res = g_new0 (MonoMarshalSpec, 1);
8324 res->native = minfo->type;
8326 switch (minfo->type) {
8327 case MONO_NATIVE_LPARRAY:
8328 res->data.array_data.elem_type = minfo->eltype;
8329 if (minfo->has_size) {
8330 res->data.array_data.param_num = minfo->param_num;
8331 res->data.array_data.num_elem = minfo->count;
8332 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8335 res->data.array_data.param_num = -1;
8336 res->data.array_data.num_elem = -1;
8337 res->data.array_data.elem_mult = -1;
8341 case MONO_NATIVE_BYVALTSTR:
8342 case MONO_NATIVE_BYVALARRAY:
8343 res->data.array_data.num_elem = minfo->count;
8346 case MONO_NATIVE_CUSTOM:
8347 if (minfo->marshaltyperef)
8348 res->data.custom_data.custom_name =
8349 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8351 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8361 MonoReflectionMarshal*
8362 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8363 MonoMarshalSpec *spec)
8365 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8366 MonoReflectionMarshal *minfo;
8369 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8370 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8371 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8372 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8375 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8376 minfo->type = spec->native;
8378 switch (minfo->type) {
8379 case MONO_NATIVE_LPARRAY:
8380 minfo->eltype = spec->data.array_data.elem_type;
8381 minfo->count = spec->data.array_data.num_elem;
8382 minfo->param_num = spec->data.array_data.param_num;
8385 case MONO_NATIVE_BYVALTSTR:
8386 case MONO_NATIVE_BYVALARRAY:
8387 minfo->count = spec->data.array_data.num_elem;
8390 case MONO_NATIVE_CUSTOM:
8391 if (spec->data.custom_data.custom_name) {
8392 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8394 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8396 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8398 if (spec->data.custom_data.cookie)
8399 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8410 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8411 ReflectionMethodBuilder *rmb,
8412 MonoMethodSignature *sig)
8415 MonoMethodNormal *pm;
8416 MonoMarshalSpec **specs;
8417 MonoReflectionMethodAux *method_aux;
8422 g_assert (!klass->generic_class);
8425 * Methods created using a MethodBuilder should have their memory allocated
8426 * inside the image mempool, while dynamic methods should have their memory
8429 dynamic = rmb->refs != NULL;
8430 mp = dynamic ? NULL : klass->image->mempool;
8432 mono_loader_lock ();
8434 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8435 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8436 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8438 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8440 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8442 pm = (MonoMethodNormal*)m;
8444 m->dynamic = dynamic;
8446 m->flags = rmb->attrs;
8447 m->iflags = rmb->iattrs;
8448 m->name = mp_string_to_utf8 (mp, rmb->name);
8451 m->skip_visibility = rmb->skip_visibility;
8453 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8455 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8456 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8459 m->signature->pinvoke = 1;
8460 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8461 m->signature->pinvoke = 1;
8463 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8465 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8466 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8468 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8470 if (klass->image->dynamic)
8471 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8473 mono_loader_unlock ();
8476 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8477 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8478 MonoMethodHeader *header;
8480 gint32 max_stack, i;
8481 gint32 num_locals = 0;
8482 gint32 num_clauses = 0;
8486 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8487 code_size = rmb->ilgen->code_len;
8488 max_stack = rmb->ilgen->max_stack;
8489 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8490 if (rmb->ilgen->ex_handlers)
8491 num_clauses = method_count_clauses (rmb->ilgen);
8494 code = mono_array_addr (rmb->code, guint8, 0);
8495 code_size = mono_array_length (rmb->code);
8496 /* we probably need to run a verifier on the code... */
8506 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8507 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8508 header->code_size = code_size;
8509 header->code = mp_g_malloc (mp, code_size);
8510 memcpy ((char*)header->code, code, code_size);
8511 header->max_stack = max_stack;
8512 header->init_locals = rmb->init_locals;
8513 header->num_locals = num_locals;
8515 for (i = 0; i < num_locals; ++i) {
8516 MonoReflectionLocalBuilder *lb =
8517 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8519 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8520 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8523 header->num_clauses = num_clauses;
8525 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8526 rmb->ilgen, num_clauses);
8529 pm->header = header;
8532 if (rmb->generic_params) {
8533 int count = mono_array_length (rmb->generic_params);
8534 MonoGenericContainer *container;
8536 m->generic_container = container = rmb->generic_container;
8537 container->type_argc = count;
8538 container->type_params = g_new0 (MonoGenericParam, count);
8539 container->owner.method = m;
8541 for (i = 0; i < count; i++) {
8542 MonoReflectionGenericParam *gp =
8543 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8545 container->type_params [i] = *gp->type.type->data.generic_param;
8548 if (klass->generic_container) {
8549 container->parent = klass->generic_container;
8550 container->context.class_inst = klass->generic_container->context.class_inst;
8552 container->context.method_inst = mono_get_shared_generic_inst (container);
8556 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8560 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8562 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8563 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8564 for (i = 0; i < rmb->nrefs; ++i)
8565 data [i + 1] = rmb->refs [i];
8570 /* Parameter info */
8573 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8574 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8575 for (i = 0; i <= m->signature->param_count; ++i) {
8576 MonoReflectionParamBuilder *pb;
8577 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8578 if ((i > 0) && (pb->attrs)) {
8579 /* Make a copy since it might point to a shared type structure */
8580 /* FIXME: Alloc this from a mempool */
8581 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8582 m->signature->params [i - 1]->attrs = pb->attrs;
8585 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8586 MonoDynamicImage *assembly;
8587 guint32 idx, def_type, len;
8591 if (!method_aux->param_defaults) {
8592 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8593 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8595 assembly = (MonoDynamicImage*)klass->image;
8596 idx = encode_constant (assembly, pb->def_value, &def_type);
8597 /* Copy the data from the blob since it might get realloc-ed */
8598 p = assembly->blob.data + idx;
8599 len = mono_metadata_decode_blob_size (p, &p2);
8601 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8602 method_aux->param_default_types [i] = def_type;
8603 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8607 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8609 if (!method_aux->param_cattr)
8610 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8611 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8617 /* Parameter marshalling */
8620 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8621 MonoReflectionParamBuilder *pb;
8622 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8623 if (pb->marshal_info) {
8625 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8626 specs [pb->position] =
8627 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8631 if (specs != NULL) {
8633 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8634 method_aux->param_marshall = specs;
8637 if (klass->image->dynamic && method_aux)
8638 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8640 mono_loader_unlock ();
8646 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8648 ReflectionMethodBuilder rmb;
8649 MonoMethodSignature *sig;
8651 mono_loader_lock ();
8652 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8653 mono_loader_unlock ();
8655 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8657 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8658 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8660 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8661 /* ilgen is no longer needed */
8669 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8671 ReflectionMethodBuilder rmb;
8672 MonoMethodSignature *sig;
8674 mono_loader_lock ();
8675 sig = method_builder_to_signature (klass->image->mempool, mb);
8676 mono_loader_unlock ();
8678 reflection_methodbuilder_from_method_builder (&rmb, mb);
8680 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8681 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8683 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8684 /* ilgen is no longer needed */
8690 static MonoClassField*
8691 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8693 MonoClassField *field;
8697 field = g_new0 (MonoClassField, 1);
8699 field->name = mono_string_to_utf8 (fb->name);
8701 /* FIXME: handle type modifiers */
8702 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8703 field->type->attrs = fb->attrs;
8705 field->type = fb->type->type;
8707 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8708 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8709 if (fb->offset != -1)
8710 field->offset = fb->offset;
8711 field->parent = klass;
8712 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8714 if (fb->def_value) {
8715 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8716 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8717 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8718 /* Copy the data from the blob since it might get realloc-ed */
8719 p = assembly->blob.data + idx;
8720 len = mono_metadata_decode_blob_size (p, &p2);
8722 field->data = g_malloc (len);
8723 memcpy ((gpointer)field->data, p, len);
8730 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8733 MonoReflectionTypeBuilder *tb = NULL;
8734 gboolean is_dynamic = FALSE;
8738 mono_loader_lock ();
8740 domain = mono_object_domain (type);
8742 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8743 tb = (MonoReflectionTypeBuilder *) type;
8746 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8747 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8748 MonoReflectionType *rgt = rgi->generic_type;
8750 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8751 tb = (MonoReflectionTypeBuilder *) rgt;
8756 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8757 if (tb && tb->generic_container)
8758 mono_reflection_create_generic_class (tb);
8760 klass = mono_class_from_mono_type (type->type);
8761 if (!klass->generic_container) {
8762 mono_loader_unlock ();
8766 if (klass->wastypebuilder) {
8767 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8772 mono_loader_unlock ();
8774 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8776 return &geninst->byval_arg;
8780 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8782 MonoGenericClass *gclass;
8783 MonoGenericInst *inst;
8785 g_assert (klass->generic_container);
8787 inst = mono_metadata_get_generic_inst (type_argc, types);
8788 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8790 return mono_generic_class_get_class (gclass);
8793 MonoReflectionMethod*
8794 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8797 MonoMethod *method, *inflated;
8798 MonoMethodInflated *imethod;
8799 MonoReflectionMethodBuilder *mb = NULL;
8800 MonoGenericContext tmp_context;
8801 MonoGenericInst *ginst;
8802 MonoType **type_argv;
8805 MONO_ARCH_SAVE_REGS;
8806 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8807 MonoReflectionTypeBuilder *tb;
8810 mb = (MonoReflectionMethodBuilder *) rmethod;
8811 tb = (MonoReflectionTypeBuilder *) mb->type;
8812 klass = mono_class_from_mono_type (tb->type.type);
8814 method = methodbuilder_to_mono_method (klass, mb);
8816 method = rmethod->method;
8819 klass = method->klass;
8821 if (method->is_inflated)
8822 method = ((MonoMethodInflated *) method)->declaring;
8824 count = mono_method_signature (method)->generic_param_count;
8825 if (count != mono_array_length (types))
8828 type_argv = g_new0 (MonoType *, count);
8829 for (i = 0; i < count; i++) {
8830 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8831 type_argv [i] = garg->type;
8833 ginst = mono_metadata_get_generic_inst (count, type_argv);
8836 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8837 tmp_context.method_inst = ginst;
8839 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8840 imethod = (MonoMethodInflated *) inflated;
8842 MOVING_GC_REGISTER (&imethod->reflection_info);
8843 imethod->reflection_info = rmethod;
8845 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8849 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8851 MonoMethodInflated *imethod;
8852 MonoGenericContext tmp_context;
8853 MonoGenericContext *context;
8856 klass = mono_class_from_mono_type (type->type.type);
8857 g_assert (klass->generic_class);
8858 context = mono_class_get_context (klass);
8860 if (method->generic_container) {
8861 g_assert (method->klass == klass->generic_class->container_class);
8863 tmp_context.class_inst = klass->generic_class->context.class_inst;
8864 tmp_context.method_inst = method->generic_container->context.method_inst;
8865 context = &tmp_context;
8868 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8869 if (method->generic_container) {
8870 MOVING_GC_REGISTER (&imethod->reflection_info);
8871 imethod->reflection_info = obj;
8873 return (MonoMethod *) imethod;
8877 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8882 gklass = mono_class_from_mono_type (type->generic_type->type);
8884 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8885 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8886 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8887 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8888 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8889 method = ((MonoReflectionMethod *) obj)->method;
8891 method = NULL; /* prevent compiler warning */
8892 g_assert_not_reached ();
8895 return inflate_mono_method (type, method, obj);
8899 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8900 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8903 MonoGenericClass *gclass;
8904 MonoDynamicGenericClass *dgclass;
8905 MonoClass *klass, *gklass;
8908 MONO_ARCH_SAVE_REGS;
8910 klass = mono_class_from_mono_type (type->type.type);
8911 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
8912 gclass = type->type.type->data.generic_class;
8914 g_assert (gclass->is_dynamic);
8915 dgclass = (MonoDynamicGenericClass *) gclass;
8917 if (dgclass->initialized)
8920 gklass = gclass->container_class;
8921 mono_class_init (gklass);
8923 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8924 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8925 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8926 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8927 dgclass->count_events = events ? mono_array_length (events) : 0;
8929 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8930 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8931 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8932 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8933 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8935 for (i = 0; i < dgclass->count_methods; i++) {
8936 MonoObject *obj = mono_array_get (methods, gpointer, i);
8938 dgclass->methods [i] = inflate_method (type, obj);
8941 for (i = 0; i < dgclass->count_ctors; i++) {
8942 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8944 dgclass->ctors [i] = inflate_method (type, obj);
8947 for (i = 0; i < dgclass->count_fields; i++) {
8948 MonoObject *obj = mono_array_get (fields, gpointer, i);
8949 MonoClassField *field;
8950 MonoInflatedField *ifield;
8952 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8953 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8954 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8955 field = ((MonoReflectionField *) obj)->field;
8957 field = NULL; /* prevent compiler warning */
8958 g_assert_not_reached ();
8961 ifield = g_new0 (MonoInflatedField, 1);
8962 ifield->generic_type = field->type;
8963 MOVING_GC_REGISTER (&ifield->reflection_info);
8964 ifield->reflection_info = obj;
8966 dgclass->fields [i] = *field;
8967 dgclass->fields [i].parent = klass;
8968 dgclass->fields [i].generic_info = ifield;
8969 dgclass->fields [i].type = mono_class_inflate_generic_type (
8970 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
8973 for (i = 0; i < dgclass->count_properties; i++) {
8974 MonoObject *obj = mono_array_get (properties, gpointer, i);
8975 MonoProperty *property = &dgclass->properties [i];
8977 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8978 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8980 property->parent = klass;
8981 property->attrs = pb->attrs;
8982 property->name = mono_string_to_utf8 (pb->name);
8984 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8986 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8987 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8988 *property = *((MonoReflectionProperty *) obj)->property;
8991 property->get = inflate_mono_method (type, property->get, NULL);
8993 property->set = inflate_mono_method (type, property->set, NULL);
8995 g_assert_not_reached ();
8998 for (i = 0; i < dgclass->count_events; i++) {
8999 MonoObject *obj = mono_array_get (events, gpointer, i);
9000 MonoEvent *event = &dgclass->events [i];
9002 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9003 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9005 event->parent = klass;
9006 event->attrs = eb->attrs;
9007 event->name = mono_string_to_utf8 (eb->name);
9009 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9010 if (eb->remove_method)
9011 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9012 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9013 *event = *((MonoReflectionEvent *) obj)->event;
9016 event->add = inflate_mono_method (type, event->add, NULL);
9018 event->remove = inflate_mono_method (type, event->remove, NULL);
9020 g_assert_not_reached ();
9023 dgclass->initialized = TRUE;
9027 ensure_runtime_vtable (MonoClass *klass)
9029 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9032 if (!tb || klass->wastypebuilder)
9035 ensure_runtime_vtable (klass->parent);
9037 num = tb->ctors? mono_array_length (tb->ctors): 0;
9038 num += tb->num_methods;
9039 klass->method.count = num;
9040 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9041 num = tb->ctors? mono_array_length (tb->ctors): 0;
9042 for (i = 0; i < num; ++i)
9043 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9044 num = tb->num_methods;
9046 for (i = 0; i < num; ++i)
9047 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9049 if (tb->interfaces) {
9050 klass->interface_count = mono_array_length (tb->interfaces);
9051 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9052 for (i = 0; i < klass->interface_count; ++i) {
9053 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9054 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9058 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9059 for (i = 0; i < klass->method.count; ++i)
9060 klass->methods [i]->slot = i;
9062 mono_class_setup_interface_offsets (klass);
9066 * The generic vtable is needed even if image->run is not set since some
9067 * runtime code like ves_icall_Type_GetMethodsByName depends on
9068 * method->slot being defined.
9072 * tb->methods could not be freed since it is used for determining
9073 * overrides during dynamic vtable construction.
9078 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9080 MonoReflectionTypeBuilder *tb;
9086 g_assert (klass->image->dynamic);
9088 if (!klass->reflection_info)
9091 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9093 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9097 for (i = 0; i < tb->num_methods; ++i) {
9098 MonoReflectionMethodBuilder *mb =
9099 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9100 if (mb->override_method)
9106 *overrides = g_new0 (MonoMethod*, onum * 2);
9109 for (i = 0; i < tb->num_methods; ++i) {
9110 MonoReflectionMethodBuilder *mb =
9111 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9112 if (mb->override_method) {
9113 (*overrides) [onum * 2] =
9114 mb->override_method->method;
9115 (*overrides) [onum * 2 + 1] =
9118 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9119 g_assert (mb->override_method->method);
9120 g_assert (mb->mhandle);
9127 *num_overrides = onum;
9131 typebuilder_setup_fields (MonoClass *klass)
9133 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9134 MonoReflectionFieldBuilder *fb;
9135 MonoClassField *field;
9140 klass->field.count = tb->num_fields;
9141 klass->field.first = 0;
9143 if (!klass->field.count)
9146 klass->fields = g_new0 (MonoClassField, klass->field.count);
9148 for (i = 0; i < klass->field.count; ++i) {
9149 fb = mono_array_get (tb->fields, gpointer, i);
9150 field = &klass->fields [i];
9151 field->name = mono_string_to_utf8 (fb->name);
9153 /* FIXME: handle type modifiers */
9154 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9155 field->type->attrs = fb->attrs;
9157 field->type = fb->type->type;
9159 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9160 field->data = mono_array_addr (fb->rva_data, char, 0);
9161 if (fb->offset != -1)
9162 field->offset = fb->offset;
9163 field->parent = klass;
9165 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9167 if (fb->def_value) {
9168 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9169 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9170 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9171 /* Copy the data from the blob since it might get realloc-ed */
9172 p = assembly->blob.data + idx;
9173 len = mono_metadata_decode_blob_size (p, &p2);
9175 field->data = g_malloc (len);
9176 memcpy ((gpointer)field->data, p, len);
9179 mono_class_layout_fields (klass);
9183 typebuilder_setup_properties (MonoClass *klass)
9185 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9186 MonoReflectionPropertyBuilder *pb;
9189 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9190 klass->property.first = 0;
9192 klass->properties = g_new0 (MonoProperty, klass->property.count);
9193 for (i = 0; i < klass->property.count; ++i) {
9194 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9195 klass->properties [i].parent = klass;
9196 klass->properties [i].attrs = pb->attrs;
9197 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9199 klass->properties [i].get = pb->get_method->mhandle;
9201 klass->properties [i].set = pb->set_method->mhandle;
9203 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9207 MonoReflectionEvent *
9208 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9210 MonoEvent *event = g_new0 (MonoEvent, 1);
9214 klass = my_mono_class_from_mono_type (tb->type.type);
9216 event->parent = klass;
9217 event->attrs = eb->attrs;
9218 event->name = mono_string_to_utf8 (eb->name);
9220 event->add = eb->add_method->mhandle;
9221 if (eb->remove_method)
9222 event->remove = eb->remove_method->mhandle;
9223 if (eb->raise_method)
9224 event->raise = eb->raise_method->mhandle;
9226 if (eb->other_methods) {
9227 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9228 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9229 MonoReflectionMethodBuilder *mb =
9230 mono_array_get (eb->other_methods,
9231 MonoReflectionMethodBuilder*, j);
9232 event->other [j] = mb->mhandle;
9236 return mono_event_get_object (mono_object_domain (tb), klass, event);
9240 typebuilder_setup_events (MonoClass *klass)
9242 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9243 MonoReflectionEventBuilder *eb;
9246 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9247 klass->event.first = 0;
9249 klass->events = g_new0 (MonoEvent, klass->event.count);
9250 for (i = 0; i < klass->event.count; ++i) {
9251 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9252 klass->events [i].parent = klass;
9253 klass->events [i].attrs = eb->attrs;
9254 klass->events [i].name = mono_string_to_utf8 (eb->name);
9256 klass->events [i].add = eb->add_method->mhandle;
9257 if (eb->remove_method)
9258 klass->events [i].remove = eb->remove_method->mhandle;
9259 if (eb->raise_method)
9260 klass->events [i].raise = eb->raise_method->mhandle;
9262 if (eb->other_methods) {
9263 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9264 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9265 MonoReflectionMethodBuilder *mb =
9266 mono_array_get (eb->other_methods,
9267 MonoReflectionMethodBuilder*, j);
9268 klass->events [i].other [j] = mb->mhandle;
9275 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9279 MonoReflectionType* res;
9282 MONO_ARCH_SAVE_REGS;
9284 domain = mono_object_domain (tb);
9285 klass = my_mono_class_from_mono_type (tb->type.type);
9287 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9290 * we need to lock the domain because the lock will be taken inside
9291 * So, we need to keep the locking order correct.
9293 mono_domain_lock (domain);
9294 mono_loader_lock ();
9295 if (klass->wastypebuilder) {
9296 mono_loader_unlock ();
9297 mono_domain_unlock (domain);
9298 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9301 * Fields to set in klass:
9302 * the various flags: delegate/unicode/contextbound etc.
9304 klass->flags = tb->attrs;
9305 klass->has_cctor = 1;
9306 klass->has_finalize = 1;
9309 if (!((MonoDynamicImage*)klass->image)->run) {
9310 if (klass->generic_container) {
9311 /* FIXME: The code below can't handle generic classes */
9312 klass->wastypebuilder = TRUE;
9313 mono_loader_unlock ();
9314 mono_domain_unlock (domain);
9315 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9320 /* enums are done right away */
9321 if (!klass->enumtype)
9322 ensure_runtime_vtable (klass);
9325 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9326 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9327 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9331 /* fields and object layout */
9332 if (klass->parent) {
9333 if (!klass->parent->size_inited)
9334 mono_class_init (klass->parent);
9335 klass->instance_size = klass->parent->instance_size;
9336 klass->sizes.class_size = 0;
9337 klass->min_align = klass->parent->min_align;
9338 /* if the type has no fields we won't call the field_setup
9339 * routine which sets up klass->has_references.
9341 klass->has_references |= klass->parent->has_references;
9343 klass->instance_size = sizeof (MonoObject);
9344 klass->min_align = 1;
9347 /* FIXME: handle packing_size and instance_size */
9348 typebuilder_setup_fields (klass);
9350 typebuilder_setup_properties (klass);
9352 typebuilder_setup_events (klass);
9354 klass->wastypebuilder = TRUE;
9355 mono_loader_unlock ();
9356 mono_domain_unlock (domain);
9358 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9359 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9360 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9363 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9364 g_assert (res != (MonoReflectionType*)tb);
9370 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9372 MonoGenericParam *param;
9375 MONO_ARCH_SAVE_REGS;
9377 param = g_new0 (MonoGenericParam, 1);
9379 if (gparam->mbuilder) {
9380 if (!gparam->mbuilder->generic_container)
9381 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9382 param->owner = gparam->mbuilder->generic_container;
9383 } else if (gparam->tbuilder) {
9384 g_assert (gparam->tbuilder->generic_container);
9385 param->owner = gparam->tbuilder->generic_container;
9388 param->name = mono_string_to_utf8 (gparam->name);
9389 param->num = gparam->index;
9391 image = &gparam->tbuilder->module->dynamic_image->image;
9392 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9394 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9395 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9397 gparam->type.type = g_new0 (MonoType, 1);
9398 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9399 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9400 gparam->type.type->data.generic_param = param;
9404 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9406 MonoDynamicImage *assembly = sig->module->dynamic_image;
9407 guint32 na = mono_array_length (sig->arguments);
9412 sigbuffer_init (&buf, 32);
9414 sigbuffer_add_value (&buf, 0x07);
9415 sigbuffer_add_value (&buf, na);
9416 for (i = 0; i < na; ++i) {
9417 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9418 encode_reflection_type (assembly, type, &buf);
9421 buflen = buf.p - buf.buf;
9422 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9423 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9424 sigbuffer_free (&buf);
9430 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9432 MonoDynamicImage *assembly = sig->module->dynamic_image;
9433 guint32 na = mono_array_length (sig->arguments);
9438 sigbuffer_init (&buf, 32);
9440 sigbuffer_add_value (&buf, 0x06);
9441 for (i = 0; i < na; ++i) {
9442 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9443 encode_reflection_type (assembly, type, &buf);
9446 buflen = buf.p - buf.buf;
9447 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9448 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9449 sigbuffer_free (&buf);
9455 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9457 ReflectionMethodBuilder rmb;
9458 MonoMethodSignature *sig;
9463 sig = dynamic_method_to_signature (mb);
9465 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9468 * Resolve references.
9471 * Every second entry in the refs array is reserved for storing handle_class,
9472 * which is needed by the ldtoken implementation in the JIT.
9474 rmb.nrefs = mb->nrefs;
9475 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9476 for (i = 0; i < mb->nrefs; i += 2) {
9477 MonoClass *handle_class;
9479 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9481 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9482 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9484 * The referenced DynamicMethod should already be created by the managed
9485 * code, except in the case of circular references. In that case, we store
9486 * method in the refs array, and fix it up later when the referenced
9487 * DynamicMethod is created.
9489 if (method->mhandle) {
9490 ref = method->mhandle;
9492 /* FIXME: GC object stored in unmanaged memory */
9495 /* FIXME: GC object stored in unmanaged memory */
9496 method->referenced_by = g_slist_append (method->referenced_by, mb);
9498 handle_class = mono_defaults.methodhandle_class;
9500 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9503 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9508 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9509 rmb.refs [i + 1] = handle_class;
9512 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9514 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9516 /* Fix up refs entries pointing at us */
9517 for (l = mb->referenced_by; l; l = l->next) {
9518 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9519 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9522 g_assert (method->mhandle);
9524 data = (gpointer*)wrapper->method_data;
9525 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9526 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9527 data [i + 1] = mb->mhandle;
9530 g_slist_free (mb->referenced_by);
9534 /* ilgen is no longer needed */
9539 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9544 mono_runtime_free_method (
9545 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9549 * mono_reflection_lookup_dynamic_token:
9551 * Finish the Builder object pointed to by TOKEN and return the corresponding
9552 * runtime structure. HANDLE_CLASS is set to the class required by
9556 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context)
9558 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9561 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9564 return resolve_object (image, obj, handle_class, context);
9568 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9570 gpointer result = NULL;
9572 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9573 result = mono_string_intern ((MonoString*)obj);
9574 *handle_class = NULL;
9576 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9577 MonoReflectionType *tb = (MonoReflectionType*)obj;
9579 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9580 result = mono_class_from_mono_type (inflated);
9581 mono_metadata_free_type (inflated);
9583 result = mono_class_from_mono_type (tb->type);
9585 *handle_class = mono_defaults.typehandle_class;
9587 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9588 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9589 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9590 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9591 result = ((MonoReflectionMethod*)obj)->method;
9592 result = mono_class_inflate_generic_method (result, context);
9593 *handle_class = mono_defaults.methodhandle_class;
9595 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9596 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9597 result = mb->mhandle;
9599 /* Type is not yet created */
9600 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9602 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9605 * Hopefully this has been filled in by calling CreateType() on the
9609 * TODO: This won't work if the application finishes another
9610 * TypeBuilder instance instead of this one.
9612 result = mb->mhandle;
9614 result = mono_class_inflate_generic_method (result, context);
9615 *handle_class = mono_defaults.methodhandle_class;
9616 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9617 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9619 result = cb->mhandle;
9621 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9623 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9624 result = cb->mhandle;
9626 result = mono_class_inflate_generic_method (result, context);
9627 *handle_class = mono_defaults.methodhandle_class;
9628 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9629 result = ((MonoReflectionField*)obj)->field;
9630 *handle_class = mono_defaults.fieldhandle_class;
9632 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9633 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9634 result = fb->handle;
9637 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9639 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9640 result = fb->handle;
9642 *handle_class = mono_defaults.fieldhandle_class;
9643 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9644 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9647 klass = tb->type.type->data.klass;
9648 if (klass->wastypebuilder) {
9649 /* Already created */
9653 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9654 result = tb->type.type->data.klass;
9657 *handle_class = mono_defaults.typehandle_class;
9658 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9659 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9660 MonoMethodSignature *sig;
9663 if (helper->arguments)
9664 nargs = mono_array_length (helper->arguments);
9668 sig = mono_metadata_signature_alloc (image, nargs);
9669 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9670 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9672 if (helper->call_conv == 0) /* unmanaged */
9673 sig->call_convention = helper->unmanaged_call_conv - 1;
9675 if (helper->call_conv & 0x02)
9676 sig->call_convention = MONO_CALL_VARARG;
9678 sig->call_convention = MONO_CALL_DEFAULT;
9680 sig->param_count = nargs;
9681 /* TODO: Copy type ? */
9682 sig->ret = helper->return_type->type;
9683 for (i = 0; i < nargs; ++i) {
9684 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9685 sig->params [i] = rt->type;
9689 *handle_class = NULL;
9690 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9691 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9692 /* Already created by the managed code */
9693 g_assert (method->mhandle);
9694 result = method->mhandle;
9695 *handle_class = mono_defaults.methodhandle_class;
9696 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9697 MonoReflectionType *tb = (MonoReflectionType*)obj;
9698 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9699 *handle_class = mono_defaults.typehandle_class;
9701 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9702 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9703 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9704 *handle_class = mono_defaults.typehandle_class;
9707 g_print (obj->vtable->klass->name);
9708 g_assert_not_reached ();
9714 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9715 const static guint32 declsec_flags_map[] = {
9716 0x00000000, /* empty */
9717 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9718 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9719 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9720 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9721 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9722 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9723 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9724 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9725 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9726 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9727 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9728 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9729 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9730 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9731 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9732 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9733 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9734 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9738 * Returns flags that includes all available security action associated to the handle.
9739 * @token: metadata token (either for a class or a method)
9740 * @image: image where resides the metadata.
9743 mono_declsec_get_flags (MonoImage *image, guint32 token)
9745 int index = mono_metadata_declsec_from_index (image, token);
9746 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9751 /* HasSecurity can be present for other, not specially encoded, attributes,
9752 e.g. SuppressUnmanagedCodeSecurityAttribute */
9756 for (i = index; i < t->rows; i++) {
9757 guint32 cols [MONO_DECL_SECURITY_SIZE];
9759 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9760 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9763 action = cols [MONO_DECL_SECURITY_ACTION];
9764 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9765 result |= declsec_flags_map [action];
9767 g_assert_not_reached ();
9774 * Get the security actions (in the form of flags) associated with the specified method.
9776 * @method: The method for which we want the declarative security flags.
9777 * Return the declarative security flags for the method (only).
9779 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9780 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9783 mono_declsec_flags_from_method (MonoMethod *method)
9785 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9786 /* FIXME: No cache (for the moment) */
9787 guint32 idx = mono_method_get_index (method);
9788 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9789 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9790 return mono_declsec_get_flags (method->klass->image, idx);
9796 * Get the security actions (in the form of flags) associated with the specified class.
9798 * @klass: The class for which we want the declarative security flags.
9799 * Return the declarative security flags for the class.
9801 * Note: We cache the flags inside the MonoClass structure as this will get
9802 * called very often (at least for each method).
9805 mono_declsec_flags_from_class (MonoClass *klass)
9807 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9808 if (!klass->declsec_flags) {
9809 guint32 idx = mono_metadata_token_index (klass->type_token);
9810 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9811 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9812 /* we cache the flags on classes */
9813 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9815 return klass->declsec_flags;
9821 * Get the security actions (in the form of flags) associated with the specified assembly.
9823 * @assembly: The assembly for which we want the declarative security flags.
9824 * Return the declarative security flags for the assembly.
9827 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9829 guint32 idx = 1; /* there is only one assembly */
9830 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9831 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9832 return mono_declsec_get_flags (assembly->image, idx);
9837 * Fill actions for the specific index (which may either be an encoded class token or
9838 * an encoded method token) from the metadata image.
9839 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9842 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9843 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9845 MonoBoolean result = FALSE;
9847 guint32 cols [MONO_DECL_SECURITY_SIZE];
9848 int index = mono_metadata_declsec_from_index (image, token);
9851 t = &image->tables [MONO_TABLE_DECLSECURITY];
9852 for (i = index; i < t->rows; i++) {
9853 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9855 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9858 /* if present only replace (class) permissions with method permissions */
9859 /* if empty accept either class or method permissions */
9860 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9861 if (!actions->demand.blob) {
9862 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9863 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9864 actions->demand.blob = (char*) (blob + 2);
9865 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9868 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9869 if (!actions->noncasdemand.blob) {
9870 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9871 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9872 actions->noncasdemand.blob = (char*) (blob + 2);
9873 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9876 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9877 if (!actions->demandchoice.blob) {
9878 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9879 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9880 actions->demandchoice.blob = (char*) (blob + 2);
9881 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9891 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9892 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9894 guint32 idx = mono_metadata_token_index (klass->type_token);
9895 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9896 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9897 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9901 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9902 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9904 guint32 idx = mono_method_get_index (method);
9905 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9906 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9907 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9911 * Collect all actions (that requires to generate code in mini) assigned for
9912 * the specified method.
9913 * Note: Don't use the content of actions if the function return FALSE.
9916 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9918 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9919 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9920 MonoBoolean result = FALSE;
9923 /* quick exit if no declarative security is present in the metadata */
9924 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9927 /* we want the original as the wrapper is "free" of the security informations */
9928 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9929 method = mono_marshal_method_from_wrapper (method);
9934 /* First we look for method-level attributes */
9935 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9936 mono_class_init (method->klass);
9937 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9939 result = mono_declsec_get_method_demands_params (method, demands,
9940 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9943 /* Here we use (or create) the class declarative cache to look for demands */
9944 flags = mono_declsec_flags_from_class (method->klass);
9947 mono_class_init (method->klass);
9948 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9950 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9951 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9954 /* The boolean return value is used as a shortcut in case nothing needs to
9955 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9961 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9963 * Note: Don't use the content of actions if the function return FALSE.
9966 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9968 MonoBoolean result = FALSE;
9971 /* quick exit if no declarative security is present in the metadata */
9972 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9975 /* we want the original as the wrapper is "free" of the security informations */
9976 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9977 method = mono_marshal_method_from_wrapper (method);
9982 /* results are independant - zeroize both */
9983 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9984 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9986 /* First we look for method-level attributes */
9987 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9988 mono_class_init (method->klass);
9990 result = mono_declsec_get_method_demands_params (method, cmethod,
9991 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9994 /* Here we use (or create) the class declarative cache to look for demands */
9995 flags = mono_declsec_flags_from_class (method->klass);
9996 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9997 mono_class_init (method->klass);
9999 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10000 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10007 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10009 * @klass The inherited class - this is the class that provides the security check (attributes)
10011 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10013 * Note: Don't use the content of actions if the function return FALSE.
10016 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10018 MonoBoolean result = FALSE;
10021 /* quick exit if no declarative security is present in the metadata */
10022 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10025 /* Here we use (or create) the class declarative cache to look for demands */
10026 flags = mono_declsec_flags_from_class (klass);
10027 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10028 mono_class_init (klass);
10029 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10031 result |= mono_declsec_get_class_demands_params (klass, demands,
10032 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10039 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10041 * Note: Don't use the content of actions if the function return FALSE.
10044 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10046 /* quick exit if no declarative security is present in the metadata */
10047 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10050 /* we want the original as the wrapper is "free" of the security informations */
10051 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10052 method = mono_marshal_method_from_wrapper (method);
10057 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10058 mono_class_init (method->klass);
10059 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10061 return mono_declsec_get_method_demands_params (method, demands,
10062 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10069 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10071 guint32 cols [MONO_DECL_SECURITY_SIZE];
10075 int index = mono_metadata_declsec_from_index (image, token);
10079 t = &image->tables [MONO_TABLE_DECLSECURITY];
10080 for (i = index; i < t->rows; i++) {
10081 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10083 /* shortcut - index are ordered */
10084 if (token != cols [MONO_DECL_SECURITY_PARENT])
10087 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10088 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10089 entry->blob = (char*) (metadata + 2);
10090 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10099 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10101 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10102 guint32 idx = mono_method_get_index (method);
10103 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10104 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10105 return get_declsec_action (method->klass->image, idx, action, entry);
10111 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10114 guint32 flags = mono_declsec_flags_from_class (klass);
10115 if (declsec_flags_map [action] & flags) {
10116 guint32 idx = mono_metadata_token_index (klass->type_token);
10117 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10118 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10119 return get_declsec_action (klass->image, idx, action, entry);
10125 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10127 guint32 idx = 1; /* there is only one assembly */
10128 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10129 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10131 return get_declsec_action (assembly->image, idx, action, entry);
10135 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10137 MonoObject *res, *exc;
10139 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10140 static MonoMethod *method = NULL;
10142 if (!System_Reflection_Emit_TypeBuilder) {
10143 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10144 g_assert (System_Reflection_Emit_TypeBuilder);
10146 if (method == NULL) {
10147 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10152 * The result of mono_type_get_object () might be a System.MonoType but we
10153 * need a TypeBuilder so use klass->reflection_info.
10155 g_assert (klass->reflection_info);
10156 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10158 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10160 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10164 return *(MonoBoolean*)mono_object_unbox (res);