2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/gc-internal.h"
17 #include "mono/metadata/tokentype.h"
18 #include "mono/metadata/domain-internals.h"
19 #include "mono/metadata/opcodes.h"
20 #include "mono/metadata/assembly.h"
21 #include "mono/metadata/object-internals.h"
22 #include <mono/metadata/exception.h>
23 #include <mono/metadata/marshal.h>
24 #include <mono/metadata/security-manager.h>
33 #include "rawbuffer.h"
34 #include "mono-endian.h"
35 #include <mono/os/gc_wrapper.h>
43 #define TEXT_OFFSET 512
44 #define CLI_H_SIZE 136
45 #define FILE_ALIGN 512
46 #define VIRT_ALIGN 8192
47 #define START_TEXT_RVA 0x00002000
50 MonoReflectionILGen *ilgen;
51 MonoReflectionType *rtype;
52 MonoArray *parameters;
53 MonoArray *generic_params;
54 MonoGenericContainer *generic_container;
60 guint32 *table_idx; /* note: it's a pointer */
64 MonoBoolean init_locals;
65 MonoBoolean skip_visibility;
66 MonoArray *return_modreq;
67 MonoArray *return_modopt;
68 MonoArray *param_modreq;
69 MonoArray *param_modopt;
70 MonoArray *permissions;
75 int charset, extra_flags, native_cc;
76 MonoString *dll, *dllentry;
77 } ReflectionMethodBuilder;
81 MonoReflectionGenericParam *gparam;
82 } GenericParamTableEntry;
84 const unsigned char table_sizes [MONO_TABLE_NUM] = {
94 MONO_INTERFACEIMPL_SIZE,
95 MONO_MEMBERREF_SIZE, /* 0x0A */
97 MONO_CUSTOM_ATTR_SIZE,
98 MONO_FIELD_MARSHAL_SIZE,
99 MONO_DECL_SECURITY_SIZE,
100 MONO_CLASS_LAYOUT_SIZE,
101 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
102 MONO_STAND_ALONE_SIGNATURE_SIZE,
106 MONO_PROPERTY_MAP_SIZE,
109 MONO_METHOD_SEMA_SIZE,
110 MONO_METHODIMPL_SIZE,
111 MONO_MODULEREF_SIZE, /* 0x1A */
117 MONO_ASSEMBLY_SIZE, /* 0x20 */
118 MONO_ASSEMBLY_PROCESSOR_SIZE,
119 MONO_ASSEMBLYOS_SIZE,
120 MONO_ASSEMBLYREF_SIZE,
121 MONO_ASSEMBLYREFPROC_SIZE,
122 MONO_ASSEMBLYREFOS_SIZE,
126 MONO_NESTED_CLASS_SIZE,
128 MONO_GENERICPARAM_SIZE, /* 0x2A */
129 MONO_METHODSPEC_SIZE,
130 MONO_GENPARCONSTRAINT_SIZE
134 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
135 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
136 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
137 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
138 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
139 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
140 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
141 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
142 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
143 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
144 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
145 static void ensure_runtime_vtable (MonoClass *klass);
146 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
147 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
148 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
149 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
150 static inline MonoType *dup_type (const MonoType *original);
151 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
153 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
154 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
155 static CRITICAL_SECTION reflection_mutex;
158 mono_reflection_init (void)
160 InitializeCriticalSection (&reflection_mutex);
164 sigbuffer_init (SigBuffer *buf, int size)
166 buf->buf = g_malloc (size);
168 buf->end = buf->buf + size;
172 sigbuffer_make_room (SigBuffer *buf, int size)
174 if (buf->end - buf->p < size) {
175 int new_size = buf->end - buf->buf + size + 32;
176 char *p = g_realloc (buf->buf, new_size);
177 size = buf->p - buf->buf;
180 buf->end = buf->buf + new_size;
185 sigbuffer_add_value (SigBuffer *buf, guint32 val)
187 sigbuffer_make_room (buf, 6);
188 mono_metadata_encode_value (val, buf->p, &buf->p);
192 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
194 sigbuffer_make_room (buf, 1);
200 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
202 sigbuffer_make_room (buf, size);
203 memcpy (buf->p, p, size);
208 sigbuffer_free (SigBuffer *buf)
216 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
220 mp_g_malloc (MonoMemPool *mp, guint size)
223 return mono_mempool_alloc (mp, size);
225 return g_malloc (size);
231 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
235 mp_g_malloc0 (MonoMemPool *mp, guint size)
238 return mono_mempool_alloc0 (mp, size);
240 return g_malloc0 (size);
243 #define mp_g_new(mp,struct_type, n_structs) \
244 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
246 #define mp_g_new0(mp,struct_type, n_structs) \
247 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
250 alloc_table (MonoDynamicTable *table, guint nrows)
253 g_assert (table->columns);
254 if (nrows + 1 >= table->alloc_rows) {
255 while (nrows + 1 >= table->alloc_rows) {
256 if (table->alloc_rows == 0)
257 table->alloc_rows = 16;
259 table->alloc_rows *= 2;
262 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
267 make_room_in_stream (MonoDynamicStream *stream, int size)
269 if (size <= stream->alloc_size)
272 while (stream->alloc_size <= size) {
273 if (stream->alloc_size < 4096)
274 stream->alloc_size = 4096;
276 stream->alloc_size *= 2;
279 stream->data = g_realloc (stream->data, stream->alloc_size);
283 string_heap_insert (MonoDynamicStream *sh, const char *str)
287 gpointer oldkey, oldval;
289 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
290 return GPOINTER_TO_UINT (oldval);
292 len = strlen (str) + 1;
295 make_room_in_stream (sh, idx + len);
298 * We strdup the string even if we already copy them in sh->data
299 * so that the string pointers in the hash remain valid even if
300 * we need to realloc sh->data. We may want to avoid that later.
302 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
303 memcpy (sh->data + idx, str, len);
309 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
311 char *name = mono_string_to_utf8 (str);
313 idx = string_heap_insert (sh, name);
319 string_heap_init (MonoDynamicStream *sh)
322 sh->alloc_size = 4096;
323 sh->data = g_malloc (4096);
324 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
325 string_heap_insert (sh, "");
329 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
333 make_room_in_stream (stream, stream->index + len);
334 memcpy (stream->data + stream->index, data, len);
336 stream->index += len;
338 * align index? Not without adding an additional param that controls it since
339 * we may store a blob value in pieces.
345 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
349 make_room_in_stream (stream, stream->index + len);
350 memset (stream->data + stream->index, 0, len);
352 stream->index += len;
357 stream_data_align (MonoDynamicStream *stream)
360 guint32 count = stream->index % 4;
362 /* we assume the stream data will be aligned */
364 mono_image_add_stream_data (stream, buf, 4 - count);
368 mono_blob_entry_hash (const char* str)
372 len = mono_metadata_decode_blob_size (str, &str);
376 for (str += 1; str < end; str++)
377 h = (h << 5) - h + *str;
385 mono_blob_entry_equal (const char *str1, const char *str2) {
389 len = mono_metadata_decode_blob_size (str1, &end1);
390 len2 = mono_metadata_decode_blob_size (str2, &end2);
393 return memcmp (end1, end2, len) == 0;
397 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
401 gpointer oldkey, oldval;
403 copy = g_malloc (s1+s2);
404 memcpy (copy, b1, s1);
405 memcpy (copy + s1, b2, s2);
406 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
408 idx = GPOINTER_TO_UINT (oldval);
410 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
411 mono_image_add_stream_data (&assembly->blob, b2, s2);
412 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
418 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
422 guint32 size = buf->p - buf->buf;
424 g_assert (size <= (buf->end - buf->buf));
425 mono_metadata_encode_value (size, b, &b);
426 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
430 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
431 * dest may be misaligned.
434 swap_with_size (char *dest, const char* val, int len, int nelem) {
435 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
438 for (elem = 0; elem < nelem; ++elem) {
464 g_assert_not_reached ();
470 memcpy (dest, val, len * nelem);
475 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
479 guint32 idx = 0, len;
481 len = str->length * 2;
482 mono_metadata_encode_value (len, b, &b);
483 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
485 char *swapped = g_malloc (2 * mono_string_length (str));
486 const char *p = (const char*)mono_string_chars (str);
488 swap_with_size (swapped, p, 2, mono_string_length (str));
489 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
493 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
498 /* modified version needed to handle building corlib */
500 my_mono_class_from_mono_type (MonoType *type) {
501 switch (type->type) {
502 case MONO_TYPE_ARRAY:
504 case MONO_TYPE_SZARRAY:
505 case MONO_TYPE_GENERICINST:
506 return mono_class_from_mono_type (type);
509 g_assert (type->data.generic_param->pklass);
510 return type->data.generic_param->pklass;
512 /* should be always valid when we reach this case... */
513 return type->data.klass;
518 default_class_from_mono_type (MonoType *type)
520 switch (type->type) {
521 case MONO_TYPE_OBJECT:
522 return mono_defaults.object_class;
524 return mono_defaults.void_class;
525 case MONO_TYPE_BOOLEAN:
526 return mono_defaults.boolean_class;
528 return mono_defaults.char_class;
530 return mono_defaults.sbyte_class;
532 return mono_defaults.byte_class;
534 return mono_defaults.int16_class;
536 return mono_defaults.uint16_class;
538 return mono_defaults.int32_class;
540 return mono_defaults.uint32_class;
542 return mono_defaults.int_class;
544 return mono_defaults.uint_class;
546 return mono_defaults.int64_class;
548 return mono_defaults.uint64_class;
550 return mono_defaults.single_class;
552 return mono_defaults.double_class;
553 case MONO_TYPE_STRING:
554 return mono_defaults.string_class;
556 g_warning ("implement me 0x%02x\n", type->type);
557 g_assert_not_reached ();
564 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
569 g_assert_not_reached ();
573 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
574 encode_type (assembly, &gclass->container_class->byval_arg, buf);
575 sigbuffer_add_value (buf, gclass->inst->type_argc);
576 for (i = 0; i < gclass->inst->type_argc; ++i)
577 encode_type (assembly, gclass->inst->type_argv [i], buf);
582 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
585 g_assert_not_reached ();
590 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
594 case MONO_TYPE_BOOLEAN:
608 case MONO_TYPE_STRING:
609 case MONO_TYPE_OBJECT:
610 case MONO_TYPE_TYPEDBYREF:
611 sigbuffer_add_value (buf, type->type);
614 sigbuffer_add_value (buf, type->type);
615 encode_type (assembly, type->data.type, buf);
617 case MONO_TYPE_SZARRAY:
618 sigbuffer_add_value (buf, type->type);
619 encode_type (assembly, &type->data.klass->byval_arg, buf);
621 case MONO_TYPE_VALUETYPE:
622 case MONO_TYPE_CLASS: {
623 MonoClass *k = mono_class_from_mono_type (type);
625 * Make sure we use the correct type.
627 sigbuffer_add_value (buf, k->byval_arg.type);
629 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
630 * otherwise two typerefs could point to the same type, leading to
631 * verification errors.
633 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
636 case MONO_TYPE_ARRAY:
637 sigbuffer_add_value (buf, type->type);
638 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
639 sigbuffer_add_value (buf, type->data.array->rank);
640 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
641 sigbuffer_add_value (buf, 0);
643 case MONO_TYPE_GENERICINST:
644 encode_generic_class (assembly, type->data.generic_class, buf);
648 sigbuffer_add_value (buf, type->type);
649 sigbuffer_add_value (buf, type->data.generic_param->num);
652 g_error ("need to encode type %x", type->type);
657 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
660 sigbuffer_add_value (buf, MONO_TYPE_VOID);
665 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
666 encode_type (assembly, type->type, buf);
670 g_assert_not_reached ();
675 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
680 for (i = 0; i < mono_array_length (modreq); ++i) {
681 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
682 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
683 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
687 for (i = 0; i < mono_array_length (modopt); ++i) {
688 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
689 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
690 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
696 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
700 guint32 nparams = sig->param_count;
706 sigbuffer_init (&buf, 32);
708 * FIXME: vararg, explicit_this, differenc call_conv values...
710 idx = sig->call_convention;
712 idx |= 0x20; /* hasthis */
713 if (sig->generic_param_count)
714 idx |= 0x10; /* generic */
715 sigbuffer_add_byte (&buf, idx);
716 if (sig->generic_param_count)
717 sigbuffer_add_value (&buf, sig->generic_param_count);
718 sigbuffer_add_value (&buf, nparams);
719 encode_type (assembly, sig->ret, &buf);
720 for (i = 0; i < nparams; ++i) {
721 if (i == sig->sentinelpos)
722 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
723 encode_type (assembly, sig->params [i], &buf);
725 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
726 sigbuffer_free (&buf);
731 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
734 * FIXME: reuse code from method_encode_signature().
738 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
739 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
740 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
743 sigbuffer_init (&buf, 32);
744 /* LAMESPEC: all the call conv spec is foobared */
745 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
746 if (mb->call_conv & 2)
747 idx |= 0x5; /* vararg */
748 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
749 idx |= 0x20; /* hasthis */
751 idx |= 0x10; /* generic */
752 sigbuffer_add_byte (&buf, idx);
754 sigbuffer_add_value (&buf, ngparams);
755 sigbuffer_add_value (&buf, nparams + notypes);
756 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
757 encode_reflection_type (assembly, mb->rtype, &buf);
758 for (i = 0; i < nparams; ++i) {
759 MonoArray *modreq = NULL;
760 MonoArray *modopt = NULL;
761 MonoReflectionType *pt;
763 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
764 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
765 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
766 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
767 encode_custom_modifiers (assembly, modreq, modopt, &buf);
768 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
769 encode_reflection_type (assembly, pt, &buf);
772 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
773 for (i = 0; i < notypes; ++i) {
774 MonoReflectionType *pt;
776 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
777 encode_reflection_type (assembly, pt, &buf);
780 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
781 sigbuffer_free (&buf);
786 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
788 MonoDynamicTable *table;
790 guint32 idx, sig_idx;
791 guint nl = mono_array_length (ilgen->locals);
795 sigbuffer_init (&buf, 32);
796 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
797 idx = table->next_idx ++;
799 alloc_table (table, table->rows);
800 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
802 sigbuffer_add_value (&buf, 0x07);
803 sigbuffer_add_value (&buf, nl);
804 for (i = 0; i < nl; ++i) {
805 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
808 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
810 encode_reflection_type (assembly, lb->type, &buf);
812 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
813 sigbuffer_free (&buf);
815 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
821 method_count_clauses (MonoReflectionILGen *ilgen)
823 guint32 num_clauses = 0;
826 MonoILExceptionInfo *ex_info;
827 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
828 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
829 if (ex_info->handlers)
830 num_clauses += mono_array_length (ex_info->handlers);
838 static MonoExceptionClause*
839 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
841 MonoExceptionClause *clauses;
842 MonoExceptionClause *clause;
843 MonoILExceptionInfo *ex_info;
844 MonoILExceptionBlock *ex_block;
845 guint32 finally_start;
846 int i, j, clause_index;;
848 clauses = g_new0 (MonoExceptionClause, num_clauses);
851 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
852 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
853 finally_start = ex_info->start + ex_info->len;
854 if (!ex_info->handlers)
856 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
857 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
858 clause = &(clauses [clause_index]);
860 clause->flags = ex_block->type;
861 clause->try_offset = ex_info->start;
863 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
864 clause->try_len = finally_start - ex_info->start;
866 clause->try_len = ex_info->len;
867 clause->handler_offset = ex_block->start;
868 clause->handler_len = ex_block->len;
869 if (ex_block->extype) {
870 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
872 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
873 clause->data.filter_offset = ex_block->filter_offset;
875 clause->data.filter_offset = 0;
877 finally_start = ex_block->start + ex_block->len;
887 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
893 gint32 num_locals = 0;
894 gint32 num_exception = 0;
897 char fat_header [12];
900 guint32 local_sig = 0;
901 guint32 header_size = 12;
904 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
905 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
909 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
911 code = mb->ilgen->code;
912 code_size = mb->ilgen->code_len;
913 max_stack = mb->ilgen->max_stack;
914 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
915 if (mb->ilgen->ex_handlers)
916 num_exception = method_count_clauses (mb->ilgen);
920 char *name = mono_string_to_utf8 (mb->name);
921 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
922 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
925 mono_raise_exception (exception);
928 code_size = mono_array_length (code);
929 max_stack = 8; /* we probably need to run a verifier on the code... */
932 stream_data_align (&assembly->code);
934 /* check for exceptions, maxstack, locals */
935 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
937 if (code_size < 64 && !(code_size & 1)) {
938 flags = (code_size << 2) | 0x2;
939 } else if (code_size < 32 && (code_size & 1)) {
940 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
944 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
945 /* add to the fixup todo list */
946 if (mb->ilgen && mb->ilgen->num_token_fixups)
947 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
948 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
949 return assembly->text_rva + idx;
953 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
955 * FIXME: need to set also the header size in fat_flags.
956 * (and more sects and init locals flags)
960 fat_flags |= METHOD_HEADER_MORE_SECTS;
962 fat_flags |= METHOD_HEADER_INIT_LOCALS;
963 fat_header [0] = fat_flags;
964 fat_header [1] = (header_size / 4 ) << 4;
965 short_value = GUINT16_TO_LE (max_stack);
966 memcpy (fat_header + 2, &short_value, 2);
967 int_value = GUINT32_TO_LE (code_size);
968 memcpy (fat_header + 4, &int_value, 4);
969 int_value = GUINT32_TO_LE (local_sig);
970 memcpy (fat_header + 8, &int_value, 4);
971 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
972 /* add to the fixup todo list */
973 if (mb->ilgen && mb->ilgen->num_token_fixups)
974 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
976 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
978 unsigned char sheader [4];
979 MonoILExceptionInfo * ex_info;
980 MonoILExceptionBlock * ex_block;
983 stream_data_align (&assembly->code);
984 /* always use fat format for now */
985 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
986 num_exception *= 6 * sizeof (guint32);
987 num_exception += 4; /* include the size of the header */
988 sheader [1] = num_exception & 0xff;
989 sheader [2] = (num_exception >> 8) & 0xff;
990 sheader [3] = (num_exception >> 16) & 0xff;
991 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
992 /* fat header, so we are already aligned */
994 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
995 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
996 if (ex_info->handlers) {
997 int finally_start = ex_info->start + ex_info->len;
998 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1000 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1002 val = GUINT32_TO_LE (ex_block->type);
1003 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1005 val = GUINT32_TO_LE (ex_info->start);
1006 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1007 /* need fault, too, probably */
1008 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1009 val = GUINT32_TO_LE (finally_start - ex_info->start);
1011 val = GUINT32_TO_LE (ex_info->len);
1012 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1013 /* handler offset */
1014 val = GUINT32_TO_LE (ex_block->start);
1015 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1017 val = GUINT32_TO_LE (ex_block->len);
1018 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1019 finally_start = ex_block->start + ex_block->len;
1020 if (ex_block->extype) {
1021 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1023 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1024 val = ex_block->filter_offset;
1028 val = GUINT32_TO_LE (val);
1029 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1030 /*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",
1031 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);*/
1034 g_error ("No clauses for ex info block %d", i);
1038 return assembly->text_rva + idx;
1042 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1045 MonoDynamicTable *table;
1048 table = &assembly->tables [table_idx];
1050 g_assert (col < table->columns);
1052 values = table->values + table->columns;
1053 for (i = 1; i <= table->rows; ++i) {
1054 if (values [col] == token)
1056 values += table->columns;
1061 /* protected by reflection_mutex:
1062 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1064 static GHashTable *dynamic_custom_attrs = NULL;
1066 static MonoCustomAttrInfo*
1067 lookup_custom_attr (void *member)
1069 MonoCustomAttrInfo *ainfo;
1070 mono_reflection_lock ();
1071 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1072 mono_reflection_unlock ();
1077 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1079 /* FIXME: Need to do more checks */
1080 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1081 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1083 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1090 static MonoCustomAttrInfo*
1091 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1093 int i, index, count, not_visible;
1094 MonoCustomAttrInfo *ainfo;
1095 MonoReflectionCustomAttr *cattr;
1099 /* FIXME: check in assembly the Run flag is set */
1101 count = mono_array_length (cattrs);
1103 /* Skip nonpublic attributes since MS.NET seems to do the same */
1104 /* FIXME: This needs to be done more globally */
1106 for (i = 0; i < count; ++i) {
1107 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1108 if (!custom_attr_visible (image, cattr))
1111 count -= not_visible;
1113 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1115 ainfo->image = image;
1116 ainfo->num_attrs = count;
1118 mono_loader_lock ();
1119 for (i = 0; i < count; ++i) {
1120 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1121 if (custom_attr_visible (image, cattr)) {
1122 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1123 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1124 ainfo->attrs [index].ctor = cattr->ctor->method;
1125 ainfo->attrs [index].data = saved;
1126 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1130 mono_loader_unlock ();
1136 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1138 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1143 mono_reflection_lock ();
1144 if (!dynamic_custom_attrs)
1145 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1147 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1148 ainfo->cached = TRUE;
1149 mono_reflection_unlock ();
1153 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1160 * idx is the table index of the object
1161 * type is one of MONO_CUSTOM_ATTR_*
1164 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1166 MonoDynamicTable *table;
1167 MonoReflectionCustomAttr *cattr;
1169 guint32 count, i, token;
1171 char *p = blob_size;
1173 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1176 count = mono_array_length (cattrs);
1177 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1178 table->rows += count;
1179 alloc_table (table, table->rows);
1180 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1181 idx <<= MONO_CUSTOM_ATTR_BITS;
1183 for (i = 0; i < count; ++i) {
1184 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1185 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1186 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1187 type = mono_metadata_token_index (token);
1188 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1189 switch (mono_metadata_token_table (token)) {
1190 case MONO_TABLE_METHOD:
1191 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1193 case MONO_TABLE_MEMBERREF:
1194 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1197 g_warning ("got wrong token in custom attr");
1200 values [MONO_CUSTOM_ATTR_TYPE] = type;
1202 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1203 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1204 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1205 values += MONO_CUSTOM_ATTR_SIZE;
1211 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1213 MonoDynamicTable *table;
1215 guint32 count, i, idx;
1216 MonoReflectionPermissionSet *perm;
1221 count = mono_array_length (permissions);
1222 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1223 table->rows += count;
1224 alloc_table (table, table->rows);
1226 for (i = 0; i < mono_array_length (permissions); ++i) {
1227 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1229 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1231 idx = mono_metadata_token_index (parent_token);
1232 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1233 switch (mono_metadata_token_table (parent_token)) {
1234 case MONO_TABLE_TYPEDEF:
1235 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1237 case MONO_TABLE_METHOD:
1238 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1240 case MONO_TABLE_ASSEMBLY:
1241 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1244 g_assert_not_reached ();
1247 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1248 values [MONO_DECL_SECURITY_PARENT] = idx;
1249 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1256 * Fill in the MethodDef and ParamDef tables for a method.
1257 * This is used for both normal methods and constructors.
1260 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1262 MonoDynamicTable *table;
1266 /* room in this table is already allocated */
1267 table = &assembly->tables [MONO_TABLE_METHOD];
1268 *mb->table_idx = table->next_idx ++;
1269 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1270 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1271 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1272 values [MONO_METHOD_FLAGS] = mb->attrs;
1273 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1274 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1275 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1277 table = &assembly->tables [MONO_TABLE_PARAM];
1278 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1280 mono_image_add_decl_security (assembly,
1281 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1284 MonoDynamicTable *mtable;
1287 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1288 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1291 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1292 if (mono_array_get (mb->pinfo, gpointer, i))
1295 table->rows += count;
1296 alloc_table (table, table->rows);
1297 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1298 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1299 MonoReflectionParamBuilder *pb;
1300 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1301 values [MONO_PARAM_FLAGS] = pb->attrs;
1302 values [MONO_PARAM_SEQUENCE] = i;
1303 if (pb->name != NULL) {
1304 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1306 values [MONO_PARAM_NAME] = 0;
1308 values += MONO_PARAM_SIZE;
1309 if (pb->marshal_info) {
1311 alloc_table (mtable, mtable->rows);
1312 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1313 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1314 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1316 pb->table_idx = table->next_idx++;
1317 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1318 guint32 field_type = 0;
1319 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1321 alloc_table (mtable, mtable->rows);
1322 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1323 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1324 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1325 mvalues [MONO_CONSTANT_TYPE] = field_type;
1326 mvalues [MONO_CONSTANT_PADDING] = 0;
1334 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1336 rmb->ilgen = mb->ilgen;
1337 rmb->rtype = mb->rtype;
1338 rmb->parameters = mb->parameters;
1339 rmb->generic_params = mb->generic_params;
1340 rmb->generic_container = mb->generic_container;
1341 rmb->opt_types = NULL;
1342 rmb->pinfo = mb->pinfo;
1343 rmb->attrs = mb->attrs;
1344 rmb->iattrs = mb->iattrs;
1345 rmb->call_conv = mb->call_conv;
1346 rmb->code = mb->code;
1347 rmb->type = mb->type;
1348 rmb->name = mb->name;
1349 rmb->table_idx = &mb->table_idx;
1350 rmb->init_locals = mb->init_locals;
1351 rmb->return_modreq = mb->return_modreq;
1352 rmb->return_modopt = mb->return_modopt;
1353 rmb->param_modreq = mb->param_modreq;
1354 rmb->param_modopt = mb->param_modopt;
1355 rmb->permissions = mb->permissions;
1356 rmb->mhandle = mb->mhandle;
1361 rmb->charset = mb->charset;
1362 rmb->extra_flags = mb->extra_flags;
1363 rmb->native_cc = mb->native_cc;
1364 rmb->dllentry = mb->dllentry;
1370 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1372 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1374 rmb->ilgen = mb->ilgen;
1375 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1376 rmb->parameters = mb->parameters;
1377 rmb->generic_params = NULL;
1378 rmb->generic_container = NULL;
1379 rmb->opt_types = NULL;
1380 rmb->pinfo = mb->pinfo;
1381 rmb->attrs = mb->attrs;
1382 rmb->iattrs = mb->iattrs;
1383 rmb->call_conv = mb->call_conv;
1385 rmb->type = mb->type;
1386 rmb->name = mono_string_new (mono_domain_get (), name);
1387 rmb->table_idx = &mb->table_idx;
1388 rmb->init_locals = mb->init_locals;
1389 rmb->return_modreq = NULL;
1390 rmb->return_modopt = NULL;
1391 rmb->param_modreq = mb->param_modreq;
1392 rmb->param_modopt = mb->param_modopt;
1393 rmb->permissions = mb->permissions;
1394 rmb->mhandle = mb->mhandle;
1400 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1402 rmb->ilgen = mb->ilgen;
1403 rmb->rtype = mb->rtype;
1404 rmb->parameters = mb->parameters;
1405 rmb->generic_params = NULL;
1406 rmb->generic_container = NULL;
1407 rmb->opt_types = NULL;
1409 rmb->attrs = mb->attrs;
1411 rmb->call_conv = mb->call_conv;
1414 rmb->name = mb->name;
1415 rmb->table_idx = NULL;
1416 rmb->init_locals = mb->init_locals;
1417 rmb->skip_visibility = mb->skip_visibility;
1418 rmb->return_modreq = NULL;
1419 rmb->return_modopt = NULL;
1420 rmb->param_modreq = NULL;
1421 rmb->param_modopt = NULL;
1422 rmb->permissions = NULL;
1423 rmb->mhandle = mb->mhandle;
1429 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1431 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1432 MonoDynamicTable *table;
1436 if (!mb->override_method)
1439 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1441 alloc_table (table, table->rows);
1442 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1443 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1444 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1446 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1447 switch (mono_metadata_token_table (tok)) {
1448 case MONO_TABLE_MEMBERREF:
1449 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1451 case MONO_TABLE_METHOD:
1452 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1455 g_assert_not_reached ();
1457 values [MONO_METHODIMPL_DECLARATION] = tok;
1461 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1463 MonoDynamicTable *table;
1465 ReflectionMethodBuilder rmb;
1468 reflection_methodbuilder_from_method_builder (&rmb, mb);
1470 mono_image_basic_method (&rmb, assembly);
1471 mb->table_idx = *rmb.table_idx;
1473 if (mb->dll) { /* It's a P/Invoke method */
1475 /* map CharSet values to on-disk values */
1476 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1477 int extra_flags = mb->extra_flags;
1478 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1480 alloc_table (table, table->rows);
1481 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1483 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1484 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1486 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1488 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1489 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1490 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1491 table = &assembly->tables [MONO_TABLE_MODULEREF];
1493 alloc_table (table, table->rows);
1494 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1495 values [MONO_IMPLMAP_SCOPE] = table->rows;
1499 if (mb->generic_params) {
1500 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1501 table->rows += mono_array_length (mb->generic_params);
1502 alloc_table (table, table->rows);
1503 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1504 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1506 mono_image_get_generic_param_info (
1507 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1514 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1516 ReflectionMethodBuilder rmb;
1518 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1520 mono_image_basic_method (&rmb, assembly);
1521 mb->table_idx = *rmb.table_idx;
1525 type_get_fully_qualified_name (MonoType *type)
1527 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1531 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1535 klass = my_mono_class_from_mono_type (type);
1537 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1538 ta = klass->image->assembly;
1539 if (ta->dynamic || (ta == ass))
1540 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1542 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1546 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1551 if (!assembly->save)
1554 sigbuffer_init (&buf, 32);
1556 sigbuffer_add_value (&buf, 0x06);
1557 /* encode custom attributes before the type */
1558 encode_type (assembly, type, &buf);
1559 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1560 sigbuffer_free (&buf);
1565 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1570 sigbuffer_init (&buf, 32);
1572 sigbuffer_add_value (&buf, 0x06);
1573 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1574 /* encode custom attributes before the type */
1575 encode_reflection_type (assembly, fb->type, &buf);
1576 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1577 sigbuffer_free (&buf);
1582 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1583 char blob_size [64];
1584 char *b = blob_size;
1587 guint32 idx = 0, len = 0, dummy = 0;
1589 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1590 guint32 fpa_double [2];
1595 p = buf = g_malloc (64);
1597 *ret_type = MONO_TYPE_CLASS;
1599 box_val = (char*)&dummy;
1601 box_val = ((char*)val) + sizeof (MonoObject);
1602 *ret_type = val->vtable->klass->byval_arg.type;
1605 switch (*ret_type) {
1606 case MONO_TYPE_BOOLEAN:
1611 case MONO_TYPE_CHAR:
1628 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1629 fpa_p = (guint32*)box_val;
1630 fpa_double [0] = fpa_p [1];
1631 fpa_double [1] = fpa_p [0];
1632 box_val = (char*)fpa_double;
1636 case MONO_TYPE_VALUETYPE:
1637 if (val->vtable->klass->enumtype) {
1638 *ret_type = val->vtable->klass->enum_basetype->type;
1641 g_error ("we can't encode valuetypes");
1642 case MONO_TYPE_CLASS:
1644 case MONO_TYPE_STRING: {
1645 MonoString *str = (MonoString*)val;
1646 /* there is no signature */
1647 len = str->length * 2;
1648 mono_metadata_encode_value (len, b, &b);
1649 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1651 char *swapped = g_malloc (2 * mono_string_length (str));
1652 const char *p = (const char*)mono_string_chars (str);
1654 swap_with_size (swapped, p, 2, mono_string_length (str));
1655 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1659 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1665 case MONO_TYPE_GENERICINST:
1666 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1669 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1672 /* there is no signature */
1673 mono_metadata_encode_value (len, b, &b);
1674 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1675 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1676 swap_with_size (blob_size, box_val, len, 1);
1677 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1679 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1687 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1692 sigbuffer_init (&buf, 32);
1694 sigbuffer_add_value (&buf, minfo->type);
1696 switch (minfo->type) {
1697 case MONO_NATIVE_BYVALTSTR:
1698 case MONO_NATIVE_BYVALARRAY:
1699 sigbuffer_add_value (&buf, minfo->count);
1701 case MONO_NATIVE_LPARRAY:
1702 if (minfo->eltype || minfo->has_size) {
1703 sigbuffer_add_value (&buf, minfo->eltype);
1704 if (minfo->has_size) {
1705 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1706 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1708 /* LAMESPEC: ElemMult is undocumented */
1709 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1713 case MONO_NATIVE_CUSTOM:
1715 str = mono_string_to_utf8 (minfo->guid);
1717 sigbuffer_add_value (&buf, len);
1718 sigbuffer_add_mem (&buf, str, len);
1721 sigbuffer_add_value (&buf, 0);
1723 /* native type name */
1724 sigbuffer_add_value (&buf, 0);
1725 /* custom marshaler type name */
1726 if (minfo->marshaltype || minfo->marshaltyperef) {
1727 if (minfo->marshaltyperef)
1728 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1730 str = mono_string_to_utf8 (minfo->marshaltype);
1732 sigbuffer_add_value (&buf, len);
1733 sigbuffer_add_mem (&buf, str, len);
1736 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1737 sigbuffer_add_value (&buf, 0);
1739 if (minfo->mcookie) {
1740 str = mono_string_to_utf8 (minfo->mcookie);
1742 sigbuffer_add_value (&buf, len);
1743 sigbuffer_add_mem (&buf, str, len);
1746 sigbuffer_add_value (&buf, 0);
1752 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1753 sigbuffer_free (&buf);
1758 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1760 MonoDynamicTable *table;
1763 /* maybe this fixup should be done in the C# code */
1764 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1765 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1766 table = &assembly->tables [MONO_TABLE_FIELD];
1767 fb->table_idx = table->next_idx ++;
1768 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1769 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1770 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1771 values [MONO_FIELD_FLAGS] = fb->attrs;
1772 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1774 if (fb->offset != -1) {
1775 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1777 alloc_table (table, table->rows);
1778 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1779 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1780 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1782 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1783 guint32 field_type = 0;
1784 table = &assembly->tables [MONO_TABLE_CONSTANT];
1786 alloc_table (table, table->rows);
1787 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1788 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1789 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1790 values [MONO_CONSTANT_TYPE] = field_type;
1791 values [MONO_CONSTANT_PADDING] = 0;
1793 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1795 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1797 alloc_table (table, table->rows);
1798 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1799 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1801 * We store it in the code section because it's simpler for now.
1804 if (mono_array_length (fb->rva_data) >= 10)
1805 stream_data_align (&assembly->code);
1806 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1808 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1809 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1811 if (fb->marshal_info) {
1812 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1814 alloc_table (table, table->rows);
1815 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1816 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1817 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1822 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1825 guint32 nparams = 0;
1826 MonoReflectionMethodBuilder *mb = fb->get_method;
1827 MonoReflectionMethodBuilder *smb = fb->set_method;
1830 if (mb && mb->parameters)
1831 nparams = mono_array_length (mb->parameters);
1832 if (!mb && smb && smb->parameters)
1833 nparams = mono_array_length (smb->parameters) - 1;
1834 sigbuffer_init (&buf, 32);
1835 sigbuffer_add_byte (&buf, 0x08);
1836 sigbuffer_add_value (&buf, nparams);
1838 encode_reflection_type (assembly, mb->rtype, &buf);
1839 for (i = 0; i < nparams; ++i) {
1840 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1841 encode_reflection_type (assembly, pt, &buf);
1843 } else if (smb && smb->parameters) {
1844 /* the property type is the last param */
1845 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1846 for (i = 0; i < nparams; ++i) {
1847 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1848 encode_reflection_type (assembly, pt, &buf);
1851 encode_reflection_type (assembly, fb->type, &buf);
1854 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1855 sigbuffer_free (&buf);
1860 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1862 MonoDynamicTable *table;
1864 guint num_methods = 0;
1868 * we need to set things in the following tables:
1869 * PROPERTYMAP (info already filled in _get_type_info ())
1870 * PROPERTY (rows already preallocated in _get_type_info ())
1871 * METHOD (method info already done with the generic method code)
1874 table = &assembly->tables [MONO_TABLE_PROPERTY];
1875 pb->table_idx = table->next_idx ++;
1876 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1877 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1878 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1879 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1881 /* FIXME: we still don't handle 'other' methods */
1882 if (pb->get_method) num_methods ++;
1883 if (pb->set_method) num_methods ++;
1885 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1886 table->rows += num_methods;
1887 alloc_table (table, table->rows);
1889 if (pb->get_method) {
1890 semaidx = table->next_idx ++;
1891 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1892 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1893 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1894 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1896 if (pb->set_method) {
1897 semaidx = table->next_idx ++;
1898 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1899 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1900 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1901 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1906 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1908 MonoDynamicTable *table;
1910 guint num_methods = 0;
1914 * we need to set things in the following tables:
1915 * EVENTMAP (info already filled in _get_type_info ())
1916 * EVENT (rows already preallocated in _get_type_info ())
1917 * METHOD (method info already done with the generic method code)
1920 table = &assembly->tables [MONO_TABLE_EVENT];
1921 eb->table_idx = table->next_idx ++;
1922 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1923 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1924 values [MONO_EVENT_FLAGS] = eb->attrs;
1925 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1928 * FIXME: we still don't handle 'other' methods
1930 if (eb->add_method) num_methods ++;
1931 if (eb->remove_method) num_methods ++;
1932 if (eb->raise_method) num_methods ++;
1934 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1935 table->rows += num_methods;
1936 alloc_table (table, table->rows);
1938 if (eb->add_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1942 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1945 if (eb->remove_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1949 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1952 if (eb->raise_method) {
1953 semaidx = table->next_idx ++;
1954 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1955 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1956 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1957 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1962 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1964 MonoDynamicTable *table;
1965 guint32 num_constraints, i;
1969 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1970 num_constraints = gparam->iface_constraints ?
1971 mono_array_length (gparam->iface_constraints) : 0;
1972 table->rows += num_constraints;
1973 if (gparam->base_type)
1975 alloc_table (table, table->rows);
1977 if (gparam->base_type) {
1978 table_idx = table->next_idx ++;
1979 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1981 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1982 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1983 assembly, gparam->base_type->type);
1986 for (i = 0; i < num_constraints; i++) {
1987 MonoReflectionType *constraint = mono_array_get (
1988 gparam->iface_constraints, gpointer, i);
1990 table_idx = table->next_idx ++;
1991 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1993 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1994 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1995 assembly, constraint->type);
2000 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2002 GenericParamTableEntry *entry;
2005 * The GenericParam table must be sorted according to the `owner' field.
2006 * We need to do this sorting prior to writing the GenericParamConstraint
2007 * table, since we have to use the final GenericParam table indices there
2008 * and they must also be sorted.
2011 entry = g_new0 (GenericParamTableEntry, 1);
2012 entry->owner = owner;
2014 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2015 MONO_GC_REGISTER_ROOT (entry->gparam);
2017 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2019 g_ptr_array_add (assembly->gen_params, entry);
2023 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2025 MonoDynamicTable *table;
2026 MonoGenericParam *param;
2030 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2031 table_idx = table->next_idx ++;
2032 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2034 param = entry->gparam->type.type->data.generic_param;
2036 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2037 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2038 values [MONO_GENERICPARAM_NUMBER] = param->num;
2039 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2041 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2043 encode_constraints (entry->gparam, table_idx, assembly);
2047 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2049 MonoDynamicTable *table;
2052 guint32 cols [MONO_ASSEMBLY_SIZE];
2056 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2059 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2060 table = &assembly->tables [MONO_TABLE_MODULEREF];
2061 token = table->next_idx ++;
2063 alloc_table (table, table->rows);
2064 values = table->values + token * MONO_MODULEREF_SIZE;
2065 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2067 token <<= MONO_RESOLTION_SCOPE_BITS;
2068 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2069 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2074 if (image->assembly->dynamic)
2076 memset (cols, 0, sizeof (cols));
2078 /* image->assembly->image is the manifest module */
2079 image = image->assembly->image;
2080 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2083 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2084 token = table->next_idx ++;
2086 alloc_table (table, table->rows);
2087 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2088 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2089 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2090 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2091 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2092 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2093 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2094 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2095 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2097 if (strcmp ("", image->assembly->aname.culture)) {
2098 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2099 image->assembly->aname.culture);
2102 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2103 guchar pubtoken [9];
2105 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2106 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2108 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2110 token <<= MONO_RESOLTION_SCOPE_BITS;
2111 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2112 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2117 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2119 MonoDynamicTable *table;
2124 sigbuffer_init (&buf, 32);
2125 switch (type->type) {
2126 case MONO_TYPE_FNPTR:
2128 case MONO_TYPE_SZARRAY:
2129 case MONO_TYPE_ARRAY:
2131 case MONO_TYPE_MVAR:
2132 case MONO_TYPE_GENERICINST:
2133 encode_type (assembly, type, &buf);
2135 case MONO_TYPE_CLASS:
2136 case MONO_TYPE_VALUETYPE: {
2137 MonoClass *k = mono_class_from_mono_type (type);
2138 if (!k || !k->generic_class) {
2139 sigbuffer_free (&buf);
2142 encode_generic_class (assembly, k->generic_class, &buf);
2146 sigbuffer_free (&buf);
2150 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2151 if (assembly->save) {
2152 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2153 alloc_table (table, table->rows + 1);
2154 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2155 values [MONO_TYPESPEC_SIGNATURE] = token;
2157 sigbuffer_free (&buf);
2159 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2160 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2166 * Despite the name, we handle also TypeSpec (with the above helper).
2169 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2171 MonoDynamicTable *table;
2173 guint32 token, scope, enclosing;
2176 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2179 token = create_typespec (assembly, type);
2182 klass = my_mono_class_from_mono_type (type);
2184 klass = mono_class_from_mono_type (type);
2187 * If it's in the same module and not a generic type parameter:
2189 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2190 (type->type != MONO_TYPE_MVAR)) {
2191 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2192 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2193 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2197 if (klass->nested_in) {
2198 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2199 /* get the typeref idx of the enclosing type */
2200 enclosing >>= MONO_TYPEDEFORREF_BITS;
2201 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2203 scope = resolution_scope_from_image (assembly, klass->image);
2205 table = &assembly->tables [MONO_TABLE_TYPEREF];
2206 if (assembly->save) {
2207 alloc_table (table, table->rows + 1);
2208 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2209 values [MONO_TYPEREF_SCOPE] = scope;
2210 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2211 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2213 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2214 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2216 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2221 * Insert a memberef row into the metadata: the token that point to the memberref
2222 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2223 * mono_image_get_fieldref_token()).
2224 * The sig param is an index to an already built signature.
2227 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2229 MonoDynamicTable *table;
2231 guint32 token, pclass;
2234 parent = mono_image_typedef_or_ref (assembly, type);
2235 switch (parent & MONO_TYPEDEFORREF_MASK) {
2236 case MONO_TYPEDEFORREF_TYPEREF:
2237 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2239 case MONO_TYPEDEFORREF_TYPESPEC:
2240 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2242 case MONO_TYPEDEFORREF_TYPEDEF:
2243 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2246 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2249 /* extract the index */
2250 parent >>= MONO_TYPEDEFORREF_BITS;
2252 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2254 if (assembly->save) {
2255 alloc_table (table, table->rows + 1);
2256 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2257 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2258 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2259 values [MONO_MEMBERREF_SIGNATURE] = sig;
2262 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2269 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2272 MonoMethodSignature *sig;
2274 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2279 * A methodref signature can't contain an unmanaged calling convention.
2281 sig = mono_metadata_signature_dup (mono_method_signature (method));
2282 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2283 sig->call_convention = MONO_CALL_DEFAULT;
2284 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2285 method->name, method_encode_signature (assembly, sig));
2287 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2292 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2293 const gchar *name, guint32 sig)
2295 MonoDynamicTable *table;
2299 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2301 if (assembly->save) {
2302 alloc_table (table, table->rows + 1);
2303 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2304 values [MONO_MEMBERREF_CLASS] = original;
2305 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2306 values [MONO_MEMBERREF_SIGNATURE] = sig;
2309 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2316 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2319 ReflectionMethodBuilder rmb;
2321 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2325 reflection_methodbuilder_from_method_builder (&rmb, mb);
2327 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2328 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2329 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2334 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2337 ReflectionMethodBuilder rmb;
2339 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2343 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2345 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2346 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2347 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2352 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2357 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2360 g_assert (f->field->parent);
2361 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2362 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2363 f->field->name, fieldref_encode_signature (assembly, type));
2364 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2369 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2373 guint32 nparams = gmethod->inst->type_argc;
2376 if (!assembly->save)
2379 sigbuffer_init (&buf, 32);
2381 * FIXME: vararg, explicit_this, differenc call_conv values...
2383 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2384 sigbuffer_add_value (&buf, nparams);
2386 for (i = 0; i < nparams; i++)
2387 encode_type (assembly, gmethod->inst->type_argv [i], &buf);
2389 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2390 sigbuffer_free (&buf);
2395 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2397 MonoDynamicTable *table;
2399 guint32 token, mtoken = 0, sig;
2400 MonoMethodInflated *imethod;
2401 MonoMethod *declaring;
2403 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2405 g_assert (method->is_inflated);
2406 imethod = (MonoMethodInflated *) method;
2407 declaring = imethod->declaring;
2409 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2410 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2412 if (!mono_method_signature (declaring)->generic_param_count)
2415 switch (mono_metadata_token_table (mtoken)) {
2416 case MONO_TABLE_MEMBERREF:
2417 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2419 case MONO_TABLE_METHOD:
2420 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2423 g_assert_not_reached ();
2426 sig = encode_generic_method_sig (assembly, mono_method_get_context (method)->gmethod);
2428 if (assembly->save) {
2429 alloc_table (table, table->rows + 1);
2430 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2431 values [MONO_METHODSPEC_METHOD] = mtoken;
2432 values [MONO_METHODSPEC_SIGNATURE] = sig;
2435 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2442 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2444 MonoMethodInflated *imethod;
2445 MonoMethod *inflated;
2448 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2452 g_assert (method->is_inflated);
2453 inflated = mono_get_inflated_method (method);
2454 imethod = (MonoMethodInflated *) inflated;
2456 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2457 token = method_encode_methodspec (assembly, inflated);
2459 guint32 sig = method_encode_signature (
2460 assembly, mono_method_signature (imethod->declaring));
2461 token = mono_image_get_memberref_token (
2462 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2465 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2470 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2472 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2475 m = mono_get_inflated_method (m);
2477 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2478 token = mono_image_get_memberref_token (
2479 assembly, &m->klass->byval_arg, m->name, sig);
2485 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2487 MonoDynamicTable *table;
2495 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2496 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2497 * Because of this, we must not insert it into the `typeref' hash table.
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2504 sigbuffer_init (&buf, 32);
2506 g_assert (tb->generic_params);
2507 klass = mono_class_from_mono_type (tb->type.type);
2509 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2510 encode_type (assembly, &klass->byval_arg, &buf);
2512 count = mono_array_length (tb->generic_params);
2513 sigbuffer_add_value (&buf, count);
2514 for (i = 0; i < count; i++) {
2515 MonoReflectionGenericParam *gparam;
2517 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2519 encode_type (assembly, gparam->type.type, &buf);
2522 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2524 if (assembly->save) {
2525 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2526 alloc_table (table, table->rows + 1);
2527 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2528 values [MONO_TYPESPEC_SIGNATURE] = token;
2530 sigbuffer_free (&buf);
2532 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2533 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2539 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2541 MonoDynamicTable *table;
2544 guint32 token, pclass, parent, sig;
2547 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2551 klass = mono_class_from_mono_type (fb->typeb->type);
2552 name = mono_string_to_utf8 (fb->name);
2554 sig = fieldref_encode_signature (assembly, fb->type->type);
2556 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2557 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2559 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2560 parent >>= MONO_TYPEDEFORREF_BITS;
2562 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2564 if (assembly->save) {
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2567 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2568 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2569 values [MONO_MEMBERREF_SIGNATURE] = sig;
2572 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2574 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2579 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2586 if (!assembly->save)
2590 g_assert (helper->type == 2);
2592 if (helper->arguments)
2593 nargs = mono_array_length (helper->arguments);
2597 size = 10 + (nargs * 10);
2599 sigbuffer_init (&buf, 32);
2601 /* Encode calling convention */
2602 /* Change Any to Standard */
2603 if ((helper->call_conv & 0x03) == 0x03)
2604 helper->call_conv = 0x01;
2605 /* explicit_this implies has_this */
2606 if (helper->call_conv & 0x40)
2607 helper->call_conv &= 0x20;
2609 if (helper->call_conv == 0) { /* Unmanaged */
2610 idx = helper->unmanaged_call_conv - 1;
2613 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2614 if (helper->call_conv & 0x02) /* varargs */
2618 sigbuffer_add_byte (&buf, idx);
2619 sigbuffer_add_value (&buf, nargs);
2620 encode_reflection_type (assembly, helper->return_type, &buf);
2621 for (i = 0; i < nargs; ++i) {
2622 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2623 encode_reflection_type (assembly, pt, &buf);
2625 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2626 sigbuffer_free (&buf);
2632 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2635 MonoDynamicTable *table;
2638 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2639 idx = table->next_idx ++;
2641 alloc_table (table, table->rows);
2642 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2644 values [MONO_STAND_ALONE_SIGNATURE] =
2645 mono_reflection_encode_sighelper (assembly, helper);
2651 reflection_cc_to_file (int call_conv) {
2652 switch (call_conv & 0x3) {
2654 case 1: return MONO_CALL_DEFAULT;
2655 case 2: return MONO_CALL_VARARG;
2657 g_assert_not_reached ();
2664 MonoMethodSignature *sig;
2670 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2675 MonoMethodSignature *sig;
2678 name = mono_string_to_utf8 (m->name);
2679 nparams = mono_array_length (m->parameters);
2680 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2682 sig->sentinelpos = -1;
2683 sig->call_convention = reflection_cc_to_file (m->call_conv);
2684 sig->param_count = nparams;
2685 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2686 for (i = 0; i < nparams; ++i) {
2687 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2688 sig->params [i] = t->type;
2691 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2693 if (strcmp (name, am->name) == 0 &&
2694 mono_metadata_type_equal (am->parent, m->parent->type) &&
2695 mono_metadata_signature_equal (am->sig, sig)) {
2698 m->table_idx = am->token & 0xffffff;
2702 am = g_new0 (ArrayMethod, 1);
2705 am->parent = m->parent->type;
2706 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2707 method_encode_signature (assembly, sig));
2708 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2709 m->table_idx = am->token & 0xffffff;
2714 * Insert into the metadata tables all the info about the TypeBuilder tb.
2715 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2718 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2720 MonoDynamicTable *table;
2722 int i, is_object = 0, is_system = 0;
2725 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2726 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2727 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2728 n = mono_string_to_utf8 (tb->name);
2729 if (strcmp (n, "Object") == 0)
2731 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2733 n = mono_string_to_utf8 (tb->nspace);
2734 if (strcmp (n, "System") == 0)
2736 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2738 if (tb->parent && !(is_system && is_object) &&
2739 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2740 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2742 values [MONO_TYPEDEF_EXTENDS] = 0;
2744 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2745 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2748 * if we have explicitlayout or sequentiallayouts, output data in the
2749 * ClassLayout table.
2751 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2752 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2753 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2755 alloc_table (table, table->rows);
2756 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2757 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2758 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2759 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2762 /* handle interfaces */
2763 if (tb->interfaces) {
2764 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2766 table->rows += mono_array_length (tb->interfaces);
2767 alloc_table (table, table->rows);
2768 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2769 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2770 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2771 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2772 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2773 values += MONO_INTERFACEIMPL_SIZE;
2779 table = &assembly->tables [MONO_TABLE_FIELD];
2780 table->rows += tb->num_fields;
2781 alloc_table (table, table->rows);
2782 for (i = 0; i < tb->num_fields; ++i)
2783 mono_image_get_field_info (
2784 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2787 /* handle constructors */
2789 table = &assembly->tables [MONO_TABLE_METHOD];
2790 table->rows += mono_array_length (tb->ctors);
2791 alloc_table (table, table->rows);
2792 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2793 mono_image_get_ctor_info (domain,
2794 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2797 /* handle methods */
2799 table = &assembly->tables [MONO_TABLE_METHOD];
2800 table->rows += tb->num_methods;
2801 alloc_table (table, table->rows);
2802 for (i = 0; i < tb->num_methods; ++i)
2803 mono_image_get_method_info (
2804 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2807 /* Do the same with properties etc.. */
2808 if (tb->events && mono_array_length (tb->events)) {
2809 table = &assembly->tables [MONO_TABLE_EVENT];
2810 table->rows += mono_array_length (tb->events);
2811 alloc_table (table, table->rows);
2812 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2814 alloc_table (table, table->rows);
2815 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2816 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2817 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2818 for (i = 0; i < mono_array_length (tb->events); ++i)
2819 mono_image_get_event_info (
2820 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2822 if (tb->properties && mono_array_length (tb->properties)) {
2823 table = &assembly->tables [MONO_TABLE_PROPERTY];
2824 table->rows += mono_array_length (tb->properties);
2825 alloc_table (table, table->rows);
2826 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2828 alloc_table (table, table->rows);
2829 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2830 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2831 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2832 for (i = 0; i < mono_array_length (tb->properties); ++i)
2833 mono_image_get_property_info (
2834 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2837 /* handle generic parameters */
2838 if (tb->generic_params) {
2839 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2840 table->rows += mono_array_length (tb->generic_params);
2841 alloc_table (table, table->rows);
2842 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2843 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2845 mono_image_get_generic_param_info (
2846 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2850 mono_image_add_decl_security (assembly,
2851 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2854 MonoDynamicTable *ntable;
2856 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2857 ntable->rows += mono_array_length (tb->subtypes);
2858 alloc_table (ntable, ntable->rows);
2859 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2861 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2862 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2864 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2865 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2866 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2867 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2868 mono_string_to_utf8 (tb->name), tb->table_idx,
2869 ntable->next_idx, ntable->rows);*/
2870 values += MONO_NESTED_CLASS_SIZE;
2877 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2881 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2883 if (!type->subtypes)
2886 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2887 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2888 collect_types (types, subtype);
2893 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2895 if ((*type1)->table_idx < (*type2)->table_idx)
2898 if ((*type1)->table_idx > (*type2)->table_idx)
2905 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2910 for (i = 0; i < mono_array_length (pinfo); ++i) {
2911 MonoReflectionParamBuilder *pb;
2912 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2915 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2920 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2923 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2925 for (i = 0; i < tb->num_fields; ++i) {
2926 MonoReflectionFieldBuilder* fb;
2927 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2928 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2932 for (i = 0; i < mono_array_length (tb->events); ++i) {
2933 MonoReflectionEventBuilder* eb;
2934 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2935 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2938 if (tb->properties) {
2939 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2940 MonoReflectionPropertyBuilder* pb;
2941 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2942 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2946 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2947 MonoReflectionCtorBuilder* cb;
2948 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2949 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2950 params_add_cattrs (assembly, cb->pinfo);
2955 for (i = 0; i < tb->num_methods; ++i) {
2956 MonoReflectionMethodBuilder* mb;
2957 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2958 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2959 params_add_cattrs (assembly, mb->pinfo);
2964 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2965 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2970 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
2974 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
2976 if (moduleb->global_methods) {
2977 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2978 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_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);
2984 if (moduleb->global_fields) {
2985 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2986 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
2987 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2991 if (moduleb->types) {
2992 for (i = 0; i < moduleb->num_types; ++i)
2993 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
2998 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3000 MonoDynamicTable *table;
3004 char *b = blob_size;
3007 table = &assembly->tables [MONO_TABLE_FILE];
3009 alloc_table (table, table->rows);
3010 values = table->values + table->next_idx * MONO_FILE_SIZE;
3011 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3012 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3013 if (module->image->dynamic) {
3014 /* This depends on the fact that the main module is emitted last */
3015 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3016 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3019 path = g_strdup (module->image->name);
3021 mono_sha1_get_digest_from_file (path, hash);
3024 mono_metadata_encode_value (20, b, &b);
3025 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3026 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3031 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3033 MonoDynamicTable *table;
3036 table = &assembly->tables [MONO_TABLE_MODULE];
3037 mb->table_idx = table->next_idx ++;
3038 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3039 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3042 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3043 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3044 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3045 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3049 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3050 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3052 MonoDynamicTable *table;
3056 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3057 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3060 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3062 alloc_table (table, table->rows);
3063 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3065 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3066 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3067 if (klass->nested_in)
3068 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3070 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3071 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3072 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3074 res = table->next_idx;
3078 /* Emit nested types */
3079 if (klass->nested_classes) {
3082 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3083 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3090 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3091 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3096 klass = mono_class_from_mono_type (tb->type.type);
3098 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3100 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3101 parent_index, assembly);
3105 * We need to do this ourselves since klass->nested_classes is not set up.
3108 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3109 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3114 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3115 guint32 module_index, MonoDynamicImage *assembly)
3117 MonoImage *image = module->image;
3121 t = &image->tables [MONO_TABLE_TYPEDEF];
3123 for (i = 0; i < t->rows; ++i) {
3124 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3126 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3127 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3132 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3134 MonoDynamicTable *table;
3140 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3142 if (assemblyb->type_forwarders) {
3143 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3144 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3150 klass = mono_class_from_mono_type (t->type);
3152 scope = resolution_scope_from_image (assembly, klass->image);
3153 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3154 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3157 alloc_table (table, table->rows);
3158 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3160 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3161 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3162 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3163 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3164 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3169 #define align_pointer(base,p)\
3171 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3173 (p) += 4 - (__diff & 3);\
3177 compare_constants (const void *a, const void *b)
3179 const guint32 *a_values = a;
3180 const guint32 *b_values = b;
3181 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3185 compare_semantics (const void *a, const void *b)
3187 const guint32 *a_values = a;
3188 const guint32 *b_values = b;
3189 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3192 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3196 compare_custom_attrs (const void *a, const void *b)
3198 const guint32 *a_values = a;
3199 const guint32 *b_values = b;
3201 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3205 compare_field_marshal (const void *a, const void *b)
3207 const guint32 *a_values = a;
3208 const guint32 *b_values = b;
3210 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3214 compare_nested (const void *a, const void *b)
3216 const guint32 *a_values = a;
3217 const guint32 *b_values = b;
3219 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3223 compare_genericparam (const void *a, const void *b)
3225 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3226 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3228 if ((*b_entry)->owner == (*a_entry)->owner)
3230 (*a_entry)->gparam->type.type->data.generic_param->num -
3231 (*b_entry)->gparam->type.type->data.generic_param->num;
3233 return (*a_entry)->owner - (*b_entry)->owner;
3237 compare_declsecurity_attrs (const void *a, const void *b)
3239 const guint32 *a_values = a;
3240 const guint32 *b_values = b;
3242 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3246 pad_heap (MonoDynamicStream *sh)
3248 if (sh->index & 3) {
3249 int sz = 4 - (sh->index & 3);
3250 memset (sh->data + sh->index, 0, sz);
3257 MonoDynamicStream *stream;
3261 * build_compressed_metadata() fills in the blob of data that represents the
3262 * raw metadata as it will be saved in the PE file. The five streams are output
3263 * and the metadata tables are comnpressed from the guint32 array representation,
3264 * to the compressed on-disk format.
3267 build_compressed_metadata (MonoDynamicImage *assembly)
3269 MonoDynamicTable *table;
3271 guint64 valid_mask = 0;
3272 guint64 sorted_mask;
3273 guint32 heapt_size = 0;
3274 guint32 meta_size = 256; /* allow for header and other stuff */
3275 guint32 table_offset;
3276 guint32 ntables = 0;
3282 struct StreamDesc stream_desc [5];
3284 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3285 for (i = 0; i < assembly->gen_params->len; i++){
3286 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3287 write_generic_param_entry (assembly, entry);
3290 stream_desc [0].name = "#~";
3291 stream_desc [0].stream = &assembly->tstream;
3292 stream_desc [1].name = "#Strings";
3293 stream_desc [1].stream = &assembly->sheap;
3294 stream_desc [2].name = "#US";
3295 stream_desc [2].stream = &assembly->us;
3296 stream_desc [3].name = "#Blob";
3297 stream_desc [3].stream = &assembly->blob;
3298 stream_desc [4].name = "#GUID";
3299 stream_desc [4].stream = &assembly->guid;
3301 /* tables that are sorted */
3302 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3303 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3304 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3305 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3306 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3307 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3309 /* Compute table sizes */
3310 /* the MonoImage has already been created in mono_image_basic_init() */
3311 meta = &assembly->image;
3313 /* sizes should be multiple of 4 */
3314 pad_heap (&assembly->blob);
3315 pad_heap (&assembly->guid);
3316 pad_heap (&assembly->sheap);
3317 pad_heap (&assembly->us);
3319 /* Setup the info used by compute_sizes () */
3320 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3321 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3322 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3324 meta_size += assembly->blob.index;
3325 meta_size += assembly->guid.index;
3326 meta_size += assembly->sheap.index;
3327 meta_size += assembly->us.index;
3329 for (i=0; i < MONO_TABLE_NUM; ++i)
3330 meta->tables [i].rows = assembly->tables [i].rows;
3332 for (i = 0; i < MONO_TABLE_NUM; i++){
3333 if (meta->tables [i].rows == 0)
3335 valid_mask |= (guint64)1 << i;
3337 meta->tables [i].row_size = mono_metadata_compute_size (
3338 meta, i, &meta->tables [i].size_bitfield);
3339 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3341 heapt_size += 24; /* #~ header size */
3342 heapt_size += ntables * 4;
3343 /* make multiple of 4 */
3346 meta_size += heapt_size;
3347 meta->raw_metadata = g_malloc0 (meta_size);
3348 p = (unsigned char*)meta->raw_metadata;
3349 /* the metadata signature */
3350 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3351 /* version numbers and 4 bytes reserved */
3352 int16val = (guint16*)p;
3353 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3354 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3356 /* version string */
3357 int32val = (guint32*)p;
3358 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3360 memcpy (p, meta->version, strlen (meta->version));
3361 p += GUINT32_FROM_LE (*int32val);
3362 align_pointer (meta->raw_metadata, p);
3363 int16val = (guint16*)p;
3364 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3365 *int16val = GUINT16_TO_LE (5); /* number of streams */
3369 * write the stream info.
3371 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3372 table_offset += 3; table_offset &= ~3;
3374 assembly->tstream.index = heapt_size;
3375 for (i = 0; i < 5; ++i) {
3376 int32val = (guint32*)p;
3377 stream_desc [i].stream->offset = table_offset;
3378 *int32val++ = GUINT32_TO_LE (table_offset);
3379 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3380 table_offset += GUINT32_FROM_LE (*int32val);
3381 table_offset += 3; table_offset &= ~3;
3383 strcpy ((char*)p, stream_desc [i].name);
3384 p += strlen (stream_desc [i].name) + 1;
3385 align_pointer (meta->raw_metadata, p);
3388 * now copy the data, the table stream header and contents goes first.
3390 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3391 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3392 int32val = (guint32*)p;
3393 *int32val = GUINT32_TO_LE (0); /* reserved */
3396 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3397 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3398 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3399 *p++ = 2; /* version */
3402 *p++ = 1; /* version */
3406 if (meta->idx_string_wide)
3408 if (meta->idx_guid_wide)
3410 if (meta->idx_blob_wide)
3413 *p++ = 1; /* reserved */
3414 int64val = (guint64*)p;
3415 *int64val++ = GUINT64_TO_LE (valid_mask);
3416 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3418 int32val = (guint32*)p;
3419 for (i = 0; i < MONO_TABLE_NUM; i++){
3420 if (meta->tables [i].rows == 0)
3422 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3424 p = (unsigned char*)int32val;
3426 /* sort the tables that still need sorting */
3427 table = &assembly->tables [MONO_TABLE_CONSTANT];
3429 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3430 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3432 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3433 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3435 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3436 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3438 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3439 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3441 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3442 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3443 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3445 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3447 /* compress the tables */
3448 for (i = 0; i < MONO_TABLE_NUM; i++){
3451 guint32 bitfield = meta->tables [i].size_bitfield;
3452 if (!meta->tables [i].rows)
3454 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3455 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3456 meta->tables [i].base = (char*)p;
3457 for (row = 1; row <= meta->tables [i].rows; ++row) {
3458 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3459 for (col = 0; col < assembly->tables [i].columns; ++col) {
3460 switch (mono_metadata_table_size (bitfield, col)) {
3462 *p++ = values [col];
3465 *p++ = values [col] & 0xff;
3466 *p++ = (values [col] >> 8) & 0xff;
3469 *p++ = values [col] & 0xff;
3470 *p++ = (values [col] >> 8) & 0xff;
3471 *p++ = (values [col] >> 16) & 0xff;
3472 *p++ = (values [col] >> 24) & 0xff;
3475 g_assert_not_reached ();
3479 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3482 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3483 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3484 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3485 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3486 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3488 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3492 * Some tables in metadata need to be sorted according to some criteria, but
3493 * when methods and fields are first created with reflection, they may be assigned a token
3494 * that doesn't correspond to the final token they will get assigned after the sorting.
3495 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3496 * with the reflection objects that represent them. Once all the tables are set up, the
3497 * reflection objects will contains the correct table index. fixup_method() will fixup the
3498 * tokens for the method with ILGenerator @ilgen.
3501 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3502 guint32 code_idx = GPOINTER_TO_UINT (value);
3503 MonoReflectionILTokenInfo *iltoken;
3504 MonoReflectionFieldBuilder *field;
3505 MonoReflectionCtorBuilder *ctor;
3506 MonoReflectionMethodBuilder *method;
3507 MonoReflectionTypeBuilder *tb;
3508 MonoReflectionArrayMethod *am;
3510 unsigned char *target;
3512 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3513 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3514 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3515 switch (target [3]) {
3516 case MONO_TABLE_FIELD:
3517 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3518 field = (MonoReflectionFieldBuilder *)iltoken->member;
3519 idx = field->table_idx;
3520 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3521 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3522 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3524 g_assert_not_reached ();
3527 case MONO_TABLE_METHOD:
3528 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3529 method = (MonoReflectionMethodBuilder *)iltoken->member;
3530 idx = method->table_idx;
3531 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3532 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3533 idx = ctor->table_idx;
3534 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3535 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3536 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3537 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3539 g_assert_not_reached ();
3542 case MONO_TABLE_TYPEDEF:
3543 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3544 g_assert_not_reached ();
3545 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3546 idx = tb->table_idx;
3548 case MONO_TABLE_MEMBERREF:
3549 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3550 am = (MonoReflectionArrayMethod*)iltoken->member;
3551 idx = am->table_idx;
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3553 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3554 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3555 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3556 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3557 g_assert (m->klass->generic_class || m->klass->generic_container);
3559 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3561 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3562 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3563 g_assert (f->generic_info);
3565 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3568 g_assert_not_reached ();
3571 case MONO_TABLE_METHODSPEC:
3572 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3573 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3574 g_assert (mono_method_signature (m)->generic_param_count);
3577 g_assert_not_reached ();
3581 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3583 target [0] = idx & 0xff;
3584 target [1] = (idx >> 8) & 0xff;
3585 target [2] = (idx >> 16) & 0xff;
3592 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3593 * value is not known when the table is emitted.
3596 fixup_cattrs (MonoDynamicImage *assembly)
3598 MonoDynamicTable *table;
3600 guint32 type, i, idx, token;
3603 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3605 for (i = 0; i < table->rows; ++i) {
3606 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3608 type = values [MONO_CUSTOM_ATTR_TYPE];
3609 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3610 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3611 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3612 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3615 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3616 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3617 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3618 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3625 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3627 MonoDynamicTable *table;
3630 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3632 alloc_table (table, table->rows);
3633 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3634 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3635 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3636 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3637 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3642 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3644 MonoDynamicTable *table;
3648 char *b = blob_size;
3650 guint32 idx, offset;
3652 if (rsrc->filename) {
3653 name = mono_string_to_utf8 (rsrc->filename);
3654 sname = g_path_get_basename (name);
3656 table = &assembly->tables [MONO_TABLE_FILE];
3658 alloc_table (table, table->rows);
3659 values = table->values + table->next_idx * MONO_FILE_SIZE;
3660 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3661 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3664 mono_sha1_get_digest_from_file (name, hash);
3665 mono_metadata_encode_value (20, b, &b);
3666 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3667 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3669 idx = table->next_idx++;
3671 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3677 data = mono_array_addr (rsrc->data, char, 0);
3678 len = mono_array_length (rsrc->data);
3684 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3685 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3686 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3687 mono_image_add_stream_data (&assembly->resources, data, len);
3691 * The entry should be emitted into the MANIFESTRESOURCE table of
3692 * the main module, but that needs to reference the FILE table
3693 * which isn't emitted yet.
3700 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3704 set_version_from_string (MonoString *version, guint32 *values)
3706 gchar *ver, *p, *str;
3709 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3710 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3711 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3712 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3715 ver = str = mono_string_to_utf8 (version);
3716 for (i = 0; i < 4; ++i) {
3717 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3723 /* handle Revision and Build */
3733 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3737 char *b = blob_size;
3742 len = mono_array_length (pkey);
3743 mono_metadata_encode_value (len, b, &b);
3744 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3745 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3747 /* Special case: check for ECMA key (16 bytes) */
3748 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3749 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3750 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3751 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3752 /* minimum key size (in 2.0) is 384 bits */
3753 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3755 /* FIXME - verifier */
3756 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3757 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3759 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3765 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3767 MonoDynamicTable *table;
3768 MonoDynamicImage *assembly;
3769 MonoReflectionAssemblyBuilder *assemblyb;
3773 guint32 module_index;
3775 assemblyb = moduleb->assemblyb;
3776 assembly = moduleb->dynamic_image;
3777 domain = mono_object_domain (assemblyb);
3779 /* Emit ASSEMBLY table */
3780 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3781 alloc_table (table, 1);
3782 values = table->values + MONO_ASSEMBLY_SIZE;
3783 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3784 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3785 if (assemblyb->culture) {
3786 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3788 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3790 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3791 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3792 set_version_from_string (assemblyb->version, values);
3794 /* Emit FILE + EXPORTED_TYPE table */
3796 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3798 MonoReflectionModuleBuilder *file_module =
3799 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3800 if (file_module != moduleb) {
3801 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3803 if (file_module->types) {
3804 for (j = 0; j < file_module->num_types; ++j) {
3805 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3806 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3811 if (assemblyb->loaded_modules) {
3812 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3813 MonoReflectionModule *file_module =
3814 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3815 mono_image_fill_file_table (domain, file_module, assembly);
3817 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3820 if (assemblyb->type_forwarders)
3821 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3823 /* Emit MANIFESTRESOURCE table */
3825 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3827 MonoReflectionModuleBuilder *file_module =
3828 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3829 /* The table for the main module is emitted later */
3830 if (file_module != moduleb) {
3832 if (file_module->resources) {
3833 int len = mono_array_length (file_module->resources);
3834 for (j = 0; j < len; ++j) {
3835 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3836 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3844 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3845 * for the modulebuilder @moduleb.
3846 * At the end of the process, method and field tokens are fixed up and the
3847 * on-disk compressed metadata representation is created.
3850 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3852 MonoDynamicTable *table;
3853 MonoDynamicImage *assembly;
3854 MonoReflectionAssemblyBuilder *assemblyb;
3860 assemblyb = moduleb->assemblyb;
3861 assembly = moduleb->dynamic_image;
3862 domain = mono_object_domain (assemblyb);
3864 if (assembly->text_rva)
3867 assembly->text_rva = START_TEXT_RVA;
3869 if (moduleb->is_main) {
3870 mono_image_emit_manifest (moduleb);
3873 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3874 table->rows = 1; /* .<Module> */
3876 alloc_table (table, table->rows);
3878 * Set the first entry.
3880 values = table->values + table->columns;
3881 values [MONO_TYPEDEF_FLAGS] = 0;
3882 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3883 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3884 values [MONO_TYPEDEF_EXTENDS] = 0;
3885 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3886 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3889 * handle global methods
3890 * FIXME: test what to do when global methods are defined in multiple modules.
3892 if (moduleb->global_methods) {
3893 table = &assembly->tables [MONO_TABLE_METHOD];
3894 table->rows += mono_array_length (moduleb->global_methods);
3895 alloc_table (table, table->rows);
3896 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3897 mono_image_get_method_info (
3898 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3900 if (moduleb->global_fields) {
3901 table = &assembly->tables [MONO_TABLE_FIELD];
3902 table->rows += mono_array_length (moduleb->global_fields);
3903 alloc_table (table, table->rows);
3904 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3905 mono_image_get_field_info (
3906 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3909 table = &assembly->tables [MONO_TABLE_MODULE];
3910 alloc_table (table, 1);
3911 mono_image_fill_module_table (domain, moduleb, assembly);
3913 /* Collect all types into a list sorted by their table_idx */
3914 types = g_ptr_array_new ();
3917 for (i = 0; i < moduleb->num_types; ++i) {
3918 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3919 collect_types (types, type);
3922 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3923 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3924 table->rows += types->len;
3925 alloc_table (table, table->rows);
3928 * Emit type names + namespaces at one place inside the string heap,
3929 * so load_class_names () needs to touch fewer pages.
3931 for (i = 0; i < types->len; ++i) {
3932 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3933 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3935 for (i = 0; i < types->len; ++i) {
3936 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3937 string_heap_insert_mstring (&assembly->sheap, tb->name);
3940 for (i = 0; i < types->len; ++i) {
3941 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3942 mono_image_get_type_info (domain, type, assembly);
3946 * table->rows is already set above and in mono_image_fill_module_table.
3948 /* add all the custom attributes at the end, once all the indexes are stable */
3949 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3951 /* CAS assembly permissions */
3952 if (assemblyb->permissions_minimum)
3953 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3954 if (assemblyb->permissions_optional)
3955 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3956 if (assemblyb->permissions_refused)
3957 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3959 module_add_cattrs (assembly, moduleb);
3962 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3964 /* Create the MethodImpl table. We do this after emitting all methods so we already know
3965 * the final tokens and don't need another fixup pass. */
3967 if (moduleb->global_methods) {
3968 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3969 MonoReflectionMethodBuilder *mb = mono_array_get (
3970 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3971 mono_image_add_methodimpl (assembly, mb);
3975 for (i = 0; i < types->len; ++i) {
3976 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3977 if (type->methods) {
3978 for (j = 0; j < type->num_methods; ++j) {
3979 MonoReflectionMethodBuilder *mb = mono_array_get (
3980 type->methods, MonoReflectionMethodBuilder*, j);
3982 mono_image_add_methodimpl (assembly, mb);
3987 g_ptr_array_free (types, TRUE);
3989 fixup_cattrs (assembly);
3993 * mono_image_insert_string:
3994 * @module: module builder object
3997 * Insert @str into the user string stream of @module.
4000 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4002 MonoDynamicImage *assembly;
4007 MONO_ARCH_SAVE_REGS;
4009 if (!module->dynamic_image)
4010 mono_image_module_basic_init (module);
4012 assembly = module->dynamic_image;
4014 if (assembly->save) {
4015 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4016 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4017 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4019 char *swapped = g_malloc (2 * mono_string_length (str));
4020 const char *p = (const char*)mono_string_chars (str);
4022 swap_with_size (swapped, p, 2, mono_string_length (str));
4023 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4027 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4029 mono_image_add_stream_data (&assembly->us, "", 1);
4031 idx = assembly->us.index ++;
4034 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4036 return MONO_TOKEN_STRING | idx;
4040 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4045 klass = obj->vtable->klass;
4046 if (strcmp (klass->name, "MonoMethod") == 0) {
4047 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4048 MonoMethodSignature *sig, *old;
4049 guint32 sig_token, parent;
4052 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4054 nargs = mono_array_length (opt_param_types);
4055 old = mono_method_signature (method);
4056 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4058 sig->hasthis = old->hasthis;
4059 sig->explicit_this = old->explicit_this;
4060 sig->call_convention = old->call_convention;
4061 sig->generic_param_count = old->generic_param_count;
4062 sig->param_count = old->param_count + nargs;
4063 sig->sentinelpos = old->param_count;
4064 sig->ret = old->ret;
4066 for (i = 0; i < old->param_count; i++)
4067 sig->params [i] = old->params [i];
4069 for (i = 0; i < nargs; i++) {
4070 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4071 sig->params [old->param_count + i] = rt->type;
4074 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4075 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4076 parent >>= MONO_TYPEDEFORREF_BITS;
4078 parent <<= MONO_MEMBERREF_PARENT_BITS;
4079 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4081 sig_token = method_encode_signature (assembly, sig);
4082 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4083 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4084 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4085 ReflectionMethodBuilder rmb;
4086 guint32 parent, sig;
4088 reflection_methodbuilder_from_method_builder (&rmb, mb);
4089 rmb.opt_types = opt_param_types;
4091 sig = method_builder_encode_signature (assembly, &rmb);
4093 parent = mono_image_create_token (assembly, obj, TRUE);
4094 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4096 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4097 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4099 token = mono_image_get_varargs_method_token (
4100 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4102 g_error ("requested method token for %s\n", klass->name);
4109 * mono_image_create_token:
4110 * @assembly: a dynamic assembly
4113 * Get a token to insert in the IL code stream for the given MemberInfo.
4114 * @obj can be one of:
4115 * ConstructorBuilder
4125 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4130 klass = obj->vtable->klass;
4131 if (strcmp (klass->name, "MethodBuilder") == 0) {
4132 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4134 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4135 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4137 token = mono_image_get_methodbuilder_token (assembly, mb);
4138 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4139 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4140 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4142 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4143 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4145 token = mono_image_get_ctorbuilder_token (assembly, mb);
4146 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4147 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4148 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4149 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4150 if (tb->generic_params) {
4151 token = mono_image_get_generic_field_token (assembly, fb);
4153 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4155 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4156 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4157 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4158 } else if (strcmp (klass->name, "MonoType") == 0 ||
4159 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4160 MonoReflectionType *tb = (MonoReflectionType *)obj;
4161 token = mono_metadata_token_from_dor (
4162 mono_image_typedef_or_ref (assembly, tb->type));
4163 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4164 MonoReflectionType *tb = (MonoReflectionType *)obj;
4165 token = mono_metadata_token_from_dor (
4166 mono_image_typedef_or_ref (assembly, tb->type));
4167 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4168 strcmp (klass->name, "MonoMethod") == 0 ||
4169 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4170 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4171 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4172 if (m->method->is_inflated) {
4173 if (create_methodspec)
4174 token = mono_image_get_methodspec_token (assembly, m->method);
4176 token = mono_image_get_inflated_method_token (assembly, m->method);
4177 } else if ((m->method->klass->image == &assembly->image) &&
4178 !m->method->klass->generic_class) {
4179 static guint32 method_table_idx = 0xffffff;
4180 if (m->method->klass->wastypebuilder) {
4181 /* we use the same token as the one that was assigned
4182 * to the Methodbuilder.
4183 * FIXME: do the equivalent for Fields.
4185 token = m->method->token;
4188 * Each token should have a unique index, but the indexes are
4189 * assigned by managed code, so we don't know about them. An
4190 * easy solution is to count backwards...
4192 method_table_idx --;
4193 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4196 token = mono_image_get_methodref_token (assembly, m->method);
4198 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4199 } else if (strcmp (klass->name, "MonoField") == 0) {
4200 MonoReflectionField *f = (MonoReflectionField *)obj;
4201 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4202 static guint32 field_table_idx = 0xffffff;
4204 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4206 token = mono_image_get_fieldref_token (assembly, f);
4208 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4209 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4210 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4211 token = mono_image_get_array_token (assembly, m);
4212 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4213 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4214 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4215 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4216 MonoReflectionType *tb = (MonoReflectionType *)obj;
4217 token = mono_metadata_token_from_dor (
4218 mono_image_typedef_or_ref (assembly, tb->type));
4220 g_error ("requested token for %s\n", klass->name);
4223 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4229 guint32 import_lookup_table;
4233 guint32 import_address_table_rva;
4241 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4243 static MonoDynamicImage*
4244 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4246 static const guchar entrycode [16] = {0xff, 0x25, 0};
4247 MonoDynamicImage *image;
4250 const char *version = mono_get_runtime_info ()->runtime_version;
4253 image = GC_MALLOC (sizeof (MonoDynamicImage));
4255 image = g_new0 (MonoDynamicImage, 1);
4258 /*g_print ("created image %p\n", image);*/
4259 /* keep in sync with image.c */
4260 image->image.name = assembly_name;
4261 image->image.assembly_name = image->image.name; /* they may be different */
4262 image->image.module_name = module_name;
4263 image->image.version = g_strdup (version);
4264 image->image.md_version_major = 1;
4265 image->image.md_version_minor = 1;
4266 image->image.dynamic = TRUE;
4268 image->image.references = g_new0 (MonoAssembly*, 1);
4269 image->image.references [0] = NULL;
4271 mono_image_init (&image->image);
4273 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4274 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4275 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4276 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4277 image->handleref = g_hash_table_new (NULL, NULL);
4278 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4279 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4280 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4281 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4282 image->gen_params = g_ptr_array_new ();
4284 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4285 string_heap_init (&image->sheap);
4286 mono_image_add_stream_data (&image->us, "", 1);
4287 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4288 /* import tables... */
4289 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4290 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4291 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4292 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4293 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4294 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4295 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4296 stream_data_align (&image->code);
4298 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4300 for (i=0; i < MONO_TABLE_NUM; ++i) {
4301 image->tables [i].next_idx = 1;
4302 image->tables [i].columns = table_sizes [i];
4305 image->image.assembly = (MonoAssembly*)assembly;
4306 image->run = assembly->run;
4307 image->save = assembly->save;
4308 image->pe_kind = 0x1; /* ILOnly */
4309 image->machine = 0x14c; /* I386 */
4315 * mono_image_basic_init:
4316 * @assembly: an assembly builder object
4318 * Create the MonoImage that represents the assembly builder and setup some
4319 * of the helper hash table and the basic metadata streams.
4322 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4324 MonoDynamicAssembly *assembly;
4325 MonoDynamicImage *image;
4326 MonoDomain *domain = mono_object_domain (assemblyb);
4328 MONO_ARCH_SAVE_REGS;
4330 if (assemblyb->dynamic_assembly)
4334 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4336 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4339 assembly->assembly.ref_count = 1;
4340 assembly->assembly.dynamic = TRUE;
4341 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4342 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4343 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4344 if (assemblyb->culture)
4345 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4347 assembly->assembly.aname.culture = g_strdup ("");
4349 if (assemblyb->version) {
4350 char *vstr = mono_string_to_utf8 (assemblyb->version);
4351 char **version = g_strsplit (vstr, ".", 4);
4352 char **parts = version;
4353 assembly->assembly.aname.major = atoi (*parts++);
4354 assembly->assembly.aname.minor = atoi (*parts++);
4355 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4356 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4358 g_strfreev (version);
4361 assembly->assembly.aname.major = 0;
4362 assembly->assembly.aname.minor = 0;
4363 assembly->assembly.aname.build = 0;
4364 assembly->assembly.aname.revision = 0;
4367 assembly->run = assemblyb->access != 2;
4368 assembly->save = assemblyb->access != 1;
4370 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4371 image->initial_image = TRUE;
4372 assembly->assembly.aname.name = image->image.name;
4373 assembly->assembly.image = &image->image;
4375 mono_domain_assemblies_lock (domain);
4376 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4377 mono_domain_assemblies_unlock (domain);
4379 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4380 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4384 calc_section_size (MonoDynamicImage *assembly)
4388 /* alignment constraints */
4389 assembly->code.index += 3;
4390 assembly->code.index &= ~3;
4391 assembly->meta_size += 3;
4392 assembly->meta_size &= ~3;
4393 assembly->resources.index += 3;
4394 assembly->resources.index &= ~3;
4396 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4397 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4400 if (assembly->win32_res) {
4401 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4403 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4404 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4408 assembly->sections [MONO_SECTION_RELOC].size = 12;
4409 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4419 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4423 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4425 ResTreeNode *t1 = (ResTreeNode*)a;
4426 ResTreeNode *t2 = (ResTreeNode*)b;
4428 return t1->id - t2->id;
4432 * resource_tree_create:
4434 * Organize the resources into a resource tree.
4436 static ResTreeNode *
4437 resource_tree_create (MonoArray *win32_resources)
4439 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4443 tree = g_new0 (ResTreeNode, 1);
4445 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4446 MonoReflectionWin32Resource *win32_res =
4447 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4451 /* FIXME: BUG: this stores managed references in unmanaged memory */
4452 lang_node = g_new0 (ResTreeNode, 1);
4453 lang_node->id = win32_res->lang_id;
4454 lang_node->win32_res = win32_res;
4456 /* Create type node if neccesary */
4458 for (l = tree->children; l; l = l->next)
4459 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4460 type_node = (ResTreeNode*)l->data;
4465 type_node = g_new0 (ResTreeNode, 1);
4466 type_node->id = win32_res->res_type;
4469 * The resource types have to be sorted otherwise
4470 * Windows Explorer can't display the version information.
4472 tree->children = g_slist_insert_sorted (tree->children,
4473 type_node, resource_tree_compare_by_id);
4476 /* Create res node if neccesary */
4478 for (l = type_node->children; l; l = l->next)
4479 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4480 res_node = (ResTreeNode*)l->data;
4485 res_node = g_new0 (ResTreeNode, 1);
4486 res_node->id = win32_res->res_id;
4487 type_node->children = g_slist_append (type_node->children, res_node);
4490 res_node->children = g_slist_append (res_node->children, lang_node);
4497 * resource_tree_encode:
4499 * Encode the resource tree into the format used in the PE file.
4502 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4505 MonoPEResourceDir dir;
4506 MonoPEResourceDirEntry dir_entry;
4507 MonoPEResourceDataEntry data_entry;
4511 * For the format of the resource directory, see the article
4512 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4516 memset (&dir, 0, sizeof (dir));
4517 memset (&dir_entry, 0, sizeof (dir_entry));
4518 memset (&data_entry, 0, sizeof (data_entry));
4520 g_assert (sizeof (dir) == 16);
4521 g_assert (sizeof (dir_entry) == 8);
4522 g_assert (sizeof (data_entry) == 16);
4524 node->offset = p - begin;
4526 /* IMAGE_RESOURCE_DIRECTORY */
4527 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4529 memcpy (p, &dir, sizeof (dir));
4532 /* Reserve space for entries */
4534 p += sizeof (dir_entry) * dir.res_id_entries;
4536 /* Write children */
4537 for (l = node->children; l; l = l->next) {
4538 ResTreeNode *child = (ResTreeNode*)l->data;
4540 if (child->win32_res) {
4542 child->offset = p - begin;
4544 /* IMAGE_RESOURCE_DATA_ENTRY */
4545 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4546 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4548 memcpy (p, &data_entry, sizeof (data_entry));
4549 p += sizeof (data_entry);
4551 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4552 p += data_entry.rde_size;
4554 resource_tree_encode (child, begin, p, &p);
4558 /* IMAGE_RESOURCE_ENTRY */
4559 for (l = node->children; l; l = l->next) {
4560 ResTreeNode *child = (ResTreeNode*)l->data;
4561 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4563 dir_entry.is_dir = child->win32_res ? 0 : 1;
4564 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4566 memcpy (entries, &dir_entry, sizeof (dir_entry));
4567 entries += sizeof (dir_entry);
4574 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4579 MonoReflectionWin32Resource *win32_res;
4582 if (!assemblyb->win32_resources)
4586 * Resources are stored in a three level tree inside the PE file.
4587 * - level one contains a node for each type of resource
4588 * - level two contains a node for each resource
4589 * - level three contains a node for each instance of a resource for a
4590 * specific language.
4593 tree = resource_tree_create (assemblyb->win32_resources);
4595 /* Estimate the size of the encoded tree */
4597 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4598 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4599 size += mono_array_length (win32_res->res_data);
4601 /* Directory structure */
4602 size += mono_array_length (assemblyb->win32_resources) * 256;
4603 p = buf = g_malloc (size);
4605 resource_tree_encode (tree, p, p, &p);
4607 g_assert (p - buf < size);
4609 assembly->win32_res = g_malloc (p - buf);
4610 assembly->win32_res_size = p - buf;
4611 memcpy (assembly->win32_res, buf, p - buf);
4617 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4619 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4622 p += sizeof (MonoPEResourceDir);
4623 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4624 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4625 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4626 if (dir_entry->is_dir) {
4627 fixup_resource_directory (res_section, child, rva);
4629 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4630 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4633 p += sizeof (MonoPEResourceDirEntry);
4638 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4641 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4642 g_error ("WriteFile returned %d\n", GetLastError ());
4646 * mono_image_create_pefile:
4647 * @mb: a module builder object
4649 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4650 * assembly->pefile where it can be easily retrieved later in chunks.
4653 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4654 MonoMSDOSHeader *msdos;
4655 MonoDotNetHeader *header;
4656 MonoSectionTable *section;
4657 MonoCLIHeader *cli_header;
4658 guint32 size, image_size, virtual_base, text_offset;
4659 guint32 header_start, section_start, file_offset, virtual_offset;
4660 MonoDynamicImage *assembly;
4661 MonoReflectionAssemblyBuilder *assemblyb;
4662 MonoDynamicStream pefile_stream = {0};
4663 MonoDynamicStream *pefile = &pefile_stream;
4665 guint32 *rva, value;
4667 static const unsigned char msheader[] = {
4668 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4669 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4672 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4673 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4674 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4675 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4678 assemblyb = mb->assemblyb;
4680 mono_image_basic_init (assemblyb);
4681 assembly = mb->dynamic_image;
4683 assembly->pe_kind = assemblyb->pe_kind;
4684 assembly->machine = assemblyb->machine;
4685 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4686 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4688 mono_image_build_metadata (mb);
4690 if (mb->is_main && assemblyb->resources) {
4691 int len = mono_array_length (assemblyb->resources);
4692 for (i = 0; i < len; ++i)
4693 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4696 if (mb->resources) {
4697 int len = mono_array_length (mb->resources);
4698 for (i = 0; i < len; ++i)
4699 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4702 build_compressed_metadata (assembly);
4705 assembly_add_win32_resources (assembly, assemblyb);
4707 nsections = calc_section_size (assembly);
4709 /* The DOS header and stub */
4710 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4711 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4713 /* the dotnet header */
4714 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4716 /* the section tables */
4717 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4719 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4720 virtual_offset = VIRT_ALIGN;
4723 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4724 if (!assembly->sections [i].size)
4727 file_offset += FILE_ALIGN - 1;
4728 file_offset &= ~(FILE_ALIGN - 1);
4729 virtual_offset += VIRT_ALIGN - 1;
4730 virtual_offset &= ~(VIRT_ALIGN - 1);
4732 assembly->sections [i].offset = file_offset;
4733 assembly->sections [i].rva = virtual_offset;
4735 file_offset += assembly->sections [i].size;
4736 virtual_offset += assembly->sections [i].size;
4737 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4740 file_offset += FILE_ALIGN - 1;
4741 file_offset &= ~(FILE_ALIGN - 1);
4743 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4745 /* back-patch info */
4746 msdos = (MonoMSDOSHeader*)pefile->data;
4747 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4749 header = (MonoDotNetHeader*)(pefile->data + header_start);
4750 header->pesig [0] = 'P';
4751 header->pesig [1] = 'E';
4753 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4754 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4755 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4756 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4757 if (assemblyb->pekind == 1) {
4759 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4762 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4765 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4767 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4768 header->pe.pe_major = 6;
4769 header->pe.pe_minor = 0;
4770 size = assembly->sections [MONO_SECTION_TEXT].size;
4771 size += FILE_ALIGN - 1;
4772 size &= ~(FILE_ALIGN - 1);
4773 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4774 size = assembly->sections [MONO_SECTION_RSRC].size;
4775 size += FILE_ALIGN - 1;
4776 size &= ~(FILE_ALIGN - 1);
4777 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4778 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4779 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4780 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4781 /* pe_rva_entry_point always at the beginning of the text section */
4782 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4784 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4785 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4786 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4787 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4788 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4789 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4790 size = section_start;
4791 size += FILE_ALIGN - 1;
4792 size &= ~(FILE_ALIGN - 1);
4793 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4795 size += VIRT_ALIGN - 1;
4796 size &= ~(VIRT_ALIGN - 1);
4797 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4800 // Translate the PEFileKind value to the value expected by the Windows loader
4806 // PEFileKinds.Dll == 1
4807 // PEFileKinds.ConsoleApplication == 2
4808 // PEFileKinds.WindowApplication == 3
4811 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4812 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4814 if (assemblyb->pekind == 3)
4819 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4821 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4822 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4823 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4824 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4825 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4826 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4828 /* fill data directory entries */
4830 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4831 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4833 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4834 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4836 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4837 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4838 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4839 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4840 /* patch entrypoint name */
4841 if (assemblyb->pekind == 1)
4842 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4844 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4845 /* patch imported function RVA name */
4846 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4847 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4849 /* the import table */
4850 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4851 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4852 /* patch imported dll RVA name and other entries in the dir */
4853 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4854 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4855 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4856 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4857 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4858 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4860 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4861 value = (assembly->text_rva + assembly->imp_names_offset);
4862 *p++ = (value) & 0xff;
4863 *p++ = (value >> 8) & (0xff);
4864 *p++ = (value >> 16) & (0xff);
4865 *p++ = (value >> 24) & (0xff);
4867 /* the CLI header info */
4868 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4869 cli_header->ch_size = GUINT32_FROM_LE (72);
4870 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4871 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4872 if (assemblyb->entry_point) {
4873 guint32 table_idx = 0;
4874 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4875 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4876 table_idx = methodb->table_idx;
4878 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4880 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4882 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4884 /* The embedded managed resources */
4885 text_offset = assembly->text_rva + assembly->code.index;
4886 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4887 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4888 text_offset += assembly->resources.index;
4889 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4890 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4891 text_offset += assembly->meta_size;
4892 if (assembly->strong_name_size) {
4893 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4894 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4895 text_offset += assembly->strong_name_size;
4898 /* write the section tables and section content */
4899 section = (MonoSectionTable*)(pefile->data + section_start);
4900 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4901 static const char section_names [][7] = {
4902 ".text", ".rsrc", ".reloc"
4904 if (!assembly->sections [i].size)
4906 strcpy (section->st_name, section_names [i]);
4907 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4908 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4909 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4910 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4911 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4912 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4913 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4917 checked_write_file (file, pefile->data, pefile->index);
4919 mono_dynamic_stream_reset (pefile);
4921 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4922 if (!assembly->sections [i].size)
4925 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4926 g_error ("SetFilePointer returned %d\n", GetLastError ());
4929 case MONO_SECTION_TEXT:
4930 /* patch entry point */
4931 p = (guchar*)(assembly->code.data + 2);
4932 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4933 *p++ = (value) & 0xff;
4934 *p++ = (value >> 8) & 0xff;
4935 *p++ = (value >> 16) & 0xff;
4936 *p++ = (value >> 24) & 0xff;
4938 checked_write_file (file, assembly->code.data, assembly->code.index);
4939 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4940 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4941 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4944 g_free (assembly->image.raw_metadata);
4946 case MONO_SECTION_RELOC: {
4950 guint16 type_and_offset;
4954 g_assert (sizeof (reloc) == 12);
4956 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4957 reloc.block_size = GUINT32_FROM_LE (12);
4960 * the entrypoint is always at the start of the text section
4961 * 3 is IMAGE_REL_BASED_HIGHLOW
4962 * 2 is patch_size_rva - text_rva
4964 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4967 checked_write_file (file, &reloc, sizeof (reloc));
4971 case MONO_SECTION_RSRC:
4972 if (assembly->win32_res) {
4974 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4975 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4976 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4980 g_assert_not_reached ();
4984 /* check that the file is properly padded */
4985 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4986 g_error ("SetFilePointer returned %d\n", GetLastError ());
4987 if (! SetEndOfFile (file))
4988 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4990 mono_dynamic_stream_reset (&assembly->code);
4991 mono_dynamic_stream_reset (&assembly->us);
4992 mono_dynamic_stream_reset (&assembly->blob);
4993 mono_dynamic_stream_reset (&assembly->guid);
4994 mono_dynamic_stream_reset (&assembly->sheap);
4996 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4997 g_hash_table_destroy (assembly->blob_cache);
4998 assembly->blob_cache = NULL;
5001 MonoReflectionModule *
5002 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5006 MonoImageOpenStatus status;
5007 MonoDynamicAssembly *assembly;
5008 guint32 module_count;
5009 MonoImage **new_modules;
5011 name = mono_string_to_utf8 (fileName);
5013 image = mono_image_open (name, &status);
5016 if (status == MONO_IMAGE_ERROR_ERRNO)
5017 exc = mono_get_exception_file_not_found (fileName);
5019 exc = mono_get_exception_bad_image_format (name);
5021 mono_raise_exception (exc);
5026 assembly = ab->dynamic_assembly;
5027 image->assembly = (MonoAssembly*)assembly;
5029 module_count = image->assembly->image->module_count;
5030 new_modules = g_new0 (MonoImage *, module_count + 1);
5032 if (image->assembly->image->modules)
5033 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5034 new_modules [module_count] = image;
5035 mono_image_addref (image);
5037 g_free (image->assembly->image->modules);
5038 image->assembly->image->modules = new_modules;
5039 image->assembly->image->module_count ++;
5041 mono_assembly_load_references (image, &status);
5043 mono_image_close (image);
5044 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5047 return mono_module_get_object (mono_domain_get (), image);
5051 * We need to return always the same object for MethodInfo, FieldInfo etc..
5052 * but we need to consider the reflected type.
5053 * type uses a different hash, since it uses custom hash/equal functions.
5058 MonoClass *refclass;
5062 reflected_equal (gconstpointer a, gconstpointer b) {
5063 const ReflectedEntry *ea = a;
5064 const ReflectedEntry *eb = b;
5066 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5070 reflected_hash (gconstpointer a) {
5071 const ReflectedEntry *ea = a;
5072 return mono_aligned_addr_hash (ea->item);
5075 #define CHECK_OBJECT(t,p,k) \
5081 mono_domain_lock (domain); \
5082 if (!domain->refobject_hash) \
5083 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5084 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5085 mono_domain_unlock (domain); \
5088 mono_domain_unlock (domain); \
5092 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5094 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5096 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5099 #define CACHE_OBJECT(t,p,o,k) \
5102 ReflectedEntry pe; \
5104 pe.refclass = (k); \
5105 mono_domain_lock (domain); \
5106 if (!domain->refobject_hash) \
5107 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5108 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5110 ReflectedEntry *e = ALLOC_REFENTRY; \
5112 e->refclass = (k); \
5113 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5116 mono_domain_unlock (domain); \
5121 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5123 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5127 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5129 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5133 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5135 MonoDynamicImage *image = moduleb->dynamic_image;
5136 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5139 MonoImage **new_modules;
5142 * FIXME: we already created an image in mono_image_basic_init (), but
5143 * we don't know which module it belongs to, since that is only
5144 * determined at assembly save time.
5146 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5147 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5149 moduleb->module.image = &image->image;
5150 moduleb->dynamic_image = image;
5151 register_module (mono_object_domain (moduleb), moduleb, image);
5153 /* register the module with the assembly */
5154 ass = ab->dynamic_assembly->assembly.image;
5155 module_count = ass->module_count;
5156 new_modules = g_new0 (MonoImage *, module_count + 1);
5159 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5160 new_modules [module_count] = &image->image;
5161 mono_image_addref (&image->image);
5163 g_free (ass->modules);
5164 ass->modules = new_modules;
5165 ass->module_count ++;
5170 * mono_assembly_get_object:
5171 * @domain: an app domain
5172 * @assembly: an assembly
5174 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5176 MonoReflectionAssembly*
5177 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5179 static MonoClass *System_Reflection_Assembly;
5180 MonoReflectionAssembly *res;
5182 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5183 if (!System_Reflection_Assembly)
5184 System_Reflection_Assembly = mono_class_from_name (
5185 mono_defaults.corlib, "System.Reflection", "Assembly");
5186 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5187 res->assembly = assembly;
5189 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5194 MonoReflectionModule*
5195 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5197 static MonoClass *System_Reflection_Module;
5198 MonoReflectionModule *res;
5201 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5202 if (!System_Reflection_Module)
5203 System_Reflection_Module = mono_class_from_name (
5204 mono_defaults.corlib, "System.Reflection", "Module");
5205 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5208 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5210 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5211 basename = g_path_get_basename (image->name);
5212 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5213 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5217 if (image->assembly->image == image) {
5218 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5222 if (image->assembly->image->modules) {
5223 for (i = 0; i < image->assembly->image->module_count; i++) {
5224 if (image->assembly->image->modules [i] == image)
5225 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5227 g_assert (res->token);
5231 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5234 MonoReflectionModule*
5235 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5237 static MonoClass *System_Reflection_Module;
5238 MonoReflectionModule *res;
5239 MonoTableInfo *table;
5240 guint32 cols [MONO_FILE_SIZE];
5242 guint32 i, name_idx;
5245 if (!System_Reflection_Module)
5246 System_Reflection_Module = mono_class_from_name (
5247 mono_defaults.corlib, "System.Reflection", "Module");
5248 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5250 table = &image->tables [MONO_TABLE_FILE];
5251 g_assert (table_index < table->rows);
5252 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5255 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5256 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5258 /* Check whenever the row has a corresponding row in the moduleref table */
5259 table = &image->tables [MONO_TABLE_MODULEREF];
5260 for (i = 0; i < table->rows; ++i) {
5261 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5262 val = mono_metadata_string_heap (image, name_idx);
5263 if (strcmp (val, name) == 0)
5264 res->image = image->modules [i];
5267 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5268 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5269 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5270 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5271 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5277 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5279 if ((t1->type != t2->type) ||
5280 (t1->byref != t2->byref))
5284 case MONO_TYPE_VOID:
5285 case MONO_TYPE_BOOLEAN:
5286 case MONO_TYPE_CHAR:
5297 case MONO_TYPE_STRING:
5300 case MONO_TYPE_OBJECT:
5301 case MONO_TYPE_TYPEDBYREF:
5303 case MONO_TYPE_VALUETYPE:
5304 case MONO_TYPE_CLASS:
5305 case MONO_TYPE_SZARRAY:
5306 return t1->data.klass == t2->data.klass;
5308 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5309 case MONO_TYPE_ARRAY:
5310 if (t1->data.array->rank != t2->data.array->rank)
5312 return t1->data.array->eklass == t2->data.array->eklass;
5313 case MONO_TYPE_GENERICINST: {
5315 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5317 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5318 &t2->data.generic_class->container_class->byval_arg))
5320 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5321 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5327 case MONO_TYPE_MVAR:
5328 return t1->data.generic_param == t2->data.generic_param;
5330 g_error ("implement type compare for %0x!", t1->type);
5338 mymono_metadata_type_hash (MonoType *t1)
5344 hash |= t1->byref << 6; /* do not collide with t1->type values */
5346 case MONO_TYPE_VALUETYPE:
5347 case MONO_TYPE_CLASS:
5348 case MONO_TYPE_SZARRAY:
5349 /* check if the distribution is good enough */
5350 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5352 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5353 case MONO_TYPE_GENERICINST: {
5355 MonoGenericInst *inst = t1->data.generic_class->inst;
5356 hash += g_str_hash (t1->data.generic_class->container_class->name);
5358 for (i = 0; i < inst->type_argc; ++i) {
5359 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5368 static MonoReflectionGenericClass*
5369 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5371 static MonoClass *System_Reflection_MonoGenericClass;
5372 MonoReflectionGenericClass *res;
5373 MonoClass *klass, *gklass;
5375 if (!System_Reflection_MonoGenericClass) {
5376 System_Reflection_MonoGenericClass = mono_class_from_name (
5377 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5378 g_assert (System_Reflection_MonoGenericClass);
5381 klass = mono_class_from_mono_type (geninst);
5382 gklass = klass->generic_class->container_class;
5384 mono_class_init (klass);
5387 /* FIXME: allow unpinned later */
5388 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5390 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5393 res->type.type = geninst;
5394 if (gklass->wastypebuilder && gklass->reflection_info)
5395 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5397 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5403 verify_safe_for_managed_space (MonoType *type)
5405 switch (type->type) {
5407 case MONO_TYPE_ARRAY:
5408 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5410 return verify_safe_for_managed_space (type->data.type);
5411 case MONO_TYPE_SZARRAY:
5412 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5413 case MONO_TYPE_GENERICINST: {
5414 MonoGenericInst *inst = type->data.generic_class->inst;
5418 for (i = 0; i < inst->type_argc; ++i)
5419 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5425 case MONO_TYPE_MVAR:
5432 * mono_type_get_object:
5433 * @domain: an app domain
5436 * Return an System.MonoType object representing the type @type.
5439 mono_type_get_object (MonoDomain *domain, MonoType *type)
5441 MonoReflectionType *res;
5442 MonoClass *klass = mono_class_from_mono_type (type);
5444 mono_domain_lock (domain);
5445 if (!domain->type_hash)
5446 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5447 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5448 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5449 mono_domain_unlock (domain);
5452 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5453 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5454 mono_g_hash_table_insert (domain->type_hash, type, res);
5455 mono_domain_unlock (domain);
5459 if (!verify_safe_for_managed_space (type)) {
5460 mono_domain_unlock (domain);
5461 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5464 if (klass->reflection_info && !klass->wastypebuilder) {
5465 /* g_assert_not_reached (); */
5466 /* should this be considered an error condition? */
5468 mono_domain_unlock (domain);
5469 return klass->reflection_info;
5472 mono_class_init (klass);
5474 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5476 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5479 mono_g_hash_table_insert (domain->type_hash, type, res);
5480 mono_domain_unlock (domain);
5485 * mono_method_get_object:
5486 * @domain: an app domain
5488 * @refclass: the reflected type (can be NULL)
5490 * Return an System.Reflection.MonoMethod object representing the method @method.
5492 MonoReflectionMethod*
5493 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5496 * We use the same C representation for methods and constructors, but the type
5497 * name in C# is different.
5499 static MonoClass *System_Reflection_MonoMethod = NULL;
5500 static MonoClass *System_Reflection_MonoCMethod = NULL;
5501 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5502 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5504 MonoReflectionMethod *ret;
5506 if (method->is_inflated) {
5507 MonoReflectionGenericMethod *gret;
5509 method = mono_get_inflated_method (method);
5510 refclass = method->klass;
5511 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5512 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5513 if (!System_Reflection_MonoGenericCMethod)
5514 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5515 klass = System_Reflection_MonoGenericCMethod;
5517 if (!System_Reflection_MonoGenericMethod)
5518 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5519 klass = System_Reflection_MonoGenericMethod;
5521 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5522 gret->method.method = method;
5523 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5524 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5525 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5529 refclass = method->klass;
5531 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5532 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5533 if (!System_Reflection_MonoCMethod)
5534 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5535 klass = System_Reflection_MonoCMethod;
5538 if (!System_Reflection_MonoMethod)
5539 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5540 klass = System_Reflection_MonoMethod;
5542 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5543 ret->method = method;
5544 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5545 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5546 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5550 * mono_field_get_object:
5551 * @domain: an app domain
5555 * Return an System.Reflection.MonoField object representing the field @field
5558 MonoReflectionField*
5559 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5561 MonoReflectionField *res;
5564 CHECK_OBJECT (MonoReflectionField *, field, klass);
5565 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5566 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5569 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5570 if (field->generic_info)
5571 res->attrs = field->generic_info->generic_type->attrs;
5573 res->attrs = field->type->attrs;
5574 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5575 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5579 * mono_property_get_object:
5580 * @domain: an app domain
5582 * @property: a property
5584 * Return an System.Reflection.MonoProperty object representing the property @property
5587 MonoReflectionProperty*
5588 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5590 MonoReflectionProperty *res;
5593 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5594 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5595 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5597 res->property = property;
5598 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5602 * mono_event_get_object:
5603 * @domain: an app domain
5607 * Return an System.Reflection.MonoEvent object representing the event @event
5610 MonoReflectionEvent*
5611 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5613 MonoReflectionEvent *res;
5616 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5617 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5618 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5621 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5625 * mono_param_get_objects:
5626 * @domain: an app domain
5629 * Return an System.Reflection.ParameterInfo array object representing the parameters
5630 * in the method @method.
5633 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5635 static MonoClass *System_Reflection_ParameterInfo;
5636 MonoArray *res = NULL;
5637 MonoReflectionMethod *member = NULL;
5638 MonoReflectionParameter *param = NULL;
5639 char **names, **blobs = NULL;
5640 guint32 *types = NULL;
5641 MonoType *type = NULL;
5642 MonoObject *dbnull = mono_get_dbnull_object (domain);
5643 MonoMarshalSpec **mspecs;
5644 MonoMethodSignature *sig;
5647 if (!System_Reflection_ParameterInfo)
5648 System_Reflection_ParameterInfo = mono_class_from_name (
5649 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5651 if (!mono_method_signature (method)->param_count)
5652 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5654 /* Note: the cache is based on the address of the signature into the method
5655 * since we already cache MethodInfos with the method as keys.
5657 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5659 sig = mono_method_signature (method);
5660 member = mono_method_get_object (domain, method, NULL);
5661 names = g_new (char *, sig->param_count);
5662 mono_method_get_param_names (method, (const char **) names);
5664 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5665 mono_method_get_marshal_info (method, mspecs);
5667 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5668 for (i = 0; i < sig->param_count; ++i) {
5669 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5670 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5671 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5672 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5673 param->PositionImpl = i;
5674 param->AttrsImpl = sig->params [i]->attrs;
5676 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5677 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5681 blobs = g_new0 (char *, sig->param_count);
5682 types = g_new0 (guint32, sig->param_count);
5683 get_default_param_value_blobs (method, blobs, types);
5686 /* Build MonoType for the type from the Constant Table */
5688 type = g_new0 (MonoType, 1);
5689 type->type = types [i];
5690 type->data.klass = NULL;
5691 if (types [i] == MONO_TYPE_CLASS)
5692 type->data.klass = mono_defaults.object_class;
5693 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5694 /* For enums, types [i] contains the base type */
5696 type->type = MONO_TYPE_VALUETYPE;
5697 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5699 type->data.klass = mono_class_from_mono_type (type);
5701 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5703 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5704 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5705 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5710 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5712 mono_array_setref (res, i, param);
5719 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5721 mono_metadata_free_marshal_spec (mspecs [i]);
5724 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5728 * mono_method_body_get_object:
5729 * @domain: an app domain
5732 * Return an System.Reflection.MethodBody object representing the method @method.
5734 MonoReflectionMethodBody*
5735 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5737 static MonoClass *System_Reflection_MethodBody = NULL;
5738 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5739 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5740 MonoReflectionMethodBody *ret;
5741 MonoMethodNormal *mn;
5742 MonoMethodHeader *header;
5743 guint32 method_rva, local_var_sig_token;
5745 unsigned char format, flags;
5748 if (!System_Reflection_MethodBody)
5749 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5750 if (!System_Reflection_LocalVariableInfo)
5751 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5752 if (!System_Reflection_ExceptionHandlingClause)
5753 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5755 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5757 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5758 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5759 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5760 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5762 mn = (MonoMethodNormal *)method;
5763 header = mono_method_get_header (method);
5765 /* Obtain local vars signature token */
5766 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5767 ptr = mono_image_rva_map (method->klass->image, method_rva);
5768 flags = *(const unsigned char *) ptr;
5769 format = flags & METHOD_HEADER_FORMAT_MASK;
5771 case METHOD_HEADER_TINY_FORMAT:
5772 case METHOD_HEADER_TINY_FORMAT1:
5773 local_var_sig_token = 0;
5775 case METHOD_HEADER_FAT_FORMAT:
5779 local_var_sig_token = read32 (ptr);
5782 g_assert_not_reached ();
5785 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5787 ret->init_locals = header->init_locals;
5788 ret->max_stack = header->max_stack;
5789 ret->local_var_sig_token = local_var_sig_token;
5790 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5791 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5794 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5795 for (i = 0; i < header->num_locals; ++i) {
5796 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5797 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5798 info->is_pinned = header->locals [i]->pinned;
5799 info->local_index = i;
5800 mono_array_setref (ret->locals, i, info);
5804 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5805 for (i = 0; i < header->num_clauses; ++i) {
5806 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5807 MonoExceptionClause *clause = &header->clauses [i];
5809 info->flags = clause->flags;
5810 info->try_offset = clause->try_offset;
5811 info->try_length = clause->try_len;
5812 info->handler_offset = clause->handler_offset;
5813 info->handler_length = clause->handler_len;
5814 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5815 info->filter_offset = clause->data.filter_offset;
5816 else if (clause->data.catch_class)
5817 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5819 mono_array_setref (ret->clauses, i, info);
5822 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5827 mono_get_dbnull_object (MonoDomain *domain)
5831 static MonoClassField *dbnull_value_field = NULL;
5833 if (!dbnull_value_field) {
5834 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5835 mono_class_init (klass);
5836 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5837 g_assert (dbnull_value_field);
5839 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5846 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5848 guint32 param_index, i, lastp, crow = 0;
5849 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5852 MonoClass *klass = method->klass;
5853 MonoImage *image = klass->image;
5854 MonoMethodSignature *methodsig = mono_method_signature (method);
5856 MonoTableInfo *constt;
5857 MonoTableInfo *methodt;
5858 MonoTableInfo *paramt;
5860 if (!methodsig->param_count)
5863 mono_class_init (klass);
5865 if (klass->image->dynamic) {
5866 MonoReflectionMethodAux *aux;
5867 if (method->is_inflated)
5868 method = ((MonoMethodInflated*)method)->declaring;
5869 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5870 if (aux && aux->param_defaults) {
5871 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5872 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5877 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5878 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5879 constt = &image->tables [MONO_TABLE_CONSTANT];
5881 idx = mono_method_get_index (method) - 1;
5882 g_assert (idx != -1);
5884 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5885 if (idx + 1 < methodt->rows)
5886 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5888 lastp = paramt->rows + 1;
5890 for (i = param_index; i < lastp; ++i) {
5893 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5894 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5896 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5899 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5904 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5905 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5906 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5913 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5918 MonoType *basetype = type;
5923 klass = mono_class_from_mono_type (type);
5924 if (klass->valuetype) {
5925 object = mono_object_new (domain, klass);
5926 retval = ((gchar *) object + sizeof (MonoObject));
5927 if (klass->enumtype)
5928 basetype = klass->enum_basetype;
5933 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5940 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5944 memset (assembly, 0, sizeof (MonoAssemblyName));
5946 assembly->culture = "";
5947 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5949 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5952 while (g_ascii_isspace (*p) || *p == ',') {
5961 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5963 assembly->major = strtoul (p, &s, 10);
5964 if (s == p || *s != '.')
5967 assembly->minor = strtoul (p, &s, 10);
5968 if (s == p || *s != '.')
5971 assembly->build = strtoul (p, &s, 10);
5972 if (s == p || *s != '.')
5975 assembly->revision = strtoul (p, &s, 10);
5979 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5981 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5982 assembly->culture = "";
5985 assembly->culture = p;
5986 while (*p && *p != ',') {
5990 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5992 if (strncmp (p, "null", 4) == 0) {
5997 while (*p && *p != ',') {
6000 len = (p - start + 1);
6001 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6002 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6003 g_strlcpy ((char*)assembly->public_key_token, start, len);
6006 while (*p && *p != ',')
6010 while (g_ascii_isspace (*p) || *p == ',') {
6024 * mono_reflection_parse_type:
6027 * Parse a type name as accepted by the GetType () method and output the info
6028 * extracted in the info structure.
6029 * the name param will be mangled, so, make a copy before passing it to this function.
6030 * The fields in info will be valid until the memory pointed to by name is valid.
6032 * See also mono_type_get_name () below.
6034 * Returns: 0 on parse error.
6037 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6038 MonoTypeNameParse *info)
6040 char *start, *p, *w, *temp, *last_point, *startn;
6041 int in_modifiers = 0;
6042 int isbyref = 0, rank, arity = 0, i;
6044 start = p = w = name;
6046 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6047 info->name = info->name_space = NULL;
6048 info->nested = NULL;
6049 info->modifiers = NULL;
6050 info->type_arguments = NULL;
6052 /* last_point separates the namespace from the name */
6058 *p = 0; /* NULL terminate the name */
6060 info->nested = g_list_append (info->nested, startn);
6061 /* we have parsed the nesting namespace + name */
6065 info->name_space = start;
6067 info->name = last_point + 1;
6069 info->name_space = (char *)"";
6088 i = strtol (p, &temp, 10);
6105 info->name_space = start;
6107 info->name = last_point + 1;
6109 info->name_space = (char *)"";
6116 if (isbyref) /* only one level allowed by the spec */
6119 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6123 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6129 info->type_arguments = g_ptr_array_new ();
6130 for (i = 0; i < arity; i++) {
6131 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6132 gboolean fqname = FALSE;
6134 g_ptr_array_add (info->type_arguments, subinfo);
6141 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6152 while (*p && (*p != ']'))
6160 if (g_ascii_isspace (*aname)) {
6167 !assembly_name_to_aname (&subinfo->assembly, aname))
6171 if (i + 1 < arity) {
6191 else if (*p != '*') /* '*' means unknown lower bound */
6197 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6208 if (g_ascii_isspace (*p)) {
6215 return 0; /* missing assembly name */
6216 if (!assembly_name_to_aname (&info->assembly, p))
6222 if (info->assembly.name)
6225 // *w = 0; /* terminate class name */
6227 if (!info->name || !*info->name)
6231 /* add other consistency checks */
6236 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6238 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6242 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6244 gboolean type_resolve = FALSE;
6247 if (info->assembly.name) {
6248 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6250 /* then we must load the assembly ourselve - see #60439 */
6251 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6255 image = assembly->image;
6256 } else if (!image) {
6257 image = mono_defaults.corlib;
6260 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6261 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6262 image = mono_defaults.corlib;
6263 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6270 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6277 image = mono_defaults.corlib;
6280 klass = mono_class_from_name_case (image, info->name_space, info->name);
6282 klass = mono_class_from_name (image, info->name_space, info->name);
6285 for (mod = info->nested; mod; mod = mod->next) {
6288 mono_class_init (klass);
6289 nested = klass->nested_classes;
6292 klass = nested->data;
6294 if (g_strcasecmp (klass->name, mod->data) == 0)
6297 if (strcmp (klass->name, mod->data) == 0)
6301 nested = nested->next;
6308 mono_class_init (klass);
6310 if (info->type_arguments) {
6311 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6312 MonoReflectionType *the_type;
6316 for (i = 0; i < info->type_arguments->len; i++) {
6317 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6319 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6320 if (!type_args [i]) {
6326 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6328 instance = mono_reflection_bind_generic_parameters (
6329 the_type, info->type_arguments->len, type_args);
6336 klass = mono_class_from_mono_type (instance);
6339 for (mod = info->modifiers; mod; mod = mod->next) {
6340 modval = GPOINTER_TO_UINT (mod->data);
6341 if (!modval) { /* byref: must be last modifier */
6342 return &klass->this_arg;
6343 } else if (modval == -1) {
6344 klass = mono_ptr_class_get (&klass->byval_arg);
6345 } else { /* array rank */
6346 klass = mono_array_class_get (klass, modval);
6348 mono_class_init (klass);
6351 return &klass->byval_arg;
6355 * mono_reflection_get_type:
6356 * @image: a metadata context
6357 * @info: type description structure
6358 * @ignorecase: flag for case-insensitive string compares
6359 * @type_resolve: whenever type resolve was already tried
6361 * Build a MonoType from the type description in @info.
6366 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6369 MonoReflectionAssembly *assembly;
6373 type = mono_reflection_get_type_internal (image, info, ignorecase);
6376 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6383 *type_resolve = TRUE;
6386 /* Reconstruct the type name */
6387 fullName = g_string_new ("");
6388 if (info->name_space && (info->name_space [0] != '\0'))
6389 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6391 g_string_printf (fullName, info->name);
6392 for (mod = info->nested; mod; mod = mod->next)
6393 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6395 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6397 if (assembly->assembly->dynamic) {
6398 /* Enumerate all modules */
6399 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6403 if (abuilder->modules) {
6404 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6405 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6406 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6412 if (!type && abuilder->loaded_modules) {
6413 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6414 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6415 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6422 type = mono_reflection_get_type_internal (assembly->assembly->image,
6425 g_string_free (fullName, TRUE);
6430 free_type_info (MonoTypeNameParse *info)
6432 g_list_free (info->modifiers);
6433 g_list_free (info->nested);
6435 if (info->type_arguments) {
6438 for (i = 0; i < info->type_arguments->len; i++) {
6439 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6441 free_type_info (subinfo);
6444 g_ptr_array_free (info->type_arguments, TRUE);
6449 * mono_reflection_type_from_name:
6451 * @image: a metadata context (can be NULL).
6453 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6454 * it defaults to get the type from @image or, if @image is NULL or loading
6455 * from it fails, uses corlib.
6459 mono_reflection_type_from_name (char *name, MonoImage *image)
6461 MonoType *type = NULL;
6462 MonoTypeNameParse info;
6465 /* Make a copy since parse_type modifies its argument */
6466 tmp = g_strdup (name);
6468 /*g_print ("requested type %s\n", str);*/
6469 if (mono_reflection_parse_type (tmp, &info)) {
6470 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6474 free_type_info (&info);
6479 * mono_reflection_get_token:
6481 * Return the metadata token of OBJ which should be an object
6482 * representing a metadata element.
6485 mono_reflection_get_token (MonoObject *obj)
6490 klass = obj->vtable->klass;
6492 if (strcmp (klass->name, "MethodBuilder") == 0) {
6493 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6495 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6496 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6497 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6499 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6500 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6501 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6502 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6503 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6504 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6505 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6506 } else if (strcmp (klass->name, "MonoType") == 0) {
6507 MonoReflectionType *tb = (MonoReflectionType *)obj;
6508 token = mono_class_from_mono_type (tb->type)->type_token;
6509 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6510 strcmp (klass->name, "MonoMethod") == 0 ||
6511 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6512 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6513 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6514 if (m->method->is_inflated) {
6515 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6516 return inflated->declaring->token;
6518 token = m->method->token;
6520 } else if (strcmp (klass->name, "MonoField") == 0) {
6521 MonoReflectionField *f = (MonoReflectionField*)obj;
6523 if (f->field->generic_info && f->field->generic_info->reflection_info)
6524 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6526 token = mono_class_get_field_token (f->field);
6527 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6528 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6530 token = mono_class_get_property_token (p->property);
6531 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6532 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6534 token = mono_class_get_event_token (p->event);
6535 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6536 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6538 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6539 } else if (strcmp (klass->name, "Module") == 0) {
6540 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6543 } else if (strcmp (klass->name, "Assembly") == 0) {
6544 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6546 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6547 MonoException *ex = mono_get_exception_not_implemented (msg);
6549 mono_raise_exception (ex);
6556 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6558 int slen, type = t->type;
6559 MonoClass *tklass = t->data.klass;
6565 case MONO_TYPE_BOOLEAN: {
6566 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6571 case MONO_TYPE_CHAR:
6573 case MONO_TYPE_I2: {
6574 guint16 *val = g_malloc (sizeof (guint16));
6579 #if SIZEOF_VOID_P == 4
6585 case MONO_TYPE_I4: {
6586 guint32 *val = g_malloc (sizeof (guint32));
6591 #if SIZEOF_VOID_P == 8
6592 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6597 case MONO_TYPE_I8: {
6598 guint64 *val = g_malloc (sizeof (guint64));
6603 case MONO_TYPE_VALUETYPE:
6604 if (t->data.klass->enumtype) {
6605 type = t->data.klass->enum_basetype->type;
6608 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6611 case MONO_TYPE_STRING:
6612 if (*p == (char)0xFF) {
6616 slen = mono_metadata_decode_value (p, &p);
6618 return mono_string_new_len (mono_domain_get (), p, slen);
6619 case MONO_TYPE_CLASS: {
6622 if (*p == (char)0xFF) {
6627 slen = mono_metadata_decode_value (p, &p);
6628 n = g_memdup (p, slen + 1);
6630 t = mono_reflection_type_from_name (n, image);
6632 g_warning ("Cannot load type '%s'", n);
6636 return mono_type_get_object (mono_domain_get (), t);
6640 case MONO_TYPE_OBJECT: {
6643 MonoClass *subc = NULL;
6648 } else if (subt == 0x0E) {
6649 type = MONO_TYPE_STRING;
6651 } else if (subt == 0x1D) {
6652 MonoType simple_type = {{0}};
6656 type = MONO_TYPE_SZARRAY;
6657 simple_type.type = etype;
6658 tklass = mono_class_from_mono_type (&simple_type);
6660 } else if (subt == 0x55) {
6663 slen = mono_metadata_decode_value (p, &p);
6664 n = g_memdup (p, slen + 1);
6666 t = mono_reflection_type_from_name (n, image);
6668 g_error ("Cannot load type '%s'", n);
6671 subc = mono_class_from_mono_type (t);
6672 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6673 MonoType simple_type = {{0}};
6674 simple_type.type = subt;
6675 subc = mono_class_from_mono_type (&simple_type);
6677 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6679 val = load_cattr_value (image, &subc->byval_arg, p, end);
6680 obj = mono_object_new (mono_domain_get (), subc);
6681 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6685 case MONO_TYPE_SZARRAY: {
6687 guint32 i, alen, basetype;
6690 if (alen == 0xffffffff) {
6694 arr = mono_array_new (mono_domain_get(), tklass, alen);
6695 basetype = tklass->byval_arg.type;
6696 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6697 basetype = tklass->enum_basetype->type;
6702 case MONO_TYPE_BOOLEAN:
6703 for (i = 0; i < alen; i++) {
6704 MonoBoolean val = *p++;
6705 mono_array_set (arr, MonoBoolean, i, val);
6708 case MONO_TYPE_CHAR:
6711 for (i = 0; i < alen; i++) {
6712 guint16 val = read16 (p);
6713 mono_array_set (arr, guint16, i, val);
6720 for (i = 0; i < alen; i++) {
6721 guint32 val = read32 (p);
6722 mono_array_set (arr, guint32, i, val);
6729 for (i = 0; i < alen; i++) {
6730 guint64 val = read64 (p);
6731 mono_array_set (arr, guint64, i, val);
6735 case MONO_TYPE_CLASS:
6736 case MONO_TYPE_OBJECT:
6737 case MONO_TYPE_STRING:
6738 for (i = 0; i < alen; i++) {
6739 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6740 mono_array_setref (arr, i, item);
6744 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6750 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6756 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6758 static MonoClass *klass;
6759 static MonoMethod *ctor;
6761 void *params [2], *unboxed;
6764 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6766 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6768 params [0] = mono_type_get_object (mono_domain_get (), t);
6770 retval = mono_object_new (mono_domain_get (), klass);
6771 unboxed = mono_object_unbox (retval);
6772 mono_runtime_invoke (ctor, unboxed, params, NULL);
6778 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6780 static MonoClass *klass;
6781 static MonoMethod *ctor;
6783 void *unboxed, *params [2];
6786 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6788 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6791 params [1] = typedarg;
6792 retval = mono_object_new (mono_domain_get (), klass);
6793 unboxed = mono_object_unbox (retval);
6794 mono_runtime_invoke (ctor, unboxed, params, NULL);
6800 type_is_reference (MonoType *type)
6802 switch (type->type) {
6803 case MONO_TYPE_BOOLEAN:
6804 case MONO_TYPE_CHAR:
6817 case MONO_TYPE_VALUETYPE:
6825 free_param_data (MonoMethodSignature *sig, void **params) {
6827 for (i = 0; i < sig->param_count; ++i) {
6828 if (!type_is_reference (sig->params [i]))
6829 g_free (params [i]);
6834 * Find the field index in the metadata FieldDef table.
6837 find_field_index (MonoClass *klass, MonoClassField *field) {
6840 for (i = 0; i < klass->field.count; ++i) {
6841 if (field == &klass->fields [i])
6842 return klass->field.first + 1 + i;
6848 * Find the property index in the metadata Property table.
6851 find_property_index (MonoClass *klass, MonoProperty *property) {
6854 for (i = 0; i < klass->property.count; ++i) {
6855 if (property == &klass->properties [i])
6856 return klass->property.first + 1 + i;
6862 * Find the event index in the metadata Event table.
6865 find_event_index (MonoClass *klass, MonoEvent *event) {
6868 for (i = 0; i < klass->event.count; ++i) {
6869 if (event == &klass->events [i])
6870 return klass->event.first + 1 + i;
6876 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6878 const char *p = (const char*)data;
6880 guint32 i, j, num_named;
6884 mono_class_init (method->klass);
6887 attr = mono_object_new (mono_domain_get (), method->klass);
6888 mono_runtime_invoke (method, attr, NULL, NULL);
6892 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6895 /*g_print ("got attr %s\n", method->klass->name);*/
6897 /* Allocate using alloca so it gets GC tracking */
6898 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6902 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6903 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6907 attr = mono_object_new (mono_domain_get (), method->klass);
6908 mono_runtime_invoke (method, attr, params, NULL);
6909 free_param_data (method->signature, params);
6910 num_named = read16 (named);
6912 for (j = 0; j < num_named; j++) {
6914 char *name, named_type, data_type;
6915 named_type = *named++;
6916 data_type = *named++; /* type of data */
6917 if (data_type == MONO_TYPE_SZARRAY)
6918 data_type = *named++;
6919 if (data_type == MONO_TYPE_ENUM) {
6922 type_len = mono_metadata_decode_blob_size (named, &named);
6923 type_name = g_malloc (type_len + 1);
6924 memcpy (type_name, named, type_len);
6925 type_name [type_len] = 0;
6927 /* FIXME: lookup the type and check type consistency */
6930 name_len = mono_metadata_decode_blob_size (named, &named);
6931 name = g_malloc (name_len + 1);
6932 memcpy (name, named, name_len);
6933 name [name_len] = 0;
6935 if (named_type == 0x53) {
6936 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6937 void *val = load_cattr_value (image, field->type, named, &named);
6938 mono_field_set_value (attr, field, val);
6939 if (!type_is_reference (field->type))
6941 } else if (named_type == 0x54) {
6944 MonoType *prop_type;
6946 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6947 /* can we have more that 1 arg in a custom attr named property? */
6948 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6949 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6950 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6951 mono_property_set_value (prop, attr, pparams, NULL);
6952 if (!type_is_reference (prop_type))
6953 g_free (pparams [0]);
6962 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6964 MonoArray *typedargs, *namedargs;
6965 MonoClass *attrklass;
6966 static MonoClass *klass;
6967 static MonoMethod *ctor;
6970 const char *p = (const char*)data;
6972 guint32 i, j, num_named;
6975 mono_class_init (method->klass);
6978 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6980 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6982 domain = mono_domain_get ();
6984 /* This is for Attributes with no parameters */
6985 attr = mono_object_new (domain, klass);
6986 params [0] = mono_method_get_object (domain, method, NULL);
6987 params [1] = params [2] = NULL;
6988 mono_runtime_invoke (method, attr, params, NULL);
6992 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6995 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6999 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7000 MonoObject *obj, *typedarg;
7003 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7004 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7005 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7006 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7007 mono_array_setref (typedargs, i, typedarg);
7009 if (!type_is_reference (mono_method_signature (method)->params [i]))
7014 num_named = read16 (named);
7015 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7017 attrklass = method->klass;
7018 for (j = 0; j < num_named; j++) {
7020 char *name, named_type, data_type;
7021 named_type = *named++;
7022 data_type = *named++; /* type of data */
7023 if (data_type == MONO_TYPE_SZARRAY)
7024 data_type = *named++;
7025 if (data_type == MONO_TYPE_ENUM) {
7028 type_len = mono_metadata_decode_blob_size (named, &named);
7029 type_name = g_malloc (type_len + 1);
7030 memcpy (type_name, named, type_len);
7031 type_name [type_len] = 0;
7033 /* FIXME: lookup the type and check type consistency */
7036 name_len = mono_metadata_decode_blob_size (named, &named);
7037 name = g_malloc (name_len + 1);
7038 memcpy (name, named, name_len);
7039 name [name_len] = 0;
7041 if (named_type == 0x53) {
7042 MonoObject *obj, *typedarg, *namedarg;
7043 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7044 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7046 minfo = mono_field_get_object (domain, NULL, field);
7047 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7048 typedarg = create_cattr_typed_arg (field->type, obj);
7049 namedarg = create_cattr_named_arg (minfo, typedarg);
7050 mono_array_setref (namedargs, j, namedarg);
7051 if (!type_is_reference (field->type))
7053 } else if (named_type == 0x54) {
7054 MonoObject *obj, *typedarg, *namedarg;
7055 MonoType *prop_type;
7057 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7059 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7060 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7061 minfo = mono_property_get_object (domain, NULL, prop);
7062 val = load_cattr_value (image, prop_type, named, &named);
7063 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7064 typedarg = create_cattr_typed_arg (prop_type, obj);
7065 namedarg = create_cattr_named_arg (minfo, typedarg);
7066 mono_array_setref (namedargs, j, namedarg);
7067 if (!type_is_reference (prop_type))
7072 attr = mono_object_new (domain, klass);
7073 params [0] = mono_method_get_object (domain, method, NULL);
7074 params [1] = typedargs;
7075 params [2] = namedargs;
7076 mono_runtime_invoke (ctor, attr, params, NULL);
7081 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7088 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7089 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7090 for (i = 0; i < cinfo->num_attrs; ++i) {
7091 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7092 mono_array_setref (result, i, attr);
7098 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7106 for (i = 0; i < cinfo->num_attrs; ++i) {
7107 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7111 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7112 result = mono_array_new (mono_domain_get (), klass, n);
7114 for (i = 0; i < cinfo->num_attrs; ++i) {
7115 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7116 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7117 mono_array_setref (result, n, attr);
7125 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7128 static MonoClass *klass;
7133 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7135 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7136 for (i = 0; i < cinfo->num_attrs; ++i) {
7137 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7138 mono_array_setref (result, i, attr);
7144 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7146 guint32 mtoken, i, len;
7147 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7149 MonoCustomAttrInfo *ainfo;
7150 GList *tmp, *list = NULL;
7153 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7155 i = mono_metadata_custom_attrs_from_index (image, idx);
7159 while (i < ca->rows) {
7160 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7162 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7165 len = g_list_length (list);
7168 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7169 ainfo->num_attrs = len;
7170 ainfo->image = image;
7171 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7172 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7173 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7174 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7175 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7176 mtoken |= MONO_TOKEN_METHOD_DEF;
7178 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7179 mtoken |= MONO_TOKEN_MEMBER_REF;
7182 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7185 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7186 if (!ainfo->attrs [i].ctor)
7187 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7188 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7189 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7190 ainfo->attrs [i].data = (guchar*)data;
7198 mono_custom_attrs_from_method (MonoMethod *method)
7200 MonoCustomAttrInfo *cinfo;
7203 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7205 idx = mono_method_get_index (method);
7206 idx <<= MONO_CUSTOM_ATTR_BITS;
7207 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7208 return mono_custom_attrs_from_index (method->klass->image, idx);
7212 mono_custom_attrs_from_class (MonoClass *klass)
7214 MonoCustomAttrInfo *cinfo;
7217 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7219 idx = mono_metadata_token_index (klass->type_token);
7220 idx <<= MONO_CUSTOM_ATTR_BITS;
7221 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7222 return mono_custom_attrs_from_index (klass->image, idx);
7226 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7228 MonoCustomAttrInfo *cinfo;
7231 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7233 idx = 1; /* there is only one assembly */
7234 idx <<= MONO_CUSTOM_ATTR_BITS;
7235 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7236 return mono_custom_attrs_from_index (assembly->image, idx);
7239 static MonoCustomAttrInfo*
7240 mono_custom_attrs_from_module (MonoImage *image)
7242 MonoCustomAttrInfo *cinfo;
7245 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7247 idx = 1; /* there is only one module */
7248 idx <<= MONO_CUSTOM_ATTR_BITS;
7249 idx |= MONO_CUSTOM_ATTR_MODULE;
7250 return mono_custom_attrs_from_index (image, idx);
7254 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7256 MonoCustomAttrInfo *cinfo;
7259 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7261 idx = find_property_index (klass, property);
7262 idx <<= MONO_CUSTOM_ATTR_BITS;
7263 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7264 return mono_custom_attrs_from_index (klass->image, idx);
7268 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7270 MonoCustomAttrInfo *cinfo;
7273 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7275 idx = find_event_index (klass, event);
7276 idx <<= MONO_CUSTOM_ATTR_BITS;
7277 idx |= MONO_CUSTOM_ATTR_EVENT;
7278 return mono_custom_attrs_from_index (klass->image, idx);
7282 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7284 MonoCustomAttrInfo *cinfo;
7287 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7289 idx = find_field_index (klass, field);
7290 idx <<= MONO_CUSTOM_ATTR_BITS;
7291 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7292 return mono_custom_attrs_from_index (klass->image, idx);
7296 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7299 guint32 i, idx, method_index;
7300 guint32 param_list, param_last, param_pos, found;
7302 MonoReflectionMethodAux *aux;
7304 if (method->klass->image->dynamic) {
7305 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7306 if (!aux || !aux->param_cattr)
7308 return aux->param_cattr [param];
7311 image = method->klass->image;
7312 method_index = mono_method_get_index (method);
7313 ca = &image->tables [MONO_TABLE_METHOD];
7315 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7316 if (method_index == ca->rows) {
7317 ca = &image->tables [MONO_TABLE_PARAM];
7318 param_last = ca->rows + 1;
7320 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7321 ca = &image->tables [MONO_TABLE_PARAM];
7324 for (i = param_list; i < param_last; ++i) {
7325 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7326 if (param_pos == param) {
7334 idx <<= MONO_CUSTOM_ATTR_BITS;
7335 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7336 return mono_custom_attrs_from_index (image, idx);
7340 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7344 for (i = 0; i < ainfo->num_attrs; ++i) {
7345 klass = ainfo->attrs [i].ctor->klass;
7346 if (mono_class_has_parent (klass, attr_klass))
7353 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7360 for (i = 0; i < ainfo->num_attrs; ++i) {
7361 klass = ainfo->attrs [i].ctor->klass;
7362 if (mono_class_has_parent (klass, attr_klass)) {
7367 if (attr_index == -1)
7370 attrs = mono_custom_attrs_construct (ainfo);
7372 return mono_array_get (attrs, MonoObject*, attr_index);
7378 * mono_reflection_get_custom_attrs_info:
7379 * @obj: a reflection object handle
7381 * Return the custom attribute info for attributes defined for the
7382 * reflection handle @obj. The objects.
7385 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7388 MonoCustomAttrInfo *cinfo = NULL;
7390 klass = obj->vtable->klass;
7391 if (klass == mono_defaults.monotype_class) {
7392 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7393 klass = mono_class_from_mono_type (rtype->type);
7394 cinfo = mono_custom_attrs_from_class (klass);
7395 } else if (strcmp ("Assembly", klass->name) == 0) {
7396 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7397 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7398 } else if (strcmp ("Module", klass->name) == 0) {
7399 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7400 cinfo = mono_custom_attrs_from_module (module->image);
7401 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7402 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7403 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7404 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7405 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7406 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7407 } else if (strcmp ("MonoField", klass->name) == 0) {
7408 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7409 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7410 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7411 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7412 cinfo = mono_custom_attrs_from_method (rmethod->method);
7413 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7414 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7415 cinfo = mono_custom_attrs_from_method (method);
7416 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7417 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7418 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7419 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7420 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7421 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7422 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7423 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7424 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7425 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7426 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7427 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7428 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7429 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7430 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7431 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7432 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7433 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7434 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7435 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7436 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7437 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7438 } else { /* handle other types here... */
7439 g_error ("get custom attrs not yet supported for %s", klass->name);
7446 * mono_reflection_get_custom_attrs_by_type:
7447 * @obj: a reflection object handle
7449 * Return an array with all the custom attributes defined of the
7450 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7451 * of that type are returned. The objects are fully build.
7454 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7457 MonoCustomAttrInfo *cinfo;
7459 cinfo = mono_reflection_get_custom_attrs_info (obj);
7462 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7464 result = mono_custom_attrs_construct (cinfo);
7466 mono_custom_attrs_free (cinfo);
7469 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7470 result = mono_array_new (mono_domain_get (), klass, 0);
7477 * mono_reflection_get_custom_attrs:
7478 * @obj: a reflection object handle
7480 * Return an array with all the custom attributes defined of the
7481 * reflection handle @obj. The objects are fully build.
7484 mono_reflection_get_custom_attrs (MonoObject *obj)
7486 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7490 * mono_reflection_get_custom_attrs_data:
7491 * @obj: a reflection obj handle
7493 * Returns an array of System.Reflection.CustomAttributeData,
7494 * which include information about attributes reflected on
7495 * types loaded using the Reflection Only methods
7498 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7501 MonoCustomAttrInfo *cinfo;
7503 cinfo = mono_reflection_get_custom_attrs_info (obj);
7505 result = mono_custom_attrs_data_construct (cinfo);
7507 mono_custom_attrs_free (cinfo);
7510 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7511 result = mono_array_new (mono_domain_get (), klass, 0);
7517 static MonoReflectionType*
7518 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7520 MonoMethod *method_get_underlying_system_type;
7522 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7523 mono_class_get_method_from_name (mono_object_class (t),
7524 "get_UnderlyingSystemType",
7526 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7530 mono_reflection_type_get_handle (MonoReflectionType* t)
7535 t = mono_reflection_type_get_underlying_system_type (t);
7543 * LOCKING: Assumes the loader lock is held.
7545 static MonoMethodSignature*
7546 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7547 MonoMethodSignature *sig;
7550 count = parameters? mono_array_length (parameters): 0;
7552 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7553 sig->param_count = count;
7554 sig->sentinelpos = -1; /* FIXME */
7555 for (i = 0; i < count; ++i) {
7556 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7557 sig->params [i] = mono_reflection_type_get_handle (pt);
7563 * LOCKING: Assumes the loader lock is held.
7565 static MonoMethodSignature*
7566 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7567 MonoMethodSignature *sig;
7569 sig = parameters_to_signature (mp, ctor->parameters);
7570 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7571 sig->ret = &mono_defaults.void_class->byval_arg;
7576 * LOCKING: Assumes the loader lock is held.
7578 static MonoMethodSignature*
7579 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7580 MonoMethodSignature *sig;
7582 sig = parameters_to_signature (mp, method->parameters);
7583 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7584 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7585 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7589 static MonoMethodSignature*
7590 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7591 MonoMethodSignature *sig;
7593 sig = parameters_to_signature (NULL, method->parameters);
7594 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7595 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7596 sig->generic_param_count = 0;
7601 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7603 MonoClass *klass = mono_object_class (prop);
7604 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7605 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7606 *name = mono_string_to_utf8 (pb->name);
7607 *type = pb->type->type;
7609 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7610 *name = g_strdup (p->property->name);
7611 if (p->property->get)
7612 *type = mono_method_signature (p->property->get)->ret;
7614 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7619 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7621 MonoClass *klass = mono_object_class (field);
7622 if (strcmp (klass->name, "FieldBuilder") == 0) {
7623 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7624 *name = mono_string_to_utf8 (fb->name);
7625 *type = fb->type->type;
7627 MonoReflectionField *f = (MonoReflectionField *)field;
7628 *name = g_strdup (f->field->name);
7629 *type = f->field->type;
7634 * Encode a value in a custom attribute stream of bytes.
7635 * The value to encode is either supplied as an object in argument val
7636 * (valuetypes are boxed), or as a pointer to the data in the
7638 * @type represents the type of the value
7639 * @buffer is the start of the buffer
7640 * @p the current position in the buffer
7641 * @buflen contains the size of the buffer and is used to return the new buffer size
7642 * if this needs to be realloced.
7643 * @retbuffer and @retp return the start and the position of the buffer
7646 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7648 MonoTypeEnum simple_type;
7650 if ((p-buffer) + 10 >= *buflen) {
7653 newbuf = g_realloc (buffer, *buflen);
7654 p = newbuf + (p-buffer);
7658 argval = ((char*)arg + sizeof (MonoObject));
7659 simple_type = type->type;
7661 switch (simple_type) {
7662 case MONO_TYPE_BOOLEAN:
7667 case MONO_TYPE_CHAR:
7670 swap_with_size (p, argval, 2, 1);
7676 swap_with_size (p, argval, 4, 1);
7682 swap_with_size (p, argval, 8, 1);
7685 case MONO_TYPE_VALUETYPE:
7686 if (type->data.klass->enumtype) {
7687 simple_type = type->data.klass->enum_basetype->type;
7690 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7693 case MONO_TYPE_STRING: {
7700 str = mono_string_to_utf8 ((MonoString*)arg);
7701 slen = strlen (str);
7702 if ((p-buffer) + 10 + slen >= *buflen) {
7706 newbuf = g_realloc (buffer, *buflen);
7707 p = newbuf + (p-buffer);
7710 mono_metadata_encode_value (slen, p, &p);
7711 memcpy (p, str, slen);
7716 case MONO_TYPE_CLASS: {
7724 k = mono_object_class (arg);
7725 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7726 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7727 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7730 if (rt && (rtc = mono_object_class (rt)) &&
7731 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7732 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7733 arg = (MonoObject *) rt;
7736 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7739 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7740 slen = strlen (str);
7741 if ((p-buffer) + 10 + slen >= *buflen) {
7745 newbuf = g_realloc (buffer, *buflen);
7746 p = newbuf + (p-buffer);
7749 mono_metadata_encode_value (slen, p, &p);
7750 memcpy (p, str, slen);
7755 case MONO_TYPE_SZARRAY: {
7757 MonoClass *eclass, *arg_eclass;
7760 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7763 len = mono_array_length ((MonoArray*)arg);
7765 *p++ = (len >> 8) & 0xff;
7766 *p++ = (len >> 16) & 0xff;
7767 *p++ = (len >> 24) & 0xff;
7769 *retbuffer = buffer;
7770 eclass = type->data.klass;
7771 arg_eclass = mono_object_class (arg)->element_class;
7774 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7775 eclass = mono_defaults.object_class;
7777 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7778 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7779 int elsize = mono_class_array_element_size (arg_eclass);
7780 for (i = 0; i < len; ++i) {
7781 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7784 } else if (eclass->valuetype && arg_eclass->valuetype) {
7785 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7786 int elsize = mono_class_array_element_size (eclass);
7787 for (i = 0; i < len; ++i) {
7788 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7792 for (i = 0; i < len; ++i) {
7793 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7798 case MONO_TYPE_OBJECT: {
7804 * The parameter type is 'object' but the type of the actual
7805 * argument is not. So we have to add type information to the blob
7806 * too. This is completely undocumented in the spec.
7810 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7815 klass = mono_object_class (arg);
7817 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7820 } else if (klass->enumtype) {
7822 } else if (klass == mono_defaults.string_class) {
7823 simple_type = MONO_TYPE_STRING;
7826 } else if (klass->rank == 1) {
7828 *p++ = klass->element_class->byval_arg.type;
7829 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7831 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7832 *p++ = simple_type = klass->byval_arg.type;
7835 g_error ("unhandled type in custom attr");
7837 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7838 slen = strlen (str);
7839 if ((p-buffer) + 10 + slen >= *buflen) {
7843 newbuf = g_realloc (buffer, *buflen);
7844 p = newbuf + (p-buffer);
7847 mono_metadata_encode_value (slen, p, &p);
7848 memcpy (p, str, slen);
7851 simple_type = klass->enum_basetype->type;
7855 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7858 *retbuffer = buffer;
7862 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7864 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7865 char *str = type_get_qualified_name (type, NULL);
7866 int slen = strlen (str);
7870 * This seems to be optional...
7873 mono_metadata_encode_value (slen, p, &p);
7874 memcpy (p, str, slen);
7877 } else if (type->type == MONO_TYPE_OBJECT) {
7879 } else if (type->type == MONO_TYPE_CLASS) {
7880 /* it should be a type: encode_cattr_value () has the check */
7883 mono_metadata_encode_value (type->type, p, &p);
7884 if (type->type == MONO_TYPE_SZARRAY)
7885 /* See the examples in Partition VI, Annex B */
7886 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7893 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7896 /* Preallocate a large enough buffer */
7897 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7898 char *str = type_get_qualified_name (type, NULL);
7901 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7902 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7908 len += strlen (name);
7910 if ((p-buffer) + 20 + len >= *buflen) {
7914 newbuf = g_realloc (buffer, *buflen);
7915 p = newbuf + (p-buffer);
7919 encode_field_or_prop_type (type, p, &p);
7921 len = strlen (name);
7922 mono_metadata_encode_value (len, p, &p);
7923 memcpy (p, name, len);
7925 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7927 *retbuffer = buffer;
7931 * mono_reflection_get_custom_attrs_blob:
7932 * @ctor: custom attribute constructor
7933 * @ctorArgs: arguments o the constructor
7939 * Creates the blob of data that needs to be saved in the metadata and that represents
7940 * the custom attributed described by @ctor, @ctorArgs etc.
7941 * Returns: a Byte array representing the blob of data.
7944 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7947 MonoMethodSignature *sig;
7952 MONO_ARCH_SAVE_REGS;
7954 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7955 /* sig is freed later so allocate it in the heap */
7956 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
7958 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7961 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7963 p = buffer = g_malloc (buflen);
7964 /* write the prolog */
7967 for (i = 0; i < sig->param_count; ++i) {
7968 arg = mono_array_get (ctorArgs, MonoObject*, i);
7969 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7973 i += mono_array_length (properties);
7975 i += mono_array_length (fields);
7977 *p++ = (i >> 8) & 0xff;
7980 for (i = 0; i < mono_array_length (properties); ++i) {
7984 prop = mono_array_get (properties, gpointer, i);
7985 get_prop_name_and_type (prop, &pname, &ptype);
7986 *p++ = 0x54; /* PROPERTY signature */
7987 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7994 for (i = 0; i < mono_array_length (fields); ++i) {
7998 field = mono_array_get (fields, gpointer, i);
7999 get_field_name_and_type (field, &fname, &ftype);
8000 *p++ = 0x53; /* FIELD signature */
8001 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8006 g_assert (p - buffer <= buflen);
8007 buflen = p - buffer;
8008 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8009 p = mono_array_addr (result, char, 0);
8010 memcpy (p, buffer, buflen);
8012 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8018 static void* reflection_info_desc = NULL;
8019 #define MOVING_GC_REGISTER(addr) do { \
8020 if (!reflection_info_desc) { \
8022 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8024 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8027 #define MOVING_GC_REGISTER(addr)
8031 * mono_reflection_setup_internal_class:
8032 * @tb: a TypeBuilder object
8034 * Creates a MonoClass that represents the TypeBuilder.
8035 * This is a trick that lets us simplify a lot of reflection code
8036 * (and will allow us to support Build and Run assemblies easier).
8039 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8041 MonoClass *klass, *parent;
8043 MONO_ARCH_SAVE_REGS;
8045 mono_loader_lock ();
8048 /* check so we can compile corlib correctly */
8049 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8050 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8051 parent = tb->parent->type->data.klass;
8053 parent = my_mono_class_from_mono_type (tb->parent->type);
8059 /* the type has already being created: it means we just have to change the parent */
8060 if (tb->type.type) {
8061 klass = mono_class_from_mono_type (tb->type.type);
8062 klass->parent = NULL;
8063 /* fool mono_class_setup_parent */
8064 klass->supertypes = NULL;
8065 mono_class_setup_parent (klass, parent);
8066 mono_class_setup_mono_type (klass);
8067 mono_loader_unlock ();
8071 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8073 klass->image = &tb->module->dynamic_image->image;
8075 klass->inited = 1; /* we lie to the runtime */
8076 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8077 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8078 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8079 klass->flags = tb->attrs;
8081 klass->element_class = klass;
8083 MOVING_GC_REGISTER (&klass->reflection_info);
8084 klass->reflection_info = tb;
8086 /* Put into cache so mono_class_get () will find it */
8087 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8089 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8090 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8092 if (parent != NULL) {
8093 mono_class_setup_parent (klass, parent);
8094 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8095 const char *old_n = klass->name;
8096 /* trick to get relative numbering right when compiling corlib */
8097 klass->name = "BuildingObject";
8098 mono_class_setup_parent (klass, mono_defaults.object_class);
8099 klass->name = old_n;
8102 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8103 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8104 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8105 klass->instance_size = sizeof (MonoObject);
8106 klass->size_inited = 1;
8107 mono_class_setup_vtable_general (klass, NULL, 0);
8110 mono_class_setup_mono_type (klass);
8112 mono_class_setup_supertypes (klass);
8115 * FIXME: handle interfaces.
8118 tb->type.type = &klass->byval_arg;
8120 if (tb->nesting_type) {
8121 g_assert (tb->nesting_type->type);
8122 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8125 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8127 mono_loader_unlock ();
8131 * mono_reflection_setup_generic_class:
8132 * @tb: a TypeBuilder object
8134 * Setup the generic class before adding the first generic parameter.
8137 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8141 MONO_ARCH_SAVE_REGS;
8143 klass = my_mono_class_from_mono_type (tb->type.type);
8144 if (tb->generic_container)
8147 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8148 tb->generic_container->owner.klass = klass;
8152 * mono_reflection_create_generic_class:
8153 * @tb: a TypeBuilder object
8155 * Creates the generic class after all generic parameters have been added.
8158 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8163 MONO_ARCH_SAVE_REGS;
8165 klass = my_mono_class_from_mono_type (tb->type.type);
8167 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8169 if (klass->generic_container || (count == 0))
8172 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8174 klass->generic_container = tb->generic_container;
8176 klass->generic_container->type_argc = count;
8177 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8179 for (i = 0; i < count; i++) {
8180 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8181 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8182 g_assert (klass->generic_container->type_params [i].owner);
8185 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8189 * mono_reflection_create_internal_class:
8190 * @tb: a TypeBuilder object
8192 * Actually create the MonoClass that is associated with the TypeBuilder.
8195 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8199 MONO_ARCH_SAVE_REGS;
8201 klass = my_mono_class_from_mono_type (tb->type.type);
8203 mono_loader_lock ();
8204 if (klass->enumtype && klass->enum_basetype == NULL) {
8205 MonoReflectionFieldBuilder *fb;
8208 g_assert (tb->fields != NULL);
8209 g_assert (mono_array_length (tb->fields) >= 1);
8211 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8213 klass->enum_basetype = fb->type->type;
8214 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8215 if (!klass->element_class)
8216 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8219 * get the element_class from the current corlib.
8221 ec = default_class_from_mono_type (klass->enum_basetype);
8222 klass->instance_size = ec->instance_size;
8223 klass->size_inited = 1;
8225 * this is almost safe to do with enums and it's needed to be able
8226 * to create objects of the enum type (for use in SetConstant).
8228 /* FIXME: Does this mean enums can't have method overrides ? */
8229 mono_class_setup_vtable_general (klass, NULL, 0);
8231 mono_loader_unlock ();
8234 static MonoMarshalSpec*
8235 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8236 MonoReflectionMarshal *minfo)
8238 MonoMarshalSpec *res;
8240 res = g_new0 (MonoMarshalSpec, 1);
8241 res->native = minfo->type;
8243 switch (minfo->type) {
8244 case MONO_NATIVE_LPARRAY:
8245 res->data.array_data.elem_type = minfo->eltype;
8246 if (minfo->has_size) {
8247 res->data.array_data.param_num = minfo->param_num;
8248 res->data.array_data.num_elem = minfo->count;
8249 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8252 res->data.array_data.param_num = -1;
8253 res->data.array_data.num_elem = -1;
8254 res->data.array_data.elem_mult = -1;
8258 case MONO_NATIVE_BYVALTSTR:
8259 case MONO_NATIVE_BYVALARRAY:
8260 res->data.array_data.num_elem = minfo->count;
8263 case MONO_NATIVE_CUSTOM:
8264 if (minfo->marshaltyperef)
8265 res->data.custom_data.custom_name =
8266 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8268 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8278 MonoReflectionMarshal*
8279 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8280 MonoMarshalSpec *spec)
8282 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8283 MonoReflectionMarshal *minfo;
8286 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8287 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8288 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8289 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8292 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8293 minfo->type = spec->native;
8295 switch (minfo->type) {
8296 case MONO_NATIVE_LPARRAY:
8297 minfo->eltype = spec->data.array_data.elem_type;
8298 minfo->count = spec->data.array_data.num_elem;
8299 minfo->param_num = spec->data.array_data.param_num;
8302 case MONO_NATIVE_BYVALTSTR:
8303 case MONO_NATIVE_BYVALARRAY:
8304 minfo->count = spec->data.array_data.num_elem;
8307 case MONO_NATIVE_CUSTOM:
8308 if (spec->data.custom_data.custom_name) {
8309 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8311 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8313 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8315 if (spec->data.custom_data.cookie)
8316 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8327 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8328 ReflectionMethodBuilder *rmb,
8329 MonoMethodSignature *sig)
8332 MonoMethodNormal *pm;
8333 MonoMarshalSpec **specs;
8334 MonoReflectionMethodAux *method_aux;
8339 g_assert (!klass->generic_class);
8342 * Methods created using a MethodBuilder should have their memory allocated
8343 * inside the image mempool, while dynamic methods should have their memory
8346 dynamic = rmb->refs != NULL;
8347 mp = dynamic ? NULL : klass->image->mempool;
8349 mono_loader_lock ();
8351 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8352 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8353 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8355 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8357 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8359 pm = (MonoMethodNormal*)m;
8362 m->flags = rmb->attrs;
8363 m->iflags = rmb->iattrs;
8364 m->name = dynamic ? mono_string_to_utf8 (rmb->name) : mono_string_to_utf8_mp (mp, rmb->name);
8367 m->skip_visibility = rmb->skip_visibility;
8369 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8371 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8372 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8375 m->signature->pinvoke = 1;
8376 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8377 m->signature->pinvoke = 1;
8379 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8381 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8382 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8384 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8386 if (klass->image->dynamic)
8387 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8389 mono_loader_unlock ();
8392 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8393 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8394 MonoMethodHeader *header;
8396 gint32 max_stack, i;
8397 gint32 num_locals = 0;
8398 gint32 num_clauses = 0;
8402 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8403 code_size = rmb->ilgen->code_len;
8404 max_stack = rmb->ilgen->max_stack;
8405 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8406 if (rmb->ilgen->ex_handlers)
8407 num_clauses = method_count_clauses (rmb->ilgen);
8410 code = mono_array_addr (rmb->code, guint8, 0);
8411 code_size = mono_array_length (rmb->code);
8412 /* we probably need to run a verifier on the code... */
8422 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8423 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8424 header->code_size = code_size;
8425 header->code = mp_g_malloc (mp, code_size);
8426 memcpy ((char*)header->code, code, code_size);
8427 header->max_stack = max_stack;
8428 header->init_locals = rmb->init_locals;
8429 header->num_locals = num_locals;
8431 for (i = 0; i < num_locals; ++i) {
8432 MonoReflectionLocalBuilder *lb =
8433 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8435 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8436 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8439 header->num_clauses = num_clauses;
8441 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8442 rmb->ilgen, num_clauses);
8445 pm->header = header;
8448 if (rmb->generic_params) {
8449 int count = mono_array_length (rmb->generic_params);
8450 MonoGenericContainer *container;
8452 m->generic_container = container = rmb->generic_container;
8453 container->type_argc = count;
8454 container->type_params = g_new0 (MonoGenericParam, count);
8455 container->owner.method = m;
8457 for (i = 0; i < count; i++) {
8458 MonoReflectionGenericParam *gp =
8459 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8461 container->type_params [i] = *gp->type.type->data.generic_param;
8464 if (klass->generic_container) {
8465 container->parent = klass->generic_container;
8466 container->context.class_inst = klass->generic_container->context.class_inst;
8468 container->context.gmethod = mono_get_shared_generic_method (container);
8472 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8476 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8478 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8479 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8480 for (i = 0; i < rmb->nrefs; ++i)
8481 data [i + 1] = rmb->refs [i];
8486 /* Parameter info */
8489 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8490 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8491 for (i = 0; i <= m->signature->param_count; ++i) {
8492 MonoReflectionParamBuilder *pb;
8493 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8494 if ((i > 0) && (pb->attrs)) {
8495 /* Make a copy since it might point to a shared type structure */
8496 /* FIXME: Alloc this from a mempool */
8497 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8498 m->signature->params [i - 1]->attrs = pb->attrs;
8501 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8502 MonoDynamicImage *assembly;
8503 guint32 idx, def_type, len;
8507 if (!method_aux->param_defaults) {
8508 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8509 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8511 assembly = (MonoDynamicImage*)klass->image;
8512 idx = encode_constant (assembly, pb->def_value, &def_type);
8513 /* Copy the data from the blob since it might get realloc-ed */
8514 p = assembly->blob.data + idx;
8515 len = mono_metadata_decode_blob_size (p, &p2);
8517 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8518 method_aux->param_default_types [i] = def_type;
8519 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8523 method_aux->param_names [i] = dynamic ? mono_string_to_utf8 (pb->name) : mono_string_to_utf8_mp (mp, pb->name);
8525 if (!method_aux->param_cattr)
8526 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8527 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8533 /* Parameter marshalling */
8536 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8537 MonoReflectionParamBuilder *pb;
8538 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8539 if (pb->marshal_info) {
8541 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8542 specs [pb->position] =
8543 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8547 if (specs != NULL) {
8549 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8550 method_aux->param_marshall = specs;
8553 if (klass->image->dynamic && method_aux)
8554 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8556 mono_loader_unlock ();
8562 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8564 ReflectionMethodBuilder rmb;
8565 MonoMethodSignature *sig;
8567 mono_loader_lock ();
8568 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8569 mono_loader_unlock ();
8571 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8573 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8574 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8576 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8577 /* ilgen is no longer needed */
8585 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8587 ReflectionMethodBuilder rmb;
8588 MonoMethodSignature *sig;
8590 mono_loader_lock ();
8591 sig = method_builder_to_signature (klass->image->mempool, mb);
8592 mono_loader_unlock ();
8594 reflection_methodbuilder_from_method_builder (&rmb, mb);
8596 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8597 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8599 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8600 /* ilgen is no longer needed */
8606 static MonoClassField*
8607 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8609 MonoClassField *field;
8613 field = g_new0 (MonoClassField, 1);
8615 field->name = mono_string_to_utf8 (fb->name);
8617 /* FIXME: handle type modifiers */
8618 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8619 field->type->attrs = fb->attrs;
8621 field->type = fb->type->type;
8623 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8624 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8625 if (fb->offset != -1)
8626 field->offset = fb->offset;
8627 field->parent = klass;
8628 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8630 if (fb->def_value) {
8631 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8632 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8633 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8634 /* Copy the data from the blob since it might get realloc-ed */
8635 p = assembly->blob.data + idx;
8636 len = mono_metadata_decode_blob_size (p, &p2);
8638 field->data = g_malloc (len);
8639 memcpy ((gpointer)field->data, p, len);
8646 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8649 MonoReflectionTypeBuilder *tb = NULL;
8650 MonoGenericClass *gclass, *cached;
8651 gboolean is_dynamic = FALSE;
8656 mono_loader_lock ();
8658 domain = mono_object_domain (type);
8660 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8661 tb = (MonoReflectionTypeBuilder *) type;
8664 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8665 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8666 MonoReflectionType *rgt = rgi->generic_type;
8668 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8669 tb = (MonoReflectionTypeBuilder *) rgt;
8674 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8675 if (tb && tb->generic_container)
8676 mono_reflection_create_generic_class (tb);
8678 klass = mono_class_from_mono_type (type->type);
8679 if (!klass->generic_container) {
8680 mono_loader_unlock ();
8684 if (klass->wastypebuilder) {
8685 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8691 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
8692 gclass = &dgclass->generic_class;
8693 gclass->is_dynamic = TRUE;
8695 gclass = g_new0 (MonoGenericClass, 1);
8698 gclass->inst = g_new0 (MonoGenericInst, 1);
8700 gclass->inst->type_argc = type_argc;
8701 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8702 gclass->inst->is_reference = 1;
8704 for (i = 0; i < gclass->inst->type_argc; ++i) {
8705 MonoType *t = dup_type (types [i]);
8707 if (!gclass->inst->is_open)
8708 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8709 if (gclass->inst->is_reference)
8710 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8711 gclass->inst->type_argv [i] = t;
8714 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8716 gclass->container_class = klass;
8718 geninst = g_new0 (MonoType, 1);
8719 geninst->type = MONO_TYPE_GENERICINST;
8721 cached = mono_metadata_lookup_generic_class (gclass);
8724 mono_loader_unlock ();
8725 geninst->data.generic_class = cached;
8729 geninst->data.generic_class = gclass;
8731 mono_loader_unlock ();
8737 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8740 MonoGenericClass *gclass, *cached;
8744 klass = mono_class_from_mono_type (type);
8745 if (!klass->generic_container && !klass->generic_class &&
8746 !(klass->nested_in && klass->nested_in->generic_container))
8749 mono_loader_lock ();
8751 gclass = g_new0 (MonoGenericClass, 1);
8753 gclass->inst = g_new0 (MonoGenericInst, 1);
8754 gclass->inst->type_argc = type_argc;
8755 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8756 gclass->inst->is_reference = 1;
8758 for (i = 0; i < gclass->inst->type_argc; ++i) {
8759 MonoType *t = dup_type (types [i]);
8761 if (!gclass->inst->is_open)
8762 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8763 if (gclass->inst->is_reference)
8764 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8766 gclass->inst->type_argv [i] = t;
8769 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8771 gclass->container_class = klass;
8773 if (klass->generic_class) {
8774 MonoGenericClass *kgclass = klass->generic_class;
8775 MonoGenericClass *ogclass = gclass;
8777 gclass = g_new0 (MonoGenericClass, 1);
8779 gclass->inst = g_new0 (MonoGenericInst, 1);
8780 gclass->inst->type_argc = kgclass->inst->type_argc;
8781 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8782 gclass->inst->is_reference = 1;
8784 for (i = 0; i < gclass->inst->type_argc; i++) {
8785 MonoType *t = kgclass->inst->type_argv [i];
8787 t = mono_class_inflate_generic_type (t, mono_generic_class_get_context (ogclass));
8789 if (!gclass->inst->is_open)
8790 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8791 if (gclass->inst->is_reference)
8792 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8794 gclass->inst->type_argv [i] = t;
8797 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8799 gclass->container_class = kgclass->container_class;
8802 geninst = g_new0 (MonoType, 1);
8803 geninst->type = MONO_TYPE_GENERICINST;
8805 cached = mono_metadata_lookup_generic_class (gclass);
8808 mono_loader_unlock ();
8809 geninst->data.generic_class = cached;
8813 geninst->data.generic_class = gclass;
8815 mono_loader_unlock ();
8820 static inline MonoType*
8821 dup_type (const MonoType *original)
8823 MonoType *r = g_new0 (MonoType, 1);
8825 r->attrs = original->attrs;
8826 r->byref = original->byref;
8827 if (original->type == MONO_TYPE_PTR)
8828 r->data.type = dup_type (original->data.type);
8829 else if (original->type == MONO_TYPE_ARRAY)
8830 r->data.array = mono_dup_array_type (original->data.array);
8831 else if (original->type == MONO_TYPE_FNPTR)
8832 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8833 mono_stats.generics_metadata_size += sizeof (MonoType);
8837 MonoReflectionMethod*
8838 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8840 MonoMethod *method, *inflated;
8841 MonoReflectionMethodBuilder *mb = NULL;
8842 MonoGenericContainer *container;
8843 MonoGenericMethod *gmethod;
8844 MonoGenericContext *context;
8845 MonoGenericInst *ginst;
8848 MONO_ARCH_SAVE_REGS;
8849 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8850 MonoReflectionTypeBuilder *tb;
8853 mb = (MonoReflectionMethodBuilder *) rmethod;
8854 tb = (MonoReflectionTypeBuilder *) mb->type;
8855 klass = mono_class_from_mono_type (tb->type.type);
8857 method = methodbuilder_to_mono_method (klass, mb);
8859 method = rmethod->method;
8862 method = mono_get_inflated_method (method);
8864 count = mono_method_signature (method)->generic_param_count;
8865 if (count != mono_array_length (types))
8868 container = method->generic_container;
8869 g_assert (container);
8871 if (!container->method_hash)
8872 container->method_hash = g_hash_table_new (
8873 (GHashFunc) mono_metadata_generic_method_hash,
8874 (GCompareFunc) mono_metadata_generic_method_equal);
8876 ginst = g_new0 (MonoGenericInst,1 );
8877 ginst->type_argc = count;
8878 ginst->type_argv = g_new0 (MonoType *, count);
8879 ginst->is_reference = 1;
8880 for (i = 0; i < count; i++) {
8881 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8882 ginst->type_argv [i] = dup_type (garg->type);
8884 if (!ginst->is_open)
8885 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8886 if (ginst->is_reference)
8887 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8889 ginst = mono_metadata_lookup_generic_inst (ginst);
8891 gmethod = g_new0 (MonoGenericMethod, 1);
8892 if (method->klass->generic_class)
8893 gmethod->class_inst = method->klass->generic_class->inst;
8894 gmethod->container = container;
8895 gmethod->inst = ginst;
8897 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8901 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8904 MOVING_GC_REGISTER (&gmethod->reflection_info);
8905 gmethod->reflection_info = rmethod;
8907 context = g_new0 (MonoGenericContext, 1);
8908 context->class_inst = gmethod->class_inst;
8909 context->gmethod = gmethod;
8911 if (method->is_inflated)
8912 method = ((MonoMethodInflated *) method)->declaring;
8914 inflated = mono_class_inflate_generic_method (method, context);
8915 g_hash_table_insert (container->method_hash, gmethod, inflated);
8917 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8921 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8923 MonoGenericMethod *gmethod = NULL;
8924 MonoGenericContext *context;
8927 klass = mono_class_from_mono_type (type->type.type);
8928 g_assert (klass->generic_class);
8929 context = mono_class_get_context (klass);
8931 if (method->generic_container) {
8932 g_assert (method->klass == klass->generic_class->container_class);
8934 gmethod = g_new0 (MonoGenericMethod, 1);
8935 gmethod->class_inst = klass->generic_class->inst;
8936 gmethod->container = method->generic_container;
8937 MOVING_GC_REGISTER (&gmethod->reflection_info);
8938 gmethod->reflection_info = obj;
8939 gmethod->inst = method->generic_container->context.gmethod->inst;
8941 context = g_new0 (MonoGenericContext, 1);
8942 context->class_inst = klass->generic_class->inst;
8943 context->gmethod = gmethod;
8946 return mono_class_inflate_generic_method_full (method, klass, context);
8950 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8955 gklass = mono_class_from_mono_type (type->generic_type->type);
8957 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8958 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8959 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8960 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8961 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8962 method = ((MonoReflectionMethod *) obj)->method;
8964 method = NULL; /* prevent compiler warning */
8965 g_assert_not_reached ();
8968 return inflate_mono_method (type, method, obj);
8972 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8973 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8976 MonoGenericClass *gclass;
8977 MonoDynamicGenericClass *dgclass;
8978 MonoClass *klass, *gklass;
8981 MONO_ARCH_SAVE_REGS;
8983 klass = mono_class_from_mono_type (type->type.type);
8984 gclass = type->type.type->data.generic_class;
8986 g_assert (gclass->is_dynamic);
8987 dgclass = (MonoDynamicGenericClass *) gclass;
8989 if (dgclass->initialized)
8992 gklass = gclass->container_class;
8993 mono_class_init (gklass);
8995 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8996 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8997 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8998 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8999 dgclass->count_events = events ? mono_array_length (events) : 0;
9001 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9002 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9003 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9004 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9005 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9007 for (i = 0; i < dgclass->count_methods; i++) {
9008 MonoObject *obj = mono_array_get (methods, gpointer, i);
9010 dgclass->methods [i] = inflate_method (type, obj);
9013 for (i = 0; i < dgclass->count_ctors; i++) {
9014 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9016 dgclass->ctors [i] = inflate_method (type, obj);
9019 for (i = 0; i < dgclass->count_fields; i++) {
9020 MonoObject *obj = mono_array_get (fields, gpointer, i);
9021 MonoClassField *field;
9022 MonoInflatedField *ifield;
9024 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9025 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9026 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9027 field = ((MonoReflectionField *) obj)->field;
9029 field = NULL; /* prevent compiler warning */
9030 g_assert_not_reached ();
9033 ifield = g_new0 (MonoInflatedField, 1);
9034 ifield->generic_type = field->type;
9035 MOVING_GC_REGISTER (&ifield->reflection_info);
9036 ifield->reflection_info = obj;
9038 dgclass->fields [i] = *field;
9039 dgclass->fields [i].parent = klass;
9040 dgclass->fields [i].generic_info = ifield;
9041 dgclass->fields [i].type = mono_class_inflate_generic_type (
9042 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9045 for (i = 0; i < dgclass->count_properties; i++) {
9046 MonoObject *obj = mono_array_get (properties, gpointer, i);
9047 MonoProperty *property = &dgclass->properties [i];
9049 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9050 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9052 property->parent = klass;
9053 property->attrs = pb->attrs;
9054 property->name = mono_string_to_utf8 (pb->name);
9056 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9058 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9059 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9060 *property = *((MonoReflectionProperty *) obj)->property;
9063 property->get = inflate_mono_method (type, property->get, NULL);
9065 property->set = inflate_mono_method (type, property->set, NULL);
9067 g_assert_not_reached ();
9070 for (i = 0; i < dgclass->count_events; i++) {
9071 MonoObject *obj = mono_array_get (events, gpointer, i);
9072 MonoEvent *event = &dgclass->events [i];
9074 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9075 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9077 event->parent = klass;
9078 event->attrs = eb->attrs;
9079 event->name = mono_string_to_utf8 (eb->name);
9081 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9082 if (eb->remove_method)
9083 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9084 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9085 *event = *((MonoReflectionEvent *) obj)->event;
9088 event->add = inflate_mono_method (type, event->add, NULL);
9090 event->remove = inflate_mono_method (type, event->remove, NULL);
9092 g_assert_not_reached ();
9095 dgclass->initialized = TRUE;
9099 ensure_runtime_vtable (MonoClass *klass)
9101 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9104 if (!tb || klass->wastypebuilder)
9107 ensure_runtime_vtable (klass->parent);
9109 num = tb->ctors? mono_array_length (tb->ctors): 0;
9110 num += tb->num_methods;
9111 klass->method.count = num;
9112 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9113 num = tb->ctors? mono_array_length (tb->ctors): 0;
9114 for (i = 0; i < num; ++i)
9115 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9116 num = tb->num_methods;
9118 for (i = 0; i < num; ++i)
9119 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9121 if (tb->interfaces) {
9122 klass->interface_count = mono_array_length (tb->interfaces);
9123 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9124 for (i = 0; i < klass->interface_count; ++i) {
9125 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9126 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9130 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9131 for (i = 0; i < klass->method.count; ++i)
9132 klass->methods [i]->slot = i;
9134 mono_class_setup_interface_offsets (klass);
9138 * The generic vtable is needed even if image->run is not set since some
9139 * runtime code like ves_icall_Type_GetMethodsByName depends on
9140 * method->slot being defined.
9144 * tb->methods could not be freed since it is used for determining
9145 * overrides during dynamic vtable construction.
9150 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9152 MonoReflectionTypeBuilder *tb;
9158 g_assert (klass->image->dynamic);
9160 if (!klass->reflection_info)
9163 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9165 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9169 for (i = 0; i < tb->num_methods; ++i) {
9170 MonoReflectionMethodBuilder *mb =
9171 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9172 if (mb->override_method)
9178 *overrides = g_new0 (MonoMethod*, onum * 2);
9181 for (i = 0; i < tb->num_methods; ++i) {
9182 MonoReflectionMethodBuilder *mb =
9183 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9184 if (mb->override_method) {
9185 (*overrides) [onum * 2] =
9186 mb->override_method->method;
9187 (*overrides) [onum * 2 + 1] =
9190 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9191 g_assert (mb->override_method->method);
9192 g_assert (mb->mhandle);
9199 *num_overrides = onum;
9203 typebuilder_setup_fields (MonoClass *klass)
9205 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9206 MonoReflectionFieldBuilder *fb;
9207 MonoClassField *field;
9212 klass->field.count = tb->num_fields;
9213 klass->field.first = 0;
9215 if (!klass->field.count)
9218 klass->fields = g_new0 (MonoClassField, klass->field.count);
9220 for (i = 0; i < klass->field.count; ++i) {
9221 fb = mono_array_get (tb->fields, gpointer, i);
9222 field = &klass->fields [i];
9223 field->name = mono_string_to_utf8 (fb->name);
9225 /* FIXME: handle type modifiers */
9226 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9227 field->type->attrs = fb->attrs;
9229 field->type = fb->type->type;
9231 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9232 field->data = mono_array_addr (fb->rva_data, char, 0);
9233 if (fb->offset != -1)
9234 field->offset = fb->offset;
9235 field->parent = klass;
9237 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9239 if (fb->def_value) {
9240 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9241 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9242 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9243 /* Copy the data from the blob since it might get realloc-ed */
9244 p = assembly->blob.data + idx;
9245 len = mono_metadata_decode_blob_size (p, &p2);
9247 field->data = g_malloc (len);
9248 memcpy ((gpointer)field->data, p, len);
9251 mono_class_layout_fields (klass);
9255 typebuilder_setup_properties (MonoClass *klass)
9257 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9258 MonoReflectionPropertyBuilder *pb;
9261 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9262 klass->property.first = 0;
9264 klass->properties = g_new0 (MonoProperty, klass->property.count);
9265 for (i = 0; i < klass->property.count; ++i) {
9266 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9267 klass->properties [i].parent = klass;
9268 klass->properties [i].attrs = pb->attrs;
9269 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9271 klass->properties [i].get = pb->get_method->mhandle;
9273 klass->properties [i].set = pb->set_method->mhandle;
9275 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9279 MonoReflectionEvent *
9280 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9282 MonoEvent *event = g_new0 (MonoEvent, 1);
9286 klass = my_mono_class_from_mono_type (tb->type.type);
9288 event->parent = klass;
9289 event->attrs = eb->attrs;
9290 event->name = mono_string_to_utf8 (eb->name);
9292 event->add = eb->add_method->mhandle;
9293 if (eb->remove_method)
9294 event->remove = eb->remove_method->mhandle;
9295 if (eb->raise_method)
9296 event->raise = eb->raise_method->mhandle;
9298 if (eb->other_methods) {
9299 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9300 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9301 MonoReflectionMethodBuilder *mb =
9302 mono_array_get (eb->other_methods,
9303 MonoReflectionMethodBuilder*, j);
9304 event->other [j] = mb->mhandle;
9308 return mono_event_get_object (mono_object_domain (tb), klass, event);
9312 typebuilder_setup_events (MonoClass *klass)
9314 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9315 MonoReflectionEventBuilder *eb;
9318 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9319 klass->event.first = 0;
9321 klass->events = g_new0 (MonoEvent, klass->event.count);
9322 for (i = 0; i < klass->event.count; ++i) {
9323 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9324 klass->events [i].parent = klass;
9325 klass->events [i].attrs = eb->attrs;
9326 klass->events [i].name = mono_string_to_utf8 (eb->name);
9328 klass->events [i].add = eb->add_method->mhandle;
9329 if (eb->remove_method)
9330 klass->events [i].remove = eb->remove_method->mhandle;
9331 if (eb->raise_method)
9332 klass->events [i].raise = eb->raise_method->mhandle;
9334 if (eb->other_methods) {
9335 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9336 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9337 MonoReflectionMethodBuilder *mb =
9338 mono_array_get (eb->other_methods,
9339 MonoReflectionMethodBuilder*, j);
9340 klass->events [i].other [j] = mb->mhandle;
9347 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9351 MonoReflectionType* res;
9354 MONO_ARCH_SAVE_REGS;
9356 domain = mono_object_domain (tb);
9357 klass = my_mono_class_from_mono_type (tb->type.type);
9359 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9362 * we need to lock the domain because the lock will be taken inside
9363 * So, we need to keep the locking order correct.
9365 mono_domain_lock (domain);
9366 mono_loader_lock ();
9367 if (klass->wastypebuilder) {
9368 mono_loader_unlock ();
9369 mono_domain_unlock (domain);
9370 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9373 * Fields to set in klass:
9374 * the various flags: delegate/unicode/contextbound etc.
9376 klass->flags = tb->attrs;
9377 klass->has_cctor = 1;
9378 klass->has_finalize = 1;
9381 if (!((MonoDynamicImage*)klass->image)->run) {
9382 if (klass->generic_container) {
9383 /* FIXME: The code below can't handle generic classes */
9384 klass->wastypebuilder = TRUE;
9385 mono_loader_unlock ();
9386 mono_domain_unlock (domain);
9387 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9392 /* enums are done right away */
9393 if (!klass->enumtype)
9394 ensure_runtime_vtable (klass);
9397 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9398 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9399 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9403 /* fields and object layout */
9404 if (klass->parent) {
9405 if (!klass->parent->size_inited)
9406 mono_class_init (klass->parent);
9407 klass->instance_size = klass->parent->instance_size;
9408 klass->sizes.class_size = 0;
9409 klass->min_align = klass->parent->min_align;
9410 /* if the type has no fields we won't call the field_setup
9411 * routine which sets up klass->has_references.
9413 klass->has_references |= klass->parent->has_references;
9415 klass->instance_size = sizeof (MonoObject);
9416 klass->min_align = 1;
9419 /* FIXME: handle packing_size and instance_size */
9420 typebuilder_setup_fields (klass);
9422 typebuilder_setup_properties (klass);
9424 typebuilder_setup_events (klass);
9426 klass->wastypebuilder = TRUE;
9427 mono_loader_unlock ();
9428 mono_domain_unlock (domain);
9430 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9431 g_assert (res != (MonoReflectionType*)tb);
9437 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9439 MonoGenericParam *param;
9442 MONO_ARCH_SAVE_REGS;
9444 param = g_new0 (MonoGenericParam, 1);
9446 if (gparam->mbuilder) {
9447 if (!gparam->mbuilder->generic_container)
9448 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9449 param->owner = gparam->mbuilder->generic_container;
9450 } else if (gparam->tbuilder) {
9451 g_assert (gparam->tbuilder->generic_container);
9452 param->owner = gparam->tbuilder->generic_container;
9455 param->name = mono_string_to_utf8 (gparam->name);
9456 param->num = gparam->index;
9458 image = &gparam->tbuilder->module->dynamic_image->image;
9459 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9461 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9462 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9464 gparam->type.type = g_new0 (MonoType, 1);
9465 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9466 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9467 gparam->type.type->data.generic_param = param;
9471 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9473 MonoDynamicImage *assembly = sig->module->dynamic_image;
9474 guint32 na = mono_array_length (sig->arguments);
9479 sigbuffer_init (&buf, 32);
9481 sigbuffer_add_value (&buf, 0x07);
9482 sigbuffer_add_value (&buf, na);
9483 for (i = 0; i < na; ++i) {
9484 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9485 encode_reflection_type (assembly, type, &buf);
9488 buflen = buf.p - buf.buf;
9489 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9490 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9491 sigbuffer_free (&buf);
9497 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9499 MonoDynamicImage *assembly = sig->module->dynamic_image;
9500 guint32 na = mono_array_length (sig->arguments);
9505 sigbuffer_init (&buf, 32);
9507 sigbuffer_add_value (&buf, 0x06);
9508 for (i = 0; i < na; ++i) {
9509 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9510 encode_reflection_type (assembly, type, &buf);
9513 buflen = buf.p - buf.buf;
9514 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9515 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9516 sigbuffer_free (&buf);
9522 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9524 ReflectionMethodBuilder rmb;
9525 MonoMethodSignature *sig;
9529 sig = dynamic_method_to_signature (mb);
9531 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9534 * Resolve references.
9537 * Every second entry in the refs array is reserved for storing handle_class,
9538 * which is needed by the ldtoken implementation in the JIT.
9540 rmb.nrefs = mb->nrefs;
9541 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9542 for (i = 0; i < mb->nrefs; i += 2) {
9543 MonoClass *handle_class;
9545 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9547 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9548 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9550 * The referenced DynamicMethod should already be created by the managed
9551 * code, except in the case of circular references. In that case, we store
9552 * method in the refs array, and fix it up later when the referenced
9553 * DynamicMethod is created.
9555 if (method->mhandle) {
9556 ref = method->mhandle;
9558 /* FIXME: GC object stored in unmanaged memory */
9561 /* FIXME: GC object stored in unmanaged memory */
9562 method->referenced_by = g_slist_append (method->referenced_by, mb);
9564 handle_class = mono_defaults.methodhandle_class;
9566 ref = resolve_object (mb->module->image, obj, &handle_class);
9569 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9574 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9575 rmb.refs [i + 1] = handle_class;
9579 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9581 /* Fix up refs entries pointing at us */
9582 for (l = mb->referenced_by; l; l = l->next) {
9583 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9584 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9587 g_assert (method->mhandle);
9589 data = (gpointer*)wrapper->method_data;
9590 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9591 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9592 data [i + 1] = mb->mhandle;
9595 g_slist_free (mb->referenced_by);
9599 /* ilgen is no longer needed */
9604 * mono_reflection_lookup_dynamic_token:
9606 * Finish the Builder object pointed to by TOKEN and return the corresponding
9607 * runtime structure. HANDLE_CLASS is set to the class required by
9611 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9613 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9616 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9619 return resolve_object (image, obj, handle_class);
9623 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9625 gpointer result = NULL;
9627 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9628 result = mono_string_intern ((MonoString*)obj);
9629 *handle_class = NULL;
9631 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9632 MonoReflectionType *tb = (MonoReflectionType*)obj;
9633 result = mono_class_from_mono_type (tb->type);
9634 *handle_class = mono_defaults.typehandle_class;
9636 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9637 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9638 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9639 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9640 result = ((MonoReflectionMethod*)obj)->method;
9641 *handle_class = mono_defaults.methodhandle_class;
9643 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9644 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9645 result = mb->mhandle;
9647 /* Type is not yet created */
9648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9650 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9653 * Hopefully this has been filled in by calling CreateType() on the
9657 * TODO: This won't work if the application finishes another
9658 * TypeBuilder instance instead of this one.
9660 result = mb->mhandle;
9662 *handle_class = mono_defaults.methodhandle_class;
9663 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9664 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9666 result = cb->mhandle;
9668 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9670 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9671 result = cb->mhandle;
9673 *handle_class = mono_defaults.methodhandle_class;
9674 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9675 result = ((MonoReflectionField*)obj)->field;
9676 *handle_class = mono_defaults.fieldhandle_class;
9678 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9679 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9680 result = fb->handle;
9683 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9685 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9686 result = fb->handle;
9688 *handle_class = mono_defaults.fieldhandle_class;
9689 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9690 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9693 klass = tb->type.type->data.klass;
9694 if (klass->wastypebuilder) {
9695 /* Already created */
9699 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9700 result = tb->type.type->data.klass;
9703 *handle_class = mono_defaults.typehandle_class;
9704 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9705 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9706 MonoMethodSignature *sig;
9709 if (helper->arguments)
9710 nargs = mono_array_length (helper->arguments);
9714 sig = mono_metadata_signature_alloc (image, nargs);
9715 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9716 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9718 if (helper->call_conv == 0) /* unmanaged */
9719 sig->call_convention = helper->unmanaged_call_conv - 1;
9721 if (helper->call_conv & 0x02)
9722 sig->call_convention = MONO_CALL_VARARG;
9724 sig->call_convention = MONO_CALL_DEFAULT;
9726 sig->param_count = nargs;
9727 /* TODO: Copy type ? */
9728 sig->ret = helper->return_type->type;
9729 for (i = 0; i < nargs; ++i) {
9730 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9731 sig->params [i] = rt->type;
9735 *handle_class = NULL;
9736 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9737 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9738 /* Already created by the managed code */
9739 g_assert (method->mhandle);
9740 result = method->mhandle;
9741 *handle_class = mono_defaults.methodhandle_class;
9743 g_print (obj->vtable->klass->name);
9744 g_assert_not_reached ();
9750 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9751 const static guint32 declsec_flags_map[] = {
9752 0x00000000, /* empty */
9753 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9754 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9755 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9756 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9757 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9758 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9759 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9760 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9761 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9762 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9763 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9764 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9765 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9766 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9767 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9768 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9769 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9770 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9774 * Returns flags that includes all available security action associated to the handle.
9775 * @token: metadata token (either for a class or a method)
9776 * @image: image where resides the metadata.
9779 mono_declsec_get_flags (MonoImage *image, guint32 token)
9781 guint32 index = mono_metadata_declsec_from_index (image, token);
9782 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9787 for (i = index; i < t->rows; i++) {
9788 guint32 cols [MONO_DECL_SECURITY_SIZE];
9790 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9791 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9794 action = cols [MONO_DECL_SECURITY_ACTION];
9795 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9796 result |= declsec_flags_map [action];
9798 g_assert_not_reached ();
9805 * Get the security actions (in the form of flags) associated with the specified method.
9807 * @method: The method for which we want the declarative security flags.
9808 * Return the declarative security flags for the method (only).
9810 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9811 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9814 mono_declsec_flags_from_method (MonoMethod *method)
9816 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9817 /* FIXME: No cache (for the moment) */
9818 guint32 idx = mono_method_get_index (method);
9819 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9820 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9821 return mono_declsec_get_flags (method->klass->image, idx);
9827 * Get the security actions (in the form of flags) associated with the specified class.
9829 * @klass: The class for which we want the declarative security flags.
9830 * Return the declarative security flags for the class.
9832 * Note: We cache the flags inside the MonoClass structure as this will get
9833 * called very often (at least for each method).
9836 mono_declsec_flags_from_class (MonoClass *klass)
9838 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9839 if (!klass->declsec_flags) {
9840 guint32 idx = mono_metadata_token_index (klass->type_token);
9841 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9842 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9843 /* we cache the flags on classes */
9844 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9846 return klass->declsec_flags;
9852 * Get the security actions (in the form of flags) associated with the specified assembly.
9854 * @assembly: The assembly for which we want the declarative security flags.
9855 * Return the declarative security flags for the assembly.
9858 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9860 guint32 idx = 1; /* there is only one assembly */
9861 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9862 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9863 return mono_declsec_get_flags (assembly->image, idx);
9868 * Fill actions for the specific index (which may either be an encoded class token or
9869 * an encoded method token) from the metadata image.
9870 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9873 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9874 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9876 MonoBoolean result = FALSE;
9878 guint32 cols [MONO_DECL_SECURITY_SIZE];
9879 int index = mono_metadata_declsec_from_index (image, token);
9882 t = &image->tables [MONO_TABLE_DECLSECURITY];
9883 for (i = index; i < t->rows; i++) {
9884 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9886 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9889 /* if present only replace (class) permissions with method permissions */
9890 /* if empty accept either class or method permissions */
9891 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9892 if (!actions->demand.blob) {
9893 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9894 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9895 actions->demand.blob = (char*) (blob + 2);
9896 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9899 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9900 if (!actions->noncasdemand.blob) {
9901 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9902 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9903 actions->noncasdemand.blob = (char*) (blob + 2);
9904 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9907 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9908 if (!actions->demandchoice.blob) {
9909 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9910 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9911 actions->demandchoice.blob = (char*) (blob + 2);
9912 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9922 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9923 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9925 guint32 idx = mono_metadata_token_index (klass->type_token);
9926 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9927 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9928 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9932 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9933 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9935 guint32 idx = mono_method_get_index (method);
9936 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9937 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9938 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9942 * Collect all actions (that requires to generate code in mini) assigned for
9943 * the specified method.
9944 * Note: Don't use the content of actions if the function return FALSE.
9947 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9949 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9950 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9951 MonoBoolean result = FALSE;
9954 /* quick exit if no declarative security is present in the metadata */
9955 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9958 /* we want the original as the wrapper is "free" of the security informations */
9959 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9960 method = mono_marshal_method_from_wrapper (method);
9965 /* First we look for method-level attributes */
9966 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9967 mono_class_init (method->klass);
9968 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9970 result = mono_declsec_get_method_demands_params (method, demands,
9971 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9974 /* Here we use (or create) the class declarative cache to look for demands */
9975 flags = mono_declsec_flags_from_class (method->klass);
9978 mono_class_init (method->klass);
9979 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9981 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9982 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9985 /* The boolean return value is used as a shortcut in case nothing needs to
9986 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9992 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9994 * Note: Don't use the content of actions if the function return FALSE.
9997 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9999 MonoBoolean result = FALSE;
10002 /* quick exit if no declarative security is present in the metadata */
10003 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10006 /* we want the original as the wrapper is "free" of the security informations */
10007 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10008 method = mono_marshal_method_from_wrapper (method);
10013 /* results are independant - zeroize both */
10014 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10015 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10017 /* First we look for method-level attributes */
10018 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10019 mono_class_init (method->klass);
10021 result = mono_declsec_get_method_demands_params (method, cmethod,
10022 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10025 /* Here we use (or create) the class declarative cache to look for demands */
10026 flags = mono_declsec_flags_from_class (method->klass);
10027 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10028 mono_class_init (method->klass);
10030 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10031 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10038 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10040 * @klass The inherited class - this is the class that provides the security check (attributes)
10042 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10044 * Note: Don't use the content of actions if the function return FALSE.
10047 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10049 MonoBoolean result = FALSE;
10052 /* quick exit if no declarative security is present in the metadata */
10053 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10056 /* Here we use (or create) the class declarative cache to look for demands */
10057 flags = mono_declsec_flags_from_class (klass);
10058 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10059 mono_class_init (klass);
10060 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10062 result |= mono_declsec_get_class_demands_params (klass, demands,
10063 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10070 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10072 * Note: Don't use the content of actions if the function return FALSE.
10075 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10077 /* quick exit if no declarative security is present in the metadata */
10078 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10081 /* we want the original as the wrapper is "free" of the security informations */
10082 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10083 method = mono_marshal_method_from_wrapper (method);
10088 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10089 mono_class_init (method->klass);
10090 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10092 return mono_declsec_get_method_demands_params (method, demands,
10093 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10100 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10102 guint32 cols [MONO_DECL_SECURITY_SIZE];
10106 int index = mono_metadata_declsec_from_index (image, token);
10110 t = &image->tables [MONO_TABLE_DECLSECURITY];
10111 for (i = index; i < t->rows; i++) {
10112 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10114 /* shortcut - index are ordered */
10115 if (token != cols [MONO_DECL_SECURITY_PARENT])
10118 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10119 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10120 entry->blob = (char*) (metadata + 2);
10121 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10130 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10132 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10133 guint32 idx = mono_method_get_index (method);
10134 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10135 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10136 return get_declsec_action (method->klass->image, idx, action, entry);
10142 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10145 guint32 flags = mono_declsec_flags_from_class (klass);
10146 if (declsec_flags_map [action] & flags) {
10147 guint32 idx = mono_metadata_token_index (klass->type_token);
10148 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10149 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10150 return get_declsec_action (klass->image, idx, action, entry);
10156 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10158 guint32 idx = 1; /* there is only one assembly */
10159 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10160 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10162 return get_declsec_action (assembly->image, idx, action, entry);
10166 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10168 MonoObject *res, *exc;
10170 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10171 static MonoMethod *method = NULL;
10173 if (!System_Reflection_Emit_TypeBuilder) {
10174 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10175 g_assert (System_Reflection_Emit_TypeBuilder);
10177 if (method == NULL) {
10178 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10183 * The result of mono_type_get_object () might be a System.MonoType but we
10184 * need a TypeBuilder so use klass->reflection_info.
10186 g_assert (klass->reflection_info);
10187 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10189 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10191 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10195 return *(MonoBoolean*)mono_object_unbox (res);