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);
152 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
154 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
155 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
156 static CRITICAL_SECTION reflection_mutex;
159 mono_reflection_init (void)
161 InitializeCriticalSection (&reflection_mutex);
165 sigbuffer_init (SigBuffer *buf, int size)
167 buf->buf = g_malloc (size);
169 buf->end = buf->buf + size;
173 sigbuffer_make_room (SigBuffer *buf, int size)
175 if (buf->end - buf->p < size) {
176 int new_size = buf->end - buf->buf + size + 32;
177 char *p = g_realloc (buf->buf, new_size);
178 size = buf->p - buf->buf;
181 buf->end = buf->buf + new_size;
186 sigbuffer_add_value (SigBuffer *buf, guint32 val)
188 sigbuffer_make_room (buf, 6);
189 mono_metadata_encode_value (val, buf->p, &buf->p);
193 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
195 sigbuffer_make_room (buf, 1);
201 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
203 sigbuffer_make_room (buf, size);
204 memcpy (buf->p, p, size);
209 sigbuffer_free (SigBuffer *buf)
217 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
221 mp_g_malloc (MonoMemPool *mp, guint size)
224 return mono_mempool_alloc (mp, size);
226 return g_malloc (size);
232 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
236 mp_g_malloc0 (MonoMemPool *mp, guint size)
239 return mono_mempool_alloc0 (mp, size);
241 return g_malloc0 (size);
247 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
248 * memory from the C heap.
251 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
254 return mono_string_to_utf8_mp (mp, s);
256 return mono_string_to_utf8 (s);
259 #define mp_g_new(mp,struct_type, n_structs) \
260 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
262 #define mp_g_new0(mp,struct_type, n_structs) \
263 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
266 alloc_table (MonoDynamicTable *table, guint nrows)
269 g_assert (table->columns);
270 if (nrows + 1 >= table->alloc_rows) {
271 while (nrows + 1 >= table->alloc_rows) {
272 if (table->alloc_rows == 0)
273 table->alloc_rows = 16;
275 table->alloc_rows *= 2;
278 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
283 make_room_in_stream (MonoDynamicStream *stream, int size)
285 if (size <= stream->alloc_size)
288 while (stream->alloc_size <= size) {
289 if (stream->alloc_size < 4096)
290 stream->alloc_size = 4096;
292 stream->alloc_size *= 2;
295 stream->data = g_realloc (stream->data, stream->alloc_size);
299 string_heap_insert (MonoDynamicStream *sh, const char *str)
303 gpointer oldkey, oldval;
305 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
306 return GPOINTER_TO_UINT (oldval);
308 len = strlen (str) + 1;
311 make_room_in_stream (sh, idx + len);
314 * We strdup the string even if we already copy them in sh->data
315 * so that the string pointers in the hash remain valid even if
316 * we need to realloc sh->data. We may want to avoid that later.
318 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
319 memcpy (sh->data + idx, str, len);
325 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
327 char *name = mono_string_to_utf8 (str);
329 idx = string_heap_insert (sh, name);
335 string_heap_init (MonoDynamicStream *sh)
338 sh->alloc_size = 4096;
339 sh->data = g_malloc (4096);
340 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
341 string_heap_insert (sh, "");
345 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
349 make_room_in_stream (stream, stream->index + len);
350 memcpy (stream->data + stream->index, data, len);
352 stream->index += len;
354 * align index? Not without adding an additional param that controls it since
355 * we may store a blob value in pieces.
361 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
365 make_room_in_stream (stream, stream->index + len);
366 memset (stream->data + stream->index, 0, len);
368 stream->index += len;
373 stream_data_align (MonoDynamicStream *stream)
376 guint32 count = stream->index % 4;
378 /* we assume the stream data will be aligned */
380 mono_image_add_stream_data (stream, buf, 4 - count);
384 mono_blob_entry_hash (const char* str)
388 len = mono_metadata_decode_blob_size (str, &str);
392 for (str += 1; str < end; str++)
393 h = (h << 5) - h + *str;
401 mono_blob_entry_equal (const char *str1, const char *str2) {
405 len = mono_metadata_decode_blob_size (str1, &end1);
406 len2 = mono_metadata_decode_blob_size (str2, &end2);
409 return memcmp (end1, end2, len) == 0;
413 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
417 gpointer oldkey, oldval;
419 copy = g_malloc (s1+s2);
420 memcpy (copy, b1, s1);
421 memcpy (copy + s1, b2, s2);
422 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
424 idx = GPOINTER_TO_UINT (oldval);
426 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
427 mono_image_add_stream_data (&assembly->blob, b2, s2);
428 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
434 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
438 guint32 size = buf->p - buf->buf;
440 g_assert (size <= (buf->end - buf->buf));
441 mono_metadata_encode_value (size, b, &b);
442 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
446 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
447 * dest may be misaligned.
450 swap_with_size (char *dest, const char* val, int len, int nelem) {
451 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
454 for (elem = 0; elem < nelem; ++elem) {
480 g_assert_not_reached ();
486 memcpy (dest, val, len * nelem);
491 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
495 guint32 idx = 0, len;
497 len = str->length * 2;
498 mono_metadata_encode_value (len, b, &b);
499 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
501 char *swapped = g_malloc (2 * mono_string_length (str));
502 const char *p = (const char*)mono_string_chars (str);
504 swap_with_size (swapped, p, 2, mono_string_length (str));
505 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
509 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
514 /* modified version needed to handle building corlib */
516 my_mono_class_from_mono_type (MonoType *type) {
517 switch (type->type) {
518 case MONO_TYPE_ARRAY:
520 case MONO_TYPE_SZARRAY:
521 case MONO_TYPE_GENERICINST:
522 return mono_class_from_mono_type (type);
525 g_assert (type->data.generic_param->pklass);
526 return type->data.generic_param->pklass;
528 /* should be always valid when we reach this case... */
529 return type->data.klass;
534 default_class_from_mono_type (MonoType *type)
536 switch (type->type) {
537 case MONO_TYPE_OBJECT:
538 return mono_defaults.object_class;
540 return mono_defaults.void_class;
541 case MONO_TYPE_BOOLEAN:
542 return mono_defaults.boolean_class;
544 return mono_defaults.char_class;
546 return mono_defaults.sbyte_class;
548 return mono_defaults.byte_class;
550 return mono_defaults.int16_class;
552 return mono_defaults.uint16_class;
554 return mono_defaults.int32_class;
556 return mono_defaults.uint32_class;
558 return mono_defaults.int_class;
560 return mono_defaults.uint_class;
562 return mono_defaults.int64_class;
564 return mono_defaults.uint64_class;
566 return mono_defaults.single_class;
568 return mono_defaults.double_class;
569 case MONO_TYPE_STRING:
570 return mono_defaults.string_class;
572 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
573 g_assert_not_reached ();
580 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
583 MonoGenericInst *class_inst;
587 class_inst = gclass->context.class_inst;
589 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
590 encode_type (assembly, &gclass->container_class->byval_arg, buf);
591 sigbuffer_add_value (buf, class_inst->type_argc);
592 for (i = 0; i < class_inst->type_argc; ++i)
593 encode_type (assembly, class_inst->type_argv [i], buf);
598 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
601 g_assert_not_reached ();
606 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
610 case MONO_TYPE_BOOLEAN:
624 case MONO_TYPE_STRING:
625 case MONO_TYPE_OBJECT:
626 case MONO_TYPE_TYPEDBYREF:
627 sigbuffer_add_value (buf, type->type);
630 sigbuffer_add_value (buf, type->type);
631 encode_type (assembly, type->data.type, buf);
633 case MONO_TYPE_SZARRAY:
634 sigbuffer_add_value (buf, type->type);
635 encode_type (assembly, &type->data.klass->byval_arg, buf);
637 case MONO_TYPE_VALUETYPE:
638 case MONO_TYPE_CLASS: {
639 MonoClass *k = mono_class_from_mono_type (type);
641 * Make sure we use the correct type.
643 sigbuffer_add_value (buf, k->byval_arg.type);
645 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
646 * otherwise two typerefs could point to the same type, leading to
647 * verification errors.
649 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
652 case MONO_TYPE_ARRAY:
653 sigbuffer_add_value (buf, type->type);
654 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
655 sigbuffer_add_value (buf, type->data.array->rank);
656 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
657 sigbuffer_add_value (buf, 0);
659 case MONO_TYPE_GENERICINST:
660 encode_generic_class (assembly, type->data.generic_class, buf);
664 sigbuffer_add_value (buf, type->type);
665 sigbuffer_add_value (buf, type->data.generic_param->num);
668 g_error ("need to encode type %x", type->type);
673 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
676 sigbuffer_add_value (buf, MONO_TYPE_VOID);
681 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
682 encode_type (assembly, type->type, buf);
686 g_assert_not_reached ();
691 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
696 for (i = 0; i < mono_array_length (modreq); ++i) {
697 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
698 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
699 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
703 for (i = 0; i < mono_array_length (modopt); ++i) {
704 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
705 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
706 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
712 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
716 guint32 nparams = sig->param_count;
722 sigbuffer_init (&buf, 32);
724 * FIXME: vararg, explicit_this, differenc call_conv values...
726 idx = sig->call_convention;
728 idx |= 0x20; /* hasthis */
729 if (sig->generic_param_count)
730 idx |= 0x10; /* generic */
731 sigbuffer_add_byte (&buf, idx);
732 if (sig->generic_param_count)
733 sigbuffer_add_value (&buf, sig->generic_param_count);
734 sigbuffer_add_value (&buf, nparams);
735 encode_type (assembly, sig->ret, &buf);
736 for (i = 0; i < nparams; ++i) {
737 if (i == sig->sentinelpos)
738 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
739 encode_type (assembly, sig->params [i], &buf);
741 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
742 sigbuffer_free (&buf);
747 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
750 * FIXME: reuse code from method_encode_signature().
754 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
755 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
756 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
759 sigbuffer_init (&buf, 32);
760 /* LAMESPEC: all the call conv spec is foobared */
761 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
762 if (mb->call_conv & 2)
763 idx |= 0x5; /* vararg */
764 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
765 idx |= 0x20; /* hasthis */
767 idx |= 0x10; /* generic */
768 sigbuffer_add_byte (&buf, idx);
770 sigbuffer_add_value (&buf, ngparams);
771 sigbuffer_add_value (&buf, nparams + notypes);
772 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
773 encode_reflection_type (assembly, mb->rtype, &buf);
774 for (i = 0; i < nparams; ++i) {
775 MonoArray *modreq = NULL;
776 MonoArray *modopt = NULL;
777 MonoReflectionType *pt;
779 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
780 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
781 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
782 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
783 encode_custom_modifiers (assembly, modreq, modopt, &buf);
784 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
785 encode_reflection_type (assembly, pt, &buf);
788 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
789 for (i = 0; i < notypes; ++i) {
790 MonoReflectionType *pt;
792 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
793 encode_reflection_type (assembly, pt, &buf);
796 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
797 sigbuffer_free (&buf);
802 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
804 MonoDynamicTable *table;
806 guint32 idx, sig_idx;
807 guint nl = mono_array_length (ilgen->locals);
811 sigbuffer_init (&buf, 32);
812 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
813 idx = table->next_idx ++;
815 alloc_table (table, table->rows);
816 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
818 sigbuffer_add_value (&buf, 0x07);
819 sigbuffer_add_value (&buf, nl);
820 for (i = 0; i < nl; ++i) {
821 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
824 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
826 encode_reflection_type (assembly, lb->type, &buf);
828 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
829 sigbuffer_free (&buf);
831 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
837 method_count_clauses (MonoReflectionILGen *ilgen)
839 guint32 num_clauses = 0;
842 MonoILExceptionInfo *ex_info;
843 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
844 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
845 if (ex_info->handlers)
846 num_clauses += mono_array_length (ex_info->handlers);
854 static MonoExceptionClause*
855 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
857 MonoExceptionClause *clauses;
858 MonoExceptionClause *clause;
859 MonoILExceptionInfo *ex_info;
860 MonoILExceptionBlock *ex_block;
861 guint32 finally_start;
862 int i, j, clause_index;;
864 clauses = g_new0 (MonoExceptionClause, num_clauses);
867 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
868 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
869 finally_start = ex_info->start + ex_info->len;
870 if (!ex_info->handlers)
872 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
873 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
874 clause = &(clauses [clause_index]);
876 clause->flags = ex_block->type;
877 clause->try_offset = ex_info->start;
879 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
880 clause->try_len = finally_start - ex_info->start;
882 clause->try_len = ex_info->len;
883 clause->handler_offset = ex_block->start;
884 clause->handler_len = ex_block->len;
885 if (ex_block->extype) {
886 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
888 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
889 clause->data.filter_offset = ex_block->filter_offset;
891 clause->data.filter_offset = 0;
893 finally_start = ex_block->start + ex_block->len;
903 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
909 gint32 num_locals = 0;
910 gint32 num_exception = 0;
913 char fat_header [12];
916 guint32 local_sig = 0;
917 guint32 header_size = 12;
920 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
921 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
925 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
927 code = mb->ilgen->code;
928 code_size = mb->ilgen->code_len;
929 max_stack = mb->ilgen->max_stack;
930 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
931 if (mb->ilgen->ex_handlers)
932 num_exception = method_count_clauses (mb->ilgen);
936 char *name = mono_string_to_utf8 (mb->name);
937 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
938 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
941 mono_raise_exception (exception);
944 code_size = mono_array_length (code);
945 max_stack = 8; /* we probably need to run a verifier on the code... */
948 stream_data_align (&assembly->code);
950 /* check for exceptions, maxstack, locals */
951 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
953 if (code_size < 64 && !(code_size & 1)) {
954 flags = (code_size << 2) | 0x2;
955 } else if (code_size < 32 && (code_size & 1)) {
956 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
960 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
961 /* add to the fixup todo list */
962 if (mb->ilgen && mb->ilgen->num_token_fixups)
963 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
964 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
965 return assembly->text_rva + idx;
969 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
971 * FIXME: need to set also the header size in fat_flags.
972 * (and more sects and init locals flags)
976 fat_flags |= METHOD_HEADER_MORE_SECTS;
978 fat_flags |= METHOD_HEADER_INIT_LOCALS;
979 fat_header [0] = fat_flags;
980 fat_header [1] = (header_size / 4 ) << 4;
981 short_value = GUINT16_TO_LE (max_stack);
982 memcpy (fat_header + 2, &short_value, 2);
983 int_value = GUINT32_TO_LE (code_size);
984 memcpy (fat_header + 4, &int_value, 4);
985 int_value = GUINT32_TO_LE (local_sig);
986 memcpy (fat_header + 8, &int_value, 4);
987 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
988 /* add to the fixup todo list */
989 if (mb->ilgen && mb->ilgen->num_token_fixups)
990 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
992 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
994 unsigned char sheader [4];
995 MonoILExceptionInfo * ex_info;
996 MonoILExceptionBlock * ex_block;
999 stream_data_align (&assembly->code);
1000 /* always use fat format for now */
1001 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1002 num_exception *= 6 * sizeof (guint32);
1003 num_exception += 4; /* include the size of the header */
1004 sheader [1] = num_exception & 0xff;
1005 sheader [2] = (num_exception >> 8) & 0xff;
1006 sheader [3] = (num_exception >> 16) & 0xff;
1007 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1008 /* fat header, so we are already aligned */
1010 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1011 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1012 if (ex_info->handlers) {
1013 int finally_start = ex_info->start + ex_info->len;
1014 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1016 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1018 val = GUINT32_TO_LE (ex_block->type);
1019 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1021 val = GUINT32_TO_LE (ex_info->start);
1022 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1023 /* need fault, too, probably */
1024 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1025 val = GUINT32_TO_LE (finally_start - ex_info->start);
1027 val = GUINT32_TO_LE (ex_info->len);
1028 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1029 /* handler offset */
1030 val = GUINT32_TO_LE (ex_block->start);
1031 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1033 val = GUINT32_TO_LE (ex_block->len);
1034 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1035 finally_start = ex_block->start + ex_block->len;
1036 if (ex_block->extype) {
1037 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1039 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1040 val = ex_block->filter_offset;
1044 val = GUINT32_TO_LE (val);
1045 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 /*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",
1047 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);*/
1050 g_error ("No clauses for ex info block %d", i);
1054 return assembly->text_rva + idx;
1058 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1061 MonoDynamicTable *table;
1064 table = &assembly->tables [table_idx];
1066 g_assert (col < table->columns);
1068 values = table->values + table->columns;
1069 for (i = 1; i <= table->rows; ++i) {
1070 if (values [col] == token)
1072 values += table->columns;
1077 /* protected by reflection_mutex:
1078 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1080 static GHashTable *dynamic_custom_attrs = NULL;
1082 static MonoCustomAttrInfo*
1083 lookup_custom_attr (void *member)
1085 MonoCustomAttrInfo *ainfo, *res;
1088 mono_reflection_lock ();
1089 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1090 mono_reflection_unlock ();
1093 /* Need to copy since it will be freed later */
1094 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
1095 res = g_malloc0 (size);
1096 memcpy (res, ainfo, size);
1103 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1105 /* FIXME: Need to do more checks */
1106 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1107 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1109 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1116 static MonoCustomAttrInfo*
1117 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1119 int i, index, count, not_visible;
1120 MonoCustomAttrInfo *ainfo;
1121 MonoReflectionCustomAttr *cattr;
1125 /* FIXME: check in assembly the Run flag is set */
1127 count = mono_array_length (cattrs);
1129 /* Skip nonpublic attributes since MS.NET seems to do the same */
1130 /* FIXME: This needs to be done more globally */
1132 for (i = 0; i < count; ++i) {
1133 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1134 if (!custom_attr_visible (image, cattr))
1137 count -= not_visible;
1139 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1141 ainfo->image = image;
1142 ainfo->num_attrs = count;
1144 mono_loader_lock ();
1145 for (i = 0; i < count; ++i) {
1146 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1147 if (custom_attr_visible (image, cattr)) {
1148 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1149 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1150 ainfo->attrs [index].ctor = cattr->ctor->method;
1151 ainfo->attrs [index].data = saved;
1152 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1156 mono_loader_unlock ();
1162 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1164 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1169 mono_reflection_lock ();
1170 if (!dynamic_custom_attrs)
1171 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1173 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1174 ainfo->cached = TRUE;
1175 mono_reflection_unlock ();
1179 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1186 * idx is the table index of the object
1187 * type is one of MONO_CUSTOM_ATTR_*
1190 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1192 MonoDynamicTable *table;
1193 MonoReflectionCustomAttr *cattr;
1195 guint32 count, i, token;
1197 char *p = blob_size;
1199 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1202 count = mono_array_length (cattrs);
1203 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1204 table->rows += count;
1205 alloc_table (table, table->rows);
1206 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1207 idx <<= MONO_CUSTOM_ATTR_BITS;
1209 for (i = 0; i < count; ++i) {
1210 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1211 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1212 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1213 type = mono_metadata_token_index (token);
1214 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1215 switch (mono_metadata_token_table (token)) {
1216 case MONO_TABLE_METHOD:
1217 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1219 case MONO_TABLE_MEMBERREF:
1220 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1223 g_warning ("got wrong token in custom attr");
1226 values [MONO_CUSTOM_ATTR_TYPE] = type;
1228 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1229 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1230 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1231 values += MONO_CUSTOM_ATTR_SIZE;
1237 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1239 MonoDynamicTable *table;
1241 guint32 count, i, idx;
1242 MonoReflectionPermissionSet *perm;
1247 count = mono_array_length (permissions);
1248 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1249 table->rows += count;
1250 alloc_table (table, table->rows);
1252 for (i = 0; i < mono_array_length (permissions); ++i) {
1253 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1255 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1257 idx = mono_metadata_token_index (parent_token);
1258 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1259 switch (mono_metadata_token_table (parent_token)) {
1260 case MONO_TABLE_TYPEDEF:
1261 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1263 case MONO_TABLE_METHOD:
1264 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1266 case MONO_TABLE_ASSEMBLY:
1267 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1270 g_assert_not_reached ();
1273 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1274 values [MONO_DECL_SECURITY_PARENT] = idx;
1275 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1282 * Fill in the MethodDef and ParamDef tables for a method.
1283 * This is used for both normal methods and constructors.
1286 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1288 MonoDynamicTable *table;
1292 /* room in this table is already allocated */
1293 table = &assembly->tables [MONO_TABLE_METHOD];
1294 *mb->table_idx = table->next_idx ++;
1295 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1296 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1297 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1298 values [MONO_METHOD_FLAGS] = mb->attrs;
1299 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1300 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1301 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1303 table = &assembly->tables [MONO_TABLE_PARAM];
1304 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1306 mono_image_add_decl_security (assembly,
1307 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1310 MonoDynamicTable *mtable;
1313 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1314 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1317 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1318 if (mono_array_get (mb->pinfo, gpointer, i))
1321 table->rows += count;
1322 alloc_table (table, table->rows);
1323 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1324 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1325 MonoReflectionParamBuilder *pb;
1326 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1327 values [MONO_PARAM_FLAGS] = pb->attrs;
1328 values [MONO_PARAM_SEQUENCE] = i;
1329 if (pb->name != NULL) {
1330 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1332 values [MONO_PARAM_NAME] = 0;
1334 values += MONO_PARAM_SIZE;
1335 if (pb->marshal_info) {
1337 alloc_table (mtable, mtable->rows);
1338 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1339 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1340 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1342 pb->table_idx = table->next_idx++;
1343 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1344 guint32 field_type = 0;
1345 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1347 alloc_table (mtable, mtable->rows);
1348 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1349 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1350 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1351 mvalues [MONO_CONSTANT_TYPE] = field_type;
1352 mvalues [MONO_CONSTANT_PADDING] = 0;
1360 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1362 rmb->ilgen = mb->ilgen;
1363 rmb->rtype = mb->rtype;
1364 rmb->parameters = mb->parameters;
1365 rmb->generic_params = mb->generic_params;
1366 rmb->generic_container = mb->generic_container;
1367 rmb->opt_types = NULL;
1368 rmb->pinfo = mb->pinfo;
1369 rmb->attrs = mb->attrs;
1370 rmb->iattrs = mb->iattrs;
1371 rmb->call_conv = mb->call_conv;
1372 rmb->code = mb->code;
1373 rmb->type = mb->type;
1374 rmb->name = mb->name;
1375 rmb->table_idx = &mb->table_idx;
1376 rmb->init_locals = mb->init_locals;
1377 rmb->return_modreq = mb->return_modreq;
1378 rmb->return_modopt = mb->return_modopt;
1379 rmb->param_modreq = mb->param_modreq;
1380 rmb->param_modopt = mb->param_modopt;
1381 rmb->permissions = mb->permissions;
1382 rmb->mhandle = mb->mhandle;
1387 rmb->charset = mb->charset;
1388 rmb->extra_flags = mb->extra_flags;
1389 rmb->native_cc = mb->native_cc;
1390 rmb->dllentry = mb->dllentry;
1396 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1398 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1400 rmb->ilgen = mb->ilgen;
1401 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1402 rmb->parameters = mb->parameters;
1403 rmb->generic_params = NULL;
1404 rmb->generic_container = NULL;
1405 rmb->opt_types = NULL;
1406 rmb->pinfo = mb->pinfo;
1407 rmb->attrs = mb->attrs;
1408 rmb->iattrs = mb->iattrs;
1409 rmb->call_conv = mb->call_conv;
1411 rmb->type = mb->type;
1412 rmb->name = mono_string_new (mono_domain_get (), name);
1413 rmb->table_idx = &mb->table_idx;
1414 rmb->init_locals = mb->init_locals;
1415 rmb->return_modreq = NULL;
1416 rmb->return_modopt = NULL;
1417 rmb->param_modreq = mb->param_modreq;
1418 rmb->param_modopt = mb->param_modopt;
1419 rmb->permissions = mb->permissions;
1420 rmb->mhandle = mb->mhandle;
1426 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1428 rmb->ilgen = mb->ilgen;
1429 rmb->rtype = mb->rtype;
1430 rmb->parameters = mb->parameters;
1431 rmb->generic_params = NULL;
1432 rmb->generic_container = NULL;
1433 rmb->opt_types = NULL;
1435 rmb->attrs = mb->attrs;
1437 rmb->call_conv = mb->call_conv;
1440 rmb->name = mb->name;
1441 rmb->table_idx = NULL;
1442 rmb->init_locals = mb->init_locals;
1443 rmb->skip_visibility = mb->skip_visibility;
1444 rmb->return_modreq = NULL;
1445 rmb->return_modopt = NULL;
1446 rmb->param_modreq = NULL;
1447 rmb->param_modopt = NULL;
1448 rmb->permissions = NULL;
1449 rmb->mhandle = mb->mhandle;
1455 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1457 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1458 MonoDynamicTable *table;
1462 if (!mb->override_method)
1465 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1467 alloc_table (table, table->rows);
1468 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1469 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1470 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1472 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1473 switch (mono_metadata_token_table (tok)) {
1474 case MONO_TABLE_MEMBERREF:
1475 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1477 case MONO_TABLE_METHOD:
1478 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1481 g_assert_not_reached ();
1483 values [MONO_METHODIMPL_DECLARATION] = tok;
1487 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1489 MonoDynamicTable *table;
1491 ReflectionMethodBuilder rmb;
1494 reflection_methodbuilder_from_method_builder (&rmb, mb);
1496 mono_image_basic_method (&rmb, assembly);
1497 mb->table_idx = *rmb.table_idx;
1499 if (mb->dll) { /* It's a P/Invoke method */
1501 /* map CharSet values to on-disk values */
1502 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1503 int extra_flags = mb->extra_flags;
1504 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1506 alloc_table (table, table->rows);
1507 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1509 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1510 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1512 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1514 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1515 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1516 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1517 table = &assembly->tables [MONO_TABLE_MODULEREF];
1519 alloc_table (table, table->rows);
1520 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1521 values [MONO_IMPLMAP_SCOPE] = table->rows;
1525 if (mb->generic_params) {
1526 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1527 table->rows += mono_array_length (mb->generic_params);
1528 alloc_table (table, table->rows);
1529 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1530 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1532 mono_image_get_generic_param_info (
1533 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1540 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1542 ReflectionMethodBuilder rmb;
1544 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1546 mono_image_basic_method (&rmb, assembly);
1547 mb->table_idx = *rmb.table_idx;
1551 type_get_fully_qualified_name (MonoType *type)
1553 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1557 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1561 klass = my_mono_class_from_mono_type (type);
1563 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1564 ta = klass->image->assembly;
1565 if (ta->dynamic || (ta == ass))
1566 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1568 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1572 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1577 if (!assembly->save)
1580 sigbuffer_init (&buf, 32);
1582 sigbuffer_add_value (&buf, 0x06);
1583 /* encode custom attributes before the type */
1584 encode_type (assembly, type, &buf);
1585 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1586 sigbuffer_free (&buf);
1591 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1596 sigbuffer_init (&buf, 32);
1598 sigbuffer_add_value (&buf, 0x06);
1599 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1600 /* encode custom attributes before the type */
1601 encode_reflection_type (assembly, fb->type, &buf);
1602 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1603 sigbuffer_free (&buf);
1608 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1609 char blob_size [64];
1610 char *b = blob_size;
1613 guint32 idx = 0, len = 0, dummy = 0;
1615 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1616 guint32 fpa_double [2];
1621 p = buf = g_malloc (64);
1623 *ret_type = MONO_TYPE_CLASS;
1625 box_val = (char*)&dummy;
1627 box_val = ((char*)val) + sizeof (MonoObject);
1628 *ret_type = val->vtable->klass->byval_arg.type;
1631 switch (*ret_type) {
1632 case MONO_TYPE_BOOLEAN:
1637 case MONO_TYPE_CHAR:
1654 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1655 fpa_p = (guint32*)box_val;
1656 fpa_double [0] = fpa_p [1];
1657 fpa_double [1] = fpa_p [0];
1658 box_val = (char*)fpa_double;
1662 case MONO_TYPE_VALUETYPE:
1663 if (val->vtable->klass->enumtype) {
1664 *ret_type = val->vtable->klass->enum_basetype->type;
1667 g_error ("we can't encode valuetypes");
1668 case MONO_TYPE_CLASS:
1670 case MONO_TYPE_STRING: {
1671 MonoString *str = (MonoString*)val;
1672 /* there is no signature */
1673 len = str->length * 2;
1674 mono_metadata_encode_value (len, b, &b);
1675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1677 char *swapped = g_malloc (2 * mono_string_length (str));
1678 const char *p = (const char*)mono_string_chars (str);
1680 swap_with_size (swapped, p, 2, mono_string_length (str));
1681 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1685 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1691 case MONO_TYPE_GENERICINST:
1692 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1695 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1698 /* there is no signature */
1699 mono_metadata_encode_value (len, b, &b);
1700 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1701 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1702 swap_with_size (blob_size, box_val, len, 1);
1703 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1705 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1713 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1718 sigbuffer_init (&buf, 32);
1720 sigbuffer_add_value (&buf, minfo->type);
1722 switch (minfo->type) {
1723 case MONO_NATIVE_BYVALTSTR:
1724 case MONO_NATIVE_BYVALARRAY:
1725 sigbuffer_add_value (&buf, minfo->count);
1727 case MONO_NATIVE_LPARRAY:
1728 if (minfo->eltype || minfo->has_size) {
1729 sigbuffer_add_value (&buf, minfo->eltype);
1730 if (minfo->has_size) {
1731 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1732 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1734 /* LAMESPEC: ElemMult is undocumented */
1735 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1739 case MONO_NATIVE_CUSTOM:
1741 str = mono_string_to_utf8 (minfo->guid);
1743 sigbuffer_add_value (&buf, len);
1744 sigbuffer_add_mem (&buf, str, len);
1747 sigbuffer_add_value (&buf, 0);
1749 /* native type name */
1750 sigbuffer_add_value (&buf, 0);
1751 /* custom marshaler type name */
1752 if (minfo->marshaltype || minfo->marshaltyperef) {
1753 if (minfo->marshaltyperef)
1754 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1756 str = mono_string_to_utf8 (minfo->marshaltype);
1758 sigbuffer_add_value (&buf, len);
1759 sigbuffer_add_mem (&buf, str, len);
1762 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1763 sigbuffer_add_value (&buf, 0);
1765 if (minfo->mcookie) {
1766 str = mono_string_to_utf8 (minfo->mcookie);
1768 sigbuffer_add_value (&buf, len);
1769 sigbuffer_add_mem (&buf, str, len);
1772 sigbuffer_add_value (&buf, 0);
1778 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1779 sigbuffer_free (&buf);
1784 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1786 MonoDynamicTable *table;
1789 /* maybe this fixup should be done in the C# code */
1790 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1791 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1792 table = &assembly->tables [MONO_TABLE_FIELD];
1793 fb->table_idx = table->next_idx ++;
1794 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1795 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1796 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1797 values [MONO_FIELD_FLAGS] = fb->attrs;
1798 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1800 if (fb->offset != -1) {
1801 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1803 alloc_table (table, table->rows);
1804 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1805 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1806 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1808 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1809 guint32 field_type = 0;
1810 table = &assembly->tables [MONO_TABLE_CONSTANT];
1812 alloc_table (table, table->rows);
1813 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1814 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1815 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1816 values [MONO_CONSTANT_TYPE] = field_type;
1817 values [MONO_CONSTANT_PADDING] = 0;
1819 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1821 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1823 alloc_table (table, table->rows);
1824 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1825 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1827 * We store it in the code section because it's simpler for now.
1830 if (mono_array_length (fb->rva_data) >= 10)
1831 stream_data_align (&assembly->code);
1832 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1834 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1835 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1837 if (fb->marshal_info) {
1838 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1840 alloc_table (table, table->rows);
1841 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1842 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1843 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1848 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1851 guint32 nparams = 0;
1852 MonoReflectionMethodBuilder *mb = fb->get_method;
1853 MonoReflectionMethodBuilder *smb = fb->set_method;
1856 if (mb && mb->parameters)
1857 nparams = mono_array_length (mb->parameters);
1858 if (!mb && smb && smb->parameters)
1859 nparams = mono_array_length (smb->parameters) - 1;
1860 sigbuffer_init (&buf, 32);
1861 sigbuffer_add_byte (&buf, 0x08);
1862 sigbuffer_add_value (&buf, nparams);
1864 encode_reflection_type (assembly, mb->rtype, &buf);
1865 for (i = 0; i < nparams; ++i) {
1866 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1867 encode_reflection_type (assembly, pt, &buf);
1869 } else if (smb && smb->parameters) {
1870 /* the property type is the last param */
1871 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1872 for (i = 0; i < nparams; ++i) {
1873 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1874 encode_reflection_type (assembly, pt, &buf);
1877 encode_reflection_type (assembly, fb->type, &buf);
1880 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1881 sigbuffer_free (&buf);
1886 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1888 MonoDynamicTable *table;
1890 guint num_methods = 0;
1894 * we need to set things in the following tables:
1895 * PROPERTYMAP (info already filled in _get_type_info ())
1896 * PROPERTY (rows already preallocated in _get_type_info ())
1897 * METHOD (method info already done with the generic method code)
1900 table = &assembly->tables [MONO_TABLE_PROPERTY];
1901 pb->table_idx = table->next_idx ++;
1902 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1903 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1904 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1905 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1907 /* FIXME: we still don't handle 'other' methods */
1908 if (pb->get_method) num_methods ++;
1909 if (pb->set_method) num_methods ++;
1911 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1912 table->rows += num_methods;
1913 alloc_table (table, table->rows);
1915 if (pb->get_method) {
1916 semaidx = table->next_idx ++;
1917 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1918 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1919 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1920 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1922 if (pb->set_method) {
1923 semaidx = table->next_idx ++;
1924 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1925 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1926 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1927 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1932 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1934 MonoDynamicTable *table;
1936 guint num_methods = 0;
1940 * we need to set things in the following tables:
1941 * EVENTMAP (info already filled in _get_type_info ())
1942 * EVENT (rows already preallocated in _get_type_info ())
1943 * METHOD (method info already done with the generic method code)
1946 table = &assembly->tables [MONO_TABLE_EVENT];
1947 eb->table_idx = table->next_idx ++;
1948 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1949 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1950 values [MONO_EVENT_FLAGS] = eb->attrs;
1951 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1954 * FIXME: we still don't handle 'other' methods
1956 if (eb->add_method) num_methods ++;
1957 if (eb->remove_method) num_methods ++;
1958 if (eb->raise_method) num_methods ++;
1960 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1961 table->rows += num_methods;
1962 alloc_table (table, table->rows);
1964 if (eb->add_method) {
1965 semaidx = table->next_idx ++;
1966 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1967 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1968 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1969 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1971 if (eb->remove_method) {
1972 semaidx = table->next_idx ++;
1973 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1974 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1975 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1976 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1978 if (eb->raise_method) {
1979 semaidx = table->next_idx ++;
1980 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1981 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1982 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1983 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1988 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1990 MonoDynamicTable *table;
1991 guint32 num_constraints, i;
1995 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1996 num_constraints = gparam->iface_constraints ?
1997 mono_array_length (gparam->iface_constraints) : 0;
1998 table->rows += num_constraints;
1999 if (gparam->base_type)
2001 alloc_table (table, table->rows);
2003 if (gparam->base_type) {
2004 table_idx = table->next_idx ++;
2005 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2007 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2008 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2009 assembly, gparam->base_type->type);
2012 for (i = 0; i < num_constraints; i++) {
2013 MonoReflectionType *constraint = mono_array_get (
2014 gparam->iface_constraints, gpointer, i);
2016 table_idx = table->next_idx ++;
2017 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2019 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2020 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2021 assembly, constraint->type);
2026 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2028 GenericParamTableEntry *entry;
2031 * The GenericParam table must be sorted according to the `owner' field.
2032 * We need to do this sorting prior to writing the GenericParamConstraint
2033 * table, since we have to use the final GenericParam table indices there
2034 * and they must also be sorted.
2037 entry = g_new0 (GenericParamTableEntry, 1);
2038 entry->owner = owner;
2040 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2041 MONO_GC_REGISTER_ROOT (entry->gparam);
2043 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2045 g_ptr_array_add (assembly->gen_params, entry);
2049 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2051 MonoDynamicTable *table;
2052 MonoGenericParam *param;
2056 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2057 table_idx = table->next_idx ++;
2058 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2060 param = entry->gparam->type.type->data.generic_param;
2062 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2063 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2064 values [MONO_GENERICPARAM_NUMBER] = param->num;
2065 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2067 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2069 encode_constraints (entry->gparam, table_idx, assembly);
2073 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2075 MonoDynamicTable *table;
2078 guint32 cols [MONO_ASSEMBLY_SIZE];
2082 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2085 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2086 table = &assembly->tables [MONO_TABLE_MODULEREF];
2087 token = table->next_idx ++;
2089 alloc_table (table, table->rows);
2090 values = table->values + token * MONO_MODULEREF_SIZE;
2091 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2093 token <<= MONO_RESOLTION_SCOPE_BITS;
2094 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2095 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2100 if (image->assembly->dynamic)
2102 memset (cols, 0, sizeof (cols));
2104 /* image->assembly->image is the manifest module */
2105 image = image->assembly->image;
2106 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2109 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2114 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2115 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2116 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2117 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2118 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2119 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2120 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2121 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2123 if (strcmp ("", image->assembly->aname.culture)) {
2124 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2125 image->assembly->aname.culture);
2128 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2129 guchar pubtoken [9];
2131 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2132 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2134 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2136 token <<= MONO_RESOLTION_SCOPE_BITS;
2137 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2138 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2143 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2145 MonoDynamicTable *table;
2150 sigbuffer_init (&buf, 32);
2151 switch (type->type) {
2152 case MONO_TYPE_FNPTR:
2154 case MONO_TYPE_SZARRAY:
2155 case MONO_TYPE_ARRAY:
2157 case MONO_TYPE_MVAR:
2158 case MONO_TYPE_GENERICINST:
2159 encode_type (assembly, type, &buf);
2161 case MONO_TYPE_CLASS:
2162 case MONO_TYPE_VALUETYPE: {
2163 MonoClass *k = mono_class_from_mono_type (type);
2164 if (!k || !k->generic_class) {
2165 sigbuffer_free (&buf);
2168 encode_generic_class (assembly, k->generic_class, &buf);
2172 sigbuffer_free (&buf);
2176 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2177 if (assembly->save) {
2178 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2179 alloc_table (table, table->rows + 1);
2180 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2181 values [MONO_TYPESPEC_SIGNATURE] = token;
2183 sigbuffer_free (&buf);
2185 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2186 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2192 * Despite the name, we handle also TypeSpec (with the above helper).
2195 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2197 MonoDynamicTable *table;
2199 guint32 token, scope, enclosing;
2202 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2205 token = create_typespec (assembly, type);
2208 klass = my_mono_class_from_mono_type (type);
2210 klass = mono_class_from_mono_type (type);
2213 * If it's in the same module and not a generic type parameter:
2215 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2216 (type->type != MONO_TYPE_MVAR)) {
2217 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2218 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2219 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2223 if (klass->nested_in) {
2224 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2225 /* get the typeref idx of the enclosing type */
2226 enclosing >>= MONO_TYPEDEFORREF_BITS;
2227 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2229 scope = resolution_scope_from_image (assembly, klass->image);
2231 table = &assembly->tables [MONO_TABLE_TYPEREF];
2232 if (assembly->save) {
2233 alloc_table (table, table->rows + 1);
2234 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2235 values [MONO_TYPEREF_SCOPE] = scope;
2236 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2237 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2239 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2240 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2247 * Insert a memberef row into the metadata: the token that point to the memberref
2248 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2249 * mono_image_get_fieldref_token()).
2250 * The sig param is an index to an already built signature.
2253 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2255 MonoDynamicTable *table;
2257 guint32 token, pclass;
2260 parent = mono_image_typedef_or_ref (assembly, type);
2261 switch (parent & MONO_TYPEDEFORREF_MASK) {
2262 case MONO_TYPEDEFORREF_TYPEREF:
2263 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2265 case MONO_TYPEDEFORREF_TYPESPEC:
2266 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2268 case MONO_TYPEDEFORREF_TYPEDEF:
2269 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2272 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2275 /* extract the index */
2276 parent >>= MONO_TYPEDEFORREF_BITS;
2278 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2280 if (assembly->save) {
2281 alloc_table (table, table->rows + 1);
2282 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2283 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2284 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2285 values [MONO_MEMBERREF_SIGNATURE] = sig;
2288 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2295 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2298 MonoMethodSignature *sig;
2300 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2305 * A methodref signature can't contain an unmanaged calling convention.
2307 sig = mono_metadata_signature_dup (mono_method_signature (method));
2308 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2309 sig->call_convention = MONO_CALL_DEFAULT;
2310 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2311 method->name, method_encode_signature (assembly, sig));
2313 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2318 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2319 const gchar *name, guint32 sig)
2321 MonoDynamicTable *table;
2325 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2327 if (assembly->save) {
2328 alloc_table (table, table->rows + 1);
2329 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2330 values [MONO_MEMBERREF_CLASS] = original;
2331 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2332 values [MONO_MEMBERREF_SIGNATURE] = sig;
2335 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2342 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2345 ReflectionMethodBuilder rmb;
2347 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2351 reflection_methodbuilder_from_method_builder (&rmb, mb);
2353 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2354 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2355 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2360 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2363 ReflectionMethodBuilder rmb;
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2369 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2371 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2372 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2373 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2378 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2383 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2386 g_assert (f->field->parent);
2387 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2388 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2389 f->field->name, fieldref_encode_signature (assembly, type));
2390 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2395 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2399 guint32 nparams = context->method_inst->type_argc;
2402 if (!assembly->save)
2405 sigbuffer_init (&buf, 32);
2407 * FIXME: vararg, explicit_this, differenc call_conv values...
2409 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2410 sigbuffer_add_value (&buf, nparams);
2412 for (i = 0; i < nparams; i++)
2413 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2415 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2416 sigbuffer_free (&buf);
2421 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2423 MonoDynamicTable *table;
2425 guint32 token, mtoken = 0, sig;
2426 MonoMethodInflated *imethod;
2427 MonoMethod *declaring;
2429 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2431 g_assert (method->is_inflated);
2432 g_assert (!method->klass->generic_container);
2433 imethod = (MonoMethodInflated *) method;
2434 declaring = imethod->declaring;
2436 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2437 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2439 if (!mono_method_signature (declaring)->generic_param_count)
2442 switch (mono_metadata_token_table (mtoken)) {
2443 case MONO_TABLE_MEMBERREF:
2444 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2446 case MONO_TABLE_METHOD:
2447 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2450 g_assert_not_reached ();
2453 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2455 if (assembly->save) {
2456 alloc_table (table, table->rows + 1);
2457 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2458 values [MONO_METHODSPEC_METHOD] = mtoken;
2459 values [MONO_METHODSPEC_SIGNATURE] = sig;
2462 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2469 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2471 MonoMethodInflated *imethod;
2474 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2478 g_assert (method->is_inflated);
2479 imethod = (MonoMethodInflated *) method;
2481 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2482 token = method_encode_methodspec (assembly, method);
2484 guint32 sig = method_encode_signature (
2485 assembly, mono_method_signature (imethod->declaring));
2486 token = mono_image_get_memberref_token (
2487 assembly, &method->klass->byval_arg, method->name, sig);
2490 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2495 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2497 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2500 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2501 token = mono_image_get_memberref_token (
2502 assembly, &m->klass->byval_arg, m->name, sig);
2508 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2510 MonoDynamicTable *table;
2518 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2519 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2520 * Because of this, we must not insert it into the `typeref' hash table.
2523 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2527 sigbuffer_init (&buf, 32);
2529 g_assert (tb->generic_params);
2530 klass = mono_class_from_mono_type (tb->type.type);
2532 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2533 encode_type (assembly, &klass->byval_arg, &buf);
2535 count = mono_array_length (tb->generic_params);
2536 sigbuffer_add_value (&buf, count);
2537 for (i = 0; i < count; i++) {
2538 MonoReflectionGenericParam *gparam;
2540 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2542 encode_type (assembly, gparam->type.type, &buf);
2545 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2547 if (assembly->save) {
2548 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2549 alloc_table (table, table->rows + 1);
2550 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2551 values [MONO_TYPESPEC_SIGNATURE] = token;
2553 sigbuffer_free (&buf);
2555 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2556 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2562 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2564 MonoDynamicTable *table;
2567 guint32 token, pclass, parent, sig;
2570 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2574 klass = mono_class_from_mono_type (fb->typeb->type);
2575 name = mono_string_to_utf8 (fb->name);
2577 sig = fieldref_encode_signature (assembly, fb->type->type);
2579 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2580 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2582 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2583 parent >>= MONO_TYPEDEFORREF_BITS;
2585 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2587 if (assembly->save) {
2588 alloc_table (table, table->rows + 1);
2589 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2590 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2591 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2592 values [MONO_MEMBERREF_SIGNATURE] = sig;
2595 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2597 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2602 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2609 if (!assembly->save)
2613 g_assert (helper->type == 2);
2615 if (helper->arguments)
2616 nargs = mono_array_length (helper->arguments);
2620 size = 10 + (nargs * 10);
2622 sigbuffer_init (&buf, 32);
2624 /* Encode calling convention */
2625 /* Change Any to Standard */
2626 if ((helper->call_conv & 0x03) == 0x03)
2627 helper->call_conv = 0x01;
2628 /* explicit_this implies has_this */
2629 if (helper->call_conv & 0x40)
2630 helper->call_conv &= 0x20;
2632 if (helper->call_conv == 0) { /* Unmanaged */
2633 idx = helper->unmanaged_call_conv - 1;
2636 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2637 if (helper->call_conv & 0x02) /* varargs */
2641 sigbuffer_add_byte (&buf, idx);
2642 sigbuffer_add_value (&buf, nargs);
2643 encode_reflection_type (assembly, helper->return_type, &buf);
2644 for (i = 0; i < nargs; ++i) {
2645 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2646 encode_reflection_type (assembly, pt, &buf);
2648 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2649 sigbuffer_free (&buf);
2655 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2658 MonoDynamicTable *table;
2661 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2662 idx = table->next_idx ++;
2664 alloc_table (table, table->rows);
2665 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2667 values [MONO_STAND_ALONE_SIGNATURE] =
2668 mono_reflection_encode_sighelper (assembly, helper);
2674 reflection_cc_to_file (int call_conv) {
2675 switch (call_conv & 0x3) {
2677 case 1: return MONO_CALL_DEFAULT;
2678 case 2: return MONO_CALL_VARARG;
2680 g_assert_not_reached ();
2687 MonoMethodSignature *sig;
2693 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2698 MonoMethodSignature *sig;
2701 name = mono_string_to_utf8 (m->name);
2702 nparams = mono_array_length (m->parameters);
2703 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2705 sig->sentinelpos = -1;
2706 sig->call_convention = reflection_cc_to_file (m->call_conv);
2707 sig->param_count = nparams;
2708 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2709 for (i = 0; i < nparams; ++i) {
2710 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2711 sig->params [i] = t->type;
2714 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2716 if (strcmp (name, am->name) == 0 &&
2717 mono_metadata_type_equal (am->parent, m->parent->type) &&
2718 mono_metadata_signature_equal (am->sig, sig)) {
2721 m->table_idx = am->token & 0xffffff;
2725 am = g_new0 (ArrayMethod, 1);
2728 am->parent = m->parent->type;
2729 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2730 method_encode_signature (assembly, sig));
2731 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2732 m->table_idx = am->token & 0xffffff;
2737 * Insert into the metadata tables all the info about the TypeBuilder tb.
2738 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2741 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2743 MonoDynamicTable *table;
2745 int i, is_object = 0, is_system = 0;
2748 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2749 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2750 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2751 n = mono_string_to_utf8 (tb->name);
2752 if (strcmp (n, "Object") == 0)
2754 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2756 n = mono_string_to_utf8 (tb->nspace);
2757 if (strcmp (n, "System") == 0)
2759 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2761 if (tb->parent && !(is_system && is_object) &&
2762 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2763 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2765 values [MONO_TYPEDEF_EXTENDS] = 0;
2767 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2768 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2771 * if we have explicitlayout or sequentiallayouts, output data in the
2772 * ClassLayout table.
2774 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2775 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2776 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2778 alloc_table (table, table->rows);
2779 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2780 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2781 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2782 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2785 /* handle interfaces */
2786 if (tb->interfaces) {
2787 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2789 table->rows += mono_array_length (tb->interfaces);
2790 alloc_table (table, table->rows);
2791 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2792 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2793 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2794 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2795 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2796 values += MONO_INTERFACEIMPL_SIZE;
2802 table = &assembly->tables [MONO_TABLE_FIELD];
2803 table->rows += tb->num_fields;
2804 alloc_table (table, table->rows);
2805 for (i = 0; i < tb->num_fields; ++i)
2806 mono_image_get_field_info (
2807 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2810 /* handle constructors */
2812 table = &assembly->tables [MONO_TABLE_METHOD];
2813 table->rows += mono_array_length (tb->ctors);
2814 alloc_table (table, table->rows);
2815 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2816 mono_image_get_ctor_info (domain,
2817 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2820 /* handle methods */
2822 table = &assembly->tables [MONO_TABLE_METHOD];
2823 table->rows += tb->num_methods;
2824 alloc_table (table, table->rows);
2825 for (i = 0; i < tb->num_methods; ++i)
2826 mono_image_get_method_info (
2827 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2830 /* Do the same with properties etc.. */
2831 if (tb->events && mono_array_length (tb->events)) {
2832 table = &assembly->tables [MONO_TABLE_EVENT];
2833 table->rows += mono_array_length (tb->events);
2834 alloc_table (table, table->rows);
2835 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2837 alloc_table (table, table->rows);
2838 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2839 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2840 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2841 for (i = 0; i < mono_array_length (tb->events); ++i)
2842 mono_image_get_event_info (
2843 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2845 if (tb->properties && mono_array_length (tb->properties)) {
2846 table = &assembly->tables [MONO_TABLE_PROPERTY];
2847 table->rows += mono_array_length (tb->properties);
2848 alloc_table (table, table->rows);
2849 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2851 alloc_table (table, table->rows);
2852 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2853 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2854 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2855 for (i = 0; i < mono_array_length (tb->properties); ++i)
2856 mono_image_get_property_info (
2857 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2860 /* handle generic parameters */
2861 if (tb->generic_params) {
2862 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2863 table->rows += mono_array_length (tb->generic_params);
2864 alloc_table (table, table->rows);
2865 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2866 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2868 mono_image_get_generic_param_info (
2869 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2873 mono_image_add_decl_security (assembly,
2874 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2877 MonoDynamicTable *ntable;
2879 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2880 ntable->rows += mono_array_length (tb->subtypes);
2881 alloc_table (ntable, ntable->rows);
2882 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2884 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2885 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2887 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2888 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2889 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2890 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2891 mono_string_to_utf8 (tb->name), tb->table_idx,
2892 ntable->next_idx, ntable->rows);*/
2893 values += MONO_NESTED_CLASS_SIZE;
2900 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2904 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2906 if (!type->subtypes)
2909 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2910 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2911 collect_types (types, subtype);
2916 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2918 if ((*type1)->table_idx < (*type2)->table_idx)
2921 if ((*type1)->table_idx > (*type2)->table_idx)
2928 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2933 for (i = 0; i < mono_array_length (pinfo); ++i) {
2934 MonoReflectionParamBuilder *pb;
2935 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2938 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2943 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2946 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2948 for (i = 0; i < tb->num_fields; ++i) {
2949 MonoReflectionFieldBuilder* fb;
2950 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2951 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2955 for (i = 0; i < mono_array_length (tb->events); ++i) {
2956 MonoReflectionEventBuilder* eb;
2957 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2958 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2961 if (tb->properties) {
2962 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2963 MonoReflectionPropertyBuilder* pb;
2964 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2965 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2969 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2970 MonoReflectionCtorBuilder* cb;
2971 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2972 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2973 params_add_cattrs (assembly, cb->pinfo);
2978 for (i = 0; i < tb->num_methods; ++i) {
2979 MonoReflectionMethodBuilder* mb;
2980 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2981 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2982 params_add_cattrs (assembly, mb->pinfo);
2987 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2988 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2993 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
2997 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
2999 if (moduleb->global_methods) {
3000 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3001 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3002 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3003 params_add_cattrs (assembly, mb->pinfo);
3007 if (moduleb->global_fields) {
3008 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3009 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3010 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3014 if (moduleb->types) {
3015 for (i = 0; i < moduleb->num_types; ++i)
3016 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3021 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3023 MonoDynamicTable *table;
3027 char *b = blob_size;
3030 table = &assembly->tables [MONO_TABLE_FILE];
3032 alloc_table (table, table->rows);
3033 values = table->values + table->next_idx * MONO_FILE_SIZE;
3034 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3035 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3036 if (module->image->dynamic) {
3037 /* This depends on the fact that the main module is emitted last */
3038 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3039 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3042 path = g_strdup (module->image->name);
3044 mono_sha1_get_digest_from_file (path, hash);
3047 mono_metadata_encode_value (20, b, &b);
3048 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3049 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3054 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3056 MonoDynamicTable *table;
3059 table = &assembly->tables [MONO_TABLE_MODULE];
3060 mb->table_idx = table->next_idx ++;
3061 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3062 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3065 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3066 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3067 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3068 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3072 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3073 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3079 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3080 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3083 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3085 alloc_table (table, table->rows);
3086 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3088 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3089 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3090 if (klass->nested_in)
3091 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3093 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3094 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3095 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3097 res = table->next_idx;
3101 /* Emit nested types */
3102 if (klass->nested_classes) {
3105 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3106 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3113 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3114 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3119 klass = mono_class_from_mono_type (tb->type.type);
3121 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3123 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3124 parent_index, assembly);
3128 * We need to do this ourselves since klass->nested_classes is not set up.
3131 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3132 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3137 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3138 guint32 module_index, MonoDynamicImage *assembly)
3140 MonoImage *image = module->image;
3144 t = &image->tables [MONO_TABLE_TYPEDEF];
3146 for (i = 0; i < t->rows; ++i) {
3147 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3149 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3150 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3155 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3157 MonoDynamicTable *table;
3163 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3165 if (assemblyb->type_forwarders) {
3166 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3167 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3173 klass = mono_class_from_mono_type (t->type);
3175 scope = resolution_scope_from_image (assembly, klass->image);
3176 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3177 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3180 alloc_table (table, table->rows);
3181 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3183 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3184 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3185 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3186 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3187 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3192 #define align_pointer(base,p)\
3194 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3196 (p) += 4 - (__diff & 3);\
3200 compare_constants (const void *a, const void *b)
3202 const guint32 *a_values = a;
3203 const guint32 *b_values = b;
3204 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3208 compare_semantics (const void *a, const void *b)
3210 const guint32 *a_values = a;
3211 const guint32 *b_values = b;
3212 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3215 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3219 compare_custom_attrs (const void *a, const void *b)
3221 const guint32 *a_values = a;
3222 const guint32 *b_values = b;
3224 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3228 compare_field_marshal (const void *a, const void *b)
3230 const guint32 *a_values = a;
3231 const guint32 *b_values = b;
3233 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3237 compare_nested (const void *a, const void *b)
3239 const guint32 *a_values = a;
3240 const guint32 *b_values = b;
3242 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3246 compare_genericparam (const void *a, const void *b)
3248 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3249 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3251 if ((*b_entry)->owner == (*a_entry)->owner)
3253 (*a_entry)->gparam->type.type->data.generic_param->num -
3254 (*b_entry)->gparam->type.type->data.generic_param->num;
3256 return (*a_entry)->owner - (*b_entry)->owner;
3260 compare_declsecurity_attrs (const void *a, const void *b)
3262 const guint32 *a_values = a;
3263 const guint32 *b_values = b;
3265 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3269 pad_heap (MonoDynamicStream *sh)
3271 if (sh->index & 3) {
3272 int sz = 4 - (sh->index & 3);
3273 memset (sh->data + sh->index, 0, sz);
3280 MonoDynamicStream *stream;
3284 * build_compressed_metadata() fills in the blob of data that represents the
3285 * raw metadata as it will be saved in the PE file. The five streams are output
3286 * and the metadata tables are comnpressed from the guint32 array representation,
3287 * to the compressed on-disk format.
3290 build_compressed_metadata (MonoDynamicImage *assembly)
3292 MonoDynamicTable *table;
3294 guint64 valid_mask = 0;
3295 guint64 sorted_mask;
3296 guint32 heapt_size = 0;
3297 guint32 meta_size = 256; /* allow for header and other stuff */
3298 guint32 table_offset;
3299 guint32 ntables = 0;
3305 struct StreamDesc stream_desc [5];
3307 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3308 for (i = 0; i < assembly->gen_params->len; i++){
3309 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3310 write_generic_param_entry (assembly, entry);
3313 stream_desc [0].name = "#~";
3314 stream_desc [0].stream = &assembly->tstream;
3315 stream_desc [1].name = "#Strings";
3316 stream_desc [1].stream = &assembly->sheap;
3317 stream_desc [2].name = "#US";
3318 stream_desc [2].stream = &assembly->us;
3319 stream_desc [3].name = "#Blob";
3320 stream_desc [3].stream = &assembly->blob;
3321 stream_desc [4].name = "#GUID";
3322 stream_desc [4].stream = &assembly->guid;
3324 /* tables that are sorted */
3325 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3326 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3327 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3328 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3329 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3330 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3332 /* Compute table sizes */
3333 /* the MonoImage has already been created in mono_image_basic_init() */
3334 meta = &assembly->image;
3336 /* sizes should be multiple of 4 */
3337 pad_heap (&assembly->blob);
3338 pad_heap (&assembly->guid);
3339 pad_heap (&assembly->sheap);
3340 pad_heap (&assembly->us);
3342 /* Setup the info used by compute_sizes () */
3343 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3344 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3345 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3347 meta_size += assembly->blob.index;
3348 meta_size += assembly->guid.index;
3349 meta_size += assembly->sheap.index;
3350 meta_size += assembly->us.index;
3352 for (i=0; i < MONO_TABLE_NUM; ++i)
3353 meta->tables [i].rows = assembly->tables [i].rows;
3355 for (i = 0; i < MONO_TABLE_NUM; i++){
3356 if (meta->tables [i].rows == 0)
3358 valid_mask |= (guint64)1 << i;
3360 meta->tables [i].row_size = mono_metadata_compute_size (
3361 meta, i, &meta->tables [i].size_bitfield);
3362 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3364 heapt_size += 24; /* #~ header size */
3365 heapt_size += ntables * 4;
3366 /* make multiple of 4 */
3369 meta_size += heapt_size;
3370 meta->raw_metadata = g_malloc0 (meta_size);
3371 p = (unsigned char*)meta->raw_metadata;
3372 /* the metadata signature */
3373 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3374 /* version numbers and 4 bytes reserved */
3375 int16val = (guint16*)p;
3376 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3377 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3379 /* version string */
3380 int32val = (guint32*)p;
3381 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3383 memcpy (p, meta->version, strlen (meta->version));
3384 p += GUINT32_FROM_LE (*int32val);
3385 align_pointer (meta->raw_metadata, p);
3386 int16val = (guint16*)p;
3387 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3388 *int16val = GUINT16_TO_LE (5); /* number of streams */
3392 * write the stream info.
3394 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3395 table_offset += 3; table_offset &= ~3;
3397 assembly->tstream.index = heapt_size;
3398 for (i = 0; i < 5; ++i) {
3399 int32val = (guint32*)p;
3400 stream_desc [i].stream->offset = table_offset;
3401 *int32val++ = GUINT32_TO_LE (table_offset);
3402 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3403 table_offset += GUINT32_FROM_LE (*int32val);
3404 table_offset += 3; table_offset &= ~3;
3406 strcpy ((char*)p, stream_desc [i].name);
3407 p += strlen (stream_desc [i].name) + 1;
3408 align_pointer (meta->raw_metadata, p);
3411 * now copy the data, the table stream header and contents goes first.
3413 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3414 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3415 int32val = (guint32*)p;
3416 *int32val = GUINT32_TO_LE (0); /* reserved */
3419 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3420 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3421 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3422 *p++ = 2; /* version */
3425 *p++ = 1; /* version */
3429 if (meta->idx_string_wide)
3431 if (meta->idx_guid_wide)
3433 if (meta->idx_blob_wide)
3436 *p++ = 1; /* reserved */
3437 int64val = (guint64*)p;
3438 *int64val++ = GUINT64_TO_LE (valid_mask);
3439 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3441 int32val = (guint32*)p;
3442 for (i = 0; i < MONO_TABLE_NUM; i++){
3443 if (meta->tables [i].rows == 0)
3445 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3447 p = (unsigned char*)int32val;
3449 /* sort the tables that still need sorting */
3450 table = &assembly->tables [MONO_TABLE_CONSTANT];
3452 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3453 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3455 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3456 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3458 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3459 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3461 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3462 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3464 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3465 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3466 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3468 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3470 /* compress the tables */
3471 for (i = 0; i < MONO_TABLE_NUM; i++){
3474 guint32 bitfield = meta->tables [i].size_bitfield;
3475 if (!meta->tables [i].rows)
3477 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3478 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3479 meta->tables [i].base = (char*)p;
3480 for (row = 1; row <= meta->tables [i].rows; ++row) {
3481 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3482 for (col = 0; col < assembly->tables [i].columns; ++col) {
3483 switch (mono_metadata_table_size (bitfield, col)) {
3485 *p++ = values [col];
3488 *p++ = values [col] & 0xff;
3489 *p++ = (values [col] >> 8) & 0xff;
3492 *p++ = values [col] & 0xff;
3493 *p++ = (values [col] >> 8) & 0xff;
3494 *p++ = (values [col] >> 16) & 0xff;
3495 *p++ = (values [col] >> 24) & 0xff;
3498 g_assert_not_reached ();
3502 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3505 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3506 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3507 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3508 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3509 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3511 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3515 * Some tables in metadata need to be sorted according to some criteria, but
3516 * when methods and fields are first created with reflection, they may be assigned a token
3517 * that doesn't correspond to the final token they will get assigned after the sorting.
3518 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3519 * with the reflection objects that represent them. Once all the tables are set up, the
3520 * reflection objects will contains the correct table index. fixup_method() will fixup the
3521 * tokens for the method with ILGenerator @ilgen.
3524 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3525 guint32 code_idx = GPOINTER_TO_UINT (value);
3526 MonoReflectionILTokenInfo *iltoken;
3527 MonoReflectionFieldBuilder *field;
3528 MonoReflectionCtorBuilder *ctor;
3529 MonoReflectionMethodBuilder *method;
3530 MonoReflectionTypeBuilder *tb;
3531 MonoReflectionArrayMethod *am;
3533 unsigned char *target;
3535 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3536 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3537 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3538 switch (target [3]) {
3539 case MONO_TABLE_FIELD:
3540 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3541 field = (MonoReflectionFieldBuilder *)iltoken->member;
3542 idx = field->table_idx;
3543 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3544 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3545 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3547 g_assert_not_reached ();
3550 case MONO_TABLE_METHOD:
3551 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3552 method = (MonoReflectionMethodBuilder *)iltoken->member;
3553 idx = method->table_idx;
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3555 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3556 idx = ctor->table_idx;
3557 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3558 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3559 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3560 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3562 g_assert_not_reached ();
3565 case MONO_TABLE_TYPEDEF:
3566 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3567 g_assert_not_reached ();
3568 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3569 idx = tb->table_idx;
3571 case MONO_TABLE_MEMBERREF:
3572 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3573 am = (MonoReflectionArrayMethod*)iltoken->member;
3574 idx = am->table_idx;
3575 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3576 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3577 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3578 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3579 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3580 g_assert (m->klass->generic_class || m->klass->generic_container);
3582 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3584 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3585 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3586 g_assert (f->generic_info);
3588 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3591 g_assert_not_reached ();
3594 case MONO_TABLE_METHODSPEC:
3595 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3596 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3597 g_assert (mono_method_signature (m)->generic_param_count);
3600 g_assert_not_reached ();
3604 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3606 target [0] = idx & 0xff;
3607 target [1] = (idx >> 8) & 0xff;
3608 target [2] = (idx >> 16) & 0xff;
3615 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3616 * value is not known when the table is emitted.
3619 fixup_cattrs (MonoDynamicImage *assembly)
3621 MonoDynamicTable *table;
3623 guint32 type, i, idx, token;
3626 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3628 for (i = 0; i < table->rows; ++i) {
3629 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3631 type = values [MONO_CUSTOM_ATTR_TYPE];
3632 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3633 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3634 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3635 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3638 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3639 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3640 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3641 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3648 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3650 MonoDynamicTable *table;
3653 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3655 alloc_table (table, table->rows);
3656 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3657 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3658 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3659 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3660 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3665 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3667 MonoDynamicTable *table;
3671 char *b = blob_size;
3673 guint32 idx, offset;
3675 if (rsrc->filename) {
3676 name = mono_string_to_utf8 (rsrc->filename);
3677 sname = g_path_get_basename (name);
3679 table = &assembly->tables [MONO_TABLE_FILE];
3681 alloc_table (table, table->rows);
3682 values = table->values + table->next_idx * MONO_FILE_SIZE;
3683 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3684 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3687 mono_sha1_get_digest_from_file (name, hash);
3688 mono_metadata_encode_value (20, b, &b);
3689 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3690 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3692 idx = table->next_idx++;
3694 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3700 data = mono_array_addr (rsrc->data, char, 0);
3701 len = mono_array_length (rsrc->data);
3707 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3708 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3709 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3710 mono_image_add_stream_data (&assembly->resources, data, len);
3714 * The entry should be emitted into the MANIFESTRESOURCE table of
3715 * the main module, but that needs to reference the FILE table
3716 * which isn't emitted yet.
3723 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3727 set_version_from_string (MonoString *version, guint32 *values)
3729 gchar *ver, *p, *str;
3732 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3733 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3734 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3735 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3738 ver = str = mono_string_to_utf8 (version);
3739 for (i = 0; i < 4; ++i) {
3740 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3746 /* handle Revision and Build */
3756 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3760 char *b = blob_size;
3765 len = mono_array_length (pkey);
3766 mono_metadata_encode_value (len, b, &b);
3767 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3768 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3770 /* Special case: check for ECMA key (16 bytes) */
3771 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3772 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3773 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3774 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3775 /* minimum key size (in 2.0) is 384 bits */
3776 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3778 /* FIXME - verifier */
3779 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3780 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3782 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3788 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3790 MonoDynamicTable *table;
3791 MonoDynamicImage *assembly;
3792 MonoReflectionAssemblyBuilder *assemblyb;
3796 guint32 module_index;
3798 assemblyb = moduleb->assemblyb;
3799 assembly = moduleb->dynamic_image;
3800 domain = mono_object_domain (assemblyb);
3802 /* Emit ASSEMBLY table */
3803 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3804 alloc_table (table, 1);
3805 values = table->values + MONO_ASSEMBLY_SIZE;
3806 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3807 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3808 if (assemblyb->culture) {
3809 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3811 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3813 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3814 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3815 set_version_from_string (assemblyb->version, values);
3817 /* Emit FILE + EXPORTED_TYPE table */
3819 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3821 MonoReflectionModuleBuilder *file_module =
3822 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3823 if (file_module != moduleb) {
3824 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3826 if (file_module->types) {
3827 for (j = 0; j < file_module->num_types; ++j) {
3828 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3829 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3834 if (assemblyb->loaded_modules) {
3835 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3836 MonoReflectionModule *file_module =
3837 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3838 mono_image_fill_file_table (domain, file_module, assembly);
3840 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3843 if (assemblyb->type_forwarders)
3844 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3846 /* Emit MANIFESTRESOURCE table */
3848 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3850 MonoReflectionModuleBuilder *file_module =
3851 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3852 /* The table for the main module is emitted later */
3853 if (file_module != moduleb) {
3855 if (file_module->resources) {
3856 int len = mono_array_length (file_module->resources);
3857 for (j = 0; j < len; ++j) {
3858 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3859 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3867 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3868 * for the modulebuilder @moduleb.
3869 * At the end of the process, method and field tokens are fixed up and the
3870 * on-disk compressed metadata representation is created.
3873 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3875 MonoDynamicTable *table;
3876 MonoDynamicImage *assembly;
3877 MonoReflectionAssemblyBuilder *assemblyb;
3883 assemblyb = moduleb->assemblyb;
3884 assembly = moduleb->dynamic_image;
3885 domain = mono_object_domain (assemblyb);
3887 if (assembly->text_rva)
3890 assembly->text_rva = START_TEXT_RVA;
3892 if (moduleb->is_main) {
3893 mono_image_emit_manifest (moduleb);
3896 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3897 table->rows = 1; /* .<Module> */
3899 alloc_table (table, table->rows);
3901 * Set the first entry.
3903 values = table->values + table->columns;
3904 values [MONO_TYPEDEF_FLAGS] = 0;
3905 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3906 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3907 values [MONO_TYPEDEF_EXTENDS] = 0;
3908 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3909 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3912 * handle global methods
3913 * FIXME: test what to do when global methods are defined in multiple modules.
3915 if (moduleb->global_methods) {
3916 table = &assembly->tables [MONO_TABLE_METHOD];
3917 table->rows += mono_array_length (moduleb->global_methods);
3918 alloc_table (table, table->rows);
3919 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3920 mono_image_get_method_info (
3921 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3923 if (moduleb->global_fields) {
3924 table = &assembly->tables [MONO_TABLE_FIELD];
3925 table->rows += mono_array_length (moduleb->global_fields);
3926 alloc_table (table, table->rows);
3927 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3928 mono_image_get_field_info (
3929 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3932 table = &assembly->tables [MONO_TABLE_MODULE];
3933 alloc_table (table, 1);
3934 mono_image_fill_module_table (domain, moduleb, assembly);
3936 /* Collect all types into a list sorted by their table_idx */
3937 types = g_ptr_array_new ();
3940 for (i = 0; i < moduleb->num_types; ++i) {
3941 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3942 collect_types (types, type);
3945 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3946 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3947 table->rows += types->len;
3948 alloc_table (table, table->rows);
3951 * Emit type names + namespaces at one place inside the string heap,
3952 * so load_class_names () needs to touch fewer pages.
3954 for (i = 0; i < types->len; ++i) {
3955 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3956 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3958 for (i = 0; i < types->len; ++i) {
3959 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3960 string_heap_insert_mstring (&assembly->sheap, tb->name);
3963 for (i = 0; i < types->len; ++i) {
3964 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3965 mono_image_get_type_info (domain, type, assembly);
3969 * table->rows is already set above and in mono_image_fill_module_table.
3971 /* add all the custom attributes at the end, once all the indexes are stable */
3972 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3974 /* CAS assembly permissions */
3975 if (assemblyb->permissions_minimum)
3976 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3977 if (assemblyb->permissions_optional)
3978 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3979 if (assemblyb->permissions_refused)
3980 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3982 module_add_cattrs (assembly, moduleb);
3985 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3987 /* Create the MethodImpl table. We do this after emitting all methods so we already know
3988 * the final tokens and don't need another fixup pass. */
3990 if (moduleb->global_methods) {
3991 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3992 MonoReflectionMethodBuilder *mb = mono_array_get (
3993 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3994 mono_image_add_methodimpl (assembly, mb);
3998 for (i = 0; i < types->len; ++i) {
3999 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4000 if (type->methods) {
4001 for (j = 0; j < type->num_methods; ++j) {
4002 MonoReflectionMethodBuilder *mb = mono_array_get (
4003 type->methods, MonoReflectionMethodBuilder*, j);
4005 mono_image_add_methodimpl (assembly, mb);
4010 g_ptr_array_free (types, TRUE);
4012 fixup_cattrs (assembly);
4016 * mono_image_insert_string:
4017 * @module: module builder object
4020 * Insert @str into the user string stream of @module.
4023 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4025 MonoDynamicImage *assembly;
4030 MONO_ARCH_SAVE_REGS;
4032 if (!module->dynamic_image)
4033 mono_image_module_basic_init (module);
4035 assembly = module->dynamic_image;
4037 if (assembly->save) {
4038 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4039 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4040 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4042 char *swapped = g_malloc (2 * mono_string_length (str));
4043 const char *p = (const char*)mono_string_chars (str);
4045 swap_with_size (swapped, p, 2, mono_string_length (str));
4046 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4050 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4052 mono_image_add_stream_data (&assembly->us, "", 1);
4054 idx = assembly->us.index ++;
4057 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4059 return MONO_TOKEN_STRING | idx;
4063 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4068 klass = obj->vtable->klass;
4069 if (strcmp (klass->name, "MonoMethod") == 0) {
4070 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4071 MonoMethodSignature *sig, *old;
4072 guint32 sig_token, parent;
4075 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4077 nargs = mono_array_length (opt_param_types);
4078 old = mono_method_signature (method);
4079 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4081 sig->hasthis = old->hasthis;
4082 sig->explicit_this = old->explicit_this;
4083 sig->call_convention = old->call_convention;
4084 sig->generic_param_count = old->generic_param_count;
4085 sig->param_count = old->param_count + nargs;
4086 sig->sentinelpos = old->param_count;
4087 sig->ret = old->ret;
4089 for (i = 0; i < old->param_count; i++)
4090 sig->params [i] = old->params [i];
4092 for (i = 0; i < nargs; i++) {
4093 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4094 sig->params [old->param_count + i] = rt->type;
4097 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4098 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4099 parent >>= MONO_TYPEDEFORREF_BITS;
4101 parent <<= MONO_MEMBERREF_PARENT_BITS;
4102 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4104 sig_token = method_encode_signature (assembly, sig);
4105 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4106 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4107 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4108 ReflectionMethodBuilder rmb;
4109 guint32 parent, sig;
4111 reflection_methodbuilder_from_method_builder (&rmb, mb);
4112 rmb.opt_types = opt_param_types;
4114 sig = method_builder_encode_signature (assembly, &rmb);
4116 parent = mono_image_create_token (assembly, obj, TRUE);
4117 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4119 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4120 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4122 token = mono_image_get_varargs_method_token (
4123 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4125 g_error ("requested method token for %s\n", klass->name);
4132 * mono_image_create_token:
4133 * @assembly: a dynamic assembly
4136 * Get a token to insert in the IL code stream for the given MemberInfo.
4137 * @obj can be one of:
4138 * ConstructorBuilder
4148 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4153 klass = obj->vtable->klass;
4154 if (strcmp (klass->name, "MethodBuilder") == 0) {
4155 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4157 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4158 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4160 token = mono_image_get_methodbuilder_token (assembly, mb);
4161 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4162 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4163 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4165 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4166 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4168 token = mono_image_get_ctorbuilder_token (assembly, mb);
4169 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4170 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4171 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4172 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4173 if (tb->generic_params) {
4174 token = mono_image_get_generic_field_token (assembly, fb);
4176 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4178 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4179 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4180 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4181 } else if (strcmp (klass->name, "MonoType") == 0 ||
4182 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4183 MonoReflectionType *tb = (MonoReflectionType *)obj;
4184 token = mono_metadata_token_from_dor (
4185 mono_image_typedef_or_ref (assembly, tb->type));
4186 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4187 MonoReflectionType *tb = (MonoReflectionType *)obj;
4188 token = mono_metadata_token_from_dor (
4189 mono_image_typedef_or_ref (assembly, tb->type));
4190 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4191 strcmp (klass->name, "MonoMethod") == 0 ||
4192 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4193 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4194 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4195 if (m->method->is_inflated) {
4196 if (create_methodspec)
4197 token = mono_image_get_methodspec_token (assembly, m->method);
4199 token = mono_image_get_inflated_method_token (assembly, m->method);
4200 } else if ((m->method->klass->image == &assembly->image) &&
4201 !m->method->klass->generic_class) {
4202 static guint32 method_table_idx = 0xffffff;
4203 if (m->method->klass->wastypebuilder) {
4204 /* we use the same token as the one that was assigned
4205 * to the Methodbuilder.
4206 * FIXME: do the equivalent for Fields.
4208 token = m->method->token;
4211 * Each token should have a unique index, but the indexes are
4212 * assigned by managed code, so we don't know about them. An
4213 * easy solution is to count backwards...
4215 method_table_idx --;
4216 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4219 token = mono_image_get_methodref_token (assembly, m->method);
4221 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4222 } else if (strcmp (klass->name, "MonoField") == 0) {
4223 MonoReflectionField *f = (MonoReflectionField *)obj;
4224 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4225 static guint32 field_table_idx = 0xffffff;
4227 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4229 token = mono_image_get_fieldref_token (assembly, f);
4231 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4232 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4233 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4234 token = mono_image_get_array_token (assembly, m);
4235 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4236 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4237 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4238 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4239 MonoReflectionType *tb = (MonoReflectionType *)obj;
4240 token = mono_metadata_token_from_dor (
4241 mono_image_typedef_or_ref (assembly, tb->type));
4243 g_error ("requested token for %s\n", klass->name);
4246 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4252 guint32 import_lookup_table;
4256 guint32 import_address_table_rva;
4264 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4266 static MonoDynamicImage*
4267 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4269 static const guchar entrycode [16] = {0xff, 0x25, 0};
4270 MonoDynamicImage *image;
4273 const char *version = mono_get_runtime_info ()->runtime_version;
4276 image = GC_MALLOC (sizeof (MonoDynamicImage));
4278 image = g_new0 (MonoDynamicImage, 1);
4281 /*g_print ("created image %p\n", image);*/
4282 /* keep in sync with image.c */
4283 image->image.name = assembly_name;
4284 image->image.assembly_name = image->image.name; /* they may be different */
4285 image->image.module_name = module_name;
4286 image->image.version = g_strdup (version);
4287 image->image.md_version_major = 1;
4288 image->image.md_version_minor = 1;
4289 image->image.dynamic = TRUE;
4291 image->image.references = g_new0 (MonoAssembly*, 1);
4292 image->image.references [0] = NULL;
4294 mono_image_init (&image->image);
4296 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4297 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4298 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4299 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4300 image->handleref = g_hash_table_new (NULL, NULL);
4301 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4302 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4303 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4304 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4305 image->gen_params = g_ptr_array_new ();
4307 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4308 string_heap_init (&image->sheap);
4309 mono_image_add_stream_data (&image->us, "", 1);
4310 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4311 /* import tables... */
4312 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4313 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4314 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4315 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4316 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4317 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4318 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4319 stream_data_align (&image->code);
4321 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4323 for (i=0; i < MONO_TABLE_NUM; ++i) {
4324 image->tables [i].next_idx = 1;
4325 image->tables [i].columns = table_sizes [i];
4328 image->image.assembly = (MonoAssembly*)assembly;
4329 image->run = assembly->run;
4330 image->save = assembly->save;
4331 image->pe_kind = 0x1; /* ILOnly */
4332 image->machine = 0x14c; /* I386 */
4338 * mono_image_basic_init:
4339 * @assembly: an assembly builder object
4341 * Create the MonoImage that represents the assembly builder and setup some
4342 * of the helper hash table and the basic metadata streams.
4345 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4347 MonoDynamicAssembly *assembly;
4348 MonoDynamicImage *image;
4349 MonoDomain *domain = mono_object_domain (assemblyb);
4351 MONO_ARCH_SAVE_REGS;
4353 if (assemblyb->dynamic_assembly)
4357 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4359 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4362 assembly->assembly.ref_count = 1;
4363 assembly->assembly.dynamic = TRUE;
4364 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4365 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4366 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4367 if (assemblyb->culture)
4368 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4370 assembly->assembly.aname.culture = g_strdup ("");
4372 if (assemblyb->version) {
4373 char *vstr = mono_string_to_utf8 (assemblyb->version);
4374 char **version = g_strsplit (vstr, ".", 4);
4375 char **parts = version;
4376 assembly->assembly.aname.major = atoi (*parts++);
4377 assembly->assembly.aname.minor = atoi (*parts++);
4378 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4379 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4381 g_strfreev (version);
4384 assembly->assembly.aname.major = 0;
4385 assembly->assembly.aname.minor = 0;
4386 assembly->assembly.aname.build = 0;
4387 assembly->assembly.aname.revision = 0;
4390 assembly->run = assemblyb->access != 2;
4391 assembly->save = assemblyb->access != 1;
4393 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4394 image->initial_image = TRUE;
4395 assembly->assembly.aname.name = image->image.name;
4396 assembly->assembly.image = &image->image;
4398 mono_domain_assemblies_lock (domain);
4399 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4400 mono_domain_assemblies_unlock (domain);
4402 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4403 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4407 calc_section_size (MonoDynamicImage *assembly)
4411 /* alignment constraints */
4412 assembly->code.index += 3;
4413 assembly->code.index &= ~3;
4414 assembly->meta_size += 3;
4415 assembly->meta_size &= ~3;
4416 assembly->resources.index += 3;
4417 assembly->resources.index &= ~3;
4419 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4420 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4423 if (assembly->win32_res) {
4424 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4426 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4427 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4431 assembly->sections [MONO_SECTION_RELOC].size = 12;
4432 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4442 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4446 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4448 ResTreeNode *t1 = (ResTreeNode*)a;
4449 ResTreeNode *t2 = (ResTreeNode*)b;
4451 return t1->id - t2->id;
4455 * resource_tree_create:
4457 * Organize the resources into a resource tree.
4459 static ResTreeNode *
4460 resource_tree_create (MonoArray *win32_resources)
4462 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4466 tree = g_new0 (ResTreeNode, 1);
4468 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4469 MonoReflectionWin32Resource *win32_res =
4470 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4474 /* FIXME: BUG: this stores managed references in unmanaged memory */
4475 lang_node = g_new0 (ResTreeNode, 1);
4476 lang_node->id = win32_res->lang_id;
4477 lang_node->win32_res = win32_res;
4479 /* Create type node if neccesary */
4481 for (l = tree->children; l; l = l->next)
4482 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4483 type_node = (ResTreeNode*)l->data;
4488 type_node = g_new0 (ResTreeNode, 1);
4489 type_node->id = win32_res->res_type;
4492 * The resource types have to be sorted otherwise
4493 * Windows Explorer can't display the version information.
4495 tree->children = g_slist_insert_sorted (tree->children,
4496 type_node, resource_tree_compare_by_id);
4499 /* Create res node if neccesary */
4501 for (l = type_node->children; l; l = l->next)
4502 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4503 res_node = (ResTreeNode*)l->data;
4508 res_node = g_new0 (ResTreeNode, 1);
4509 res_node->id = win32_res->res_id;
4510 type_node->children = g_slist_append (type_node->children, res_node);
4513 res_node->children = g_slist_append (res_node->children, lang_node);
4520 * resource_tree_encode:
4522 * Encode the resource tree into the format used in the PE file.
4525 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4528 MonoPEResourceDir dir;
4529 MonoPEResourceDirEntry dir_entry;
4530 MonoPEResourceDataEntry data_entry;
4534 * For the format of the resource directory, see the article
4535 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4539 memset (&dir, 0, sizeof (dir));
4540 memset (&dir_entry, 0, sizeof (dir_entry));
4541 memset (&data_entry, 0, sizeof (data_entry));
4543 g_assert (sizeof (dir) == 16);
4544 g_assert (sizeof (dir_entry) == 8);
4545 g_assert (sizeof (data_entry) == 16);
4547 node->offset = p - begin;
4549 /* IMAGE_RESOURCE_DIRECTORY */
4550 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4552 memcpy (p, &dir, sizeof (dir));
4555 /* Reserve space for entries */
4557 p += sizeof (dir_entry) * dir.res_id_entries;
4559 /* Write children */
4560 for (l = node->children; l; l = l->next) {
4561 ResTreeNode *child = (ResTreeNode*)l->data;
4563 if (child->win32_res) {
4565 child->offset = p - begin;
4567 /* IMAGE_RESOURCE_DATA_ENTRY */
4568 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4569 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4571 memcpy (p, &data_entry, sizeof (data_entry));
4572 p += sizeof (data_entry);
4574 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4575 p += data_entry.rde_size;
4577 resource_tree_encode (child, begin, p, &p);
4581 /* IMAGE_RESOURCE_ENTRY */
4582 for (l = node->children; l; l = l->next) {
4583 ResTreeNode *child = (ResTreeNode*)l->data;
4584 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4586 dir_entry.is_dir = child->win32_res ? 0 : 1;
4587 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4589 memcpy (entries, &dir_entry, sizeof (dir_entry));
4590 entries += sizeof (dir_entry);
4597 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4602 MonoReflectionWin32Resource *win32_res;
4605 if (!assemblyb->win32_resources)
4609 * Resources are stored in a three level tree inside the PE file.
4610 * - level one contains a node for each type of resource
4611 * - level two contains a node for each resource
4612 * - level three contains a node for each instance of a resource for a
4613 * specific language.
4616 tree = resource_tree_create (assemblyb->win32_resources);
4618 /* Estimate the size of the encoded tree */
4620 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4621 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4622 size += mono_array_length (win32_res->res_data);
4624 /* Directory structure */
4625 size += mono_array_length (assemblyb->win32_resources) * 256;
4626 p = buf = g_malloc (size);
4628 resource_tree_encode (tree, p, p, &p);
4630 g_assert (p - buf <= size);
4632 assembly->win32_res = g_malloc (p - buf);
4633 assembly->win32_res_size = p - buf;
4634 memcpy (assembly->win32_res, buf, p - buf);
4640 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4642 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4645 p += sizeof (MonoPEResourceDir);
4646 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4647 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4648 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4649 if (dir_entry->is_dir) {
4650 fixup_resource_directory (res_section, child, rva);
4652 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4653 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4656 p += sizeof (MonoPEResourceDirEntry);
4661 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4664 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4665 g_error ("WriteFile returned %d\n", GetLastError ());
4669 * mono_image_create_pefile:
4670 * @mb: a module builder object
4672 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4673 * assembly->pefile where it can be easily retrieved later in chunks.
4676 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4677 MonoMSDOSHeader *msdos;
4678 MonoDotNetHeader *header;
4679 MonoSectionTable *section;
4680 MonoCLIHeader *cli_header;
4681 guint32 size, image_size, virtual_base, text_offset;
4682 guint32 header_start, section_start, file_offset, virtual_offset;
4683 MonoDynamicImage *assembly;
4684 MonoReflectionAssemblyBuilder *assemblyb;
4685 MonoDynamicStream pefile_stream = {0};
4686 MonoDynamicStream *pefile = &pefile_stream;
4688 guint32 *rva, value;
4690 static const unsigned char msheader[] = {
4691 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4692 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4695 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4696 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4697 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4698 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4701 assemblyb = mb->assemblyb;
4703 mono_image_basic_init (assemblyb);
4704 assembly = mb->dynamic_image;
4706 assembly->pe_kind = assemblyb->pe_kind;
4707 assembly->machine = assemblyb->machine;
4708 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4709 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4711 mono_image_build_metadata (mb);
4713 if (mb->is_main && assemblyb->resources) {
4714 int len = mono_array_length (assemblyb->resources);
4715 for (i = 0; i < len; ++i)
4716 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4719 if (mb->resources) {
4720 int len = mono_array_length (mb->resources);
4721 for (i = 0; i < len; ++i)
4722 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4725 build_compressed_metadata (assembly);
4728 assembly_add_win32_resources (assembly, assemblyb);
4730 nsections = calc_section_size (assembly);
4732 /* The DOS header and stub */
4733 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4734 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4736 /* the dotnet header */
4737 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4739 /* the section tables */
4740 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4742 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4743 virtual_offset = VIRT_ALIGN;
4746 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4747 if (!assembly->sections [i].size)
4750 file_offset += FILE_ALIGN - 1;
4751 file_offset &= ~(FILE_ALIGN - 1);
4752 virtual_offset += VIRT_ALIGN - 1;
4753 virtual_offset &= ~(VIRT_ALIGN - 1);
4755 assembly->sections [i].offset = file_offset;
4756 assembly->sections [i].rva = virtual_offset;
4758 file_offset += assembly->sections [i].size;
4759 virtual_offset += assembly->sections [i].size;
4760 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4763 file_offset += FILE_ALIGN - 1;
4764 file_offset &= ~(FILE_ALIGN - 1);
4766 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4768 /* back-patch info */
4769 msdos = (MonoMSDOSHeader*)pefile->data;
4770 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4772 header = (MonoDotNetHeader*)(pefile->data + header_start);
4773 header->pesig [0] = 'P';
4774 header->pesig [1] = 'E';
4776 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4777 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4778 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4779 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4780 if (assemblyb->pekind == 1) {
4782 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4785 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4788 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4790 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4791 header->pe.pe_major = 6;
4792 header->pe.pe_minor = 0;
4793 size = assembly->sections [MONO_SECTION_TEXT].size;
4794 size += FILE_ALIGN - 1;
4795 size &= ~(FILE_ALIGN - 1);
4796 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4797 size = assembly->sections [MONO_SECTION_RSRC].size;
4798 size += FILE_ALIGN - 1;
4799 size &= ~(FILE_ALIGN - 1);
4800 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4801 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4802 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4803 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4804 /* pe_rva_entry_point always at the beginning of the text section */
4805 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4807 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4808 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4809 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4810 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4811 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4812 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4813 size = section_start;
4814 size += FILE_ALIGN - 1;
4815 size &= ~(FILE_ALIGN - 1);
4816 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4818 size += VIRT_ALIGN - 1;
4819 size &= ~(VIRT_ALIGN - 1);
4820 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4823 // Translate the PEFileKind value to the value expected by the Windows loader
4829 // PEFileKinds.Dll == 1
4830 // PEFileKinds.ConsoleApplication == 2
4831 // PEFileKinds.WindowApplication == 3
4834 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4835 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4837 if (assemblyb->pekind == 3)
4842 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4844 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4845 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4846 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4847 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4848 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4849 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4851 /* fill data directory entries */
4853 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4854 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4856 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4857 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4859 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4860 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4861 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4862 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4863 /* patch entrypoint name */
4864 if (assemblyb->pekind == 1)
4865 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4867 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4868 /* patch imported function RVA name */
4869 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4870 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4872 /* the import table */
4873 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4874 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4875 /* patch imported dll RVA name and other entries in the dir */
4876 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4877 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4878 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4879 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4880 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4881 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4883 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4884 value = (assembly->text_rva + assembly->imp_names_offset);
4885 *p++ = (value) & 0xff;
4886 *p++ = (value >> 8) & (0xff);
4887 *p++ = (value >> 16) & (0xff);
4888 *p++ = (value >> 24) & (0xff);
4890 /* the CLI header info */
4891 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4892 cli_header->ch_size = GUINT32_FROM_LE (72);
4893 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4894 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4895 if (assemblyb->entry_point) {
4896 guint32 table_idx = 0;
4897 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4898 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4899 table_idx = methodb->table_idx;
4901 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4903 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4905 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4907 /* The embedded managed resources */
4908 text_offset = assembly->text_rva + assembly->code.index;
4909 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4910 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4911 text_offset += assembly->resources.index;
4912 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4913 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4914 text_offset += assembly->meta_size;
4915 if (assembly->strong_name_size) {
4916 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4917 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4918 text_offset += assembly->strong_name_size;
4921 /* write the section tables and section content */
4922 section = (MonoSectionTable*)(pefile->data + section_start);
4923 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4924 static const char section_names [][7] = {
4925 ".text", ".rsrc", ".reloc"
4927 if (!assembly->sections [i].size)
4929 strcpy (section->st_name, section_names [i]);
4930 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4931 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4932 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4933 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4934 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4935 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4936 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4940 checked_write_file (file, pefile->data, pefile->index);
4942 mono_dynamic_stream_reset (pefile);
4944 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4945 if (!assembly->sections [i].size)
4948 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4949 g_error ("SetFilePointer returned %d\n", GetLastError ());
4952 case MONO_SECTION_TEXT:
4953 /* patch entry point */
4954 p = (guchar*)(assembly->code.data + 2);
4955 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4956 *p++ = (value) & 0xff;
4957 *p++ = (value >> 8) & 0xff;
4958 *p++ = (value >> 16) & 0xff;
4959 *p++ = (value >> 24) & 0xff;
4961 checked_write_file (file, assembly->code.data, assembly->code.index);
4962 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4963 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4964 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4967 g_free (assembly->image.raw_metadata);
4969 case MONO_SECTION_RELOC: {
4973 guint16 type_and_offset;
4977 g_assert (sizeof (reloc) == 12);
4979 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4980 reloc.block_size = GUINT32_FROM_LE (12);
4983 * the entrypoint is always at the start of the text section
4984 * 3 is IMAGE_REL_BASED_HIGHLOW
4985 * 2 is patch_size_rva - text_rva
4987 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4990 checked_write_file (file, &reloc, sizeof (reloc));
4994 case MONO_SECTION_RSRC:
4995 if (assembly->win32_res) {
4997 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4998 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4999 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5003 g_assert_not_reached ();
5007 /* check that the file is properly padded */
5008 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5009 g_error ("SetFilePointer returned %d\n", GetLastError ());
5010 if (! SetEndOfFile (file))
5011 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5013 mono_dynamic_stream_reset (&assembly->code);
5014 mono_dynamic_stream_reset (&assembly->us);
5015 mono_dynamic_stream_reset (&assembly->blob);
5016 mono_dynamic_stream_reset (&assembly->guid);
5017 mono_dynamic_stream_reset (&assembly->sheap);
5019 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5020 g_hash_table_destroy (assembly->blob_cache);
5021 assembly->blob_cache = NULL;
5024 MonoReflectionModule *
5025 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5029 MonoImageOpenStatus status;
5030 MonoDynamicAssembly *assembly;
5031 guint32 module_count;
5032 MonoImage **new_modules;
5033 gboolean *new_modules_loaded;
5035 name = mono_string_to_utf8 (fileName);
5037 image = mono_image_open (name, &status);
5040 if (status == MONO_IMAGE_ERROR_ERRNO)
5041 exc = mono_get_exception_file_not_found (fileName);
5043 exc = mono_get_exception_bad_image_format (name);
5045 mono_raise_exception (exc);
5050 assembly = ab->dynamic_assembly;
5051 image->assembly = (MonoAssembly*)assembly;
5053 module_count = image->assembly->image->module_count;
5054 new_modules = g_new0 (MonoImage *, module_count + 1);
5055 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5057 if (image->assembly->image->modules)
5058 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5059 if (image->assembly->image->modules_loaded)
5060 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5061 new_modules [module_count] = image;
5062 new_modules_loaded [module_count] = TRUE;
5063 mono_image_addref (image);
5065 g_free (image->assembly->image->modules);
5066 image->assembly->image->modules = new_modules;
5067 image->assembly->image->modules_loaded = new_modules_loaded;
5068 image->assembly->image->module_count ++;
5070 mono_assembly_load_references (image, &status);
5072 mono_image_close (image);
5073 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5076 return mono_module_get_object (mono_domain_get (), image);
5080 * We need to return always the same object for MethodInfo, FieldInfo etc..
5081 * but we need to consider the reflected type.
5082 * type uses a different hash, since it uses custom hash/equal functions.
5087 MonoClass *refclass;
5091 reflected_equal (gconstpointer a, gconstpointer b) {
5092 const ReflectedEntry *ea = a;
5093 const ReflectedEntry *eb = b;
5095 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5099 reflected_hash (gconstpointer a) {
5100 const ReflectedEntry *ea = a;
5101 return mono_aligned_addr_hash (ea->item);
5104 #define CHECK_OBJECT(t,p,k) \
5110 mono_domain_lock (domain); \
5111 if (!domain->refobject_hash) \
5112 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5113 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5114 mono_domain_unlock (domain); \
5117 mono_domain_unlock (domain); \
5121 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5123 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5125 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5128 #define CACHE_OBJECT(t,p,o,k) \
5131 ReflectedEntry pe; \
5133 pe.refclass = (k); \
5134 mono_domain_lock (domain); \
5135 if (!domain->refobject_hash) \
5136 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5137 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5139 ReflectedEntry *e = ALLOC_REFENTRY; \
5141 e->refclass = (k); \
5142 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5145 mono_domain_unlock (domain); \
5150 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5152 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5156 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5158 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5162 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5164 MonoDynamicImage *image = moduleb->dynamic_image;
5165 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5168 MonoImage **new_modules;
5171 * FIXME: we already created an image in mono_image_basic_init (), but
5172 * we don't know which module it belongs to, since that is only
5173 * determined at assembly save time.
5175 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5176 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5178 moduleb->module.image = &image->image;
5179 moduleb->dynamic_image = image;
5180 register_module (mono_object_domain (moduleb), moduleb, image);
5182 /* register the module with the assembly */
5183 ass = ab->dynamic_assembly->assembly.image;
5184 module_count = ass->module_count;
5185 new_modules = g_new0 (MonoImage *, module_count + 1);
5188 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5189 new_modules [module_count] = &image->image;
5190 mono_image_addref (&image->image);
5192 g_free (ass->modules);
5193 ass->modules = new_modules;
5194 ass->module_count ++;
5199 * mono_assembly_get_object:
5200 * @domain: an app domain
5201 * @assembly: an assembly
5203 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5205 MonoReflectionAssembly*
5206 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5208 static MonoClass *System_Reflection_Assembly;
5209 MonoReflectionAssembly *res;
5211 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5212 if (!System_Reflection_Assembly)
5213 System_Reflection_Assembly = mono_class_from_name (
5214 mono_defaults.corlib, "System.Reflection", "Assembly");
5215 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5216 res->assembly = assembly;
5218 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5223 MonoReflectionModule*
5224 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5226 static MonoClass *System_Reflection_Module;
5227 MonoReflectionModule *res;
5230 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5231 if (!System_Reflection_Module)
5232 System_Reflection_Module = mono_class_from_name (
5233 mono_defaults.corlib, "System.Reflection", "Module");
5234 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5237 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5239 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5240 basename = g_path_get_basename (image->name);
5241 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5242 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5246 if (image->assembly->image == image) {
5247 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5251 if (image->assembly->image->modules) {
5252 for (i = 0; i < image->assembly->image->module_count; i++) {
5253 if (image->assembly->image->modules [i] == image)
5254 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5256 g_assert (res->token);
5260 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5263 MonoReflectionModule*
5264 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5266 static MonoClass *System_Reflection_Module;
5267 MonoReflectionModule *res;
5268 MonoTableInfo *table;
5269 guint32 cols [MONO_FILE_SIZE];
5271 guint32 i, name_idx;
5274 if (!System_Reflection_Module)
5275 System_Reflection_Module = mono_class_from_name (
5276 mono_defaults.corlib, "System.Reflection", "Module");
5277 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5279 table = &image->tables [MONO_TABLE_FILE];
5280 g_assert (table_index < table->rows);
5281 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5284 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5285 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5287 /* Check whenever the row has a corresponding row in the moduleref table */
5288 table = &image->tables [MONO_TABLE_MODULEREF];
5289 for (i = 0; i < table->rows; ++i) {
5290 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5291 val = mono_metadata_string_heap (image, name_idx);
5292 if (strcmp (val, name) == 0)
5293 res->image = image->modules [i];
5296 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5297 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5298 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5299 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5300 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5306 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5308 if ((t1->type != t2->type) ||
5309 (t1->byref != t2->byref))
5313 case MONO_TYPE_VOID:
5314 case MONO_TYPE_BOOLEAN:
5315 case MONO_TYPE_CHAR:
5326 case MONO_TYPE_STRING:
5329 case MONO_TYPE_OBJECT:
5330 case MONO_TYPE_TYPEDBYREF:
5332 case MONO_TYPE_VALUETYPE:
5333 case MONO_TYPE_CLASS:
5334 case MONO_TYPE_SZARRAY:
5335 return t1->data.klass == t2->data.klass;
5337 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5338 case MONO_TYPE_ARRAY:
5339 if (t1->data.array->rank != t2->data.array->rank)
5341 return t1->data.array->eklass == t2->data.array->eklass;
5342 case MONO_TYPE_GENERICINST: {
5344 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5345 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5346 if (i1->type_argc != i2->type_argc)
5348 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5349 &t2->data.generic_class->container_class->byval_arg))
5351 /* FIXME: we should probably just compare the instance pointers directly. */
5352 for (i = 0; i < i1->type_argc; ++i) {
5353 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5359 case MONO_TYPE_MVAR:
5360 return t1->data.generic_param == t2->data.generic_param;
5362 g_error ("implement type compare for %0x!", t1->type);
5370 mymono_metadata_type_hash (MonoType *t1)
5376 hash |= t1->byref << 6; /* do not collide with t1->type values */
5378 case MONO_TYPE_VALUETYPE:
5379 case MONO_TYPE_CLASS:
5380 case MONO_TYPE_SZARRAY:
5381 /* check if the distribution is good enough */
5382 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5384 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5385 case MONO_TYPE_GENERICINST: {
5387 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5388 hash += g_str_hash (t1->data.generic_class->container_class->name);
5390 for (i = 0; i < inst->type_argc; ++i) {
5391 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5400 static MonoReflectionGenericClass*
5401 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5403 static MonoClass *System_Reflection_MonoGenericClass;
5404 MonoReflectionGenericClass *res;
5405 MonoClass *klass, *gklass;
5407 if (!System_Reflection_MonoGenericClass) {
5408 System_Reflection_MonoGenericClass = mono_class_from_name (
5409 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5410 g_assert (System_Reflection_MonoGenericClass);
5413 klass = mono_class_from_mono_type (geninst);
5414 gklass = klass->generic_class->container_class;
5416 mono_class_init (klass);
5419 /* FIXME: allow unpinned later */
5420 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5422 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5425 res->type.type = geninst;
5426 if (gklass->wastypebuilder && gklass->reflection_info)
5427 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5429 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5435 verify_safe_for_managed_space (MonoType *type)
5437 switch (type->type) {
5439 case MONO_TYPE_ARRAY:
5440 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5442 return verify_safe_for_managed_space (type->data.type);
5443 case MONO_TYPE_SZARRAY:
5444 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5445 case MONO_TYPE_GENERICINST: {
5446 MonoGenericInst *inst = type->data.generic_class->inst;
5450 for (i = 0; i < inst->type_argc; ++i)
5451 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5457 case MONO_TYPE_MVAR:
5464 * mono_type_get_object:
5465 * @domain: an app domain
5468 * Return an System.MonoType object representing the type @type.
5471 mono_type_get_object (MonoDomain *domain, MonoType *type)
5473 MonoReflectionType *res;
5474 MonoClass *klass = mono_class_from_mono_type (type);
5476 mono_domain_lock (domain);
5477 if (!domain->type_hash)
5478 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5479 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5480 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5481 mono_domain_unlock (domain);
5484 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5485 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5486 mono_g_hash_table_insert (domain->type_hash, type, res);
5487 mono_domain_unlock (domain);
5491 if (!verify_safe_for_managed_space (type)) {
5492 mono_domain_unlock (domain);
5493 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5496 if (klass->reflection_info && !klass->wastypebuilder) {
5497 /* g_assert_not_reached (); */
5498 /* should this be considered an error condition? */
5500 mono_domain_unlock (domain);
5501 return klass->reflection_info;
5504 mono_class_init (klass);
5506 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5508 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5511 mono_g_hash_table_insert (domain->type_hash, type, res);
5512 mono_domain_unlock (domain);
5517 * mono_method_get_object:
5518 * @domain: an app domain
5520 * @refclass: the reflected type (can be NULL)
5522 * Return an System.Reflection.MonoMethod object representing the method @method.
5524 MonoReflectionMethod*
5525 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5528 * We use the same C representation for methods and constructors, but the type
5529 * name in C# is different.
5531 static MonoClass *System_Reflection_MonoMethod = NULL;
5532 static MonoClass *System_Reflection_MonoCMethod = NULL;
5533 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5534 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5536 MonoReflectionMethod *ret;
5538 if (method->is_inflated) {
5539 MonoReflectionGenericMethod *gret;
5541 refclass = method->klass;
5542 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5543 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5544 if (!System_Reflection_MonoGenericCMethod)
5545 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5546 klass = System_Reflection_MonoGenericCMethod;
5548 if (!System_Reflection_MonoGenericMethod)
5549 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5550 klass = System_Reflection_MonoGenericMethod;
5552 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5553 gret->method.method = method;
5554 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5555 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5556 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5560 refclass = method->klass;
5562 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5563 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5564 if (!System_Reflection_MonoCMethod)
5565 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5566 klass = System_Reflection_MonoCMethod;
5569 if (!System_Reflection_MonoMethod)
5570 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5571 klass = System_Reflection_MonoMethod;
5573 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5574 ret->method = method;
5575 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5576 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5577 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5581 * mono_field_get_object:
5582 * @domain: an app domain
5586 * Return an System.Reflection.MonoField object representing the field @field
5589 MonoReflectionField*
5590 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5592 MonoReflectionField *res;
5593 static MonoClass *monofield_klass;
5595 CHECK_OBJECT (MonoReflectionField *, field, klass);
5596 if (!monofield_klass)
5597 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5598 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5601 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5602 if (field->generic_info)
5603 res->attrs = field->generic_info->generic_type->attrs;
5605 res->attrs = field->type->attrs;
5606 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5607 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5611 * mono_property_get_object:
5612 * @domain: an app domain
5614 * @property: a property
5616 * Return an System.Reflection.MonoProperty object representing the property @property
5619 MonoReflectionProperty*
5620 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5622 MonoReflectionProperty *res;
5623 static MonoClass *monoproperty_klass;
5625 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5626 if (!monoproperty_klass)
5627 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5628 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5630 res->property = property;
5631 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5635 * mono_event_get_object:
5636 * @domain: an app domain
5640 * Return an System.Reflection.MonoEvent object representing the event @event
5643 MonoReflectionEvent*
5644 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5646 MonoReflectionEvent *res;
5647 static MonoClass *monoevent_klass;
5649 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5650 if (!monoevent_klass)
5651 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5652 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5655 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5659 * mono_param_get_objects:
5660 * @domain: an app domain
5663 * Return an System.Reflection.ParameterInfo array object representing the parameters
5664 * in the method @method.
5667 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5669 static MonoClass *System_Reflection_ParameterInfo;
5670 MonoArray *res = NULL;
5671 MonoReflectionMethod *member = NULL;
5672 MonoReflectionParameter *param = NULL;
5673 char **names, **blobs = NULL;
5674 guint32 *types = NULL;
5675 MonoType *type = NULL;
5676 MonoObject *dbnull = mono_get_dbnull_object (domain);
5677 MonoMarshalSpec **mspecs;
5678 MonoMethodSignature *sig;
5681 if (!System_Reflection_ParameterInfo)
5682 System_Reflection_ParameterInfo = mono_class_from_name (
5683 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5685 if (!mono_method_signature (method)->param_count)
5686 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5688 /* Note: the cache is based on the address of the signature into the method
5689 * since we already cache MethodInfos with the method as keys.
5691 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5693 sig = mono_method_signature (method);
5694 member = mono_method_get_object (domain, method, NULL);
5695 names = g_new (char *, sig->param_count);
5696 mono_method_get_param_names (method, (const char **) names);
5698 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5699 mono_method_get_marshal_info (method, mspecs);
5701 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5702 for (i = 0; i < sig->param_count; ++i) {
5703 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5704 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5705 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5706 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5707 param->PositionImpl = i;
5708 param->AttrsImpl = sig->params [i]->attrs;
5710 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5711 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5715 blobs = g_new0 (char *, sig->param_count);
5716 types = g_new0 (guint32, sig->param_count);
5717 get_default_param_value_blobs (method, blobs, types);
5720 /* Build MonoType for the type from the Constant Table */
5722 type = g_new0 (MonoType, 1);
5723 type->type = types [i];
5724 type->data.klass = NULL;
5725 if (types [i] == MONO_TYPE_CLASS)
5726 type->data.klass = mono_defaults.object_class;
5727 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5728 /* For enums, types [i] contains the base type */
5730 type->type = MONO_TYPE_VALUETYPE;
5731 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5733 type->data.klass = mono_class_from_mono_type (type);
5735 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5737 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5738 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5739 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5744 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5746 mono_array_setref (res, i, param);
5753 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5755 mono_metadata_free_marshal_spec (mspecs [i]);
5758 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5762 * mono_method_body_get_object:
5763 * @domain: an app domain
5766 * Return an System.Reflection.MethodBody object representing the method @method.
5768 MonoReflectionMethodBody*
5769 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5771 static MonoClass *System_Reflection_MethodBody = NULL;
5772 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5773 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5774 MonoReflectionMethodBody *ret;
5775 MonoMethodNormal *mn;
5776 MonoMethodHeader *header;
5777 guint32 method_rva, local_var_sig_token;
5779 unsigned char format, flags;
5782 if (!System_Reflection_MethodBody)
5783 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5784 if (!System_Reflection_LocalVariableInfo)
5785 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5786 if (!System_Reflection_ExceptionHandlingClause)
5787 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5789 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5791 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5792 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5793 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5794 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5796 mn = (MonoMethodNormal *)method;
5797 header = mono_method_get_header (method);
5799 /* Obtain local vars signature token */
5800 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5801 ptr = mono_image_rva_map (method->klass->image, method_rva);
5802 flags = *(const unsigned char *) ptr;
5803 format = flags & METHOD_HEADER_FORMAT_MASK;
5805 case METHOD_HEADER_TINY_FORMAT:
5806 case METHOD_HEADER_TINY_FORMAT1:
5807 local_var_sig_token = 0;
5809 case METHOD_HEADER_FAT_FORMAT:
5813 local_var_sig_token = read32 (ptr);
5816 g_assert_not_reached ();
5819 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5821 ret->init_locals = header->init_locals;
5822 ret->max_stack = header->max_stack;
5823 ret->local_var_sig_token = local_var_sig_token;
5824 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5825 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5828 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5829 for (i = 0; i < header->num_locals; ++i) {
5830 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5831 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5832 info->is_pinned = header->locals [i]->pinned;
5833 info->local_index = i;
5834 mono_array_setref (ret->locals, i, info);
5838 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5839 for (i = 0; i < header->num_clauses; ++i) {
5840 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5841 MonoExceptionClause *clause = &header->clauses [i];
5843 info->flags = clause->flags;
5844 info->try_offset = clause->try_offset;
5845 info->try_length = clause->try_len;
5846 info->handler_offset = clause->handler_offset;
5847 info->handler_length = clause->handler_len;
5848 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5849 info->filter_offset = clause->data.filter_offset;
5850 else if (clause->data.catch_class)
5851 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5853 mono_array_setref (ret->clauses, i, info);
5856 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5861 mono_get_dbnull_object (MonoDomain *domain)
5864 static MonoClassField *dbnull_value_field = NULL;
5866 if (!dbnull_value_field) {
5867 MonoClass *dbnull_klass;
5868 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5869 mono_class_init (dbnull_klass);
5870 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5871 g_assert (dbnull_value_field);
5873 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5880 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5882 guint32 param_index, i, lastp, crow = 0;
5883 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5886 MonoClass *klass = method->klass;
5887 MonoImage *image = klass->image;
5888 MonoMethodSignature *methodsig = mono_method_signature (method);
5890 MonoTableInfo *constt;
5891 MonoTableInfo *methodt;
5892 MonoTableInfo *paramt;
5894 if (!methodsig->param_count)
5897 mono_class_init (klass);
5899 if (klass->image->dynamic) {
5900 MonoReflectionMethodAux *aux;
5901 if (method->is_inflated)
5902 method = ((MonoMethodInflated*)method)->declaring;
5903 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5904 if (aux && aux->param_defaults) {
5905 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5906 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5911 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5912 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5913 constt = &image->tables [MONO_TABLE_CONSTANT];
5915 idx = mono_method_get_index (method) - 1;
5916 g_assert (idx != -1);
5918 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5919 if (idx + 1 < methodt->rows)
5920 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5922 lastp = paramt->rows + 1;
5924 for (i = param_index; i < lastp; ++i) {
5927 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5928 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5930 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5933 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5938 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5939 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5940 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5947 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5952 MonoType *basetype = type;
5957 klass = mono_class_from_mono_type (type);
5958 if (klass->valuetype) {
5959 object = mono_object_new (domain, klass);
5960 retval = ((gchar *) object + sizeof (MonoObject));
5961 if (klass->enumtype)
5962 basetype = klass->enum_basetype;
5967 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5974 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5978 memset (assembly, 0, sizeof (MonoAssemblyName));
5980 assembly->culture = "";
5981 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5983 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5986 while (g_ascii_isspace (*p) || *p == ',') {
5995 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5997 assembly->major = strtoul (p, &s, 10);
5998 if (s == p || *s != '.')
6001 assembly->minor = strtoul (p, &s, 10);
6002 if (s == p || *s != '.')
6005 assembly->build = strtoul (p, &s, 10);
6006 if (s == p || *s != '.')
6009 assembly->revision = strtoul (p, &s, 10);
6013 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6015 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6016 assembly->culture = "";
6019 assembly->culture = p;
6020 while (*p && *p != ',') {
6024 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6026 if (strncmp (p, "null", 4) == 0) {
6031 while (*p && *p != ',') {
6034 len = (p - start + 1);
6035 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6036 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6037 g_strlcpy ((char*)assembly->public_key_token, start, len);
6040 while (*p && *p != ',')
6044 while (g_ascii_isspace (*p) || *p == ',') {
6058 * mono_reflection_parse_type:
6061 * Parse a type name as accepted by the GetType () method and output the info
6062 * extracted in the info structure.
6063 * the name param will be mangled, so, make a copy before passing it to this function.
6064 * The fields in info will be valid until the memory pointed to by name is valid.
6066 * See also mono_type_get_name () below.
6068 * Returns: 0 on parse error.
6071 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6072 MonoTypeNameParse *info)
6074 char *start, *p, *w, *temp, *last_point, *startn;
6075 int in_modifiers = 0;
6076 int isbyref = 0, rank, arity = 0, i;
6078 start = p = w = name;
6080 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6081 info->name = info->name_space = NULL;
6082 info->nested = NULL;
6083 info->modifiers = NULL;
6084 info->type_arguments = NULL;
6086 /* last_point separates the namespace from the name */
6092 *p = 0; /* NULL terminate the name */
6094 info->nested = g_list_append (info->nested, startn);
6095 /* we have parsed the nesting namespace + name */
6099 info->name_space = start;
6101 info->name = last_point + 1;
6103 info->name_space = (char *)"";
6122 i = strtol (p, &temp, 10);
6139 info->name_space = start;
6141 info->name = last_point + 1;
6143 info->name_space = (char *)"";
6150 if (isbyref) /* only one level allowed by the spec */
6153 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6157 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6163 info->type_arguments = g_ptr_array_new ();
6164 for (i = 0; i < arity; i++) {
6165 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6166 gboolean fqname = FALSE;
6168 g_ptr_array_add (info->type_arguments, subinfo);
6175 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6186 while (*p && (*p != ']'))
6194 if (g_ascii_isspace (*aname)) {
6201 !assembly_name_to_aname (&subinfo->assembly, aname))
6205 if (i + 1 < arity) {
6225 else if (*p != '*') /* '*' means unknown lower bound */
6231 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6242 if (g_ascii_isspace (*p)) {
6249 return 0; /* missing assembly name */
6250 if (!assembly_name_to_aname (&info->assembly, p))
6256 if (info->assembly.name)
6259 // *w = 0; /* terminate class name */
6261 if (!info->name || !*info->name)
6265 /* add other consistency checks */
6270 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6272 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6276 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6278 gboolean type_resolve = FALSE;
6280 MonoImage *rootimage = image;
6282 if (info->assembly.name) {
6283 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6285 /* then we must load the assembly ourselve - see #60439 */
6286 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6290 image = assembly->image;
6291 } else if (!image) {
6292 image = mono_defaults.corlib;
6295 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6296 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6297 image = mono_defaults.corlib;
6298 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6305 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6312 image = mono_defaults.corlib;
6315 klass = mono_class_from_name_case (image, info->name_space, info->name);
6317 klass = mono_class_from_name (image, info->name_space, info->name);
6320 for (mod = info->nested; mod; mod = mod->next) {
6323 mono_class_init (klass);
6324 nested = klass->nested_classes;
6327 klass = nested->data;
6329 if (g_strcasecmp (klass->name, mod->data) == 0)
6332 if (strcmp (klass->name, mod->data) == 0)
6336 nested = nested->next;
6343 mono_class_init (klass);
6345 if (info->type_arguments) {
6346 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6347 MonoReflectionType *the_type;
6351 for (i = 0; i < info->type_arguments->len; i++) {
6352 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6354 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6355 if (!type_args [i]) {
6361 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6363 instance = mono_reflection_bind_generic_parameters (
6364 the_type, info->type_arguments->len, type_args);
6371 klass = mono_class_from_mono_type (instance);
6374 for (mod = info->modifiers; mod; mod = mod->next) {
6375 modval = GPOINTER_TO_UINT (mod->data);
6376 if (!modval) { /* byref: must be last modifier */
6377 return &klass->this_arg;
6378 } else if (modval == -1) {
6379 klass = mono_ptr_class_get (&klass->byval_arg);
6380 } else { /* array rank */
6381 klass = mono_array_class_get (klass, modval);
6383 mono_class_init (klass);
6386 return &klass->byval_arg;
6390 * mono_reflection_get_type:
6391 * @image: a metadata context
6392 * @info: type description structure
6393 * @ignorecase: flag for case-insensitive string compares
6394 * @type_resolve: whenever type resolve was already tried
6396 * Build a MonoType from the type description in @info.
6401 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6402 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6406 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6409 MonoReflectionAssembly *assembly;
6413 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6416 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6423 *type_resolve = TRUE;
6426 /* Reconstruct the type name */
6427 fullName = g_string_new ("");
6428 if (info->name_space && (info->name_space [0] != '\0'))
6429 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6431 g_string_printf (fullName, info->name);
6432 for (mod = info->nested; mod; mod = mod->next)
6433 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6435 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6437 if (assembly->assembly->dynamic) {
6438 /* Enumerate all modules */
6439 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6443 if (abuilder->modules) {
6444 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6445 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6446 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6452 if (!type && abuilder->loaded_modules) {
6453 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6454 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6455 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6462 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6465 g_string_free (fullName, TRUE);
6470 free_type_info (MonoTypeNameParse *info)
6472 g_list_free (info->modifiers);
6473 g_list_free (info->nested);
6475 if (info->type_arguments) {
6478 for (i = 0; i < info->type_arguments->len; i++) {
6479 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6481 free_type_info (subinfo);
6484 g_ptr_array_free (info->type_arguments, TRUE);
6489 * mono_reflection_type_from_name:
6491 * @image: a metadata context (can be NULL).
6493 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6494 * it defaults to get the type from @image or, if @image is NULL or loading
6495 * from it fails, uses corlib.
6499 mono_reflection_type_from_name (char *name, MonoImage *image)
6501 MonoType *type = NULL;
6502 MonoTypeNameParse info;
6505 /* Make a copy since parse_type modifies its argument */
6506 tmp = g_strdup (name);
6508 /*g_print ("requested type %s\n", str);*/
6509 if (mono_reflection_parse_type (tmp, &info)) {
6510 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6514 free_type_info (&info);
6519 * mono_reflection_get_token:
6521 * Return the metadata token of OBJ which should be an object
6522 * representing a metadata element.
6525 mono_reflection_get_token (MonoObject *obj)
6530 klass = obj->vtable->klass;
6532 if (strcmp (klass->name, "MethodBuilder") == 0) {
6533 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6535 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6536 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6537 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6539 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6540 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6541 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6542 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6543 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6545 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6546 } else if (strcmp (klass->name, "MonoType") == 0) {
6547 MonoReflectionType *tb = (MonoReflectionType *)obj;
6548 token = mono_class_from_mono_type (tb->type)->type_token;
6549 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6550 strcmp (klass->name, "MonoMethod") == 0 ||
6551 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6552 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6553 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6554 if (m->method->is_inflated) {
6555 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6556 return inflated->declaring->token;
6558 token = m->method->token;
6560 } else if (strcmp (klass->name, "MonoField") == 0) {
6561 MonoReflectionField *f = (MonoReflectionField*)obj;
6563 if (f->field->generic_info && f->field->generic_info->reflection_info)
6564 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6566 token = mono_class_get_field_token (f->field);
6567 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6568 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6570 token = mono_class_get_property_token (p->property);
6571 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6572 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6574 token = mono_class_get_event_token (p->event);
6575 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6576 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6578 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6579 } else if (strcmp (klass->name, "Module") == 0) {
6580 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6583 } else if (strcmp (klass->name, "Assembly") == 0) {
6584 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6586 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6587 MonoException *ex = mono_get_exception_not_implemented (msg);
6589 mono_raise_exception (ex);
6596 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6598 int slen, type = t->type;
6599 MonoClass *tklass = t->data.klass;
6605 case MONO_TYPE_BOOLEAN: {
6606 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6611 case MONO_TYPE_CHAR:
6613 case MONO_TYPE_I2: {
6614 guint16 *val = g_malloc (sizeof (guint16));
6619 #if SIZEOF_VOID_P == 4
6625 case MONO_TYPE_I4: {
6626 guint32 *val = g_malloc (sizeof (guint32));
6631 #if SIZEOF_VOID_P == 8
6632 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6636 case MONO_TYPE_I8: {
6637 guint64 *val = g_malloc (sizeof (guint64));
6642 case MONO_TYPE_R8: {
6643 double *val = g_malloc (sizeof (double));
6648 case MONO_TYPE_VALUETYPE:
6649 if (t->data.klass->enumtype) {
6650 type = t->data.klass->enum_basetype->type;
6653 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6656 case MONO_TYPE_STRING:
6657 if (*p == (char)0xFF) {
6661 slen = mono_metadata_decode_value (p, &p);
6663 return mono_string_new_len (mono_domain_get (), p, slen);
6664 case MONO_TYPE_CLASS: {
6667 if (*p == (char)0xFF) {
6672 slen = mono_metadata_decode_value (p, &p);
6673 n = g_memdup (p, slen + 1);
6675 t = mono_reflection_type_from_name (n, image);
6677 g_warning ("Cannot load type '%s'", n);
6681 return mono_type_get_object (mono_domain_get (), t);
6685 case MONO_TYPE_OBJECT: {
6688 MonoClass *subc = NULL;
6693 } else if (subt == 0x0E) {
6694 type = MONO_TYPE_STRING;
6696 } else if (subt == 0x1D) {
6697 MonoType simple_type = {{0}};
6702 /* See Partition II, Appendix B3 */
6703 etype = MONO_TYPE_OBJECT;
6704 type = MONO_TYPE_SZARRAY;
6705 simple_type.type = etype;
6706 tklass = mono_class_from_mono_type (&simple_type);
6708 } else if (subt == 0x55) {
6711 slen = mono_metadata_decode_value (p, &p);
6712 n = g_memdup (p, slen + 1);
6714 t = mono_reflection_type_from_name (n, image);
6716 g_error ("Cannot load type '%s'", n);
6719 subc = mono_class_from_mono_type (t);
6720 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6721 MonoType simple_type = {{0}};
6722 simple_type.type = subt;
6723 subc = mono_class_from_mono_type (&simple_type);
6725 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6727 val = load_cattr_value (image, &subc->byval_arg, p, end);
6728 obj = mono_object_new (mono_domain_get (), subc);
6729 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6733 case MONO_TYPE_SZARRAY: {
6735 guint32 i, alen, basetype;
6738 if (alen == 0xffffffff) {
6742 arr = mono_array_new (mono_domain_get(), tklass, alen);
6743 basetype = tklass->byval_arg.type;
6744 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6745 basetype = tklass->enum_basetype->type;
6750 case MONO_TYPE_BOOLEAN:
6751 for (i = 0; i < alen; i++) {
6752 MonoBoolean val = *p++;
6753 mono_array_set (arr, MonoBoolean, i, val);
6756 case MONO_TYPE_CHAR:
6759 for (i = 0; i < alen; i++) {
6760 guint16 val = read16 (p);
6761 mono_array_set (arr, guint16, i, val);
6768 for (i = 0; i < alen; i++) {
6769 guint32 val = read32 (p);
6770 mono_array_set (arr, guint32, i, val);
6775 for (i = 0; i < alen; i++) {
6778 mono_array_set (arr, double, i, val);
6784 for (i = 0; i < alen; i++) {
6785 guint64 val = read64 (p);
6786 mono_array_set (arr, guint64, i, val);
6790 case MONO_TYPE_CLASS:
6791 case MONO_TYPE_OBJECT:
6792 case MONO_TYPE_STRING:
6793 for (i = 0; i < alen; i++) {
6794 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6795 mono_array_setref (arr, i, item);
6799 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6805 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6811 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6813 static MonoClass *klass;
6814 static MonoMethod *ctor;
6816 void *params [2], *unboxed;
6819 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6821 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6823 params [0] = mono_type_get_object (mono_domain_get (), t);
6825 retval = mono_object_new (mono_domain_get (), klass);
6826 unboxed = mono_object_unbox (retval);
6827 mono_runtime_invoke (ctor, unboxed, params, NULL);
6833 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6835 static MonoClass *klass;
6836 static MonoMethod *ctor;
6838 void *unboxed, *params [2];
6841 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6843 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6846 params [1] = typedarg;
6847 retval = mono_object_new (mono_domain_get (), klass);
6848 unboxed = mono_object_unbox (retval);
6849 mono_runtime_invoke (ctor, unboxed, params, NULL);
6855 type_is_reference (MonoType *type)
6857 switch (type->type) {
6858 case MONO_TYPE_BOOLEAN:
6859 case MONO_TYPE_CHAR:
6872 case MONO_TYPE_VALUETYPE:
6880 free_param_data (MonoMethodSignature *sig, void **params) {
6882 for (i = 0; i < sig->param_count; ++i) {
6883 if (!type_is_reference (sig->params [i]))
6884 g_free (params [i]);
6889 * Find the field index in the metadata FieldDef table.
6892 find_field_index (MonoClass *klass, MonoClassField *field) {
6895 for (i = 0; i < klass->field.count; ++i) {
6896 if (field == &klass->fields [i])
6897 return klass->field.first + 1 + i;
6903 * Find the property index in the metadata Property table.
6906 find_property_index (MonoClass *klass, MonoProperty *property) {
6909 for (i = 0; i < klass->property.count; ++i) {
6910 if (property == &klass->properties [i])
6911 return klass->property.first + 1 + i;
6917 * Find the event index in the metadata Event table.
6920 find_event_index (MonoClass *klass, MonoEvent *event) {
6923 for (i = 0; i < klass->event.count; ++i) {
6924 if (event == &klass->events [i])
6925 return klass->event.first + 1 + i;
6931 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6933 const char *p = (const char*)data;
6935 guint32 i, j, num_named;
6939 mono_class_init (method->klass);
6942 attr = mono_object_new (mono_domain_get (), method->klass);
6943 mono_runtime_invoke (method, attr, NULL, NULL);
6947 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6950 /*g_print ("got attr %s\n", method->klass->name);*/
6952 /* Allocate using alloca so it gets GC tracking */
6953 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6957 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6958 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6962 attr = mono_object_new (mono_domain_get (), method->klass);
6963 mono_runtime_invoke (method, attr, params, NULL);
6964 free_param_data (method->signature, params);
6965 num_named = read16 (named);
6967 for (j = 0; j < num_named; j++) {
6969 char *name, named_type, data_type;
6970 named_type = *named++;
6971 data_type = *named++; /* type of data */
6972 if (data_type == MONO_TYPE_SZARRAY)
6973 data_type = *named++;
6974 if (data_type == MONO_TYPE_ENUM) {
6977 type_len = mono_metadata_decode_blob_size (named, &named);
6978 type_name = g_malloc (type_len + 1);
6979 memcpy (type_name, named, type_len);
6980 type_name [type_len] = 0;
6982 /* FIXME: lookup the type and check type consistency */
6985 name_len = mono_metadata_decode_blob_size (named, &named);
6986 name = g_malloc (name_len + 1);
6987 memcpy (name, named, name_len);
6988 name [name_len] = 0;
6990 if (named_type == 0x53) {
6991 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6992 void *val = load_cattr_value (image, field->type, named, &named);
6993 mono_field_set_value (attr, field, val);
6994 if (!type_is_reference (field->type))
6996 } else if (named_type == 0x54) {
6999 MonoType *prop_type;
7001 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7002 /* can we have more that 1 arg in a custom attr named property? */
7003 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7004 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7005 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7006 mono_property_set_value (prop, attr, pparams, NULL);
7007 if (!type_is_reference (prop_type))
7008 g_free (pparams [0]);
7017 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7019 MonoArray *typedargs, *namedargs;
7020 MonoClass *attrklass;
7021 static MonoMethod *ctor;
7024 const char *p = (const char*)data;
7026 guint32 i, j, num_named;
7029 mono_class_init (method->klass);
7032 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7034 domain = mono_domain_get ();
7036 /* This is for Attributes with no parameters */
7037 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7038 params [0] = mono_method_get_object (domain, method, NULL);
7039 params [1] = params [2] = NULL;
7040 mono_runtime_invoke (method, attr, params, NULL);
7044 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7047 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7051 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7052 MonoObject *obj, *typedarg;
7055 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7056 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7057 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7058 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7059 mono_array_setref (typedargs, i, typedarg);
7061 if (!type_is_reference (mono_method_signature (method)->params [i]))
7066 num_named = read16 (named);
7067 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7069 attrklass = method->klass;
7070 for (j = 0; j < num_named; j++) {
7072 char *name, named_type, data_type;
7073 named_type = *named++;
7074 data_type = *named++; /* type of data */
7075 if (data_type == MONO_TYPE_SZARRAY)
7076 data_type = *named++;
7077 if (data_type == MONO_TYPE_ENUM) {
7080 type_len = mono_metadata_decode_blob_size (named, &named);
7081 type_name = g_malloc (type_len + 1);
7082 memcpy (type_name, named, type_len);
7083 type_name [type_len] = 0;
7085 /* FIXME: lookup the type and check type consistency */
7088 name_len = mono_metadata_decode_blob_size (named, &named);
7089 name = g_malloc (name_len + 1);
7090 memcpy (name, named, name_len);
7091 name [name_len] = 0;
7093 if (named_type == 0x53) {
7094 MonoObject *obj, *typedarg, *namedarg;
7095 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7096 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7098 minfo = mono_field_get_object (domain, NULL, field);
7099 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7100 typedarg = create_cattr_typed_arg (field->type, obj);
7101 namedarg = create_cattr_named_arg (minfo, typedarg);
7102 mono_array_setref (namedargs, j, namedarg);
7103 if (!type_is_reference (field->type))
7105 } else if (named_type == 0x54) {
7106 MonoObject *obj, *typedarg, *namedarg;
7107 MonoType *prop_type;
7109 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7111 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7112 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7113 minfo = mono_property_get_object (domain, NULL, prop);
7114 val = load_cattr_value (image, prop_type, named, &named);
7115 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7116 typedarg = create_cattr_typed_arg (prop_type, obj);
7117 namedarg = create_cattr_named_arg (minfo, typedarg);
7118 mono_array_setref (namedargs, j, namedarg);
7119 if (!type_is_reference (prop_type))
7124 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7125 params [0] = mono_method_get_object (domain, method, NULL);
7126 params [1] = typedargs;
7127 params [2] = namedargs;
7128 mono_runtime_invoke (ctor, attr, params, NULL);
7133 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7139 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7140 for (i = 0; i < cinfo->num_attrs; ++i) {
7141 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7142 mono_array_setref (result, i, attr);
7148 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7155 for (i = 0; i < cinfo->num_attrs; ++i) {
7156 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7160 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7162 for (i = 0; i < cinfo->num_attrs; ++i) {
7163 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7164 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7165 mono_array_setref (result, n, attr);
7173 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7179 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7180 for (i = 0; i < cinfo->num_attrs; ++i) {
7181 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7182 mono_array_setref (result, i, attr);
7188 * mono_custom_attrs_from_index:
7190 * Returns: NULL if no attributes are found or if a loading error occurs.
7193 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7195 guint32 mtoken, i, len;
7196 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7198 MonoCustomAttrInfo *ainfo;
7199 GList *tmp, *list = NULL;
7202 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7204 i = mono_metadata_custom_attrs_from_index (image, idx);
7208 while (i < ca->rows) {
7209 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7211 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7214 len = g_list_length (list);
7217 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7218 ainfo->num_attrs = len;
7219 ainfo->image = image;
7220 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7221 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7222 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7223 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7224 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7225 mtoken |= MONO_TOKEN_METHOD_DEF;
7227 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7228 mtoken |= MONO_TOKEN_MEMBER_REF;
7231 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7234 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7235 if (!ainfo->attrs [i].ctor) {
7236 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7241 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7242 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7243 ainfo->attrs [i].data = (guchar*)data;
7251 mono_custom_attrs_from_method (MonoMethod *method)
7253 MonoCustomAttrInfo *cinfo;
7256 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7258 idx = mono_method_get_index (method);
7259 idx <<= MONO_CUSTOM_ATTR_BITS;
7260 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7261 return mono_custom_attrs_from_index (method->klass->image, idx);
7265 mono_custom_attrs_from_class (MonoClass *klass)
7267 MonoCustomAttrInfo *cinfo;
7270 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7272 idx = mono_metadata_token_index (klass->type_token);
7273 idx <<= MONO_CUSTOM_ATTR_BITS;
7274 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7275 return mono_custom_attrs_from_index (klass->image, idx);
7279 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7281 MonoCustomAttrInfo *cinfo;
7284 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7286 idx = 1; /* there is only one assembly */
7287 idx <<= MONO_CUSTOM_ATTR_BITS;
7288 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7289 return mono_custom_attrs_from_index (assembly->image, idx);
7292 static MonoCustomAttrInfo*
7293 mono_custom_attrs_from_module (MonoImage *image)
7295 MonoCustomAttrInfo *cinfo;
7298 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7300 idx = 1; /* there is only one module */
7301 idx <<= MONO_CUSTOM_ATTR_BITS;
7302 idx |= MONO_CUSTOM_ATTR_MODULE;
7303 return mono_custom_attrs_from_index (image, idx);
7307 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7309 MonoCustomAttrInfo *cinfo;
7312 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7314 idx = find_property_index (klass, property);
7315 idx <<= MONO_CUSTOM_ATTR_BITS;
7316 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7317 return mono_custom_attrs_from_index (klass->image, idx);
7321 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7323 MonoCustomAttrInfo *cinfo;
7326 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7328 idx = find_event_index (klass, event);
7329 idx <<= MONO_CUSTOM_ATTR_BITS;
7330 idx |= MONO_CUSTOM_ATTR_EVENT;
7331 return mono_custom_attrs_from_index (klass->image, idx);
7335 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7337 MonoCustomAttrInfo *cinfo;
7340 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7342 idx = find_field_index (klass, field);
7343 idx <<= MONO_CUSTOM_ATTR_BITS;
7344 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7345 return mono_custom_attrs_from_index (klass->image, idx);
7349 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7352 guint32 i, idx, method_index;
7353 guint32 param_list, param_last, param_pos, found;
7355 MonoReflectionMethodAux *aux;
7357 if (method->klass->image->dynamic) {
7358 MonoCustomAttrInfo *res, *ainfo;
7361 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7362 if (!aux || !aux->param_cattr)
7365 /* Need to copy since it will be freed later */
7366 ainfo = aux->param_cattr [param];
7367 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7368 res = g_malloc0 (size);
7369 memcpy (res, ainfo, size);
7373 image = method->klass->image;
7374 method_index = mono_method_get_index (method);
7375 ca = &image->tables [MONO_TABLE_METHOD];
7377 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7378 if (method_index == ca->rows) {
7379 ca = &image->tables [MONO_TABLE_PARAM];
7380 param_last = ca->rows + 1;
7382 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7383 ca = &image->tables [MONO_TABLE_PARAM];
7386 for (i = param_list; i < param_last; ++i) {
7387 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7388 if (param_pos == param) {
7396 idx <<= MONO_CUSTOM_ATTR_BITS;
7397 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7398 return mono_custom_attrs_from_index (image, idx);
7402 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7406 for (i = 0; i < ainfo->num_attrs; ++i) {
7407 klass = ainfo->attrs [i].ctor->klass;
7408 if (mono_class_has_parent (klass, attr_klass))
7415 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7422 for (i = 0; i < ainfo->num_attrs; ++i) {
7423 klass = ainfo->attrs [i].ctor->klass;
7424 if (mono_class_has_parent (klass, attr_klass)) {
7429 if (attr_index == -1)
7432 attrs = mono_custom_attrs_construct (ainfo);
7434 return mono_array_get (attrs, MonoObject*, attr_index);
7440 * mono_reflection_get_custom_attrs_info:
7441 * @obj: a reflection object handle
7443 * Return the custom attribute info for attributes defined for the
7444 * reflection handle @obj. The objects.
7447 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7450 MonoCustomAttrInfo *cinfo = NULL;
7452 klass = obj->vtable->klass;
7453 if (klass == mono_defaults.monotype_class) {
7454 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7455 klass = mono_class_from_mono_type (rtype->type);
7456 cinfo = mono_custom_attrs_from_class (klass);
7457 } else if (strcmp ("Assembly", klass->name) == 0) {
7458 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7459 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7460 } else if (strcmp ("Module", klass->name) == 0) {
7461 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7462 cinfo = mono_custom_attrs_from_module (module->image);
7463 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7464 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7465 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7466 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7467 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7468 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7469 } else if (strcmp ("MonoField", klass->name) == 0) {
7470 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7471 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7472 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7473 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7474 cinfo = mono_custom_attrs_from_method (rmethod->method);
7475 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7476 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7477 cinfo = mono_custom_attrs_from_method (rmethod->method);
7478 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7479 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7480 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7481 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7482 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7483 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7484 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7485 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7486 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7487 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7488 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7489 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7490 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7491 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7492 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7493 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7494 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7495 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7496 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7497 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7498 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7499 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7500 } else { /* handle other types here... */
7501 g_error ("get custom attrs not yet supported for %s", klass->name);
7508 * mono_reflection_get_custom_attrs_by_type:
7509 * @obj: a reflection object handle
7511 * Return an array with all the custom attributes defined of the
7512 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7513 * of that type are returned. The objects are fully build. Return NULL if a loading error
7517 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7520 MonoCustomAttrInfo *cinfo;
7522 cinfo = mono_reflection_get_custom_attrs_info (obj);
7525 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7527 result = mono_custom_attrs_construct (cinfo);
7529 mono_custom_attrs_free (cinfo);
7531 if (mono_loader_get_last_error ())
7533 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7540 * mono_reflection_get_custom_attrs:
7541 * @obj: a reflection object handle
7543 * Return an array with all the custom attributes defined of the
7544 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7548 mono_reflection_get_custom_attrs (MonoObject *obj)
7550 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7554 * mono_reflection_get_custom_attrs_data:
7555 * @obj: a reflection obj handle
7557 * Returns an array of System.Reflection.CustomAttributeData,
7558 * which include information about attributes reflected on
7559 * types loaded using the Reflection Only methods
7562 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7565 MonoCustomAttrInfo *cinfo;
7567 cinfo = mono_reflection_get_custom_attrs_info (obj);
7569 result = mono_custom_attrs_data_construct (cinfo);
7571 mono_custom_attrs_free (cinfo);
7573 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7578 static MonoReflectionType*
7579 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7581 MonoMethod *method_get_underlying_system_type;
7583 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7584 mono_class_get_method_from_name (mono_object_class (t),
7585 "get_UnderlyingSystemType",
7587 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7591 mono_reflection_type_get_handle (MonoReflectionType* t)
7596 t = mono_reflection_type_get_underlying_system_type (t);
7604 * LOCKING: Assumes the loader lock is held.
7606 static MonoMethodSignature*
7607 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7608 MonoMethodSignature *sig;
7611 count = parameters? mono_array_length (parameters): 0;
7613 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7614 sig->param_count = count;
7615 sig->sentinelpos = -1; /* FIXME */
7616 for (i = 0; i < count; ++i) {
7617 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7618 sig->params [i] = mono_reflection_type_get_handle (pt);
7624 * LOCKING: Assumes the loader lock is held.
7626 static MonoMethodSignature*
7627 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7628 MonoMethodSignature *sig;
7630 sig = parameters_to_signature (mp, ctor->parameters);
7631 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7632 sig->ret = &mono_defaults.void_class->byval_arg;
7637 * LOCKING: Assumes the loader lock is held.
7639 static MonoMethodSignature*
7640 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7641 MonoMethodSignature *sig;
7643 sig = parameters_to_signature (mp, method->parameters);
7644 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7645 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7646 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7650 static MonoMethodSignature*
7651 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7652 MonoMethodSignature *sig;
7654 sig = parameters_to_signature (NULL, method->parameters);
7655 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7656 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7657 sig->generic_param_count = 0;
7662 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7664 MonoClass *klass = mono_object_class (prop);
7665 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7666 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7667 *name = mono_string_to_utf8 (pb->name);
7668 *type = pb->type->type;
7670 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7671 *name = g_strdup (p->property->name);
7672 if (p->property->get)
7673 *type = mono_method_signature (p->property->get)->ret;
7675 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7680 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7682 MonoClass *klass = mono_object_class (field);
7683 if (strcmp (klass->name, "FieldBuilder") == 0) {
7684 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7685 *name = mono_string_to_utf8 (fb->name);
7686 *type = fb->type->type;
7688 MonoReflectionField *f = (MonoReflectionField *)field;
7689 *name = g_strdup (f->field->name);
7690 *type = f->field->type;
7695 * Encode a value in a custom attribute stream of bytes.
7696 * The value to encode is either supplied as an object in argument val
7697 * (valuetypes are boxed), or as a pointer to the data in the
7699 * @type represents the type of the value
7700 * @buffer is the start of the buffer
7701 * @p the current position in the buffer
7702 * @buflen contains the size of the buffer and is used to return the new buffer size
7703 * if this needs to be realloced.
7704 * @retbuffer and @retp return the start and the position of the buffer
7707 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7709 MonoTypeEnum simple_type;
7711 if ((p-buffer) + 10 >= *buflen) {
7714 newbuf = g_realloc (buffer, *buflen);
7715 p = newbuf + (p-buffer);
7719 argval = ((char*)arg + sizeof (MonoObject));
7720 simple_type = type->type;
7722 switch (simple_type) {
7723 case MONO_TYPE_BOOLEAN:
7728 case MONO_TYPE_CHAR:
7731 swap_with_size (p, argval, 2, 1);
7737 swap_with_size (p, argval, 4, 1);
7741 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7751 swap_with_size (p, argval, 8, 1);
7757 swap_with_size (p, argval, 8, 1);
7760 case MONO_TYPE_VALUETYPE:
7761 if (type->data.klass->enumtype) {
7762 simple_type = type->data.klass->enum_basetype->type;
7765 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7768 case MONO_TYPE_STRING: {
7775 str = mono_string_to_utf8 ((MonoString*)arg);
7776 slen = strlen (str);
7777 if ((p-buffer) + 10 + slen >= *buflen) {
7781 newbuf = g_realloc (buffer, *buflen);
7782 p = newbuf + (p-buffer);
7785 mono_metadata_encode_value (slen, p, &p);
7786 memcpy (p, str, slen);
7791 case MONO_TYPE_CLASS: {
7799 k = mono_object_class (arg);
7800 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7801 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7802 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7805 if (rt && (rtc = mono_object_class (rt)) &&
7806 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7807 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7808 arg = (MonoObject *) rt;
7811 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7814 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7815 slen = strlen (str);
7816 if ((p-buffer) + 10 + slen >= *buflen) {
7820 newbuf = g_realloc (buffer, *buflen);
7821 p = newbuf + (p-buffer);
7824 mono_metadata_encode_value (slen, p, &p);
7825 memcpy (p, str, slen);
7830 case MONO_TYPE_SZARRAY: {
7832 MonoClass *eclass, *arg_eclass;
7835 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7838 len = mono_array_length ((MonoArray*)arg);
7840 *p++ = (len >> 8) & 0xff;
7841 *p++ = (len >> 16) & 0xff;
7842 *p++ = (len >> 24) & 0xff;
7844 *retbuffer = buffer;
7845 eclass = type->data.klass;
7846 arg_eclass = mono_object_class (arg)->element_class;
7849 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7850 eclass = mono_defaults.object_class;
7852 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7853 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7854 int elsize = mono_class_array_element_size (arg_eclass);
7855 for (i = 0; i < len; ++i) {
7856 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7859 } else if (eclass->valuetype && arg_eclass->valuetype) {
7860 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7861 int elsize = mono_class_array_element_size (eclass);
7862 for (i = 0; i < len; ++i) {
7863 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7867 for (i = 0; i < len; ++i) {
7868 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7873 case MONO_TYPE_OBJECT: {
7879 * The parameter type is 'object' but the type of the actual
7880 * argument is not. So we have to add type information to the blob
7881 * too. This is completely undocumented in the spec.
7885 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7890 klass = mono_object_class (arg);
7892 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7895 } else if (klass->enumtype) {
7897 } else if (klass == mono_defaults.string_class) {
7898 simple_type = MONO_TYPE_STRING;
7901 } else if (klass->rank == 1) {
7903 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7904 /* See Partition II, Appendix B3 */
7907 *p++ = klass->element_class->byval_arg.type;
7908 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7910 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7911 *p++ = simple_type = klass->byval_arg.type;
7914 g_error ("unhandled type in custom attr");
7916 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7917 slen = strlen (str);
7918 if ((p-buffer) + 10 + slen >= *buflen) {
7922 newbuf = g_realloc (buffer, *buflen);
7923 p = newbuf + (p-buffer);
7926 mono_metadata_encode_value (slen, p, &p);
7927 memcpy (p, str, slen);
7930 simple_type = klass->enum_basetype->type;
7934 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7937 *retbuffer = buffer;
7941 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7943 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7944 char *str = type_get_qualified_name (type, NULL);
7945 int slen = strlen (str);
7949 * This seems to be optional...
7952 mono_metadata_encode_value (slen, p, &p);
7953 memcpy (p, str, slen);
7956 } else if (type->type == MONO_TYPE_OBJECT) {
7958 } else if (type->type == MONO_TYPE_CLASS) {
7959 /* it should be a type: encode_cattr_value () has the check */
7962 mono_metadata_encode_value (type->type, p, &p);
7963 if (type->type == MONO_TYPE_SZARRAY)
7964 /* See the examples in Partition VI, Annex B */
7965 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
7972 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7975 /* Preallocate a large enough buffer */
7976 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7977 char *str = type_get_qualified_name (type, NULL);
7980 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
7981 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
7987 len += strlen (name);
7989 if ((p-buffer) + 20 + len >= *buflen) {
7993 newbuf = g_realloc (buffer, *buflen);
7994 p = newbuf + (p-buffer);
7998 encode_field_or_prop_type (type, p, &p);
8000 len = strlen (name);
8001 mono_metadata_encode_value (len, p, &p);
8002 memcpy (p, name, len);
8004 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8006 *retbuffer = buffer;
8010 * mono_reflection_get_custom_attrs_blob:
8011 * @ctor: custom attribute constructor
8012 * @ctorArgs: arguments o the constructor
8018 * Creates the blob of data that needs to be saved in the metadata and that represents
8019 * the custom attributed described by @ctor, @ctorArgs etc.
8020 * Returns: a Byte array representing the blob of data.
8023 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8026 MonoMethodSignature *sig;
8031 MONO_ARCH_SAVE_REGS;
8033 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8034 /* sig is freed later so allocate it in the heap */
8035 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8037 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8040 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8042 p = buffer = g_malloc (buflen);
8043 /* write the prolog */
8046 for (i = 0; i < sig->param_count; ++i) {
8047 arg = mono_array_get (ctorArgs, MonoObject*, i);
8048 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8052 i += mono_array_length (properties);
8054 i += mono_array_length (fields);
8056 *p++ = (i >> 8) & 0xff;
8059 for (i = 0; i < mono_array_length (properties); ++i) {
8063 prop = mono_array_get (properties, gpointer, i);
8064 get_prop_name_and_type (prop, &pname, &ptype);
8065 *p++ = 0x54; /* PROPERTY signature */
8066 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8073 for (i = 0; i < mono_array_length (fields); ++i) {
8077 field = mono_array_get (fields, gpointer, i);
8078 get_field_name_and_type (field, &fname, &ftype);
8079 *p++ = 0x53; /* FIELD signature */
8080 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8085 g_assert (p - buffer <= buflen);
8086 buflen = p - buffer;
8087 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8088 p = mono_array_addr (result, char, 0);
8089 memcpy (p, buffer, buflen);
8091 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8097 static void* reflection_info_desc = NULL;
8098 #define MOVING_GC_REGISTER(addr) do { \
8099 if (!reflection_info_desc) { \
8101 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8103 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8106 #define MOVING_GC_REGISTER(addr)
8110 * mono_reflection_setup_internal_class:
8111 * @tb: a TypeBuilder object
8113 * Creates a MonoClass that represents the TypeBuilder.
8114 * This is a trick that lets us simplify a lot of reflection code
8115 * (and will allow us to support Build and Run assemblies easier).
8118 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8120 MonoClass *klass, *parent;
8122 MONO_ARCH_SAVE_REGS;
8124 mono_loader_lock ();
8127 /* check so we can compile corlib correctly */
8128 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8129 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8130 parent = tb->parent->type->data.klass;
8132 parent = my_mono_class_from_mono_type (tb->parent->type);
8138 /* the type has already being created: it means we just have to change the parent */
8139 if (tb->type.type) {
8140 klass = mono_class_from_mono_type (tb->type.type);
8141 klass->parent = NULL;
8142 /* fool mono_class_setup_parent */
8143 klass->supertypes = NULL;
8144 mono_class_setup_parent (klass, parent);
8145 mono_class_setup_mono_type (klass);
8146 mono_loader_unlock ();
8150 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8152 klass->image = &tb->module->dynamic_image->image;
8154 klass->inited = 1; /* we lie to the runtime */
8155 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8156 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8157 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8158 klass->flags = tb->attrs;
8160 klass->element_class = klass;
8162 MOVING_GC_REGISTER (&klass->reflection_info);
8163 klass->reflection_info = tb;
8165 /* Put into cache so mono_class_get () will find it */
8166 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8168 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8169 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8171 if (parent != NULL) {
8172 mono_class_setup_parent (klass, parent);
8173 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8174 const char *old_n = klass->name;
8175 /* trick to get relative numbering right when compiling corlib */
8176 klass->name = "BuildingObject";
8177 mono_class_setup_parent (klass, mono_defaults.object_class);
8178 klass->name = old_n;
8181 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8182 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8183 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8184 klass->instance_size = sizeof (MonoObject);
8185 klass->size_inited = 1;
8186 mono_class_setup_vtable_general (klass, NULL, 0);
8189 mono_class_setup_mono_type (klass);
8191 mono_class_setup_supertypes (klass);
8194 * FIXME: handle interfaces.
8197 tb->type.type = &klass->byval_arg;
8199 if (tb->nesting_type) {
8200 g_assert (tb->nesting_type->type);
8201 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8204 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8206 mono_loader_unlock ();
8210 * mono_reflection_setup_generic_class:
8211 * @tb: a TypeBuilder object
8213 * Setup the generic class before adding the first generic parameter.
8216 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8220 MONO_ARCH_SAVE_REGS;
8222 klass = my_mono_class_from_mono_type (tb->type.type);
8223 if (tb->generic_container)
8226 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8227 tb->generic_container->owner.klass = klass;
8231 * mono_reflection_create_generic_class:
8232 * @tb: a TypeBuilder object
8234 * Creates the generic class after all generic parameters have been added.
8237 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8242 MONO_ARCH_SAVE_REGS;
8244 klass = my_mono_class_from_mono_type (tb->type.type);
8246 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8248 if (klass->generic_container || (count == 0))
8251 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8253 klass->generic_container = tb->generic_container;
8255 klass->generic_container->type_argc = count;
8256 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8258 for (i = 0; i < count; i++) {
8259 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8260 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8261 g_assert (klass->generic_container->type_params [i].owner);
8264 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8268 * mono_reflection_create_internal_class:
8269 * @tb: a TypeBuilder object
8271 * Actually create the MonoClass that is associated with the TypeBuilder.
8274 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8278 MONO_ARCH_SAVE_REGS;
8280 klass = my_mono_class_from_mono_type (tb->type.type);
8282 mono_loader_lock ();
8283 if (klass->enumtype && klass->enum_basetype == NULL) {
8284 MonoReflectionFieldBuilder *fb;
8287 g_assert (tb->fields != NULL);
8288 g_assert (mono_array_length (tb->fields) >= 1);
8290 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8292 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8293 mono_loader_unlock ();
8297 klass->enum_basetype = fb->type->type;
8298 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8299 if (!klass->element_class)
8300 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8303 * get the element_class from the current corlib.
8305 ec = default_class_from_mono_type (klass->enum_basetype);
8306 klass->instance_size = ec->instance_size;
8307 klass->size_inited = 1;
8309 * this is almost safe to do with enums and it's needed to be able
8310 * to create objects of the enum type (for use in SetConstant).
8312 /* FIXME: Does this mean enums can't have method overrides ? */
8313 mono_class_setup_vtable_general (klass, NULL, 0);
8315 mono_loader_unlock ();
8318 static MonoMarshalSpec*
8319 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8320 MonoReflectionMarshal *minfo)
8322 MonoMarshalSpec *res;
8324 res = g_new0 (MonoMarshalSpec, 1);
8325 res->native = minfo->type;
8327 switch (minfo->type) {
8328 case MONO_NATIVE_LPARRAY:
8329 res->data.array_data.elem_type = minfo->eltype;
8330 if (minfo->has_size) {
8331 res->data.array_data.param_num = minfo->param_num;
8332 res->data.array_data.num_elem = minfo->count;
8333 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8336 res->data.array_data.param_num = -1;
8337 res->data.array_data.num_elem = -1;
8338 res->data.array_data.elem_mult = -1;
8342 case MONO_NATIVE_BYVALTSTR:
8343 case MONO_NATIVE_BYVALARRAY:
8344 res->data.array_data.num_elem = minfo->count;
8347 case MONO_NATIVE_CUSTOM:
8348 if (minfo->marshaltyperef)
8349 res->data.custom_data.custom_name =
8350 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8352 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8362 MonoReflectionMarshal*
8363 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8364 MonoMarshalSpec *spec)
8366 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8367 MonoReflectionMarshal *minfo;
8370 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8371 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8372 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8373 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8376 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8377 minfo->type = spec->native;
8379 switch (minfo->type) {
8380 case MONO_NATIVE_LPARRAY:
8381 minfo->eltype = spec->data.array_data.elem_type;
8382 minfo->count = spec->data.array_data.num_elem;
8383 minfo->param_num = spec->data.array_data.param_num;
8386 case MONO_NATIVE_BYVALTSTR:
8387 case MONO_NATIVE_BYVALARRAY:
8388 minfo->count = spec->data.array_data.num_elem;
8391 case MONO_NATIVE_CUSTOM:
8392 if (spec->data.custom_data.custom_name) {
8393 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8395 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8397 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8399 if (spec->data.custom_data.cookie)
8400 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8411 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8412 ReflectionMethodBuilder *rmb,
8413 MonoMethodSignature *sig)
8416 MonoMethodNormal *pm;
8417 MonoMarshalSpec **specs;
8418 MonoReflectionMethodAux *method_aux;
8423 g_assert (!klass->generic_class);
8426 * Methods created using a MethodBuilder should have their memory allocated
8427 * inside the image mempool, while dynamic methods should have their memory
8430 dynamic = rmb->refs != NULL;
8431 mp = dynamic ? NULL : klass->image->mempool;
8433 mono_loader_lock ();
8435 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8436 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8437 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8439 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8441 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8443 pm = (MonoMethodNormal*)m;
8445 m->dynamic = dynamic;
8447 m->flags = rmb->attrs;
8448 m->iflags = rmb->iattrs;
8449 m->name = mp_string_to_utf8 (mp, rmb->name);
8452 m->skip_visibility = rmb->skip_visibility;
8454 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8456 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8457 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8460 m->signature->pinvoke = 1;
8461 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8462 m->signature->pinvoke = 1;
8464 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8466 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8467 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8469 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8471 if (klass->image->dynamic)
8472 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8474 mono_loader_unlock ();
8477 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8478 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8479 MonoMethodHeader *header;
8481 gint32 max_stack, i;
8482 gint32 num_locals = 0;
8483 gint32 num_clauses = 0;
8487 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8488 code_size = rmb->ilgen->code_len;
8489 max_stack = rmb->ilgen->max_stack;
8490 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8491 if (rmb->ilgen->ex_handlers)
8492 num_clauses = method_count_clauses (rmb->ilgen);
8495 code = mono_array_addr (rmb->code, guint8, 0);
8496 code_size = mono_array_length (rmb->code);
8497 /* we probably need to run a verifier on the code... */
8507 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8508 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8509 header->code_size = code_size;
8510 header->code = mp_g_malloc (mp, code_size);
8511 memcpy ((char*)header->code, code, code_size);
8512 header->max_stack = max_stack;
8513 header->init_locals = rmb->init_locals;
8514 header->num_locals = num_locals;
8516 for (i = 0; i < num_locals; ++i) {
8517 MonoReflectionLocalBuilder *lb =
8518 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8520 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8521 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8524 header->num_clauses = num_clauses;
8526 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8527 rmb->ilgen, num_clauses);
8530 pm->header = header;
8533 if (rmb->generic_params) {
8534 int count = mono_array_length (rmb->generic_params);
8535 MonoGenericContainer *container;
8537 m->generic_container = container = rmb->generic_container;
8538 container->type_argc = count;
8539 container->type_params = g_new0 (MonoGenericParam, count);
8540 container->owner.method = m;
8542 for (i = 0; i < count; i++) {
8543 MonoReflectionGenericParam *gp =
8544 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8546 container->type_params [i] = *gp->type.type->data.generic_param;
8549 if (klass->generic_container) {
8550 container->parent = klass->generic_container;
8551 container->context.class_inst = klass->generic_container->context.class_inst;
8553 container->context.method_inst = mono_get_shared_generic_inst (container);
8557 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8561 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8563 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8564 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8565 for (i = 0; i < rmb->nrefs; ++i)
8566 data [i + 1] = rmb->refs [i];
8571 /* Parameter info */
8574 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8575 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8576 for (i = 0; i <= m->signature->param_count; ++i) {
8577 MonoReflectionParamBuilder *pb;
8578 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8579 if ((i > 0) && (pb->attrs)) {
8580 /* Make a copy since it might point to a shared type structure */
8581 /* FIXME: Alloc this from a mempool */
8582 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8583 m->signature->params [i - 1]->attrs = pb->attrs;
8586 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8587 MonoDynamicImage *assembly;
8588 guint32 idx, def_type, len;
8592 if (!method_aux->param_defaults) {
8593 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8594 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8596 assembly = (MonoDynamicImage*)klass->image;
8597 idx = encode_constant (assembly, pb->def_value, &def_type);
8598 /* Copy the data from the blob since it might get realloc-ed */
8599 p = assembly->blob.data + idx;
8600 len = mono_metadata_decode_blob_size (p, &p2);
8602 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8603 method_aux->param_default_types [i] = def_type;
8604 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8608 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8610 if (!method_aux->param_cattr)
8611 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8612 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8618 /* Parameter marshalling */
8621 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8622 MonoReflectionParamBuilder *pb;
8623 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8624 if (pb->marshal_info) {
8626 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8627 specs [pb->position] =
8628 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8632 if (specs != NULL) {
8634 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8635 method_aux->param_marshall = specs;
8638 if (klass->image->dynamic && method_aux)
8639 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8641 mono_loader_unlock ();
8647 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8649 ReflectionMethodBuilder rmb;
8650 MonoMethodSignature *sig;
8652 mono_loader_lock ();
8653 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8654 mono_loader_unlock ();
8656 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8658 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8659 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8661 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8662 /* ilgen is no longer needed */
8670 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8672 ReflectionMethodBuilder rmb;
8673 MonoMethodSignature *sig;
8675 mono_loader_lock ();
8676 sig = method_builder_to_signature (klass->image->mempool, mb);
8677 mono_loader_unlock ();
8679 reflection_methodbuilder_from_method_builder (&rmb, mb);
8681 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8682 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8684 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8685 /* ilgen is no longer needed */
8691 static MonoClassField*
8692 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8694 MonoClassField *field;
8698 field = g_new0 (MonoClassField, 1);
8700 field->name = mono_string_to_utf8 (fb->name);
8702 /* FIXME: handle type modifiers */
8703 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8704 field->type->attrs = fb->attrs;
8706 field->type = fb->type->type;
8708 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8709 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8710 if (fb->offset != -1)
8711 field->offset = fb->offset;
8712 field->parent = klass;
8713 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8715 if (fb->def_value) {
8716 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8717 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8718 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8719 /* Copy the data from the blob since it might get realloc-ed */
8720 p = assembly->blob.data + idx;
8721 len = mono_metadata_decode_blob_size (p, &p2);
8723 field->data = g_malloc (len);
8724 memcpy ((gpointer)field->data, p, len);
8731 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8734 MonoReflectionTypeBuilder *tb = NULL;
8735 gboolean is_dynamic = FALSE;
8739 mono_loader_lock ();
8741 domain = mono_object_domain (type);
8743 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8744 tb = (MonoReflectionTypeBuilder *) type;
8747 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8748 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8749 MonoReflectionType *rgt = rgi->generic_type;
8751 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8752 tb = (MonoReflectionTypeBuilder *) rgt;
8757 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8758 if (tb && tb->generic_container)
8759 mono_reflection_create_generic_class (tb);
8761 klass = mono_class_from_mono_type (type->type);
8762 if (!klass->generic_container) {
8763 mono_loader_unlock ();
8767 if (klass->wastypebuilder) {
8768 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8773 mono_loader_unlock ();
8775 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8777 return &geninst->byval_arg;
8781 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8783 MonoGenericClass *gclass;
8784 MonoGenericInst *inst;
8786 g_assert (klass->generic_container);
8788 inst = mono_metadata_get_generic_inst (type_argc, types);
8789 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8791 return mono_generic_class_get_class (gclass);
8794 static inline MonoType*
8795 dup_type (const MonoType *original)
8797 MonoType *r = g_new0 (MonoType, 1);
8799 r->attrs = original->attrs;
8800 r->byref = original->byref;
8801 if (original->type == MONO_TYPE_PTR)
8802 r->data.type = dup_type (original->data.type);
8803 else if (original->type == MONO_TYPE_ARRAY)
8804 r->data.array = mono_dup_array_type (original->data.array);
8805 else if (original->type == MONO_TYPE_FNPTR)
8806 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8807 mono_stats.generics_metadata_size += sizeof (MonoType);
8811 MonoReflectionMethod*
8812 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8815 MonoMethod *method, *inflated;
8816 MonoMethodInflated *imethod;
8817 MonoReflectionMethodBuilder *mb = NULL;
8818 MonoGenericContext tmp_context;
8819 MonoGenericInst *ginst;
8820 MonoType **type_argv;
8823 MONO_ARCH_SAVE_REGS;
8824 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8825 MonoReflectionTypeBuilder *tb;
8828 mb = (MonoReflectionMethodBuilder *) rmethod;
8829 tb = (MonoReflectionTypeBuilder *) mb->type;
8830 klass = mono_class_from_mono_type (tb->type.type);
8832 method = methodbuilder_to_mono_method (klass, mb);
8834 method = rmethod->method;
8837 klass = method->klass;
8839 if (method->is_inflated)
8840 method = ((MonoMethodInflated *) method)->declaring;
8842 count = mono_method_signature (method)->generic_param_count;
8843 if (count != mono_array_length (types))
8846 type_argv = g_new0 (MonoType *, count);
8847 for (i = 0; i < count; i++) {
8848 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8849 type_argv [i] = garg->type;
8851 ginst = mono_metadata_get_generic_inst (count, type_argv);
8854 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8855 tmp_context.method_inst = ginst;
8857 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8858 imethod = (MonoMethodInflated *) inflated;
8860 MOVING_GC_REGISTER (&imethod->reflection_info);
8861 imethod->reflection_info = rmethod;
8863 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8867 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8869 MonoMethodInflated *imethod;
8870 MonoGenericContext tmp_context;
8871 MonoGenericContext *context;
8874 klass = mono_class_from_mono_type (type->type.type);
8875 g_assert (klass->generic_class);
8876 context = mono_class_get_context (klass);
8878 if (method->generic_container) {
8879 g_assert (method->klass == klass->generic_class->container_class);
8881 tmp_context.class_inst = klass->generic_class->context.class_inst;
8882 tmp_context.method_inst = method->generic_container->context.method_inst;
8883 context = &tmp_context;
8886 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8887 if (method->generic_container) {
8888 MOVING_GC_REGISTER (&imethod->reflection_info);
8889 imethod->reflection_info = obj;
8891 return (MonoMethod *) imethod;
8895 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8900 gklass = mono_class_from_mono_type (type->generic_type->type);
8902 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8903 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8904 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8905 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8906 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8907 method = ((MonoReflectionMethod *) obj)->method;
8909 method = NULL; /* prevent compiler warning */
8910 g_assert_not_reached ();
8913 return inflate_mono_method (type, method, obj);
8917 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8918 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8921 MonoGenericClass *gclass;
8922 MonoDynamicGenericClass *dgclass;
8923 MonoClass *klass, *gklass;
8926 MONO_ARCH_SAVE_REGS;
8928 klass = mono_class_from_mono_type (type->type.type);
8929 gclass = type->type.type->data.generic_class;
8931 g_assert (gclass->is_dynamic);
8932 dgclass = (MonoDynamicGenericClass *) gclass;
8934 if (dgclass->initialized)
8937 gklass = gclass->container_class;
8938 mono_class_init (gklass);
8940 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8941 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8942 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8943 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8944 dgclass->count_events = events ? mono_array_length (events) : 0;
8946 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8947 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8948 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8949 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8950 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8952 for (i = 0; i < dgclass->count_methods; i++) {
8953 MonoObject *obj = mono_array_get (methods, gpointer, i);
8955 dgclass->methods [i] = inflate_method (type, obj);
8958 for (i = 0; i < dgclass->count_ctors; i++) {
8959 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8961 dgclass->ctors [i] = inflate_method (type, obj);
8964 for (i = 0; i < dgclass->count_fields; i++) {
8965 MonoObject *obj = mono_array_get (fields, gpointer, i);
8966 MonoClassField *field;
8967 MonoInflatedField *ifield;
8969 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8970 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8971 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8972 field = ((MonoReflectionField *) obj)->field;
8974 field = NULL; /* prevent compiler warning */
8975 g_assert_not_reached ();
8978 ifield = g_new0 (MonoInflatedField, 1);
8979 ifield->generic_type = field->type;
8980 MOVING_GC_REGISTER (&ifield->reflection_info);
8981 ifield->reflection_info = obj;
8983 dgclass->fields [i] = *field;
8984 dgclass->fields [i].parent = klass;
8985 dgclass->fields [i].generic_info = ifield;
8986 dgclass->fields [i].type = mono_class_inflate_generic_type (
8987 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
8990 for (i = 0; i < dgclass->count_properties; i++) {
8991 MonoObject *obj = mono_array_get (properties, gpointer, i);
8992 MonoProperty *property = &dgclass->properties [i];
8994 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8995 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8997 property->parent = klass;
8998 property->attrs = pb->attrs;
8999 property->name = mono_string_to_utf8 (pb->name);
9001 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9003 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9004 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9005 *property = *((MonoReflectionProperty *) obj)->property;
9008 property->get = inflate_mono_method (type, property->get, NULL);
9010 property->set = inflate_mono_method (type, property->set, NULL);
9012 g_assert_not_reached ();
9015 for (i = 0; i < dgclass->count_events; i++) {
9016 MonoObject *obj = mono_array_get (events, gpointer, i);
9017 MonoEvent *event = &dgclass->events [i];
9019 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9020 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9022 event->parent = klass;
9023 event->attrs = eb->attrs;
9024 event->name = mono_string_to_utf8 (eb->name);
9026 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9027 if (eb->remove_method)
9028 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9029 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9030 *event = *((MonoReflectionEvent *) obj)->event;
9033 event->add = inflate_mono_method (type, event->add, NULL);
9035 event->remove = inflate_mono_method (type, event->remove, NULL);
9037 g_assert_not_reached ();
9040 dgclass->initialized = TRUE;
9044 ensure_runtime_vtable (MonoClass *klass)
9046 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9049 if (!tb || klass->wastypebuilder)
9052 ensure_runtime_vtable (klass->parent);
9054 num = tb->ctors? mono_array_length (tb->ctors): 0;
9055 num += tb->num_methods;
9056 klass->method.count = num;
9057 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9058 num = tb->ctors? mono_array_length (tb->ctors): 0;
9059 for (i = 0; i < num; ++i)
9060 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9061 num = tb->num_methods;
9063 for (i = 0; i < num; ++i)
9064 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9066 if (tb->interfaces) {
9067 klass->interface_count = mono_array_length (tb->interfaces);
9068 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9069 for (i = 0; i < klass->interface_count; ++i) {
9070 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9071 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9075 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9076 for (i = 0; i < klass->method.count; ++i)
9077 klass->methods [i]->slot = i;
9079 mono_class_setup_interface_offsets (klass);
9083 * The generic vtable is needed even if image->run is not set since some
9084 * runtime code like ves_icall_Type_GetMethodsByName depends on
9085 * method->slot being defined.
9089 * tb->methods could not be freed since it is used for determining
9090 * overrides during dynamic vtable construction.
9095 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9097 MonoReflectionTypeBuilder *tb;
9103 g_assert (klass->image->dynamic);
9105 if (!klass->reflection_info)
9108 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9110 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9114 for (i = 0; i < tb->num_methods; ++i) {
9115 MonoReflectionMethodBuilder *mb =
9116 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9117 if (mb->override_method)
9123 *overrides = g_new0 (MonoMethod*, onum * 2);
9126 for (i = 0; i < tb->num_methods; ++i) {
9127 MonoReflectionMethodBuilder *mb =
9128 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9129 if (mb->override_method) {
9130 (*overrides) [onum * 2] =
9131 mb->override_method->method;
9132 (*overrides) [onum * 2 + 1] =
9135 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9136 g_assert (mb->override_method->method);
9137 g_assert (mb->mhandle);
9144 *num_overrides = onum;
9148 typebuilder_setup_fields (MonoClass *klass)
9150 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9151 MonoReflectionFieldBuilder *fb;
9152 MonoClassField *field;
9157 klass->field.count = tb->num_fields;
9158 klass->field.first = 0;
9160 if (!klass->field.count)
9163 klass->fields = g_new0 (MonoClassField, klass->field.count);
9165 for (i = 0; i < klass->field.count; ++i) {
9166 fb = mono_array_get (tb->fields, gpointer, i);
9167 field = &klass->fields [i];
9168 field->name = mono_string_to_utf8 (fb->name);
9170 /* FIXME: handle type modifiers */
9171 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9172 field->type->attrs = fb->attrs;
9174 field->type = fb->type->type;
9176 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9177 field->data = mono_array_addr (fb->rva_data, char, 0);
9178 if (fb->offset != -1)
9179 field->offset = fb->offset;
9180 field->parent = klass;
9182 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9184 if (fb->def_value) {
9185 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9186 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9187 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9188 /* Copy the data from the blob since it might get realloc-ed */
9189 p = assembly->blob.data + idx;
9190 len = mono_metadata_decode_blob_size (p, &p2);
9192 field->data = g_malloc (len);
9193 memcpy ((gpointer)field->data, p, len);
9196 mono_class_layout_fields (klass);
9200 typebuilder_setup_properties (MonoClass *klass)
9202 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9203 MonoReflectionPropertyBuilder *pb;
9206 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9207 klass->property.first = 0;
9209 klass->properties = g_new0 (MonoProperty, klass->property.count);
9210 for (i = 0; i < klass->property.count; ++i) {
9211 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9212 klass->properties [i].parent = klass;
9213 klass->properties [i].attrs = pb->attrs;
9214 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9216 klass->properties [i].get = pb->get_method->mhandle;
9218 klass->properties [i].set = pb->set_method->mhandle;
9220 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9224 MonoReflectionEvent *
9225 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9227 MonoEvent *event = g_new0 (MonoEvent, 1);
9231 klass = my_mono_class_from_mono_type (tb->type.type);
9233 event->parent = klass;
9234 event->attrs = eb->attrs;
9235 event->name = mono_string_to_utf8 (eb->name);
9237 event->add = eb->add_method->mhandle;
9238 if (eb->remove_method)
9239 event->remove = eb->remove_method->mhandle;
9240 if (eb->raise_method)
9241 event->raise = eb->raise_method->mhandle;
9243 if (eb->other_methods) {
9244 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9245 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9246 MonoReflectionMethodBuilder *mb =
9247 mono_array_get (eb->other_methods,
9248 MonoReflectionMethodBuilder*, j);
9249 event->other [j] = mb->mhandle;
9253 return mono_event_get_object (mono_object_domain (tb), klass, event);
9257 typebuilder_setup_events (MonoClass *klass)
9259 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9260 MonoReflectionEventBuilder *eb;
9263 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9264 klass->event.first = 0;
9266 klass->events = g_new0 (MonoEvent, klass->event.count);
9267 for (i = 0; i < klass->event.count; ++i) {
9268 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9269 klass->events [i].parent = klass;
9270 klass->events [i].attrs = eb->attrs;
9271 klass->events [i].name = mono_string_to_utf8 (eb->name);
9273 klass->events [i].add = eb->add_method->mhandle;
9274 if (eb->remove_method)
9275 klass->events [i].remove = eb->remove_method->mhandle;
9276 if (eb->raise_method)
9277 klass->events [i].raise = eb->raise_method->mhandle;
9279 if (eb->other_methods) {
9280 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9281 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9282 MonoReflectionMethodBuilder *mb =
9283 mono_array_get (eb->other_methods,
9284 MonoReflectionMethodBuilder*, j);
9285 klass->events [i].other [j] = mb->mhandle;
9292 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9296 MonoReflectionType* res;
9299 MONO_ARCH_SAVE_REGS;
9301 domain = mono_object_domain (tb);
9302 klass = my_mono_class_from_mono_type (tb->type.type);
9304 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9307 * we need to lock the domain because the lock will be taken inside
9308 * So, we need to keep the locking order correct.
9310 mono_domain_lock (domain);
9311 mono_loader_lock ();
9312 if (klass->wastypebuilder) {
9313 mono_loader_unlock ();
9314 mono_domain_unlock (domain);
9315 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9318 * Fields to set in klass:
9319 * the various flags: delegate/unicode/contextbound etc.
9321 klass->flags = tb->attrs;
9322 klass->has_cctor = 1;
9323 klass->has_finalize = 1;
9326 if (!((MonoDynamicImage*)klass->image)->run) {
9327 if (klass->generic_container) {
9328 /* FIXME: The code below can't handle generic classes */
9329 klass->wastypebuilder = TRUE;
9330 mono_loader_unlock ();
9331 mono_domain_unlock (domain);
9332 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9337 /* enums are done right away */
9338 if (!klass->enumtype)
9339 ensure_runtime_vtable (klass);
9342 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9343 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9344 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9348 /* fields and object layout */
9349 if (klass->parent) {
9350 if (!klass->parent->size_inited)
9351 mono_class_init (klass->parent);
9352 klass->instance_size = klass->parent->instance_size;
9353 klass->sizes.class_size = 0;
9354 klass->min_align = klass->parent->min_align;
9355 /* if the type has no fields we won't call the field_setup
9356 * routine which sets up klass->has_references.
9358 klass->has_references |= klass->parent->has_references;
9360 klass->instance_size = sizeof (MonoObject);
9361 klass->min_align = 1;
9364 /* FIXME: handle packing_size and instance_size */
9365 typebuilder_setup_fields (klass);
9367 typebuilder_setup_properties (klass);
9369 typebuilder_setup_events (klass);
9371 klass->wastypebuilder = TRUE;
9372 mono_loader_unlock ();
9373 mono_domain_unlock (domain);
9375 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9376 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9377 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9380 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9381 g_assert (res != (MonoReflectionType*)tb);
9387 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9389 MonoGenericParam *param;
9392 MONO_ARCH_SAVE_REGS;
9394 param = g_new0 (MonoGenericParam, 1);
9396 if (gparam->mbuilder) {
9397 if (!gparam->mbuilder->generic_container)
9398 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9399 param->owner = gparam->mbuilder->generic_container;
9400 } else if (gparam->tbuilder) {
9401 g_assert (gparam->tbuilder->generic_container);
9402 param->owner = gparam->tbuilder->generic_container;
9405 param->name = mono_string_to_utf8 (gparam->name);
9406 param->num = gparam->index;
9408 image = &gparam->tbuilder->module->dynamic_image->image;
9409 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9411 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9412 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9414 gparam->type.type = g_new0 (MonoType, 1);
9415 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9416 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9417 gparam->type.type->data.generic_param = param;
9421 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9423 MonoDynamicImage *assembly = sig->module->dynamic_image;
9424 guint32 na = mono_array_length (sig->arguments);
9429 sigbuffer_init (&buf, 32);
9431 sigbuffer_add_value (&buf, 0x07);
9432 sigbuffer_add_value (&buf, na);
9433 for (i = 0; i < na; ++i) {
9434 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9435 encode_reflection_type (assembly, type, &buf);
9438 buflen = buf.p - buf.buf;
9439 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9440 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9441 sigbuffer_free (&buf);
9447 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9449 MonoDynamicImage *assembly = sig->module->dynamic_image;
9450 guint32 na = mono_array_length (sig->arguments);
9455 sigbuffer_init (&buf, 32);
9457 sigbuffer_add_value (&buf, 0x06);
9458 for (i = 0; i < na; ++i) {
9459 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9460 encode_reflection_type (assembly, type, &buf);
9463 buflen = buf.p - buf.buf;
9464 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9465 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9466 sigbuffer_free (&buf);
9472 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9474 ReflectionMethodBuilder rmb;
9475 MonoMethodSignature *sig;
9479 sig = dynamic_method_to_signature (mb);
9481 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9484 * Resolve references.
9487 * Every second entry in the refs array is reserved for storing handle_class,
9488 * which is needed by the ldtoken implementation in the JIT.
9490 rmb.nrefs = mb->nrefs;
9491 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9492 for (i = 0; i < mb->nrefs; i += 2) {
9493 MonoClass *handle_class;
9495 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9497 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9498 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9500 * The referenced DynamicMethod should already be created by the managed
9501 * code, except in the case of circular references. In that case, we store
9502 * method in the refs array, and fix it up later when the referenced
9503 * DynamicMethod is created.
9505 if (method->mhandle) {
9506 ref = method->mhandle;
9508 /* FIXME: GC object stored in unmanaged memory */
9511 /* FIXME: GC object stored in unmanaged memory */
9512 method->referenced_by = g_slist_append (method->referenced_by, mb);
9514 handle_class = mono_defaults.methodhandle_class;
9516 ref = resolve_object (mb->module->image, obj, &handle_class);
9519 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9524 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9525 rmb.refs [i + 1] = handle_class;
9529 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9531 /* Fix up refs entries pointing at us */
9532 for (l = mb->referenced_by; l; l = l->next) {
9533 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9534 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9537 g_assert (method->mhandle);
9539 data = (gpointer*)wrapper->method_data;
9540 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9541 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9542 data [i + 1] = mb->mhandle;
9545 g_slist_free (mb->referenced_by);
9549 /* ilgen is no longer needed */
9554 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9559 mono_runtime_free_method (
9560 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9564 * mono_reflection_lookup_dynamic_token:
9566 * Finish the Builder object pointed to by TOKEN and return the corresponding
9567 * runtime structure. HANDLE_CLASS is set to the class required by
9571 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9573 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9576 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9579 return resolve_object (image, obj, handle_class);
9583 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9585 gpointer result = NULL;
9587 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9588 result = mono_string_intern ((MonoString*)obj);
9589 *handle_class = NULL;
9591 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9592 MonoReflectionType *tb = (MonoReflectionType*)obj;
9593 result = mono_class_from_mono_type (tb->type);
9594 *handle_class = mono_defaults.typehandle_class;
9596 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9597 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9598 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9599 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9600 result = ((MonoReflectionMethod*)obj)->method;
9601 *handle_class = mono_defaults.methodhandle_class;
9603 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9604 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9605 result = mb->mhandle;
9607 /* Type is not yet created */
9608 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9610 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9613 * Hopefully this has been filled in by calling CreateType() on the
9617 * TODO: This won't work if the application finishes another
9618 * TypeBuilder instance instead of this one.
9620 result = mb->mhandle;
9622 *handle_class = mono_defaults.methodhandle_class;
9623 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9624 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9626 result = cb->mhandle;
9628 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9630 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9631 result = cb->mhandle;
9633 *handle_class = mono_defaults.methodhandle_class;
9634 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9635 result = ((MonoReflectionField*)obj)->field;
9636 *handle_class = mono_defaults.fieldhandle_class;
9638 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9639 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9640 result = fb->handle;
9643 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9645 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9646 result = fb->handle;
9648 *handle_class = mono_defaults.fieldhandle_class;
9649 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9650 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9653 klass = tb->type.type->data.klass;
9654 if (klass->wastypebuilder) {
9655 /* Already created */
9659 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9660 result = tb->type.type->data.klass;
9663 *handle_class = mono_defaults.typehandle_class;
9664 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9665 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9666 MonoMethodSignature *sig;
9669 if (helper->arguments)
9670 nargs = mono_array_length (helper->arguments);
9674 sig = mono_metadata_signature_alloc (image, nargs);
9675 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9676 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9678 if (helper->call_conv == 0) /* unmanaged */
9679 sig->call_convention = helper->unmanaged_call_conv - 1;
9681 if (helper->call_conv & 0x02)
9682 sig->call_convention = MONO_CALL_VARARG;
9684 sig->call_convention = MONO_CALL_DEFAULT;
9686 sig->param_count = nargs;
9687 /* TODO: Copy type ? */
9688 sig->ret = helper->return_type->type;
9689 for (i = 0; i < nargs; ++i) {
9690 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9691 sig->params [i] = rt->type;
9695 *handle_class = NULL;
9696 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9697 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9698 /* Already created by the managed code */
9699 g_assert (method->mhandle);
9700 result = method->mhandle;
9701 *handle_class = mono_defaults.methodhandle_class;
9703 g_print (obj->vtable->klass->name);
9704 g_assert_not_reached ();
9710 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9711 const static guint32 declsec_flags_map[] = {
9712 0x00000000, /* empty */
9713 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9714 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9715 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9716 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9717 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9718 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9719 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9720 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9721 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9722 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9723 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9724 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9725 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9726 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9727 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9728 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9729 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9730 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9734 * Returns flags that includes all available security action associated to the handle.
9735 * @token: metadata token (either for a class or a method)
9736 * @image: image where resides the metadata.
9739 mono_declsec_get_flags (MonoImage *image, guint32 token)
9741 int index = mono_metadata_declsec_from_index (image, token);
9742 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9747 /* HasSecurity can be present for other, not specially encoded, attributes,
9748 e.g. SuppressUnmanagedCodeSecurityAttribute */
9752 for (i = index; i < t->rows; i++) {
9753 guint32 cols [MONO_DECL_SECURITY_SIZE];
9755 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9756 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9759 action = cols [MONO_DECL_SECURITY_ACTION];
9760 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9761 result |= declsec_flags_map [action];
9763 g_assert_not_reached ();
9770 * Get the security actions (in the form of flags) associated with the specified method.
9772 * @method: The method for which we want the declarative security flags.
9773 * Return the declarative security flags for the method (only).
9775 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9776 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9779 mono_declsec_flags_from_method (MonoMethod *method)
9781 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9782 /* FIXME: No cache (for the moment) */
9783 guint32 idx = mono_method_get_index (method);
9784 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9785 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9786 return mono_declsec_get_flags (method->klass->image, idx);
9792 * Get the security actions (in the form of flags) associated with the specified class.
9794 * @klass: The class for which we want the declarative security flags.
9795 * Return the declarative security flags for the class.
9797 * Note: We cache the flags inside the MonoClass structure as this will get
9798 * called very often (at least for each method).
9801 mono_declsec_flags_from_class (MonoClass *klass)
9803 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9804 if (!klass->declsec_flags) {
9805 guint32 idx = mono_metadata_token_index (klass->type_token);
9806 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9807 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9808 /* we cache the flags on classes */
9809 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9811 return klass->declsec_flags;
9817 * Get the security actions (in the form of flags) associated with the specified assembly.
9819 * @assembly: The assembly for which we want the declarative security flags.
9820 * Return the declarative security flags for the assembly.
9823 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9825 guint32 idx = 1; /* there is only one assembly */
9826 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9827 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9828 return mono_declsec_get_flags (assembly->image, idx);
9833 * Fill actions for the specific index (which may either be an encoded class token or
9834 * an encoded method token) from the metadata image.
9835 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9838 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9839 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9841 MonoBoolean result = FALSE;
9843 guint32 cols [MONO_DECL_SECURITY_SIZE];
9844 int index = mono_metadata_declsec_from_index (image, token);
9847 t = &image->tables [MONO_TABLE_DECLSECURITY];
9848 for (i = index; i < t->rows; i++) {
9849 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9851 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9854 /* if present only replace (class) permissions with method permissions */
9855 /* if empty accept either class or method permissions */
9856 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9857 if (!actions->demand.blob) {
9858 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9859 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9860 actions->demand.blob = (char*) (blob + 2);
9861 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9864 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9865 if (!actions->noncasdemand.blob) {
9866 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9867 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9868 actions->noncasdemand.blob = (char*) (blob + 2);
9869 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9872 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9873 if (!actions->demandchoice.blob) {
9874 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9875 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9876 actions->demandchoice.blob = (char*) (blob + 2);
9877 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9887 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9888 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9890 guint32 idx = mono_metadata_token_index (klass->type_token);
9891 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9892 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9893 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9897 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9898 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9900 guint32 idx = mono_method_get_index (method);
9901 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9902 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9903 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9907 * Collect all actions (that requires to generate code in mini) assigned for
9908 * the specified method.
9909 * Note: Don't use the content of actions if the function return FALSE.
9912 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9914 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9915 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9916 MonoBoolean result = FALSE;
9919 /* quick exit if no declarative security is present in the metadata */
9920 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9923 /* we want the original as the wrapper is "free" of the security informations */
9924 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9925 method = mono_marshal_method_from_wrapper (method);
9930 /* First we look for method-level attributes */
9931 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9932 mono_class_init (method->klass);
9933 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9935 result = mono_declsec_get_method_demands_params (method, demands,
9936 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9939 /* Here we use (or create) the class declarative cache to look for demands */
9940 flags = mono_declsec_flags_from_class (method->klass);
9943 mono_class_init (method->klass);
9944 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9946 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9947 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9950 /* The boolean return value is used as a shortcut in case nothing needs to
9951 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9957 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9959 * Note: Don't use the content of actions if the function return FALSE.
9962 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9964 MonoBoolean result = FALSE;
9967 /* quick exit if no declarative security is present in the metadata */
9968 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9971 /* we want the original as the wrapper is "free" of the security informations */
9972 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9973 method = mono_marshal_method_from_wrapper (method);
9978 /* results are independant - zeroize both */
9979 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9980 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9982 /* First we look for method-level attributes */
9983 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9984 mono_class_init (method->klass);
9986 result = mono_declsec_get_method_demands_params (method, cmethod,
9987 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9990 /* Here we use (or create) the class declarative cache to look for demands */
9991 flags = mono_declsec_flags_from_class (method->klass);
9992 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9993 mono_class_init (method->klass);
9995 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9996 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10003 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10005 * @klass The inherited class - this is the class that provides the security check (attributes)
10007 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10009 * Note: Don't use the content of actions if the function return FALSE.
10012 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10014 MonoBoolean result = FALSE;
10017 /* quick exit if no declarative security is present in the metadata */
10018 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10021 /* Here we use (or create) the class declarative cache to look for demands */
10022 flags = mono_declsec_flags_from_class (klass);
10023 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10024 mono_class_init (klass);
10025 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10027 result |= mono_declsec_get_class_demands_params (klass, demands,
10028 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10035 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10037 * Note: Don't use the content of actions if the function return FALSE.
10040 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10042 /* quick exit if no declarative security is present in the metadata */
10043 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10046 /* we want the original as the wrapper is "free" of the security informations */
10047 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10048 method = mono_marshal_method_from_wrapper (method);
10053 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10054 mono_class_init (method->klass);
10055 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10057 return mono_declsec_get_method_demands_params (method, demands,
10058 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10065 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10067 guint32 cols [MONO_DECL_SECURITY_SIZE];
10071 int index = mono_metadata_declsec_from_index (image, token);
10075 t = &image->tables [MONO_TABLE_DECLSECURITY];
10076 for (i = index; i < t->rows; i++) {
10077 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10079 /* shortcut - index are ordered */
10080 if (token != cols [MONO_DECL_SECURITY_PARENT])
10083 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10084 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10085 entry->blob = (char*) (metadata + 2);
10086 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10095 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10097 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10098 guint32 idx = mono_method_get_index (method);
10099 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10100 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10101 return get_declsec_action (method->klass->image, idx, action, entry);
10107 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10110 guint32 flags = mono_declsec_flags_from_class (klass);
10111 if (declsec_flags_map [action] & flags) {
10112 guint32 idx = mono_metadata_token_index (klass->type_token);
10113 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10114 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10115 return get_declsec_action (klass->image, idx, action, entry);
10121 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10123 guint32 idx = 1; /* there is only one assembly */
10124 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10125 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10127 return get_declsec_action (assembly->image, idx, action, entry);
10131 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10133 MonoObject *res, *exc;
10135 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10136 static MonoMethod *method = NULL;
10138 if (!System_Reflection_Emit_TypeBuilder) {
10139 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10140 g_assert (System_Reflection_Emit_TypeBuilder);
10142 if (method == NULL) {
10143 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10148 * The result of mono_type_get_object () might be a System.MonoType but we
10149 * need a TypeBuilder so use klass->reflection_info.
10151 g_assert (klass->reflection_info);
10152 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10154 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10156 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10160 return *(MonoBoolean*)mono_object_unbox (res);