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_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
138 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
139 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
140 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
141 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
142 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
143 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
144 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
145 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
146 static void ensure_runtime_vtable (MonoClass *klass);
147 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
148 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
149 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
150 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
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;
588 class_inst = gclass->context.class_inst;
590 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
591 klass = gclass->container_class;
592 sigbuffer_add_value (buf, klass->byval_arg.type);
593 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
595 sigbuffer_add_value (buf, class_inst->type_argc);
596 for (i = 0; i < class_inst->type_argc; ++i)
597 encode_type (assembly, class_inst->type_argv [i], buf);
602 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
605 g_assert_not_reached ();
610 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
614 case MONO_TYPE_BOOLEAN:
628 case MONO_TYPE_STRING:
629 case MONO_TYPE_OBJECT:
630 case MONO_TYPE_TYPEDBYREF:
631 sigbuffer_add_value (buf, type->type);
634 sigbuffer_add_value (buf, type->type);
635 encode_type (assembly, type->data.type, buf);
637 case MONO_TYPE_SZARRAY:
638 sigbuffer_add_value (buf, type->type);
639 encode_type (assembly, &type->data.klass->byval_arg, buf);
641 case MONO_TYPE_VALUETYPE:
642 case MONO_TYPE_CLASS: {
643 MonoClass *k = mono_class_from_mono_type (type);
645 if (k->generic_container) {
646 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
647 encode_generic_class (assembly, gclass, buf);
650 * Make sure we use the correct type.
652 sigbuffer_add_value (buf, k->byval_arg.type);
654 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
655 * otherwise two typerefs could point to the same type, leading to
656 * verification errors.
658 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
662 case MONO_TYPE_ARRAY:
663 sigbuffer_add_value (buf, type->type);
664 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
665 sigbuffer_add_value (buf, type->data.array->rank);
666 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
667 sigbuffer_add_value (buf, 0);
669 case MONO_TYPE_GENERICINST:
670 encode_generic_class (assembly, type->data.generic_class, buf);
674 sigbuffer_add_value (buf, type->type);
675 sigbuffer_add_value (buf, type->data.generic_param->num);
678 g_error ("need to encode type %x", type->type);
683 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
686 sigbuffer_add_value (buf, MONO_TYPE_VOID);
691 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
692 encode_type (assembly, type->type, buf);
696 g_assert_not_reached ();
701 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
706 for (i = 0; i < mono_array_length (modreq); ++i) {
707 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
708 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
709 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
713 for (i = 0; i < mono_array_length (modopt); ++i) {
714 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
715 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
716 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
722 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
726 guint32 nparams = sig->param_count;
732 sigbuffer_init (&buf, 32);
734 * FIXME: vararg, explicit_this, differenc call_conv values...
736 idx = sig->call_convention;
738 idx |= 0x20; /* hasthis */
739 if (sig->generic_param_count)
740 idx |= 0x10; /* generic */
741 sigbuffer_add_byte (&buf, idx);
742 if (sig->generic_param_count)
743 sigbuffer_add_value (&buf, sig->generic_param_count);
744 sigbuffer_add_value (&buf, nparams);
745 encode_type (assembly, sig->ret, &buf);
746 for (i = 0; i < nparams; ++i) {
747 if (i == sig->sentinelpos)
748 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
749 encode_type (assembly, sig->params [i], &buf);
751 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
752 sigbuffer_free (&buf);
757 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
760 * FIXME: reuse code from method_encode_signature().
764 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
765 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
766 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
769 sigbuffer_init (&buf, 32);
770 /* LAMESPEC: all the call conv spec is foobared */
771 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
772 if (mb->call_conv & 2)
773 idx |= 0x5; /* vararg */
774 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
775 idx |= 0x20; /* hasthis */
777 idx |= 0x10; /* generic */
778 sigbuffer_add_byte (&buf, idx);
780 sigbuffer_add_value (&buf, ngparams);
781 sigbuffer_add_value (&buf, nparams + notypes);
782 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
783 encode_reflection_type (assembly, mb->rtype, &buf);
784 for (i = 0; i < nparams; ++i) {
785 MonoArray *modreq = NULL;
786 MonoArray *modopt = NULL;
787 MonoReflectionType *pt;
789 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
790 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
791 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
792 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
793 encode_custom_modifiers (assembly, modreq, modopt, &buf);
794 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
795 encode_reflection_type (assembly, pt, &buf);
798 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
799 for (i = 0; i < notypes; ++i) {
800 MonoReflectionType *pt;
802 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
803 encode_reflection_type (assembly, pt, &buf);
806 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
807 sigbuffer_free (&buf);
812 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
814 MonoDynamicTable *table;
816 guint32 idx, sig_idx;
817 guint nl = mono_array_length (ilgen->locals);
821 sigbuffer_init (&buf, 32);
822 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
823 idx = table->next_idx ++;
825 alloc_table (table, table->rows);
826 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
828 sigbuffer_add_value (&buf, 0x07);
829 sigbuffer_add_value (&buf, nl);
830 for (i = 0; i < nl; ++i) {
831 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
834 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
836 encode_reflection_type (assembly, lb->type, &buf);
838 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
839 sigbuffer_free (&buf);
841 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
847 method_count_clauses (MonoReflectionILGen *ilgen)
849 guint32 num_clauses = 0;
852 MonoILExceptionInfo *ex_info;
853 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
854 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
855 if (ex_info->handlers)
856 num_clauses += mono_array_length (ex_info->handlers);
864 static MonoExceptionClause*
865 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
867 MonoExceptionClause *clauses;
868 MonoExceptionClause *clause;
869 MonoILExceptionInfo *ex_info;
870 MonoILExceptionBlock *ex_block;
871 guint32 finally_start;
872 int i, j, clause_index;;
874 clauses = g_new0 (MonoExceptionClause, num_clauses);
877 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
878 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
879 finally_start = ex_info->start + ex_info->len;
880 if (!ex_info->handlers)
882 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
883 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
884 clause = &(clauses [clause_index]);
886 clause->flags = ex_block->type;
887 clause->try_offset = ex_info->start;
889 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
890 clause->try_len = finally_start - ex_info->start;
892 clause->try_len = ex_info->len;
893 clause->handler_offset = ex_block->start;
894 clause->handler_len = ex_block->len;
895 if (ex_block->extype) {
896 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
898 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
899 clause->data.filter_offset = ex_block->filter_offset;
901 clause->data.filter_offset = 0;
903 finally_start = ex_block->start + ex_block->len;
913 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
919 gint32 num_locals = 0;
920 gint32 num_exception = 0;
923 char fat_header [12];
926 guint32 local_sig = 0;
927 guint32 header_size = 12;
930 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
931 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
935 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
937 code = mb->ilgen->code;
938 code_size = mb->ilgen->code_len;
939 max_stack = mb->ilgen->max_stack;
940 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
941 if (mb->ilgen->ex_handlers)
942 num_exception = method_count_clauses (mb->ilgen);
946 char *name = mono_string_to_utf8 (mb->name);
947 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
948 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
951 mono_raise_exception (exception);
954 code_size = mono_array_length (code);
955 max_stack = 8; /* we probably need to run a verifier on the code... */
958 stream_data_align (&assembly->code);
960 /* check for exceptions, maxstack, locals */
961 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
963 if (code_size < 64 && !(code_size & 1)) {
964 flags = (code_size << 2) | 0x2;
965 } else if (code_size < 32 && (code_size & 1)) {
966 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
970 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
971 /* add to the fixup todo list */
972 if (mb->ilgen && mb->ilgen->num_token_fixups)
973 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
974 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
975 return assembly->text_rva + idx;
979 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
981 * FIXME: need to set also the header size in fat_flags.
982 * (and more sects and init locals flags)
986 fat_flags |= METHOD_HEADER_MORE_SECTS;
988 fat_flags |= METHOD_HEADER_INIT_LOCALS;
989 fat_header [0] = fat_flags;
990 fat_header [1] = (header_size / 4 ) << 4;
991 short_value = GUINT16_TO_LE (max_stack);
992 memcpy (fat_header + 2, &short_value, 2);
993 int_value = GUINT32_TO_LE (code_size);
994 memcpy (fat_header + 4, &int_value, 4);
995 int_value = GUINT32_TO_LE (local_sig);
996 memcpy (fat_header + 8, &int_value, 4);
997 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
998 /* add to the fixup todo list */
999 if (mb->ilgen && mb->ilgen->num_token_fixups)
1000 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1002 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1003 if (num_exception) {
1004 unsigned char sheader [4];
1005 MonoILExceptionInfo * ex_info;
1006 MonoILExceptionBlock * ex_block;
1009 stream_data_align (&assembly->code);
1010 /* always use fat format for now */
1011 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1012 num_exception *= 6 * sizeof (guint32);
1013 num_exception += 4; /* include the size of the header */
1014 sheader [1] = num_exception & 0xff;
1015 sheader [2] = (num_exception >> 8) & 0xff;
1016 sheader [3] = (num_exception >> 16) & 0xff;
1017 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1018 /* fat header, so we are already aligned */
1020 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1021 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1022 if (ex_info->handlers) {
1023 int finally_start = ex_info->start + ex_info->len;
1024 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1026 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1028 val = GUINT32_TO_LE (ex_block->type);
1029 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1031 val = GUINT32_TO_LE (ex_info->start);
1032 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1033 /* need fault, too, probably */
1034 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1035 val = GUINT32_TO_LE (finally_start - ex_info->start);
1037 val = GUINT32_TO_LE (ex_info->len);
1038 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1039 /* handler offset */
1040 val = GUINT32_TO_LE (ex_block->start);
1041 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1043 val = GUINT32_TO_LE (ex_block->len);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1045 finally_start = ex_block->start + ex_block->len;
1046 if (ex_block->extype) {
1047 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1049 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1050 val = ex_block->filter_offset;
1054 val = GUINT32_TO_LE (val);
1055 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1056 /*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",
1057 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);*/
1060 g_error ("No clauses for ex info block %d", i);
1064 return assembly->text_rva + idx;
1068 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1071 MonoDynamicTable *table;
1074 table = &assembly->tables [table_idx];
1076 g_assert (col < table->columns);
1078 values = table->values + table->columns;
1079 for (i = 1; i <= table->rows; ++i) {
1080 if (values [col] == token)
1082 values += table->columns;
1087 /* protected by reflection_mutex:
1088 * maps a mono runtime reflection handle to MonoCustomAttrInfo*
1090 static GHashTable *dynamic_custom_attrs = NULL;
1092 static MonoCustomAttrInfo*
1093 lookup_custom_attr (void *member)
1095 MonoCustomAttrInfo *ainfo, *res;
1098 mono_reflection_lock ();
1099 ainfo = g_hash_table_lookup (dynamic_custom_attrs, member);
1100 mono_reflection_unlock ();
1103 /* Need to copy since it will be freed later */
1104 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
1105 res = g_malloc0 (size);
1106 memcpy (res, ainfo, size);
1113 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1115 /* FIXME: Need to do more checks */
1116 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1117 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1119 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1126 static MonoCustomAttrInfo*
1127 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1129 int i, index, count, not_visible;
1130 MonoCustomAttrInfo *ainfo;
1131 MonoReflectionCustomAttr *cattr;
1135 /* FIXME: check in assembly the Run flag is set */
1137 count = mono_array_length (cattrs);
1139 /* Skip nonpublic attributes since MS.NET seems to do the same */
1140 /* FIXME: This needs to be done more globally */
1142 for (i = 0; i < count; ++i) {
1143 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1144 if (!custom_attr_visible (image, cattr))
1147 count -= not_visible;
1149 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1151 ainfo->image = image;
1152 ainfo->num_attrs = count;
1154 mono_loader_lock ();
1155 for (i = 0; i < count; ++i) {
1156 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1157 if (custom_attr_visible (image, cattr)) {
1158 unsigned char *saved = mono_mempool_alloc (image->mempool, mono_array_length (cattr->data));
1159 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1160 ainfo->attrs [index].ctor = cattr->ctor->method;
1161 ainfo->attrs [index].data = saved;
1162 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1166 mono_loader_unlock ();
1172 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1174 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1179 mono_reflection_lock ();
1180 if (!dynamic_custom_attrs)
1181 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1183 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1184 ainfo->cached = TRUE;
1185 mono_reflection_unlock ();
1189 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1196 * idx is the table index of the object
1197 * type is one of MONO_CUSTOM_ATTR_*
1200 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1202 MonoDynamicTable *table;
1203 MonoReflectionCustomAttr *cattr;
1205 guint32 count, i, token;
1207 char *p = blob_size;
1209 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1212 count = mono_array_length (cattrs);
1213 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1214 table->rows += count;
1215 alloc_table (table, table->rows);
1216 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1217 idx <<= MONO_CUSTOM_ATTR_BITS;
1219 for (i = 0; i < count; ++i) {
1220 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1221 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1222 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1223 type = mono_metadata_token_index (token);
1224 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1225 switch (mono_metadata_token_table (token)) {
1226 case MONO_TABLE_METHOD:
1227 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1229 case MONO_TABLE_MEMBERREF:
1230 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1233 g_warning ("got wrong token in custom attr");
1236 values [MONO_CUSTOM_ATTR_TYPE] = type;
1238 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1239 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1240 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1241 values += MONO_CUSTOM_ATTR_SIZE;
1247 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1249 MonoDynamicTable *table;
1251 guint32 count, i, idx;
1252 MonoReflectionPermissionSet *perm;
1257 count = mono_array_length (permissions);
1258 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1259 table->rows += count;
1260 alloc_table (table, table->rows);
1262 for (i = 0; i < mono_array_length (permissions); ++i) {
1263 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1265 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1267 idx = mono_metadata_token_index (parent_token);
1268 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1269 switch (mono_metadata_token_table (parent_token)) {
1270 case MONO_TABLE_TYPEDEF:
1271 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1273 case MONO_TABLE_METHOD:
1274 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1276 case MONO_TABLE_ASSEMBLY:
1277 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1280 g_assert_not_reached ();
1283 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1284 values [MONO_DECL_SECURITY_PARENT] = idx;
1285 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1292 * Fill in the MethodDef and ParamDef tables for a method.
1293 * This is used for both normal methods and constructors.
1296 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1298 MonoDynamicTable *table;
1302 /* room in this table is already allocated */
1303 table = &assembly->tables [MONO_TABLE_METHOD];
1304 *mb->table_idx = table->next_idx ++;
1305 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1306 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1307 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1308 values [MONO_METHOD_FLAGS] = mb->attrs;
1309 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1310 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1311 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1313 table = &assembly->tables [MONO_TABLE_PARAM];
1314 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1316 mono_image_add_decl_security (assembly,
1317 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1320 MonoDynamicTable *mtable;
1323 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1324 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1327 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1328 if (mono_array_get (mb->pinfo, gpointer, i))
1331 table->rows += count;
1332 alloc_table (table, table->rows);
1333 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1334 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1335 MonoReflectionParamBuilder *pb;
1336 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1337 values [MONO_PARAM_FLAGS] = pb->attrs;
1338 values [MONO_PARAM_SEQUENCE] = i;
1339 if (pb->name != NULL) {
1340 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1342 values [MONO_PARAM_NAME] = 0;
1344 values += MONO_PARAM_SIZE;
1345 if (pb->marshal_info) {
1347 alloc_table (mtable, mtable->rows);
1348 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1349 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1350 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1352 pb->table_idx = table->next_idx++;
1353 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1354 guint32 field_type = 0;
1355 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1357 alloc_table (mtable, mtable->rows);
1358 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1359 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1360 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1361 mvalues [MONO_CONSTANT_TYPE] = field_type;
1362 mvalues [MONO_CONSTANT_PADDING] = 0;
1370 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1372 rmb->ilgen = mb->ilgen;
1373 rmb->rtype = mb->rtype;
1374 rmb->parameters = mb->parameters;
1375 rmb->generic_params = mb->generic_params;
1376 rmb->generic_container = mb->generic_container;
1377 rmb->opt_types = NULL;
1378 rmb->pinfo = mb->pinfo;
1379 rmb->attrs = mb->attrs;
1380 rmb->iattrs = mb->iattrs;
1381 rmb->call_conv = mb->call_conv;
1382 rmb->code = mb->code;
1383 rmb->type = mb->type;
1384 rmb->name = mb->name;
1385 rmb->table_idx = &mb->table_idx;
1386 rmb->init_locals = mb->init_locals;
1387 rmb->return_modreq = mb->return_modreq;
1388 rmb->return_modopt = mb->return_modopt;
1389 rmb->param_modreq = mb->param_modreq;
1390 rmb->param_modopt = mb->param_modopt;
1391 rmb->permissions = mb->permissions;
1392 rmb->mhandle = mb->mhandle;
1397 rmb->charset = mb->charset;
1398 rmb->extra_flags = mb->extra_flags;
1399 rmb->native_cc = mb->native_cc;
1400 rmb->dllentry = mb->dllentry;
1406 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1408 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1410 rmb->ilgen = mb->ilgen;
1411 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1412 rmb->parameters = mb->parameters;
1413 rmb->generic_params = NULL;
1414 rmb->generic_container = NULL;
1415 rmb->opt_types = NULL;
1416 rmb->pinfo = mb->pinfo;
1417 rmb->attrs = mb->attrs;
1418 rmb->iattrs = mb->iattrs;
1419 rmb->call_conv = mb->call_conv;
1421 rmb->type = mb->type;
1422 rmb->name = mono_string_new (mono_domain_get (), name);
1423 rmb->table_idx = &mb->table_idx;
1424 rmb->init_locals = mb->init_locals;
1425 rmb->return_modreq = NULL;
1426 rmb->return_modopt = NULL;
1427 rmb->param_modreq = mb->param_modreq;
1428 rmb->param_modopt = mb->param_modopt;
1429 rmb->permissions = mb->permissions;
1430 rmb->mhandle = mb->mhandle;
1436 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1438 rmb->ilgen = mb->ilgen;
1439 rmb->rtype = mb->rtype;
1440 rmb->parameters = mb->parameters;
1441 rmb->generic_params = NULL;
1442 rmb->generic_container = NULL;
1443 rmb->opt_types = NULL;
1445 rmb->attrs = mb->attrs;
1447 rmb->call_conv = mb->call_conv;
1449 rmb->type = (MonoObject *) mb->owner;
1450 rmb->name = mb->name;
1451 rmb->table_idx = NULL;
1452 rmb->init_locals = mb->init_locals;
1453 rmb->skip_visibility = mb->skip_visibility;
1454 rmb->return_modreq = NULL;
1455 rmb->return_modopt = NULL;
1456 rmb->param_modreq = NULL;
1457 rmb->param_modopt = NULL;
1458 rmb->permissions = NULL;
1459 rmb->mhandle = mb->mhandle;
1465 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1467 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1468 MonoDynamicTable *table;
1472 if (!mb->override_method)
1475 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1477 alloc_table (table, table->rows);
1478 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1479 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1480 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1482 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1483 switch (mono_metadata_token_table (tok)) {
1484 case MONO_TABLE_MEMBERREF:
1485 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1487 case MONO_TABLE_METHOD:
1488 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1491 g_assert_not_reached ();
1493 values [MONO_METHODIMPL_DECLARATION] = tok;
1497 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1499 MonoDynamicTable *table;
1501 ReflectionMethodBuilder rmb;
1504 reflection_methodbuilder_from_method_builder (&rmb, mb);
1506 mono_image_basic_method (&rmb, assembly);
1507 mb->table_idx = *rmb.table_idx;
1509 if (mb->dll) { /* It's a P/Invoke method */
1511 /* map CharSet values to on-disk values */
1512 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1513 int extra_flags = mb->extra_flags;
1514 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1516 alloc_table (table, table->rows);
1517 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1519 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1520 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1522 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1524 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1525 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1526 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1527 table = &assembly->tables [MONO_TABLE_MODULEREF];
1529 alloc_table (table, table->rows);
1530 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1531 values [MONO_IMPLMAP_SCOPE] = table->rows;
1535 if (mb->generic_params) {
1536 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1537 table->rows += mono_array_length (mb->generic_params);
1538 alloc_table (table, table->rows);
1539 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1540 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1542 mono_image_get_generic_param_info (
1543 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1550 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1552 ReflectionMethodBuilder rmb;
1554 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1556 mono_image_basic_method (&rmb, assembly);
1557 mb->table_idx = *rmb.table_idx;
1561 type_get_fully_qualified_name (MonoType *type)
1563 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1567 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1571 klass = my_mono_class_from_mono_type (type);
1573 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1574 ta = klass->image->assembly;
1575 if (ta->dynamic || (ta == ass)) {
1576 if (klass->generic_class)
1577 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1579 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1582 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1586 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1591 if (!assembly->save)
1594 sigbuffer_init (&buf, 32);
1596 sigbuffer_add_value (&buf, 0x06);
1597 /* encode custom attributes before the type */
1598 encode_type (assembly, type, &buf);
1599 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1600 sigbuffer_free (&buf);
1605 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1610 sigbuffer_init (&buf, 32);
1612 sigbuffer_add_value (&buf, 0x06);
1613 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1614 /* encode custom attributes before the type */
1615 encode_reflection_type (assembly, fb->type, &buf);
1616 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1617 sigbuffer_free (&buf);
1622 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1623 char blob_size [64];
1624 char *b = blob_size;
1627 guint32 idx = 0, len = 0, dummy = 0;
1629 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1630 guint32 fpa_double [2];
1635 p = buf = g_malloc (64);
1637 *ret_type = MONO_TYPE_CLASS;
1639 box_val = (char*)&dummy;
1641 box_val = ((char*)val) + sizeof (MonoObject);
1642 *ret_type = val->vtable->klass->byval_arg.type;
1645 switch (*ret_type) {
1646 case MONO_TYPE_BOOLEAN:
1651 case MONO_TYPE_CHAR:
1668 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1669 fpa_p = (guint32*)box_val;
1670 fpa_double [0] = fpa_p [1];
1671 fpa_double [1] = fpa_p [0];
1672 box_val = (char*)fpa_double;
1676 case MONO_TYPE_VALUETYPE:
1677 if (val->vtable->klass->enumtype) {
1678 *ret_type = val->vtable->klass->enum_basetype->type;
1681 g_error ("we can't encode valuetypes");
1682 case MONO_TYPE_CLASS:
1684 case MONO_TYPE_STRING: {
1685 MonoString *str = (MonoString*)val;
1686 /* there is no signature */
1687 len = str->length * 2;
1688 mono_metadata_encode_value (len, b, &b);
1689 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1691 char *swapped = g_malloc (2 * mono_string_length (str));
1692 const char *p = (const char*)mono_string_chars (str);
1694 swap_with_size (swapped, p, 2, mono_string_length (str));
1695 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1699 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1705 case MONO_TYPE_GENERICINST:
1706 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1709 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1712 /* there is no signature */
1713 mono_metadata_encode_value (len, b, &b);
1714 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1715 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1716 swap_with_size (blob_size, box_val, len, 1);
1717 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1719 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1727 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1732 sigbuffer_init (&buf, 32);
1734 sigbuffer_add_value (&buf, minfo->type);
1736 switch (minfo->type) {
1737 case MONO_NATIVE_BYVALTSTR:
1738 case MONO_NATIVE_BYVALARRAY:
1739 sigbuffer_add_value (&buf, minfo->count);
1741 case MONO_NATIVE_LPARRAY:
1742 if (minfo->eltype || minfo->has_size) {
1743 sigbuffer_add_value (&buf, minfo->eltype);
1744 if (minfo->has_size) {
1745 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1746 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1748 /* LAMESPEC: ElemMult is undocumented */
1749 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1753 case MONO_NATIVE_CUSTOM:
1755 str = mono_string_to_utf8 (minfo->guid);
1757 sigbuffer_add_value (&buf, len);
1758 sigbuffer_add_mem (&buf, str, len);
1761 sigbuffer_add_value (&buf, 0);
1763 /* native type name */
1764 sigbuffer_add_value (&buf, 0);
1765 /* custom marshaler type name */
1766 if (minfo->marshaltype || minfo->marshaltyperef) {
1767 if (minfo->marshaltyperef)
1768 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1770 str = mono_string_to_utf8 (minfo->marshaltype);
1772 sigbuffer_add_value (&buf, len);
1773 sigbuffer_add_mem (&buf, str, len);
1776 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1777 sigbuffer_add_value (&buf, 0);
1779 if (minfo->mcookie) {
1780 str = mono_string_to_utf8 (minfo->mcookie);
1782 sigbuffer_add_value (&buf, len);
1783 sigbuffer_add_mem (&buf, str, len);
1786 sigbuffer_add_value (&buf, 0);
1792 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1793 sigbuffer_free (&buf);
1798 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1800 MonoDynamicTable *table;
1803 /* maybe this fixup should be done in the C# code */
1804 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1805 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1806 table = &assembly->tables [MONO_TABLE_FIELD];
1807 fb->table_idx = table->next_idx ++;
1808 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1809 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1810 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1811 values [MONO_FIELD_FLAGS] = fb->attrs;
1812 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1814 if (fb->offset != -1) {
1815 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1817 alloc_table (table, table->rows);
1818 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1819 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1820 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1822 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1823 guint32 field_type = 0;
1824 table = &assembly->tables [MONO_TABLE_CONSTANT];
1826 alloc_table (table, table->rows);
1827 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1828 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1829 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1830 values [MONO_CONSTANT_TYPE] = field_type;
1831 values [MONO_CONSTANT_PADDING] = 0;
1833 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1835 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1837 alloc_table (table, table->rows);
1838 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1839 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1841 * We store it in the code section because it's simpler for now.
1844 if (mono_array_length (fb->rva_data) >= 10)
1845 stream_data_align (&assembly->code);
1846 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1848 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1849 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1851 if (fb->marshal_info) {
1852 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1854 alloc_table (table, table->rows);
1855 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1856 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1857 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1862 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1865 guint32 nparams = 0;
1866 MonoReflectionMethodBuilder *mb = fb->get_method;
1867 MonoReflectionMethodBuilder *smb = fb->set_method;
1870 if (mb && mb->parameters)
1871 nparams = mono_array_length (mb->parameters);
1872 if (!mb && smb && smb->parameters)
1873 nparams = mono_array_length (smb->parameters) - 1;
1874 sigbuffer_init (&buf, 32);
1875 sigbuffer_add_byte (&buf, 0x08);
1876 sigbuffer_add_value (&buf, nparams);
1878 encode_reflection_type (assembly, mb->rtype, &buf);
1879 for (i = 0; i < nparams; ++i) {
1880 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1881 encode_reflection_type (assembly, pt, &buf);
1883 } else if (smb && smb->parameters) {
1884 /* the property type is the last param */
1885 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1886 for (i = 0; i < nparams; ++i) {
1887 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1888 encode_reflection_type (assembly, pt, &buf);
1891 encode_reflection_type (assembly, fb->type, &buf);
1894 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1895 sigbuffer_free (&buf);
1900 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1902 MonoDynamicTable *table;
1904 guint num_methods = 0;
1908 * we need to set things in the following tables:
1909 * PROPERTYMAP (info already filled in _get_type_info ())
1910 * PROPERTY (rows already preallocated in _get_type_info ())
1911 * METHOD (method info already done with the generic method code)
1914 table = &assembly->tables [MONO_TABLE_PROPERTY];
1915 pb->table_idx = table->next_idx ++;
1916 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1917 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1918 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1919 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1921 /* FIXME: we still don't handle 'other' methods */
1922 if (pb->get_method) num_methods ++;
1923 if (pb->set_method) num_methods ++;
1925 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1926 table->rows += num_methods;
1927 alloc_table (table, table->rows);
1929 if (pb->get_method) {
1930 semaidx = table->next_idx ++;
1931 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1932 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1933 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1934 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1936 if (pb->set_method) {
1937 semaidx = table->next_idx ++;
1938 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1939 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1940 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1941 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1946 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1948 MonoDynamicTable *table;
1950 guint num_methods = 0;
1954 * we need to set things in the following tables:
1955 * EVENTMAP (info already filled in _get_type_info ())
1956 * EVENT (rows already preallocated in _get_type_info ())
1957 * METHOD (method info already done with the generic method code)
1960 table = &assembly->tables [MONO_TABLE_EVENT];
1961 eb->table_idx = table->next_idx ++;
1962 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1963 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1964 values [MONO_EVENT_FLAGS] = eb->attrs;
1965 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1968 * FIXME: we still don't handle 'other' methods
1970 if (eb->add_method) num_methods ++;
1971 if (eb->remove_method) num_methods ++;
1972 if (eb->raise_method) num_methods ++;
1974 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1975 table->rows += num_methods;
1976 alloc_table (table, table->rows);
1978 if (eb->add_method) {
1979 semaidx = table->next_idx ++;
1980 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1981 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1982 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1983 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1985 if (eb->remove_method) {
1986 semaidx = table->next_idx ++;
1987 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1988 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1989 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1990 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1992 if (eb->raise_method) {
1993 semaidx = table->next_idx ++;
1994 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1995 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1996 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1997 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2002 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2004 MonoDynamicTable *table;
2005 guint32 num_constraints, i;
2009 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2010 num_constraints = gparam->iface_constraints ?
2011 mono_array_length (gparam->iface_constraints) : 0;
2012 table->rows += num_constraints;
2013 if (gparam->base_type)
2015 alloc_table (table, table->rows);
2017 if (gparam->base_type) {
2018 table_idx = table->next_idx ++;
2019 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2021 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2022 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2023 assembly, gparam->base_type->type);
2026 for (i = 0; i < num_constraints; i++) {
2027 MonoReflectionType *constraint = mono_array_get (
2028 gparam->iface_constraints, gpointer, i);
2030 table_idx = table->next_idx ++;
2031 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2033 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2034 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2035 assembly, constraint->type);
2040 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2042 GenericParamTableEntry *entry;
2045 * The GenericParam table must be sorted according to the `owner' field.
2046 * We need to do this sorting prior to writing the GenericParamConstraint
2047 * table, since we have to use the final GenericParam table indices there
2048 * and they must also be sorted.
2051 entry = g_new0 (GenericParamTableEntry, 1);
2052 entry->owner = owner;
2054 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2055 MONO_GC_REGISTER_ROOT (entry->gparam);
2057 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2059 g_ptr_array_add (assembly->gen_params, entry);
2063 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2065 MonoDynamicTable *table;
2066 MonoGenericParam *param;
2070 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2071 table_idx = table->next_idx ++;
2072 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2074 param = entry->gparam->type.type->data.generic_param;
2076 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2077 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2078 values [MONO_GENERICPARAM_NUMBER] = param->num;
2079 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2081 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2083 encode_constraints (entry->gparam, table_idx, assembly);
2087 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2089 MonoDynamicTable *table;
2092 guint32 cols [MONO_ASSEMBLY_SIZE];
2096 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2099 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2100 table = &assembly->tables [MONO_TABLE_MODULEREF];
2101 token = table->next_idx ++;
2103 alloc_table (table, table->rows);
2104 values = table->values + token * MONO_MODULEREF_SIZE;
2105 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2107 token <<= MONO_RESOLTION_SCOPE_BITS;
2108 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2109 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2114 if (image->assembly->dynamic)
2116 memset (cols, 0, sizeof (cols));
2118 /* image->assembly->image is the manifest module */
2119 image = image->assembly->image;
2120 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2123 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2124 token = table->next_idx ++;
2126 alloc_table (table, table->rows);
2127 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2128 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2129 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2130 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2131 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2132 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2133 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2134 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2135 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2137 if (strcmp ("", image->assembly->aname.culture)) {
2138 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2139 image->assembly->aname.culture);
2142 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2143 guchar pubtoken [9];
2145 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2146 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2148 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2150 token <<= MONO_RESOLTION_SCOPE_BITS;
2151 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2152 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2157 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2159 MonoDynamicTable *table;
2164 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2167 sigbuffer_init (&buf, 32);
2168 switch (type->type) {
2169 case MONO_TYPE_FNPTR:
2171 case MONO_TYPE_SZARRAY:
2172 case MONO_TYPE_ARRAY:
2174 case MONO_TYPE_MVAR:
2175 case MONO_TYPE_GENERICINST:
2176 encode_type (assembly, type, &buf);
2178 case MONO_TYPE_CLASS:
2179 case MONO_TYPE_VALUETYPE: {
2180 MonoClass *k = mono_class_from_mono_type (type);
2181 if (!k || !k->generic_container) {
2182 sigbuffer_free (&buf);
2185 encode_type (assembly, type, &buf);
2189 sigbuffer_free (&buf);
2193 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2194 if (assembly->save) {
2195 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2196 alloc_table (table, table->rows + 1);
2197 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2198 values [MONO_TYPESPEC_SIGNATURE] = token;
2200 sigbuffer_free (&buf);
2202 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2203 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2209 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2211 MonoDynamicTable *table;
2213 guint32 token, scope, enclosing;
2216 /* if the type requires a typespec, we must try that first*/
2217 if (try_typespec && (token = create_typespec (assembly, type)))
2219 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2222 klass = my_mono_class_from_mono_type (type);
2224 klass = mono_class_from_mono_type (type);
2227 * If it's in the same module and not a generic type parameter:
2229 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2230 (type->type != MONO_TYPE_MVAR)) {
2231 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2232 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2233 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2237 if (klass->nested_in) {
2238 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2239 /* get the typeref idx of the enclosing type */
2240 enclosing >>= MONO_TYPEDEFORREF_BITS;
2241 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2243 scope = resolution_scope_from_image (assembly, klass->image);
2245 table = &assembly->tables [MONO_TABLE_TYPEREF];
2246 if (assembly->save) {
2247 alloc_table (table, table->rows + 1);
2248 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2249 values [MONO_TYPEREF_SCOPE] = scope;
2250 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2251 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2253 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2254 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2256 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2261 * Despite the name, we handle also TypeSpec (with the above helper).
2264 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2266 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2270 * Insert a memberef row into the metadata: the token that point to the memberref
2271 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2272 * mono_image_get_fieldref_token()).
2273 * The sig param is an index to an already built signature.
2276 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2278 MonoDynamicTable *table;
2280 guint32 token, pclass;
2283 parent = mono_image_typedef_or_ref (assembly, type);
2284 switch (parent & MONO_TYPEDEFORREF_MASK) {
2285 case MONO_TYPEDEFORREF_TYPEREF:
2286 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2288 case MONO_TYPEDEFORREF_TYPESPEC:
2289 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2291 case MONO_TYPEDEFORREF_TYPEDEF:
2292 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2295 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2298 /* extract the index */
2299 parent >>= MONO_TYPEDEFORREF_BITS;
2301 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2303 if (assembly->save) {
2304 alloc_table (table, table->rows + 1);
2305 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2306 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2307 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2308 values [MONO_MEMBERREF_SIGNATURE] = sig;
2311 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2318 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2321 MonoMethodSignature *sig;
2323 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2328 * A methodref signature can't contain an unmanaged calling convention.
2330 sig = mono_metadata_signature_dup (mono_method_signature (method));
2331 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2332 sig->call_convention = MONO_CALL_DEFAULT;
2333 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2334 method->name, method_encode_signature (assembly, sig));
2336 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2341 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2342 const gchar *name, guint32 sig)
2344 MonoDynamicTable *table;
2348 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2350 if (assembly->save) {
2351 alloc_table (table, table->rows + 1);
2352 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2353 values [MONO_MEMBERREF_CLASS] = original;
2354 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2355 values [MONO_MEMBERREF_SIGNATURE] = sig;
2358 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2365 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2368 ReflectionMethodBuilder rmb;
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2374 reflection_methodbuilder_from_method_builder (&rmb, mb);
2376 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2377 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2378 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2383 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2386 ReflectionMethodBuilder rmb;
2388 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2392 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2394 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2395 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2396 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2401 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2406 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2409 g_assert (f->field->parent);
2410 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2411 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2412 f->field->name, fieldref_encode_signature (assembly, type));
2413 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2418 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2422 guint32 nparams = context->method_inst->type_argc;
2425 if (!assembly->save)
2428 sigbuffer_init (&buf, 32);
2430 * FIXME: vararg, explicit_this, differenc call_conv values...
2432 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2433 sigbuffer_add_value (&buf, nparams);
2435 for (i = 0; i < nparams; i++)
2436 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2438 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2439 sigbuffer_free (&buf);
2444 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2446 MonoDynamicTable *table;
2448 guint32 token, mtoken = 0, sig;
2449 MonoMethodInflated *imethod;
2450 MonoMethod *declaring;
2452 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2454 g_assert (method->is_inflated);
2455 imethod = (MonoMethodInflated *) method;
2456 declaring = imethod->declaring;
2458 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2459 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2461 if (!mono_method_signature (declaring)->generic_param_count)
2464 switch (mono_metadata_token_table (mtoken)) {
2465 case MONO_TABLE_MEMBERREF:
2466 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2468 case MONO_TABLE_METHOD:
2469 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2472 g_assert_not_reached ();
2475 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2477 if (assembly->save) {
2478 alloc_table (table, table->rows + 1);
2479 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2480 values [MONO_METHODSPEC_METHOD] = mtoken;
2481 values [MONO_METHODSPEC_SIGNATURE] = sig;
2484 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2491 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2493 MonoMethodInflated *imethod;
2496 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2500 g_assert (method->is_inflated);
2501 imethod = (MonoMethodInflated *) method;
2503 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2504 token = method_encode_methodspec (assembly, method);
2506 guint32 sig = method_encode_signature (
2507 assembly, mono_method_signature (imethod->declaring));
2508 token = mono_image_get_memberref_token (
2509 assembly, &method->klass->byval_arg, method->name, sig);
2512 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2517 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2519 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2522 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2523 token = mono_image_get_memberref_token (
2524 assembly, &m->klass->byval_arg, m->name, sig);
2530 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2532 MonoDynamicTable *table;
2540 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2541 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2542 * Because of this, we must not insert it into the `typeref' hash table.
2545 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2549 sigbuffer_init (&buf, 32);
2551 g_assert (tb->generic_params);
2552 klass = mono_class_from_mono_type (tb->type.type);
2554 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2555 g_assert (klass->generic_container);
2556 sigbuffer_add_value (&buf, klass->byval_arg.type);
2557 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2559 count = mono_array_length (tb->generic_params);
2560 sigbuffer_add_value (&buf, count);
2561 for (i = 0; i < count; i++) {
2562 MonoReflectionGenericParam *gparam;
2564 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2566 encode_type (assembly, gparam->type.type, &buf);
2569 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571 if (assembly->save) {
2572 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2573 alloc_table (table, table->rows + 1);
2574 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575 values [MONO_TYPESPEC_SIGNATURE] = token;
2577 sigbuffer_free (&buf);
2579 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2586 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2588 MonoDynamicTable *table;
2591 guint32 token, pclass, parent, sig;
2594 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2598 klass = mono_class_from_mono_type (fb->typeb->type);
2599 name = mono_string_to_utf8 (fb->name);
2601 sig = fieldref_encode_signature (assembly, fb->type->type);
2603 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2604 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2606 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2607 parent >>= MONO_TYPEDEFORREF_BITS;
2609 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2611 if (assembly->save) {
2612 alloc_table (table, table->rows + 1);
2613 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2614 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2615 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2616 values [MONO_MEMBERREF_SIGNATURE] = sig;
2619 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2621 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2626 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2633 if (!assembly->save)
2637 g_assert (helper->type == 2);
2639 if (helper->arguments)
2640 nargs = mono_array_length (helper->arguments);
2644 size = 10 + (nargs * 10);
2646 sigbuffer_init (&buf, 32);
2648 /* Encode calling convention */
2649 /* Change Any to Standard */
2650 if ((helper->call_conv & 0x03) == 0x03)
2651 helper->call_conv = 0x01;
2652 /* explicit_this implies has_this */
2653 if (helper->call_conv & 0x40)
2654 helper->call_conv &= 0x20;
2656 if (helper->call_conv == 0) { /* Unmanaged */
2657 idx = helper->unmanaged_call_conv - 1;
2660 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2661 if (helper->call_conv & 0x02) /* varargs */
2665 sigbuffer_add_byte (&buf, idx);
2666 sigbuffer_add_value (&buf, nargs);
2667 encode_reflection_type (assembly, helper->return_type, &buf);
2668 for (i = 0; i < nargs; ++i) {
2669 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2670 encode_reflection_type (assembly, pt, &buf);
2672 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2673 sigbuffer_free (&buf);
2679 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2682 MonoDynamicTable *table;
2685 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2686 idx = table->next_idx ++;
2688 alloc_table (table, table->rows);
2689 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2691 values [MONO_STAND_ALONE_SIGNATURE] =
2692 mono_reflection_encode_sighelper (assembly, helper);
2698 reflection_cc_to_file (int call_conv) {
2699 switch (call_conv & 0x3) {
2701 case 1: return MONO_CALL_DEFAULT;
2702 case 2: return MONO_CALL_VARARG;
2704 g_assert_not_reached ();
2711 MonoMethodSignature *sig;
2717 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2722 MonoMethodSignature *sig;
2725 name = mono_string_to_utf8 (m->name);
2726 nparams = mono_array_length (m->parameters);
2727 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2729 sig->sentinelpos = -1;
2730 sig->call_convention = reflection_cc_to_file (m->call_conv);
2731 sig->param_count = nparams;
2732 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2733 for (i = 0; i < nparams; ++i) {
2734 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2735 sig->params [i] = t->type;
2738 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2740 if (strcmp (name, am->name) == 0 &&
2741 mono_metadata_type_equal (am->parent, m->parent->type) &&
2742 mono_metadata_signature_equal (am->sig, sig)) {
2745 m->table_idx = am->token & 0xffffff;
2749 am = g_new0 (ArrayMethod, 1);
2752 am->parent = m->parent->type;
2753 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2754 method_encode_signature (assembly, sig));
2755 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2756 m->table_idx = am->token & 0xffffff;
2761 * Insert into the metadata tables all the info about the TypeBuilder tb.
2762 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2765 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2767 MonoDynamicTable *table;
2769 int i, is_object = 0, is_system = 0;
2772 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2773 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2774 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2775 n = mono_string_to_utf8 (tb->name);
2776 if (strcmp (n, "Object") == 0)
2778 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2780 n = mono_string_to_utf8 (tb->nspace);
2781 if (strcmp (n, "System") == 0)
2783 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2785 if (tb->parent && !(is_system && is_object) &&
2786 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2787 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2789 values [MONO_TYPEDEF_EXTENDS] = 0;
2791 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2792 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2795 * if we have explicitlayout or sequentiallayouts, output data in the
2796 * ClassLayout table.
2798 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2799 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2800 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2802 alloc_table (table, table->rows);
2803 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2804 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2805 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2806 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2809 /* handle interfaces */
2810 if (tb->interfaces) {
2811 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2813 table->rows += mono_array_length (tb->interfaces);
2814 alloc_table (table, table->rows);
2815 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2816 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2817 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2818 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2819 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2820 values += MONO_INTERFACEIMPL_SIZE;
2826 table = &assembly->tables [MONO_TABLE_FIELD];
2827 table->rows += tb->num_fields;
2828 alloc_table (table, table->rows);
2829 for (i = 0; i < tb->num_fields; ++i)
2830 mono_image_get_field_info (
2831 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2834 /* handle constructors */
2836 table = &assembly->tables [MONO_TABLE_METHOD];
2837 table->rows += mono_array_length (tb->ctors);
2838 alloc_table (table, table->rows);
2839 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2840 mono_image_get_ctor_info (domain,
2841 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2844 /* handle methods */
2846 table = &assembly->tables [MONO_TABLE_METHOD];
2847 table->rows += tb->num_methods;
2848 alloc_table (table, table->rows);
2849 for (i = 0; i < tb->num_methods; ++i)
2850 mono_image_get_method_info (
2851 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2854 /* Do the same with properties etc.. */
2855 if (tb->events && mono_array_length (tb->events)) {
2856 table = &assembly->tables [MONO_TABLE_EVENT];
2857 table->rows += mono_array_length (tb->events);
2858 alloc_table (table, table->rows);
2859 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2861 alloc_table (table, table->rows);
2862 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2863 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2864 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2865 for (i = 0; i < mono_array_length (tb->events); ++i)
2866 mono_image_get_event_info (
2867 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2869 if (tb->properties && mono_array_length (tb->properties)) {
2870 table = &assembly->tables [MONO_TABLE_PROPERTY];
2871 table->rows += mono_array_length (tb->properties);
2872 alloc_table (table, table->rows);
2873 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2875 alloc_table (table, table->rows);
2876 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2877 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2878 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2879 for (i = 0; i < mono_array_length (tb->properties); ++i)
2880 mono_image_get_property_info (
2881 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2884 /* handle generic parameters */
2885 if (tb->generic_params) {
2886 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2887 table->rows += mono_array_length (tb->generic_params);
2888 alloc_table (table, table->rows);
2889 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2890 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2892 mono_image_get_generic_param_info (
2893 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2897 mono_image_add_decl_security (assembly,
2898 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2901 MonoDynamicTable *ntable;
2903 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2904 ntable->rows += mono_array_length (tb->subtypes);
2905 alloc_table (ntable, ntable->rows);
2906 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2908 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2909 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2911 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2912 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2913 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2914 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2915 mono_string_to_utf8 (tb->name), tb->table_idx,
2916 ntable->next_idx, ntable->rows);*/
2917 values += MONO_NESTED_CLASS_SIZE;
2924 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2928 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2930 if (!type->subtypes)
2933 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2934 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2935 collect_types (types, subtype);
2940 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2942 if ((*type1)->table_idx < (*type2)->table_idx)
2945 if ((*type1)->table_idx > (*type2)->table_idx)
2952 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2957 for (i = 0; i < mono_array_length (pinfo); ++i) {
2958 MonoReflectionParamBuilder *pb;
2959 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2962 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2967 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2970 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2972 for (i = 0; i < tb->num_fields; ++i) {
2973 MonoReflectionFieldBuilder* fb;
2974 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2975 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2979 for (i = 0; i < mono_array_length (tb->events); ++i) {
2980 MonoReflectionEventBuilder* eb;
2981 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2982 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2985 if (tb->properties) {
2986 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2987 MonoReflectionPropertyBuilder* pb;
2988 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2989 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2993 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2994 MonoReflectionCtorBuilder* cb;
2995 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2996 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2997 params_add_cattrs (assembly, cb->pinfo);
3002 for (i = 0; i < tb->num_methods; ++i) {
3003 MonoReflectionMethodBuilder* mb;
3004 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3005 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3006 params_add_cattrs (assembly, mb->pinfo);
3011 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3012 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3017 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3021 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3023 if (moduleb->global_methods) {
3024 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3025 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3026 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3027 params_add_cattrs (assembly, mb->pinfo);
3031 if (moduleb->global_fields) {
3032 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3033 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3034 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3038 if (moduleb->types) {
3039 for (i = 0; i < moduleb->num_types; ++i)
3040 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3045 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3047 MonoDynamicTable *table;
3051 char *b = blob_size;
3054 table = &assembly->tables [MONO_TABLE_FILE];
3056 alloc_table (table, table->rows);
3057 values = table->values + table->next_idx * MONO_FILE_SIZE;
3058 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3059 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3060 if (module->image->dynamic) {
3061 /* This depends on the fact that the main module is emitted last */
3062 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3063 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3066 path = g_strdup (module->image->name);
3068 mono_sha1_get_digest_from_file (path, hash);
3071 mono_metadata_encode_value (20, b, &b);
3072 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3073 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3078 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3080 MonoDynamicTable *table;
3083 table = &assembly->tables [MONO_TABLE_MODULE];
3084 mb->table_idx = table->next_idx ++;
3085 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3086 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3090 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3091 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3092 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3096 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3097 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3099 MonoDynamicTable *table;
3103 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3104 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3107 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3109 alloc_table (table, table->rows);
3110 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3112 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3113 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3114 if (klass->nested_in)
3115 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3117 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3118 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3119 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3121 res = table->next_idx;
3125 /* Emit nested types */
3126 if (klass->nested_classes) {
3129 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3130 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3137 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3138 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3143 klass = mono_class_from_mono_type (tb->type.type);
3145 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3147 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3148 parent_index, assembly);
3152 * We need to do this ourselves since klass->nested_classes is not set up.
3155 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3156 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3161 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3162 guint32 module_index, MonoDynamicImage *assembly)
3164 MonoImage *image = module->image;
3168 t = &image->tables [MONO_TABLE_TYPEDEF];
3170 for (i = 0; i < t->rows; ++i) {
3171 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3173 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3174 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3179 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3181 MonoDynamicTable *table;
3187 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3189 if (assemblyb->type_forwarders) {
3190 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3191 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3197 klass = mono_class_from_mono_type (t->type);
3199 scope = resolution_scope_from_image (assembly, klass->image);
3200 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3201 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3204 alloc_table (table, table->rows);
3205 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3207 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3208 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3209 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3210 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3211 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3216 #define align_pointer(base,p)\
3218 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3220 (p) += 4 - (__diff & 3);\
3224 compare_constants (const void *a, const void *b)
3226 const guint32 *a_values = a;
3227 const guint32 *b_values = b;
3228 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3232 compare_semantics (const void *a, const void *b)
3234 const guint32 *a_values = a;
3235 const guint32 *b_values = b;
3236 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3239 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3243 compare_custom_attrs (const void *a, const void *b)
3245 const guint32 *a_values = a;
3246 const guint32 *b_values = b;
3248 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3252 compare_field_marshal (const void *a, const void *b)
3254 const guint32 *a_values = a;
3255 const guint32 *b_values = b;
3257 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3261 compare_nested (const void *a, const void *b)
3263 const guint32 *a_values = a;
3264 const guint32 *b_values = b;
3266 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3270 compare_genericparam (const void *a, const void *b)
3272 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3273 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3275 if ((*b_entry)->owner == (*a_entry)->owner)
3277 (*a_entry)->gparam->type.type->data.generic_param->num -
3278 (*b_entry)->gparam->type.type->data.generic_param->num;
3280 return (*a_entry)->owner - (*b_entry)->owner;
3284 compare_declsecurity_attrs (const void *a, const void *b)
3286 const guint32 *a_values = a;
3287 const guint32 *b_values = b;
3289 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3293 pad_heap (MonoDynamicStream *sh)
3295 if (sh->index & 3) {
3296 int sz = 4 - (sh->index & 3);
3297 memset (sh->data + sh->index, 0, sz);
3304 MonoDynamicStream *stream;
3308 * build_compressed_metadata() fills in the blob of data that represents the
3309 * raw metadata as it will be saved in the PE file. The five streams are output
3310 * and the metadata tables are comnpressed from the guint32 array representation,
3311 * to the compressed on-disk format.
3314 build_compressed_metadata (MonoDynamicImage *assembly)
3316 MonoDynamicTable *table;
3318 guint64 valid_mask = 0;
3319 guint64 sorted_mask;
3320 guint32 heapt_size = 0;
3321 guint32 meta_size = 256; /* allow for header and other stuff */
3322 guint32 table_offset;
3323 guint32 ntables = 0;
3329 struct StreamDesc stream_desc [5];
3331 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3332 for (i = 0; i < assembly->gen_params->len; i++){
3333 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3334 write_generic_param_entry (assembly, entry);
3337 stream_desc [0].name = "#~";
3338 stream_desc [0].stream = &assembly->tstream;
3339 stream_desc [1].name = "#Strings";
3340 stream_desc [1].stream = &assembly->sheap;
3341 stream_desc [2].name = "#US";
3342 stream_desc [2].stream = &assembly->us;
3343 stream_desc [3].name = "#Blob";
3344 stream_desc [3].stream = &assembly->blob;
3345 stream_desc [4].name = "#GUID";
3346 stream_desc [4].stream = &assembly->guid;
3348 /* tables that are sorted */
3349 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3350 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3351 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3352 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3353 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3354 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3356 /* Compute table sizes */
3357 /* the MonoImage has already been created in mono_image_basic_init() */
3358 meta = &assembly->image;
3360 /* sizes should be multiple of 4 */
3361 pad_heap (&assembly->blob);
3362 pad_heap (&assembly->guid);
3363 pad_heap (&assembly->sheap);
3364 pad_heap (&assembly->us);
3366 /* Setup the info used by compute_sizes () */
3367 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3368 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3369 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3371 meta_size += assembly->blob.index;
3372 meta_size += assembly->guid.index;
3373 meta_size += assembly->sheap.index;
3374 meta_size += assembly->us.index;
3376 for (i=0; i < MONO_TABLE_NUM; ++i)
3377 meta->tables [i].rows = assembly->tables [i].rows;
3379 for (i = 0; i < MONO_TABLE_NUM; i++){
3380 if (meta->tables [i].rows == 0)
3382 valid_mask |= (guint64)1 << i;
3384 meta->tables [i].row_size = mono_metadata_compute_size (
3385 meta, i, &meta->tables [i].size_bitfield);
3386 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3388 heapt_size += 24; /* #~ header size */
3389 heapt_size += ntables * 4;
3390 /* make multiple of 4 */
3393 meta_size += heapt_size;
3394 meta->raw_metadata = g_malloc0 (meta_size);
3395 p = (unsigned char*)meta->raw_metadata;
3396 /* the metadata signature */
3397 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3398 /* version numbers and 4 bytes reserved */
3399 int16val = (guint16*)p;
3400 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3401 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3403 /* version string */
3404 int32val = (guint32*)p;
3405 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3407 memcpy (p, meta->version, strlen (meta->version));
3408 p += GUINT32_FROM_LE (*int32val);
3409 align_pointer (meta->raw_metadata, p);
3410 int16val = (guint16*)p;
3411 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3412 *int16val = GUINT16_TO_LE (5); /* number of streams */
3416 * write the stream info.
3418 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3419 table_offset += 3; table_offset &= ~3;
3421 assembly->tstream.index = heapt_size;
3422 for (i = 0; i < 5; ++i) {
3423 int32val = (guint32*)p;
3424 stream_desc [i].stream->offset = table_offset;
3425 *int32val++ = GUINT32_TO_LE (table_offset);
3426 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3427 table_offset += GUINT32_FROM_LE (*int32val);
3428 table_offset += 3; table_offset &= ~3;
3430 strcpy ((char*)p, stream_desc [i].name);
3431 p += strlen (stream_desc [i].name) + 1;
3432 align_pointer (meta->raw_metadata, p);
3435 * now copy the data, the table stream header and contents goes first.
3437 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3438 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3439 int32val = (guint32*)p;
3440 *int32val = GUINT32_TO_LE (0); /* reserved */
3443 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3444 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3445 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3446 *p++ = 2; /* version */
3449 *p++ = 1; /* version */
3453 if (meta->idx_string_wide)
3455 if (meta->idx_guid_wide)
3457 if (meta->idx_blob_wide)
3460 *p++ = 1; /* reserved */
3461 int64val = (guint64*)p;
3462 *int64val++ = GUINT64_TO_LE (valid_mask);
3463 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3465 int32val = (guint32*)p;
3466 for (i = 0; i < MONO_TABLE_NUM; i++){
3467 if (meta->tables [i].rows == 0)
3469 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3471 p = (unsigned char*)int32val;
3473 /* sort the tables that still need sorting */
3474 table = &assembly->tables [MONO_TABLE_CONSTANT];
3476 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3477 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3479 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3480 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3482 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3483 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3485 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3486 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3488 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3489 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3490 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3492 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3494 /* compress the tables */
3495 for (i = 0; i < MONO_TABLE_NUM; i++){
3498 guint32 bitfield = meta->tables [i].size_bitfield;
3499 if (!meta->tables [i].rows)
3501 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3502 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3503 meta->tables [i].base = (char*)p;
3504 for (row = 1; row <= meta->tables [i].rows; ++row) {
3505 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3506 for (col = 0; col < assembly->tables [i].columns; ++col) {
3507 switch (mono_metadata_table_size (bitfield, col)) {
3509 *p++ = values [col];
3512 *p++ = values [col] & 0xff;
3513 *p++ = (values [col] >> 8) & 0xff;
3516 *p++ = values [col] & 0xff;
3517 *p++ = (values [col] >> 8) & 0xff;
3518 *p++ = (values [col] >> 16) & 0xff;
3519 *p++ = (values [col] >> 24) & 0xff;
3522 g_assert_not_reached ();
3526 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3529 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3530 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3531 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3532 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3533 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3535 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3539 * Some tables in metadata need to be sorted according to some criteria, but
3540 * when methods and fields are first created with reflection, they may be assigned a token
3541 * that doesn't correspond to the final token they will get assigned after the sorting.
3542 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3543 * with the reflection objects that represent them. Once all the tables are set up, the
3544 * reflection objects will contains the correct table index. fixup_method() will fixup the
3545 * tokens for the method with ILGenerator @ilgen.
3548 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3549 guint32 code_idx = GPOINTER_TO_UINT (value);
3550 MonoReflectionILTokenInfo *iltoken;
3551 MonoReflectionFieldBuilder *field;
3552 MonoReflectionCtorBuilder *ctor;
3553 MonoReflectionMethodBuilder *method;
3554 MonoReflectionTypeBuilder *tb;
3555 MonoReflectionArrayMethod *am;
3557 unsigned char *target;
3559 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3560 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3561 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3562 switch (target [3]) {
3563 case MONO_TABLE_FIELD:
3564 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3565 field = (MonoReflectionFieldBuilder *)iltoken->member;
3566 idx = field->table_idx;
3567 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3568 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3569 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3571 g_assert_not_reached ();
3574 case MONO_TABLE_METHOD:
3575 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3576 method = (MonoReflectionMethodBuilder *)iltoken->member;
3577 idx = method->table_idx;
3578 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3579 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3580 idx = ctor->table_idx;
3581 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3582 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3583 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3584 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3586 g_assert_not_reached ();
3589 case MONO_TABLE_TYPEDEF:
3590 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3591 g_assert_not_reached ();
3592 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3593 idx = tb->table_idx;
3595 case MONO_TABLE_MEMBERREF:
3596 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3597 am = (MonoReflectionArrayMethod*)iltoken->member;
3598 idx = am->table_idx;
3599 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3600 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3601 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3602 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3603 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3604 g_assert (m->klass->generic_class || m->klass->generic_container);
3606 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3608 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3609 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3610 g_assert (f->generic_info);
3612 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3615 g_assert_not_reached ();
3618 case MONO_TABLE_METHODSPEC:
3619 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3620 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3621 g_assert (mono_method_signature (m)->generic_param_count);
3624 g_assert_not_reached ();
3628 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3630 target [0] = idx & 0xff;
3631 target [1] = (idx >> 8) & 0xff;
3632 target [2] = (idx >> 16) & 0xff;
3639 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3640 * value is not known when the table is emitted.
3643 fixup_cattrs (MonoDynamicImage *assembly)
3645 MonoDynamicTable *table;
3647 guint32 type, i, idx, token;
3650 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3652 for (i = 0; i < table->rows; ++i) {
3653 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3655 type = values [MONO_CUSTOM_ATTR_TYPE];
3656 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3657 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3658 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3659 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3662 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3663 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3664 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3665 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3672 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3674 MonoDynamicTable *table;
3677 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3679 alloc_table (table, table->rows);
3680 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3681 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3682 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3683 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3684 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3689 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3691 MonoDynamicTable *table;
3695 char *b = blob_size;
3697 guint32 idx, offset;
3699 if (rsrc->filename) {
3700 name = mono_string_to_utf8 (rsrc->filename);
3701 sname = g_path_get_basename (name);
3703 table = &assembly->tables [MONO_TABLE_FILE];
3705 alloc_table (table, table->rows);
3706 values = table->values + table->next_idx * MONO_FILE_SIZE;
3707 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3708 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3711 mono_sha1_get_digest_from_file (name, hash);
3712 mono_metadata_encode_value (20, b, &b);
3713 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3714 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3716 idx = table->next_idx++;
3718 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3724 data = mono_array_addr (rsrc->data, char, 0);
3725 len = mono_array_length (rsrc->data);
3731 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3732 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3733 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3734 mono_image_add_stream_data (&assembly->resources, data, len);
3738 * The entry should be emitted into the MANIFESTRESOURCE table of
3739 * the main module, but that needs to reference the FILE table
3740 * which isn't emitted yet.
3747 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3751 set_version_from_string (MonoString *version, guint32 *values)
3753 gchar *ver, *p, *str;
3756 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3757 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3758 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3759 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3762 ver = str = mono_string_to_utf8 (version);
3763 for (i = 0; i < 4; ++i) {
3764 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3770 /* handle Revision and Build */
3780 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3784 char *b = blob_size;
3789 len = mono_array_length (pkey);
3790 mono_metadata_encode_value (len, b, &b);
3791 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3792 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3794 assembly->public_key = g_malloc (len);
3795 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3796 assembly->public_key_len = len;
3798 /* Special case: check for ECMA key (16 bytes) */
3799 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3800 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3801 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3802 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3803 /* minimum key size (in 2.0) is 384 bits */
3804 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3806 /* FIXME - verifier */
3807 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3808 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3810 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3816 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3818 MonoDynamicTable *table;
3819 MonoDynamicImage *assembly;
3820 MonoReflectionAssemblyBuilder *assemblyb;
3824 guint32 module_index;
3826 assemblyb = moduleb->assemblyb;
3827 assembly = moduleb->dynamic_image;
3828 domain = mono_object_domain (assemblyb);
3830 /* Emit ASSEMBLY table */
3831 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3832 alloc_table (table, 1);
3833 values = table->values + MONO_ASSEMBLY_SIZE;
3834 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3835 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3836 if (assemblyb->culture) {
3837 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3839 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3841 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3842 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3843 set_version_from_string (assemblyb->version, values);
3845 /* Emit FILE + EXPORTED_TYPE table */
3847 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3849 MonoReflectionModuleBuilder *file_module =
3850 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3851 if (file_module != moduleb) {
3852 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3854 if (file_module->types) {
3855 for (j = 0; j < file_module->num_types; ++j) {
3856 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3857 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3862 if (assemblyb->loaded_modules) {
3863 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3864 MonoReflectionModule *file_module =
3865 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3866 mono_image_fill_file_table (domain, file_module, assembly);
3868 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3871 if (assemblyb->type_forwarders)
3872 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3874 /* Emit MANIFESTRESOURCE table */
3876 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3878 MonoReflectionModuleBuilder *file_module =
3879 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3880 /* The table for the main module is emitted later */
3881 if (file_module != moduleb) {
3883 if (file_module->resources) {
3884 int len = mono_array_length (file_module->resources);
3885 for (j = 0; j < len; ++j) {
3886 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3887 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3895 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3896 * for the modulebuilder @moduleb.
3897 * At the end of the process, method and field tokens are fixed up and the
3898 * on-disk compressed metadata representation is created.
3901 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3903 MonoDynamicTable *table;
3904 MonoDynamicImage *assembly;
3905 MonoReflectionAssemblyBuilder *assemblyb;
3911 assemblyb = moduleb->assemblyb;
3912 assembly = moduleb->dynamic_image;
3913 domain = mono_object_domain (assemblyb);
3915 if (assembly->text_rva)
3918 assembly->text_rva = START_TEXT_RVA;
3920 if (moduleb->is_main) {
3921 mono_image_emit_manifest (moduleb);
3924 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3925 table->rows = 1; /* .<Module> */
3927 alloc_table (table, table->rows);
3929 * Set the first entry.
3931 values = table->values + table->columns;
3932 values [MONO_TYPEDEF_FLAGS] = 0;
3933 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3934 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3935 values [MONO_TYPEDEF_EXTENDS] = 0;
3936 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3937 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3940 * handle global methods
3941 * FIXME: test what to do when global methods are defined in multiple modules.
3943 if (moduleb->global_methods) {
3944 table = &assembly->tables [MONO_TABLE_METHOD];
3945 table->rows += mono_array_length (moduleb->global_methods);
3946 alloc_table (table, table->rows);
3947 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3948 mono_image_get_method_info (
3949 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3951 if (moduleb->global_fields) {
3952 table = &assembly->tables [MONO_TABLE_FIELD];
3953 table->rows += mono_array_length (moduleb->global_fields);
3954 alloc_table (table, table->rows);
3955 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3956 mono_image_get_field_info (
3957 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3960 table = &assembly->tables [MONO_TABLE_MODULE];
3961 alloc_table (table, 1);
3962 mono_image_fill_module_table (domain, moduleb, assembly);
3964 /* Collect all types into a list sorted by their table_idx */
3965 types = g_ptr_array_new ();
3968 for (i = 0; i < moduleb->num_types; ++i) {
3969 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3970 collect_types (types, type);
3973 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3974 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3975 table->rows += types->len;
3976 alloc_table (table, table->rows);
3979 * Emit type names + namespaces at one place inside the string heap,
3980 * so load_class_names () needs to touch fewer pages.
3982 for (i = 0; i < types->len; ++i) {
3983 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3984 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3986 for (i = 0; i < types->len; ++i) {
3987 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3988 string_heap_insert_mstring (&assembly->sheap, tb->name);
3991 for (i = 0; i < types->len; ++i) {
3992 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3993 mono_image_get_type_info (domain, type, assembly);
3997 * table->rows is already set above and in mono_image_fill_module_table.
3999 /* add all the custom attributes at the end, once all the indexes are stable */
4000 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4002 /* CAS assembly permissions */
4003 if (assemblyb->permissions_minimum)
4004 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4005 if (assemblyb->permissions_optional)
4006 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4007 if (assemblyb->permissions_refused)
4008 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4010 module_add_cattrs (assembly, moduleb);
4013 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4015 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4016 * the final tokens and don't need another fixup pass. */
4018 if (moduleb->global_methods) {
4019 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4020 MonoReflectionMethodBuilder *mb = mono_array_get (
4021 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4022 mono_image_add_methodimpl (assembly, mb);
4026 for (i = 0; i < types->len; ++i) {
4027 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4028 if (type->methods) {
4029 for (j = 0; j < type->num_methods; ++j) {
4030 MonoReflectionMethodBuilder *mb = mono_array_get (
4031 type->methods, MonoReflectionMethodBuilder*, j);
4033 mono_image_add_methodimpl (assembly, mb);
4038 g_ptr_array_free (types, TRUE);
4040 fixup_cattrs (assembly);
4044 * mono_image_insert_string:
4045 * @module: module builder object
4048 * Insert @str into the user string stream of @module.
4051 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4053 MonoDynamicImage *assembly;
4058 MONO_ARCH_SAVE_REGS;
4060 if (!module->dynamic_image)
4061 mono_image_module_basic_init (module);
4063 assembly = module->dynamic_image;
4065 if (assembly->save) {
4066 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4067 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4068 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4070 char *swapped = g_malloc (2 * mono_string_length (str));
4071 const char *p = (const char*)mono_string_chars (str);
4073 swap_with_size (swapped, p, 2, mono_string_length (str));
4074 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4078 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4080 mono_image_add_stream_data (&assembly->us, "", 1);
4082 idx = assembly->us.index ++;
4085 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4087 return MONO_TOKEN_STRING | idx;
4091 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4096 klass = obj->vtable->klass;
4097 if (strcmp (klass->name, "MonoMethod") == 0) {
4098 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4099 MonoMethodSignature *sig, *old;
4100 guint32 sig_token, parent;
4103 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4105 nargs = mono_array_length (opt_param_types);
4106 old = mono_method_signature (method);
4107 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4109 sig->hasthis = old->hasthis;
4110 sig->explicit_this = old->explicit_this;
4111 sig->call_convention = old->call_convention;
4112 sig->generic_param_count = old->generic_param_count;
4113 sig->param_count = old->param_count + nargs;
4114 sig->sentinelpos = old->param_count;
4115 sig->ret = old->ret;
4117 for (i = 0; i < old->param_count; i++)
4118 sig->params [i] = old->params [i];
4120 for (i = 0; i < nargs; i++) {
4121 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4122 sig->params [old->param_count + i] = rt->type;
4125 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4126 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4127 parent >>= MONO_TYPEDEFORREF_BITS;
4129 parent <<= MONO_MEMBERREF_PARENT_BITS;
4130 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4132 sig_token = method_encode_signature (assembly, sig);
4133 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4134 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4135 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4136 ReflectionMethodBuilder rmb;
4137 guint32 parent, sig;
4139 reflection_methodbuilder_from_method_builder (&rmb, mb);
4140 rmb.opt_types = opt_param_types;
4142 sig = method_builder_encode_signature (assembly, &rmb);
4144 parent = mono_image_create_token (assembly, obj, TRUE);
4145 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4147 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4148 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4150 token = mono_image_get_varargs_method_token (
4151 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4153 g_error ("requested method token for %s\n", klass->name);
4160 * mono_image_create_token:
4161 * @assembly: a dynamic assembly
4164 * Get a token to insert in the IL code stream for the given MemberInfo.
4165 * @obj can be one of:
4166 * ConstructorBuilder
4176 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4181 klass = obj->vtable->klass;
4182 if (strcmp (klass->name, "MethodBuilder") == 0) {
4183 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4185 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4186 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4188 token = mono_image_get_methodbuilder_token (assembly, mb);
4189 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4190 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4191 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4193 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4194 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4196 token = mono_image_get_ctorbuilder_token (assembly, mb);
4197 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4198 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4199 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4200 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4201 if (tb->generic_params) {
4202 token = mono_image_get_generic_field_token (assembly, fb);
4204 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4206 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4207 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4208 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4209 } else if (strcmp (klass->name, "MonoType") == 0) {
4210 MonoReflectionType *tb = (MonoReflectionType *)obj;
4211 MonoClass *mc = mono_class_from_mono_type (tb->type);
4212 token = mono_metadata_token_from_dor (
4213 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4214 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4215 MonoReflectionType *tb = (MonoReflectionType *)obj;
4216 token = mono_metadata_token_from_dor (
4217 mono_image_typedef_or_ref (assembly, tb->type));
4218 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4219 MonoReflectionType *tb = (MonoReflectionType *)obj;
4220 token = mono_metadata_token_from_dor (
4221 mono_image_typedef_or_ref (assembly, tb->type));
4222 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4223 strcmp (klass->name, "MonoMethod") == 0 ||
4224 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4225 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4226 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4227 if (m->method->is_inflated) {
4228 if (create_methodspec)
4229 token = mono_image_get_methodspec_token (assembly, m->method);
4231 token = mono_image_get_inflated_method_token (assembly, m->method);
4232 } else if ((m->method->klass->image == &assembly->image) &&
4233 !m->method->klass->generic_class) {
4234 static guint32 method_table_idx = 0xffffff;
4235 if (m->method->klass->wastypebuilder) {
4236 /* we use the same token as the one that was assigned
4237 * to the Methodbuilder.
4238 * FIXME: do the equivalent for Fields.
4240 token = m->method->token;
4243 * Each token should have a unique index, but the indexes are
4244 * assigned by managed code, so we don't know about them. An
4245 * easy solution is to count backwards...
4247 method_table_idx --;
4248 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4251 token = mono_image_get_methodref_token (assembly, m->method);
4253 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4254 } else if (strcmp (klass->name, "MonoField") == 0) {
4255 MonoReflectionField *f = (MonoReflectionField *)obj;
4256 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4257 static guint32 field_table_idx = 0xffffff;
4259 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4261 token = mono_image_get_fieldref_token (assembly, f);
4263 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4264 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4265 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4266 token = mono_image_get_array_token (assembly, m);
4267 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4268 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4269 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4270 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4271 MonoReflectionType *tb = (MonoReflectionType *)obj;
4272 token = mono_metadata_token_from_dor (
4273 mono_image_typedef_or_ref (assembly, tb->type));
4275 g_error ("requested token for %s\n", klass->name);
4278 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4284 guint32 import_lookup_table;
4288 guint32 import_address_table_rva;
4296 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4298 static MonoDynamicImage*
4299 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4301 static const guchar entrycode [16] = {0xff, 0x25, 0};
4302 MonoDynamicImage *image;
4305 const char *version = mono_get_runtime_info ()->runtime_version;
4308 image = GC_MALLOC (sizeof (MonoDynamicImage));
4310 image = g_new0 (MonoDynamicImage, 1);
4313 /*g_print ("created image %p\n", image);*/
4314 /* keep in sync with image.c */
4315 image->image.name = assembly_name;
4316 image->image.assembly_name = image->image.name; /* they may be different */
4317 image->image.module_name = module_name;
4318 image->image.version = g_strdup (version);
4319 image->image.md_version_major = 1;
4320 image->image.md_version_minor = 1;
4321 image->image.dynamic = TRUE;
4323 image->image.references = g_new0 (MonoAssembly*, 1);
4324 image->image.references [0] = NULL;
4326 mono_image_init (&image->image);
4328 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4329 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4330 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4331 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4332 image->handleref = g_hash_table_new (NULL, NULL);
4333 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4334 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4335 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4336 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4337 image->gen_params = g_ptr_array_new ();
4339 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4340 string_heap_init (&image->sheap);
4341 mono_image_add_stream_data (&image->us, "", 1);
4342 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4343 /* import tables... */
4344 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4345 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4346 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4347 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4348 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4349 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4350 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4351 stream_data_align (&image->code);
4353 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4355 for (i=0; i < MONO_TABLE_NUM; ++i) {
4356 image->tables [i].next_idx = 1;
4357 image->tables [i].columns = table_sizes [i];
4360 image->image.assembly = (MonoAssembly*)assembly;
4361 image->run = assembly->run;
4362 image->save = assembly->save;
4363 image->pe_kind = 0x1; /* ILOnly */
4364 image->machine = 0x14c; /* I386 */
4370 * mono_image_basic_init:
4371 * @assembly: an assembly builder object
4373 * Create the MonoImage that represents the assembly builder and setup some
4374 * of the helper hash table and the basic metadata streams.
4377 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4379 MonoDynamicAssembly *assembly;
4380 MonoDynamicImage *image;
4381 MonoDomain *domain = mono_object_domain (assemblyb);
4383 MONO_ARCH_SAVE_REGS;
4385 if (assemblyb->dynamic_assembly)
4389 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4391 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4394 assembly->assembly.ref_count = 1;
4395 assembly->assembly.dynamic = TRUE;
4396 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4397 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4398 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4399 if (assemblyb->culture)
4400 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4402 assembly->assembly.aname.culture = g_strdup ("");
4404 if (assemblyb->version) {
4405 char *vstr = mono_string_to_utf8 (assemblyb->version);
4406 char **version = g_strsplit (vstr, ".", 4);
4407 char **parts = version;
4408 assembly->assembly.aname.major = atoi (*parts++);
4409 assembly->assembly.aname.minor = atoi (*parts++);
4410 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4411 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4413 g_strfreev (version);
4416 assembly->assembly.aname.major = 0;
4417 assembly->assembly.aname.minor = 0;
4418 assembly->assembly.aname.build = 0;
4419 assembly->assembly.aname.revision = 0;
4422 assembly->run = assemblyb->access != 2;
4423 assembly->save = assemblyb->access != 1;
4425 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4426 image->initial_image = TRUE;
4427 assembly->assembly.aname.name = image->image.name;
4428 assembly->assembly.image = &image->image;
4430 mono_domain_assemblies_lock (domain);
4431 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4432 mono_domain_assemblies_unlock (domain);
4434 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4435 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4439 calc_section_size (MonoDynamicImage *assembly)
4443 /* alignment constraints */
4444 assembly->code.index += 3;
4445 assembly->code.index &= ~3;
4446 assembly->meta_size += 3;
4447 assembly->meta_size &= ~3;
4448 assembly->resources.index += 3;
4449 assembly->resources.index &= ~3;
4451 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4452 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4455 if (assembly->win32_res) {
4456 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4458 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4459 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4463 assembly->sections [MONO_SECTION_RELOC].size = 12;
4464 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4474 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4478 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4480 ResTreeNode *t1 = (ResTreeNode*)a;
4481 ResTreeNode *t2 = (ResTreeNode*)b;
4483 return t1->id - t2->id;
4487 * resource_tree_create:
4489 * Organize the resources into a resource tree.
4491 static ResTreeNode *
4492 resource_tree_create (MonoArray *win32_resources)
4494 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4498 tree = g_new0 (ResTreeNode, 1);
4500 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4501 MonoReflectionWin32Resource *win32_res =
4502 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4506 /* FIXME: BUG: this stores managed references in unmanaged memory */
4507 lang_node = g_new0 (ResTreeNode, 1);
4508 lang_node->id = win32_res->lang_id;
4509 lang_node->win32_res = win32_res;
4511 /* Create type node if neccesary */
4513 for (l = tree->children; l; l = l->next)
4514 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4515 type_node = (ResTreeNode*)l->data;
4520 type_node = g_new0 (ResTreeNode, 1);
4521 type_node->id = win32_res->res_type;
4524 * The resource types have to be sorted otherwise
4525 * Windows Explorer can't display the version information.
4527 tree->children = g_slist_insert_sorted (tree->children,
4528 type_node, resource_tree_compare_by_id);
4531 /* Create res node if neccesary */
4533 for (l = type_node->children; l; l = l->next)
4534 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4535 res_node = (ResTreeNode*)l->data;
4540 res_node = g_new0 (ResTreeNode, 1);
4541 res_node->id = win32_res->res_id;
4542 type_node->children = g_slist_append (type_node->children, res_node);
4545 res_node->children = g_slist_append (res_node->children, lang_node);
4552 * resource_tree_encode:
4554 * Encode the resource tree into the format used in the PE file.
4557 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4560 MonoPEResourceDir dir;
4561 MonoPEResourceDirEntry dir_entry;
4562 MonoPEResourceDataEntry data_entry;
4566 * For the format of the resource directory, see the article
4567 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4571 memset (&dir, 0, sizeof (dir));
4572 memset (&dir_entry, 0, sizeof (dir_entry));
4573 memset (&data_entry, 0, sizeof (data_entry));
4575 g_assert (sizeof (dir) == 16);
4576 g_assert (sizeof (dir_entry) == 8);
4577 g_assert (sizeof (data_entry) == 16);
4579 node->offset = p - begin;
4581 /* IMAGE_RESOURCE_DIRECTORY */
4582 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4584 memcpy (p, &dir, sizeof (dir));
4587 /* Reserve space for entries */
4589 p += sizeof (dir_entry) * dir.res_id_entries;
4591 /* Write children */
4592 for (l = node->children; l; l = l->next) {
4593 ResTreeNode *child = (ResTreeNode*)l->data;
4595 if (child->win32_res) {
4597 child->offset = p - begin;
4599 /* IMAGE_RESOURCE_DATA_ENTRY */
4600 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4601 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4603 memcpy (p, &data_entry, sizeof (data_entry));
4604 p += sizeof (data_entry);
4606 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4607 p += data_entry.rde_size;
4609 resource_tree_encode (child, begin, p, &p);
4613 /* IMAGE_RESOURCE_ENTRY */
4614 for (l = node->children; l; l = l->next) {
4615 ResTreeNode *child = (ResTreeNode*)l->data;
4616 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4618 dir_entry.is_dir = child->win32_res ? 0 : 1;
4619 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4621 memcpy (entries, &dir_entry, sizeof (dir_entry));
4622 entries += sizeof (dir_entry);
4629 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4634 MonoReflectionWin32Resource *win32_res;
4637 if (!assemblyb->win32_resources)
4641 * Resources are stored in a three level tree inside the PE file.
4642 * - level one contains a node for each type of resource
4643 * - level two contains a node for each resource
4644 * - level three contains a node for each instance of a resource for a
4645 * specific language.
4648 tree = resource_tree_create (assemblyb->win32_resources);
4650 /* Estimate the size of the encoded tree */
4652 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4653 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4654 size += mono_array_length (win32_res->res_data);
4656 /* Directory structure */
4657 size += mono_array_length (assemblyb->win32_resources) * 256;
4658 p = buf = g_malloc (size);
4660 resource_tree_encode (tree, p, p, &p);
4662 g_assert (p - buf <= size);
4664 assembly->win32_res = g_malloc (p - buf);
4665 assembly->win32_res_size = p - buf;
4666 memcpy (assembly->win32_res, buf, p - buf);
4672 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4674 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4677 p += sizeof (MonoPEResourceDir);
4678 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4679 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4680 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4681 if (dir_entry->is_dir) {
4682 fixup_resource_directory (res_section, child, rva);
4684 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4685 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4688 p += sizeof (MonoPEResourceDirEntry);
4693 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4696 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4697 g_error ("WriteFile returned %d\n", GetLastError ());
4701 * mono_image_create_pefile:
4702 * @mb: a module builder object
4704 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4705 * assembly->pefile where it can be easily retrieved later in chunks.
4708 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4709 MonoMSDOSHeader *msdos;
4710 MonoDotNetHeader *header;
4711 MonoSectionTable *section;
4712 MonoCLIHeader *cli_header;
4713 guint32 size, image_size, virtual_base, text_offset;
4714 guint32 header_start, section_start, file_offset, virtual_offset;
4715 MonoDynamicImage *assembly;
4716 MonoReflectionAssemblyBuilder *assemblyb;
4717 MonoDynamicStream pefile_stream = {0};
4718 MonoDynamicStream *pefile = &pefile_stream;
4720 guint32 *rva, value;
4722 static const unsigned char msheader[] = {
4723 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4724 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4726 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4727 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4728 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4729 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4730 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4733 assemblyb = mb->assemblyb;
4735 mono_image_basic_init (assemblyb);
4736 assembly = mb->dynamic_image;
4738 assembly->pe_kind = assemblyb->pe_kind;
4739 assembly->machine = assemblyb->machine;
4740 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4741 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4743 mono_image_build_metadata (mb);
4745 if (mb->is_main && assemblyb->resources) {
4746 int len = mono_array_length (assemblyb->resources);
4747 for (i = 0; i < len; ++i)
4748 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4751 if (mb->resources) {
4752 int len = mono_array_length (mb->resources);
4753 for (i = 0; i < len; ++i)
4754 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4757 build_compressed_metadata (assembly);
4760 assembly_add_win32_resources (assembly, assemblyb);
4762 nsections = calc_section_size (assembly);
4764 /* The DOS header and stub */
4765 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4766 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4768 /* the dotnet header */
4769 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4771 /* the section tables */
4772 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4774 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4775 virtual_offset = VIRT_ALIGN;
4778 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4779 if (!assembly->sections [i].size)
4782 file_offset += FILE_ALIGN - 1;
4783 file_offset &= ~(FILE_ALIGN - 1);
4784 virtual_offset += VIRT_ALIGN - 1;
4785 virtual_offset &= ~(VIRT_ALIGN - 1);
4787 assembly->sections [i].offset = file_offset;
4788 assembly->sections [i].rva = virtual_offset;
4790 file_offset += assembly->sections [i].size;
4791 virtual_offset += assembly->sections [i].size;
4792 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4795 file_offset += FILE_ALIGN - 1;
4796 file_offset &= ~(FILE_ALIGN - 1);
4798 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4800 /* back-patch info */
4801 msdos = (MonoMSDOSHeader*)pefile->data;
4802 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4804 header = (MonoDotNetHeader*)(pefile->data + header_start);
4805 header->pesig [0] = 'P';
4806 header->pesig [1] = 'E';
4808 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4809 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4810 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4811 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4812 if (assemblyb->pekind == 1) {
4814 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4817 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4820 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4822 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4823 header->pe.pe_major = 6;
4824 header->pe.pe_minor = 0;
4825 size = assembly->sections [MONO_SECTION_TEXT].size;
4826 size += FILE_ALIGN - 1;
4827 size &= ~(FILE_ALIGN - 1);
4828 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4829 size = assembly->sections [MONO_SECTION_RSRC].size;
4830 size += FILE_ALIGN - 1;
4831 size &= ~(FILE_ALIGN - 1);
4832 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4833 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4834 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4835 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4836 /* pe_rva_entry_point always at the beginning of the text section */
4837 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4839 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4840 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4841 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4842 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4843 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4844 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4845 size = section_start;
4846 size += FILE_ALIGN - 1;
4847 size &= ~(FILE_ALIGN - 1);
4848 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4850 size += VIRT_ALIGN - 1;
4851 size &= ~(VIRT_ALIGN - 1);
4852 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4855 // Translate the PEFileKind value to the value expected by the Windows loader
4861 // PEFileKinds.Dll == 1
4862 // PEFileKinds.ConsoleApplication == 2
4863 // PEFileKinds.WindowApplication == 3
4866 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4867 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4869 if (assemblyb->pekind == 3)
4874 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4876 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4877 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4878 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4879 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4880 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4881 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4883 /* fill data directory entries */
4885 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4886 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4888 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4889 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4891 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4892 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4893 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4894 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4895 /* patch entrypoint name */
4896 if (assemblyb->pekind == 1)
4897 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4899 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4900 /* patch imported function RVA name */
4901 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4902 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4904 /* the import table */
4905 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4906 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4907 /* patch imported dll RVA name and other entries in the dir */
4908 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4909 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4910 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4911 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4912 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4913 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4915 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4916 value = (assembly->text_rva + assembly->imp_names_offset);
4917 *p++ = (value) & 0xff;
4918 *p++ = (value >> 8) & (0xff);
4919 *p++ = (value >> 16) & (0xff);
4920 *p++ = (value >> 24) & (0xff);
4922 /* the CLI header info */
4923 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4924 cli_header->ch_size = GUINT32_FROM_LE (72);
4925 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4926 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4927 if (assemblyb->entry_point) {
4928 guint32 table_idx = 0;
4929 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4930 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4931 table_idx = methodb->table_idx;
4933 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4935 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4937 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4939 /* The embedded managed resources */
4940 text_offset = assembly->text_rva + assembly->code.index;
4941 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4942 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4943 text_offset += assembly->resources.index;
4944 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4945 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4946 text_offset += assembly->meta_size;
4947 if (assembly->strong_name_size) {
4948 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4949 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4950 text_offset += assembly->strong_name_size;
4953 /* write the section tables and section content */
4954 section = (MonoSectionTable*)(pefile->data + section_start);
4955 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4956 static const char section_names [][7] = {
4957 ".text", ".rsrc", ".reloc"
4959 if (!assembly->sections [i].size)
4961 strcpy (section->st_name, section_names [i]);
4962 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4963 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4964 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4965 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4966 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4967 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4968 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4972 checked_write_file (file, pefile->data, pefile->index);
4974 mono_dynamic_stream_reset (pefile);
4976 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4977 if (!assembly->sections [i].size)
4980 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4981 g_error ("SetFilePointer returned %d\n", GetLastError ());
4984 case MONO_SECTION_TEXT:
4985 /* patch entry point */
4986 p = (guchar*)(assembly->code.data + 2);
4987 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4988 *p++ = (value) & 0xff;
4989 *p++ = (value >> 8) & 0xff;
4990 *p++ = (value >> 16) & 0xff;
4991 *p++ = (value >> 24) & 0xff;
4993 checked_write_file (file, assembly->code.data, assembly->code.index);
4994 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4995 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4996 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4999 g_free (assembly->image.raw_metadata);
5001 case MONO_SECTION_RELOC: {
5005 guint16 type_and_offset;
5009 g_assert (sizeof (reloc) == 12);
5011 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5012 reloc.block_size = GUINT32_FROM_LE (12);
5015 * the entrypoint is always at the start of the text section
5016 * 3 is IMAGE_REL_BASED_HIGHLOW
5017 * 2 is patch_size_rva - text_rva
5019 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5022 checked_write_file (file, &reloc, sizeof (reloc));
5026 case MONO_SECTION_RSRC:
5027 if (assembly->win32_res) {
5029 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5030 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5031 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5035 g_assert_not_reached ();
5039 /* check that the file is properly padded */
5040 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5041 g_error ("SetFilePointer returned %d\n", GetLastError ());
5042 if (! SetEndOfFile (file))
5043 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5045 mono_dynamic_stream_reset (&assembly->code);
5046 mono_dynamic_stream_reset (&assembly->us);
5047 mono_dynamic_stream_reset (&assembly->blob);
5048 mono_dynamic_stream_reset (&assembly->guid);
5049 mono_dynamic_stream_reset (&assembly->sheap);
5051 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5052 g_hash_table_destroy (assembly->blob_cache);
5053 assembly->blob_cache = NULL;
5056 MonoReflectionModule *
5057 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5061 MonoImageOpenStatus status;
5062 MonoDynamicAssembly *assembly;
5063 guint32 module_count;
5064 MonoImage **new_modules;
5065 gboolean *new_modules_loaded;
5067 name = mono_string_to_utf8 (fileName);
5069 image = mono_image_open (name, &status);
5072 if (status == MONO_IMAGE_ERROR_ERRNO)
5073 exc = mono_get_exception_file_not_found (fileName);
5075 exc = mono_get_exception_bad_image_format (name);
5077 mono_raise_exception (exc);
5082 assembly = ab->dynamic_assembly;
5083 image->assembly = (MonoAssembly*)assembly;
5085 module_count = image->assembly->image->module_count;
5086 new_modules = g_new0 (MonoImage *, module_count + 1);
5087 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5089 if (image->assembly->image->modules)
5090 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5091 if (image->assembly->image->modules_loaded)
5092 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5093 new_modules [module_count] = image;
5094 new_modules_loaded [module_count] = TRUE;
5095 mono_image_addref (image);
5097 g_free (image->assembly->image->modules);
5098 image->assembly->image->modules = new_modules;
5099 image->assembly->image->modules_loaded = new_modules_loaded;
5100 image->assembly->image->module_count ++;
5102 mono_assembly_load_references (image, &status);
5104 mono_image_close (image);
5105 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5108 return mono_module_get_object (mono_domain_get (), image);
5112 * We need to return always the same object for MethodInfo, FieldInfo etc..
5113 * but we need to consider the reflected type.
5114 * type uses a different hash, since it uses custom hash/equal functions.
5119 MonoClass *refclass;
5123 reflected_equal (gconstpointer a, gconstpointer b) {
5124 const ReflectedEntry *ea = a;
5125 const ReflectedEntry *eb = b;
5127 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5131 reflected_hash (gconstpointer a) {
5132 const ReflectedEntry *ea = a;
5133 return mono_aligned_addr_hash (ea->item);
5136 #define CHECK_OBJECT(t,p,k) \
5142 mono_domain_lock (domain); \
5143 if (!domain->refobject_hash) \
5144 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5145 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5146 mono_domain_unlock (domain); \
5149 mono_domain_unlock (domain); \
5153 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5155 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5157 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5160 #define CACHE_OBJECT(t,p,o,k) \
5163 ReflectedEntry pe; \
5165 pe.refclass = (k); \
5166 mono_domain_lock (domain); \
5167 if (!domain->refobject_hash) \
5168 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5169 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5171 ReflectedEntry *e = ALLOC_REFENTRY; \
5173 e->refclass = (k); \
5174 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5177 mono_domain_unlock (domain); \
5182 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5184 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5188 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5190 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5194 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5196 MonoDynamicImage *image = moduleb->dynamic_image;
5197 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5200 MonoImage **new_modules;
5203 * FIXME: we already created an image in mono_image_basic_init (), but
5204 * we don't know which module it belongs to, since that is only
5205 * determined at assembly save time.
5207 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5208 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5210 moduleb->module.image = &image->image;
5211 moduleb->dynamic_image = image;
5212 register_module (mono_object_domain (moduleb), moduleb, image);
5214 /* register the module with the assembly */
5215 ass = ab->dynamic_assembly->assembly.image;
5216 module_count = ass->module_count;
5217 new_modules = g_new0 (MonoImage *, module_count + 1);
5220 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5221 new_modules [module_count] = &image->image;
5222 mono_image_addref (&image->image);
5224 g_free (ass->modules);
5225 ass->modules = new_modules;
5226 ass->module_count ++;
5231 * mono_assembly_get_object:
5232 * @domain: an app domain
5233 * @assembly: an assembly
5235 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5237 MonoReflectionAssembly*
5238 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5240 static MonoClass *System_Reflection_Assembly;
5241 MonoReflectionAssembly *res;
5243 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5244 if (!System_Reflection_Assembly)
5245 System_Reflection_Assembly = mono_class_from_name (
5246 mono_defaults.corlib, "System.Reflection", "Assembly");
5247 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5248 res->assembly = assembly;
5250 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5255 MonoReflectionModule*
5256 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5258 static MonoClass *System_Reflection_Module;
5259 MonoReflectionModule *res;
5262 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5263 if (!System_Reflection_Module)
5264 System_Reflection_Module = mono_class_from_name (
5265 mono_defaults.corlib, "System.Reflection", "Module");
5266 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5269 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5271 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5272 basename = g_path_get_basename (image->name);
5273 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5274 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5278 if (image->assembly->image == image) {
5279 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5283 if (image->assembly->image->modules) {
5284 for (i = 0; i < image->assembly->image->module_count; i++) {
5285 if (image->assembly->image->modules [i] == image)
5286 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5288 g_assert (res->token);
5292 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5295 MonoReflectionModule*
5296 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5298 static MonoClass *System_Reflection_Module;
5299 MonoReflectionModule *res;
5300 MonoTableInfo *table;
5301 guint32 cols [MONO_FILE_SIZE];
5303 guint32 i, name_idx;
5306 if (!System_Reflection_Module)
5307 System_Reflection_Module = mono_class_from_name (
5308 mono_defaults.corlib, "System.Reflection", "Module");
5309 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5311 table = &image->tables [MONO_TABLE_FILE];
5312 g_assert (table_index < table->rows);
5313 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5316 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5317 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5319 /* Check whenever the row has a corresponding row in the moduleref table */
5320 table = &image->tables [MONO_TABLE_MODULEREF];
5321 for (i = 0; i < table->rows; ++i) {
5322 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5323 val = mono_metadata_string_heap (image, name_idx);
5324 if (strcmp (val, name) == 0)
5325 res->image = image->modules [i];
5328 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5329 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5330 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5331 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5332 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5338 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5340 if ((t1->type != t2->type) ||
5341 (t1->byref != t2->byref))
5345 case MONO_TYPE_VOID:
5346 case MONO_TYPE_BOOLEAN:
5347 case MONO_TYPE_CHAR:
5358 case MONO_TYPE_STRING:
5361 case MONO_TYPE_OBJECT:
5362 case MONO_TYPE_TYPEDBYREF:
5364 case MONO_TYPE_VALUETYPE:
5365 case MONO_TYPE_CLASS:
5366 case MONO_TYPE_SZARRAY:
5367 return t1->data.klass == t2->data.klass;
5369 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5370 case MONO_TYPE_ARRAY:
5371 if (t1->data.array->rank != t2->data.array->rank)
5373 return t1->data.array->eklass == t2->data.array->eklass;
5374 case MONO_TYPE_GENERICINST: {
5376 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5377 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5378 if (i1->type_argc != i2->type_argc)
5380 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5381 &t2->data.generic_class->container_class->byval_arg))
5383 /* FIXME: we should probably just compare the instance pointers directly. */
5384 for (i = 0; i < i1->type_argc; ++i) {
5385 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5391 case MONO_TYPE_MVAR:
5392 return t1->data.generic_param == t2->data.generic_param;
5394 g_error ("implement type compare for %0x!", t1->type);
5402 mymono_metadata_type_hash (MonoType *t1)
5408 hash |= t1->byref << 6; /* do not collide with t1->type values */
5410 case MONO_TYPE_VALUETYPE:
5411 case MONO_TYPE_CLASS:
5412 case MONO_TYPE_SZARRAY:
5413 /* check if the distribution is good enough */
5414 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5416 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5417 case MONO_TYPE_GENERICINST: {
5419 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5420 hash += g_str_hash (t1->data.generic_class->container_class->name);
5422 for (i = 0; i < inst->type_argc; ++i) {
5423 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5432 static MonoReflectionGenericClass*
5433 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5435 static MonoClass *System_Reflection_MonoGenericClass;
5436 MonoReflectionGenericClass *res;
5437 MonoClass *klass, *gklass;
5439 if (!System_Reflection_MonoGenericClass) {
5440 System_Reflection_MonoGenericClass = mono_class_from_name (
5441 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5442 g_assert (System_Reflection_MonoGenericClass);
5445 klass = mono_class_from_mono_type (geninst);
5446 gklass = klass->generic_class->container_class;
5448 mono_class_init (klass);
5451 /* FIXME: allow unpinned later */
5452 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5454 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5457 res->type.type = geninst;
5458 if (gklass->wastypebuilder && gklass->reflection_info)
5459 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5461 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5467 verify_safe_for_managed_space (MonoType *type)
5469 switch (type->type) {
5471 case MONO_TYPE_ARRAY:
5472 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5474 return verify_safe_for_managed_space (type->data.type);
5475 case MONO_TYPE_SZARRAY:
5476 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5477 case MONO_TYPE_GENERICINST: {
5478 MonoGenericInst *inst = type->data.generic_class->inst;
5482 for (i = 0; i < inst->type_argc; ++i)
5483 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5489 case MONO_TYPE_MVAR:
5496 * mono_type_get_object:
5497 * @domain: an app domain
5500 * Return an System.MonoType object representing the type @type.
5503 mono_type_get_object (MonoDomain *domain, MonoType *type)
5505 MonoReflectionType *res;
5506 MonoClass *klass = mono_class_from_mono_type (type);
5508 mono_domain_lock (domain);
5509 if (!domain->type_hash)
5510 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5511 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5512 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5513 mono_domain_unlock (domain);
5516 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5517 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5518 mono_g_hash_table_insert (domain->type_hash, type, res);
5519 mono_domain_unlock (domain);
5523 if (!verify_safe_for_managed_space (type)) {
5524 mono_domain_unlock (domain);
5525 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5528 if (klass->reflection_info && !klass->wastypebuilder) {
5529 /* g_assert_not_reached (); */
5530 /* should this be considered an error condition? */
5532 mono_domain_unlock (domain);
5533 return klass->reflection_info;
5536 mono_class_init (klass);
5538 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5540 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5543 mono_g_hash_table_insert (domain->type_hash, type, res);
5544 mono_domain_unlock (domain);
5549 * mono_method_get_object:
5550 * @domain: an app domain
5552 * @refclass: the reflected type (can be NULL)
5554 * Return an System.Reflection.MonoMethod object representing the method @method.
5556 MonoReflectionMethod*
5557 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5560 * We use the same C representation for methods and constructors, but the type
5561 * name in C# is different.
5563 static MonoClass *System_Reflection_MonoMethod = NULL;
5564 static MonoClass *System_Reflection_MonoCMethod = NULL;
5565 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5566 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5568 MonoReflectionMethod *ret;
5570 if (method->is_inflated) {
5571 MonoReflectionGenericMethod *gret;
5573 refclass = method->klass;
5574 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5575 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5576 if (!System_Reflection_MonoGenericCMethod)
5577 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5578 klass = System_Reflection_MonoGenericCMethod;
5580 if (!System_Reflection_MonoGenericMethod)
5581 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5582 klass = System_Reflection_MonoGenericMethod;
5584 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5585 gret->method.method = method;
5586 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5587 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5588 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5592 refclass = method->klass;
5594 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5595 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5596 if (!System_Reflection_MonoCMethod)
5597 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5598 klass = System_Reflection_MonoCMethod;
5601 if (!System_Reflection_MonoMethod)
5602 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5603 klass = System_Reflection_MonoMethod;
5605 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5606 ret->method = method;
5607 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5608 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5612 * mono_field_get_object:
5613 * @domain: an app domain
5617 * Return an System.Reflection.MonoField object representing the field @field
5620 MonoReflectionField*
5621 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5623 MonoReflectionField *res;
5624 static MonoClass *monofield_klass;
5626 CHECK_OBJECT (MonoReflectionField *, field, klass);
5627 if (!monofield_klass)
5628 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5629 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5632 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5633 if (field->generic_info)
5634 res->attrs = field->generic_info->generic_type->attrs;
5636 res->attrs = field->type->attrs;
5637 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5638 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5642 * mono_property_get_object:
5643 * @domain: an app domain
5645 * @property: a property
5647 * Return an System.Reflection.MonoProperty object representing the property @property
5650 MonoReflectionProperty*
5651 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5653 MonoReflectionProperty *res;
5654 static MonoClass *monoproperty_klass;
5656 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5657 if (!monoproperty_klass)
5658 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5659 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5661 res->property = property;
5662 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5666 * mono_event_get_object:
5667 * @domain: an app domain
5671 * Return an System.Reflection.MonoEvent object representing the event @event
5674 MonoReflectionEvent*
5675 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5677 MonoReflectionEvent *res;
5678 static MonoClass *monoevent_klass;
5680 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5681 if (!monoevent_klass)
5682 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5683 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5686 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5690 * mono_param_get_objects:
5691 * @domain: an app domain
5694 * Return an System.Reflection.ParameterInfo array object representing the parameters
5695 * in the method @method.
5698 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5700 static MonoClass *System_Reflection_ParameterInfo;
5701 MonoArray *res = NULL;
5702 MonoReflectionMethod *member = NULL;
5703 MonoReflectionParameter *param = NULL;
5704 char **names, **blobs = NULL;
5705 guint32 *types = NULL;
5706 MonoType *type = NULL;
5707 MonoObject *dbnull = mono_get_dbnull_object (domain);
5708 MonoMarshalSpec **mspecs;
5709 MonoMethodSignature *sig;
5712 if (!System_Reflection_ParameterInfo)
5713 System_Reflection_ParameterInfo = mono_class_from_name (
5714 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5716 if (!mono_method_signature (method)->param_count)
5717 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5719 /* Note: the cache is based on the address of the signature into the method
5720 * since we already cache MethodInfos with the method as keys.
5722 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5724 sig = mono_method_signature (method);
5725 member = mono_method_get_object (domain, method, NULL);
5726 names = g_new (char *, sig->param_count);
5727 mono_method_get_param_names (method, (const char **) names);
5729 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5730 mono_method_get_marshal_info (method, mspecs);
5732 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5733 for (i = 0; i < sig->param_count; ++i) {
5734 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5735 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5736 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5737 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5738 param->PositionImpl = i;
5739 param->AttrsImpl = sig->params [i]->attrs;
5741 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5742 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5746 blobs = g_new0 (char *, sig->param_count);
5747 types = g_new0 (guint32, sig->param_count);
5748 get_default_param_value_blobs (method, blobs, types);
5751 /* Build MonoType for the type from the Constant Table */
5753 type = g_new0 (MonoType, 1);
5754 type->type = types [i];
5755 type->data.klass = NULL;
5756 if (types [i] == MONO_TYPE_CLASS)
5757 type->data.klass = mono_defaults.object_class;
5758 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5759 /* For enums, types [i] contains the base type */
5761 type->type = MONO_TYPE_VALUETYPE;
5762 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5764 type->data.klass = mono_class_from_mono_type (type);
5766 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5768 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5769 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5770 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5775 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5777 mono_array_setref (res, i, param);
5784 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5786 mono_metadata_free_marshal_spec (mspecs [i]);
5789 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5793 * mono_method_body_get_object:
5794 * @domain: an app domain
5797 * Return an System.Reflection.MethodBody object representing the method @method.
5799 MonoReflectionMethodBody*
5800 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5802 static MonoClass *System_Reflection_MethodBody = NULL;
5803 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5804 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5805 MonoReflectionMethodBody *ret;
5806 MonoMethodNormal *mn;
5807 MonoMethodHeader *header;
5808 guint32 method_rva, local_var_sig_token;
5810 unsigned char format, flags;
5813 if (!System_Reflection_MethodBody)
5814 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5815 if (!System_Reflection_LocalVariableInfo)
5816 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5817 if (!System_Reflection_ExceptionHandlingClause)
5818 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5820 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5822 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5823 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5824 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5825 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5827 mn = (MonoMethodNormal *)method;
5828 header = mono_method_get_header (method);
5830 /* Obtain local vars signature token */
5831 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5832 ptr = mono_image_rva_map (method->klass->image, method_rva);
5833 flags = *(const unsigned char *) ptr;
5834 format = flags & METHOD_HEADER_FORMAT_MASK;
5836 case METHOD_HEADER_TINY_FORMAT:
5837 case METHOD_HEADER_TINY_FORMAT1:
5838 local_var_sig_token = 0;
5840 case METHOD_HEADER_FAT_FORMAT:
5844 local_var_sig_token = read32 (ptr);
5847 g_assert_not_reached ();
5850 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5852 ret->init_locals = header->init_locals;
5853 ret->max_stack = header->max_stack;
5854 ret->local_var_sig_token = local_var_sig_token;
5855 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5856 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5859 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5860 for (i = 0; i < header->num_locals; ++i) {
5861 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5862 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5863 info->is_pinned = header->locals [i]->pinned;
5864 info->local_index = i;
5865 mono_array_setref (ret->locals, i, info);
5869 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5870 for (i = 0; i < header->num_clauses; ++i) {
5871 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5872 MonoExceptionClause *clause = &header->clauses [i];
5874 info->flags = clause->flags;
5875 info->try_offset = clause->try_offset;
5876 info->try_length = clause->try_len;
5877 info->handler_offset = clause->handler_offset;
5878 info->handler_length = clause->handler_len;
5879 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5880 info->filter_offset = clause->data.filter_offset;
5881 else if (clause->data.catch_class)
5882 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5884 mono_array_setref (ret->clauses, i, info);
5887 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5892 mono_get_dbnull_object (MonoDomain *domain)
5895 static MonoClassField *dbnull_value_field = NULL;
5897 if (!dbnull_value_field) {
5898 MonoClass *dbnull_klass;
5899 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5900 mono_class_init (dbnull_klass);
5901 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5902 g_assert (dbnull_value_field);
5904 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5911 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5913 guint32 param_index, i, lastp, crow = 0;
5914 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5917 MonoClass *klass = method->klass;
5918 MonoImage *image = klass->image;
5919 MonoMethodSignature *methodsig = mono_method_signature (method);
5921 MonoTableInfo *constt;
5922 MonoTableInfo *methodt;
5923 MonoTableInfo *paramt;
5925 if (!methodsig->param_count)
5928 mono_class_init (klass);
5930 if (klass->image->dynamic) {
5931 MonoReflectionMethodAux *aux;
5932 if (method->is_inflated)
5933 method = ((MonoMethodInflated*)method)->declaring;
5934 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5935 if (aux && aux->param_defaults) {
5936 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5937 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5942 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5943 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5944 constt = &image->tables [MONO_TABLE_CONSTANT];
5946 idx = mono_method_get_index (method) - 1;
5947 g_assert (idx != -1);
5949 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5950 if (idx + 1 < methodt->rows)
5951 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5953 lastp = paramt->rows + 1;
5955 for (i = param_index; i < lastp; ++i) {
5958 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5959 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5961 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5964 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5969 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5970 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5971 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5978 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5983 MonoType *basetype = type;
5988 klass = mono_class_from_mono_type (type);
5989 if (klass->valuetype) {
5990 object = mono_object_new (domain, klass);
5991 retval = ((gchar *) object + sizeof (MonoObject));
5992 if (klass->enumtype)
5993 basetype = klass->enum_basetype;
5998 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6005 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6009 memset (assembly, 0, sizeof (MonoAssemblyName));
6011 assembly->culture = "";
6012 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6014 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6017 while (g_ascii_isspace (*p) || *p == ',') {
6026 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6028 assembly->major = strtoul (p, &s, 10);
6029 if (s == p || *s != '.')
6032 assembly->minor = strtoul (p, &s, 10);
6033 if (s == p || *s != '.')
6036 assembly->build = strtoul (p, &s, 10);
6037 if (s == p || *s != '.')
6040 assembly->revision = strtoul (p, &s, 10);
6044 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6046 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6047 assembly->culture = "";
6050 assembly->culture = p;
6051 while (*p && *p != ',') {
6055 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6057 if (strncmp (p, "null", 4) == 0) {
6062 while (*p && *p != ',') {
6065 len = (p - start + 1);
6066 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6067 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6068 g_strlcpy ((char*)assembly->public_key_token, start, len);
6071 while (*p && *p != ',')
6075 while (g_ascii_isspace (*p) || *p == ',') {
6089 * mono_reflection_parse_type:
6092 * Parse a type name as accepted by the GetType () method and output the info
6093 * extracted in the info structure.
6094 * the name param will be mangled, so, make a copy before passing it to this function.
6095 * The fields in info will be valid until the memory pointed to by name is valid.
6097 * See also mono_type_get_name () below.
6099 * Returns: 0 on parse error.
6102 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6103 MonoTypeNameParse *info)
6105 char *start, *p, *w, *temp, *last_point, *startn;
6106 int in_modifiers = 0;
6107 int isbyref = 0, rank, arity = 0, i;
6109 start = p = w = name;
6111 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6112 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6113 info->name = info->name_space = NULL;
6114 info->nested = NULL;
6115 info->modifiers = NULL;
6116 info->type_arguments = NULL;
6118 /* last_point separates the namespace from the name */
6124 *p = 0; /* NULL terminate the name */
6126 info->nested = g_list_append (info->nested, startn);
6127 /* we have parsed the nesting namespace + name */
6131 info->name_space = start;
6133 info->name = last_point + 1;
6135 info->name_space = (char *)"";
6154 i = strtol (p, &temp, 10);
6171 info->name_space = start;
6173 info->name = last_point + 1;
6175 info->name_space = (char *)"";
6182 if (isbyref) /* only one level allowed by the spec */
6185 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6189 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6195 info->type_arguments = g_ptr_array_new ();
6196 for (i = 0; i < arity; i++) {
6197 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6198 gboolean fqname = FALSE;
6200 g_ptr_array_add (info->type_arguments, subinfo);
6207 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6218 while (*p && (*p != ']'))
6226 if (g_ascii_isspace (*aname)) {
6233 !assembly_name_to_aname (&subinfo->assembly, aname))
6237 if (i + 1 < arity) {
6257 else if (*p != '*') /* '*' means unknown lower bound */
6263 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6274 if (g_ascii_isspace (*p)) {
6281 return 0; /* missing assembly name */
6282 if (!assembly_name_to_aname (&info->assembly, p))
6288 if (info->assembly.name)
6291 // *w = 0; /* terminate class name */
6293 if (!info->name || !*info->name)
6297 /* add other consistency checks */
6302 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6304 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6308 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6310 gboolean type_resolve = FALSE;
6312 MonoImage *rootimage = image;
6314 if (info->assembly.name) {
6315 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6317 /* then we must load the assembly ourselve - see #60439 */
6318 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6322 image = assembly->image;
6323 } else if (!image) {
6324 image = mono_defaults.corlib;
6327 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6328 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6329 image = mono_defaults.corlib;
6330 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6337 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6344 image = mono_defaults.corlib;
6347 klass = mono_class_from_name_case (image, info->name_space, info->name);
6349 klass = mono_class_from_name (image, info->name_space, info->name);
6352 for (mod = info->nested; mod; mod = mod->next) {
6355 mono_class_init (klass);
6356 nested = klass->nested_classes;
6359 klass = nested->data;
6361 if (g_strcasecmp (klass->name, mod->data) == 0)
6364 if (strcmp (klass->name, mod->data) == 0)
6368 nested = nested->next;
6375 mono_class_init (klass);
6377 if (info->type_arguments) {
6378 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6379 MonoReflectionType *the_type;
6383 for (i = 0; i < info->type_arguments->len; i++) {
6384 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6386 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6387 if (!type_args [i]) {
6393 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6395 instance = mono_reflection_bind_generic_parameters (
6396 the_type, info->type_arguments->len, type_args);
6402 klass = mono_class_from_mono_type (instance);
6405 for (mod = info->modifiers; mod; mod = mod->next) {
6406 modval = GPOINTER_TO_UINT (mod->data);
6407 if (!modval) { /* byref: must be last modifier */
6408 return &klass->this_arg;
6409 } else if (modval == -1) {
6410 klass = mono_ptr_class_get (&klass->byval_arg);
6411 } else { /* array rank */
6412 klass = mono_array_class_get (klass, modval);
6414 mono_class_init (klass);
6417 return &klass->byval_arg;
6421 * mono_reflection_get_type:
6422 * @image: a metadata context
6423 * @info: type description structure
6424 * @ignorecase: flag for case-insensitive string compares
6425 * @type_resolve: whenever type resolve was already tried
6427 * Build a MonoType from the type description in @info.
6432 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6433 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6437 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6439 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6443 g_assert (assembly->dynamic);
6445 /* Enumerate all modules */
6448 if (abuilder->modules) {
6449 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6450 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6451 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6457 if (!type && abuilder->loaded_modules) {
6458 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6459 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6460 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6470 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6473 MonoReflectionAssembly *assembly;
6477 if (image && image->dynamic)
6478 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6480 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6483 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6490 *type_resolve = TRUE;
6493 /* Reconstruct the type name */
6494 fullName = g_string_new ("");
6495 if (info->name_space && (info->name_space [0] != '\0'))
6496 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6498 g_string_printf (fullName, info->name);
6499 for (mod = info->nested; mod; mod = mod->next)
6500 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6502 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6504 if (assembly->assembly->dynamic)
6505 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6507 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6510 g_string_free (fullName, TRUE);
6515 mono_reflection_free_type_info (MonoTypeNameParse *info)
6517 g_list_free (info->modifiers);
6518 g_list_free (info->nested);
6520 if (info->type_arguments) {
6523 for (i = 0; i < info->type_arguments->len; i++) {
6524 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6526 mono_reflection_free_type_info (subinfo);
6527 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6531 g_ptr_array_free (info->type_arguments, TRUE);
6536 * mono_reflection_type_from_name:
6538 * @image: a metadata context (can be NULL).
6540 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6541 * it defaults to get the type from @image or, if @image is NULL or loading
6542 * from it fails, uses corlib.
6546 mono_reflection_type_from_name (char *name, MonoImage *image)
6548 MonoType *type = NULL;
6549 MonoTypeNameParse info;
6552 /* Make a copy since parse_type modifies its argument */
6553 tmp = g_strdup (name);
6555 /*g_print ("requested type %s\n", str);*/
6556 if (mono_reflection_parse_type (tmp, &info)) {
6557 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6561 mono_reflection_free_type_info (&info);
6566 * mono_reflection_get_token:
6568 * Return the metadata token of OBJ which should be an object
6569 * representing a metadata element.
6572 mono_reflection_get_token (MonoObject *obj)
6577 klass = obj->vtable->klass;
6579 if (strcmp (klass->name, "MethodBuilder") == 0) {
6580 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6582 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6583 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6584 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6586 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6587 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6588 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6589 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6590 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6591 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6592 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6593 } else if (strcmp (klass->name, "MonoType") == 0) {
6594 MonoReflectionType *tb = (MonoReflectionType *)obj;
6595 token = mono_class_from_mono_type (tb->type)->type_token;
6596 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6597 strcmp (klass->name, "MonoMethod") == 0 ||
6598 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6599 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6600 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6601 if (m->method->is_inflated) {
6602 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6603 return inflated->declaring->token;
6605 token = m->method->token;
6607 } else if (strcmp (klass->name, "MonoField") == 0) {
6608 MonoReflectionField *f = (MonoReflectionField*)obj;
6610 if (f->field->generic_info && f->field->generic_info->reflection_info)
6611 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6613 token = mono_class_get_field_token (f->field);
6614 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6615 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6617 token = mono_class_get_property_token (p->property);
6618 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6619 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6621 token = mono_class_get_event_token (p->event);
6622 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6623 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6625 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6626 } else if (strcmp (klass->name, "Module") == 0) {
6627 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6630 } else if (strcmp (klass->name, "Assembly") == 0) {
6631 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6633 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6634 MonoException *ex = mono_get_exception_not_implemented (msg);
6636 mono_raise_exception (ex);
6643 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6645 int slen, type = t->type;
6646 MonoClass *tklass = t->data.klass;
6652 case MONO_TYPE_BOOLEAN: {
6653 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6658 case MONO_TYPE_CHAR:
6660 case MONO_TYPE_I2: {
6661 guint16 *val = g_malloc (sizeof (guint16));
6666 #if SIZEOF_VOID_P == 4
6672 case MONO_TYPE_I4: {
6673 guint32 *val = g_malloc (sizeof (guint32));
6678 #if SIZEOF_VOID_P == 8
6679 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6683 case MONO_TYPE_I8: {
6684 guint64 *val = g_malloc (sizeof (guint64));
6689 case MONO_TYPE_R8: {
6690 double *val = g_malloc (sizeof (double));
6695 case MONO_TYPE_VALUETYPE:
6696 if (t->data.klass->enumtype) {
6697 type = t->data.klass->enum_basetype->type;
6700 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6703 case MONO_TYPE_STRING:
6704 if (*p == (char)0xFF) {
6708 slen = mono_metadata_decode_value (p, &p);
6710 return mono_string_new_len (mono_domain_get (), p, slen);
6711 case MONO_TYPE_CLASS: {
6714 if (*p == (char)0xFF) {
6719 slen = mono_metadata_decode_value (p, &p);
6720 n = g_memdup (p, slen + 1);
6722 t = mono_reflection_type_from_name (n, image);
6724 g_warning ("Cannot load type '%s'", n);
6728 return mono_type_get_object (mono_domain_get (), t);
6732 case MONO_TYPE_OBJECT: {
6735 MonoClass *subc = NULL;
6740 } else if (subt == 0x0E) {
6741 type = MONO_TYPE_STRING;
6743 } else if (subt == 0x1D) {
6744 MonoType simple_type = {{0}};
6749 /* See Partition II, Appendix B3 */
6750 etype = MONO_TYPE_OBJECT;
6751 type = MONO_TYPE_SZARRAY;
6752 simple_type.type = etype;
6753 tklass = mono_class_from_mono_type (&simple_type);
6755 } else if (subt == 0x55) {
6758 slen = mono_metadata_decode_value (p, &p);
6759 n = g_memdup (p, slen + 1);
6761 t = mono_reflection_type_from_name (n, image);
6763 g_error ("Cannot load type '%s'", n);
6766 subc = mono_class_from_mono_type (t);
6767 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6768 MonoType simple_type = {{0}};
6769 simple_type.type = subt;
6770 subc = mono_class_from_mono_type (&simple_type);
6772 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6774 val = load_cattr_value (image, &subc->byval_arg, p, end);
6775 obj = mono_object_new (mono_domain_get (), subc);
6776 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6780 case MONO_TYPE_SZARRAY: {
6782 guint32 i, alen, basetype;
6785 if (alen == 0xffffffff) {
6789 arr = mono_array_new (mono_domain_get(), tklass, alen);
6790 basetype = tklass->byval_arg.type;
6791 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6792 basetype = tklass->enum_basetype->type;
6797 case MONO_TYPE_BOOLEAN:
6798 for (i = 0; i < alen; i++) {
6799 MonoBoolean val = *p++;
6800 mono_array_set (arr, MonoBoolean, i, val);
6803 case MONO_TYPE_CHAR:
6806 for (i = 0; i < alen; i++) {
6807 guint16 val = read16 (p);
6808 mono_array_set (arr, guint16, i, val);
6815 for (i = 0; i < alen; i++) {
6816 guint32 val = read32 (p);
6817 mono_array_set (arr, guint32, i, val);
6822 for (i = 0; i < alen; i++) {
6825 mono_array_set (arr, double, i, val);
6831 for (i = 0; i < alen; i++) {
6832 guint64 val = read64 (p);
6833 mono_array_set (arr, guint64, i, val);
6837 case MONO_TYPE_CLASS:
6838 case MONO_TYPE_OBJECT:
6839 case MONO_TYPE_STRING:
6840 for (i = 0; i < alen; i++) {
6841 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6842 mono_array_setref (arr, i, item);
6846 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6852 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6858 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6860 static MonoClass *klass;
6861 static MonoMethod *ctor;
6863 void *params [2], *unboxed;
6866 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6868 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6870 params [0] = mono_type_get_object (mono_domain_get (), t);
6872 retval = mono_object_new (mono_domain_get (), klass);
6873 unboxed = mono_object_unbox (retval);
6874 mono_runtime_invoke (ctor, unboxed, params, NULL);
6880 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6882 static MonoClass *klass;
6883 static MonoMethod *ctor;
6885 void *unboxed, *params [2];
6888 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6890 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6893 params [1] = typedarg;
6894 retval = mono_object_new (mono_domain_get (), klass);
6895 unboxed = mono_object_unbox (retval);
6896 mono_runtime_invoke (ctor, unboxed, params, NULL);
6902 type_is_reference (MonoType *type)
6904 switch (type->type) {
6905 case MONO_TYPE_BOOLEAN:
6906 case MONO_TYPE_CHAR:
6919 case MONO_TYPE_VALUETYPE:
6927 free_param_data (MonoMethodSignature *sig, void **params) {
6929 for (i = 0; i < sig->param_count; ++i) {
6930 if (!type_is_reference (sig->params [i]))
6931 g_free (params [i]);
6936 * Find the field index in the metadata FieldDef table.
6939 find_field_index (MonoClass *klass, MonoClassField *field) {
6942 for (i = 0; i < klass->field.count; ++i) {
6943 if (field == &klass->fields [i])
6944 return klass->field.first + 1 + i;
6950 * Find the property index in the metadata Property table.
6953 find_property_index (MonoClass *klass, MonoProperty *property) {
6956 for (i = 0; i < klass->property.count; ++i) {
6957 if (property == &klass->properties [i])
6958 return klass->property.first + 1 + i;
6964 * Find the event index in the metadata Event table.
6967 find_event_index (MonoClass *klass, MonoEvent *event) {
6970 for (i = 0; i < klass->event.count; ++i) {
6971 if (event == &klass->events [i])
6972 return klass->event.first + 1 + i;
6978 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6980 const char *p = (const char*)data;
6982 guint32 i, j, num_named;
6986 mono_class_init (method->klass);
6989 attr = mono_object_new (mono_domain_get (), method->klass);
6990 mono_runtime_invoke (method, attr, NULL, NULL);
6994 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6997 /*g_print ("got attr %s\n", method->klass->name);*/
6999 /* Allocate using alloca so it gets GC tracking */
7000 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7004 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7005 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7009 attr = mono_object_new (mono_domain_get (), method->klass);
7010 mono_runtime_invoke (method, attr, params, NULL);
7011 free_param_data (method->signature, params);
7012 num_named = read16 (named);
7014 for (j = 0; j < num_named; j++) {
7016 char *name, named_type, data_type;
7017 named_type = *named++;
7018 data_type = *named++; /* type of data */
7019 if (data_type == MONO_TYPE_SZARRAY)
7020 data_type = *named++;
7021 if (data_type == MONO_TYPE_ENUM) {
7024 type_len = mono_metadata_decode_blob_size (named, &named);
7025 type_name = g_malloc (type_len + 1);
7026 memcpy (type_name, named, type_len);
7027 type_name [type_len] = 0;
7029 /* FIXME: lookup the type and check type consistency */
7032 name_len = mono_metadata_decode_blob_size (named, &named);
7033 name = g_malloc (name_len + 1);
7034 memcpy (name, named, name_len);
7035 name [name_len] = 0;
7037 if (named_type == 0x53) {
7038 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7039 void *val = load_cattr_value (image, field->type, named, &named);
7040 mono_field_set_value (attr, field, val);
7041 if (!type_is_reference (field->type))
7043 } else if (named_type == 0x54) {
7046 MonoType *prop_type;
7048 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7049 /* can we have more that 1 arg in a custom attr named property? */
7050 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7051 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7052 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7053 mono_property_set_value (prop, attr, pparams, NULL);
7054 if (!type_is_reference (prop_type))
7055 g_free (pparams [0]);
7064 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7066 MonoArray *typedargs, *namedargs;
7067 MonoClass *attrklass;
7068 static MonoMethod *ctor;
7071 const char *p = (const char*)data;
7073 guint32 i, j, num_named;
7076 mono_class_init (method->klass);
7079 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7081 domain = mono_domain_get ();
7083 /* This is for Attributes with no parameters */
7084 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7085 params [0] = mono_method_get_object (domain, method, NULL);
7086 params [1] = params [2] = NULL;
7087 mono_runtime_invoke (method, attr, params, NULL);
7091 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7094 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7098 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7099 MonoObject *obj, *typedarg;
7102 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7103 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7104 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7105 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7106 mono_array_setref (typedargs, i, typedarg);
7108 if (!type_is_reference (mono_method_signature (method)->params [i]))
7113 num_named = read16 (named);
7114 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7116 attrklass = method->klass;
7117 for (j = 0; j < num_named; j++) {
7119 char *name, named_type, data_type;
7120 named_type = *named++;
7121 data_type = *named++; /* type of data */
7122 if (data_type == MONO_TYPE_SZARRAY)
7123 data_type = *named++;
7124 if (data_type == MONO_TYPE_ENUM) {
7127 type_len = mono_metadata_decode_blob_size (named, &named);
7128 type_name = g_malloc (type_len + 1);
7129 memcpy (type_name, named, type_len);
7130 type_name [type_len] = 0;
7132 /* FIXME: lookup the type and check type consistency */
7135 name_len = mono_metadata_decode_blob_size (named, &named);
7136 name = g_malloc (name_len + 1);
7137 memcpy (name, named, name_len);
7138 name [name_len] = 0;
7140 if (named_type == 0x53) {
7141 MonoObject *obj, *typedarg, *namedarg;
7142 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7143 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7145 minfo = mono_field_get_object (domain, NULL, field);
7146 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7147 typedarg = create_cattr_typed_arg (field->type, obj);
7148 namedarg = create_cattr_named_arg (minfo, typedarg);
7149 mono_array_setref (namedargs, j, namedarg);
7150 if (!type_is_reference (field->type))
7152 } else if (named_type == 0x54) {
7153 MonoObject *obj, *typedarg, *namedarg;
7154 MonoType *prop_type;
7156 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7158 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7159 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7160 minfo = mono_property_get_object (domain, NULL, prop);
7161 val = load_cattr_value (image, prop_type, named, &named);
7162 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7163 typedarg = create_cattr_typed_arg (prop_type, obj);
7164 namedarg = create_cattr_named_arg (minfo, typedarg);
7165 mono_array_setref (namedargs, j, namedarg);
7166 if (!type_is_reference (prop_type))
7171 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7172 params [0] = mono_method_get_object (domain, method, NULL);
7173 params [1] = typedargs;
7174 params [2] = namedargs;
7175 mono_runtime_invoke (ctor, attr, params, NULL);
7180 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7186 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7187 for (i = 0; i < cinfo->num_attrs; ++i) {
7188 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7189 mono_array_setref (result, i, attr);
7195 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7202 for (i = 0; i < cinfo->num_attrs; ++i) {
7203 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7207 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7209 for (i = 0; i < cinfo->num_attrs; ++i) {
7210 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7211 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7212 mono_array_setref (result, n, attr);
7220 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7226 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7227 for (i = 0; i < cinfo->num_attrs; ++i) {
7228 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7229 mono_array_setref (result, i, attr);
7235 * mono_custom_attrs_from_index:
7237 * Returns: NULL if no attributes are found or if a loading error occurs.
7240 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7242 guint32 mtoken, i, len;
7243 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7245 MonoCustomAttrInfo *ainfo;
7246 GList *tmp, *list = NULL;
7249 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7251 i = mono_metadata_custom_attrs_from_index (image, idx);
7255 while (i < ca->rows) {
7256 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7258 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7261 len = g_list_length (list);
7264 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7265 ainfo->num_attrs = len;
7266 ainfo->image = image;
7267 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7268 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7269 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7270 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7271 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7272 mtoken |= MONO_TOKEN_METHOD_DEF;
7274 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7275 mtoken |= MONO_TOKEN_MEMBER_REF;
7278 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7281 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7282 if (!ainfo->attrs [i].ctor) {
7283 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7288 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7289 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7290 ainfo->attrs [i].data = (guchar*)data;
7298 mono_custom_attrs_from_method (MonoMethod *method)
7300 MonoCustomAttrInfo *cinfo;
7303 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7305 idx = mono_method_get_index (method);
7306 idx <<= MONO_CUSTOM_ATTR_BITS;
7307 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7308 return mono_custom_attrs_from_index (method->klass->image, idx);
7312 mono_custom_attrs_from_class (MonoClass *klass)
7314 MonoCustomAttrInfo *cinfo;
7317 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7319 idx = mono_metadata_token_index (klass->type_token);
7320 idx <<= MONO_CUSTOM_ATTR_BITS;
7321 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7322 return mono_custom_attrs_from_index (klass->image, idx);
7326 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7328 MonoCustomAttrInfo *cinfo;
7331 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7333 idx = 1; /* there is only one assembly */
7334 idx <<= MONO_CUSTOM_ATTR_BITS;
7335 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7336 return mono_custom_attrs_from_index (assembly->image, idx);
7339 static MonoCustomAttrInfo*
7340 mono_custom_attrs_from_module (MonoImage *image)
7342 MonoCustomAttrInfo *cinfo;
7345 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7347 idx = 1; /* there is only one module */
7348 idx <<= MONO_CUSTOM_ATTR_BITS;
7349 idx |= MONO_CUSTOM_ATTR_MODULE;
7350 return mono_custom_attrs_from_index (image, idx);
7354 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7356 MonoCustomAttrInfo *cinfo;
7359 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7361 idx = find_property_index (klass, property);
7362 idx <<= MONO_CUSTOM_ATTR_BITS;
7363 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7364 return mono_custom_attrs_from_index (klass->image, idx);
7368 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7370 MonoCustomAttrInfo *cinfo;
7373 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7375 idx = find_event_index (klass, event);
7376 idx <<= MONO_CUSTOM_ATTR_BITS;
7377 idx |= MONO_CUSTOM_ATTR_EVENT;
7378 return mono_custom_attrs_from_index (klass->image, idx);
7382 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7384 MonoCustomAttrInfo *cinfo;
7387 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7389 idx = find_field_index (klass, field);
7390 idx <<= MONO_CUSTOM_ATTR_BITS;
7391 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7392 return mono_custom_attrs_from_index (klass->image, idx);
7396 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7399 guint32 i, idx, method_index;
7400 guint32 param_list, param_last, param_pos, found;
7402 MonoReflectionMethodAux *aux;
7404 if (method->klass->image->dynamic) {
7405 MonoCustomAttrInfo *res, *ainfo;
7408 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7409 if (!aux || !aux->param_cattr)
7412 /* Need to copy since it will be freed later */
7413 ainfo = aux->param_cattr [param];
7414 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7415 res = g_malloc0 (size);
7416 memcpy (res, ainfo, size);
7420 image = method->klass->image;
7421 method_index = mono_method_get_index (method);
7422 ca = &image->tables [MONO_TABLE_METHOD];
7424 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7425 if (method_index == ca->rows) {
7426 ca = &image->tables [MONO_TABLE_PARAM];
7427 param_last = ca->rows + 1;
7429 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7430 ca = &image->tables [MONO_TABLE_PARAM];
7433 for (i = param_list; i < param_last; ++i) {
7434 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7435 if (param_pos == param) {
7443 idx <<= MONO_CUSTOM_ATTR_BITS;
7444 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7445 return mono_custom_attrs_from_index (image, idx);
7449 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7453 for (i = 0; i < ainfo->num_attrs; ++i) {
7454 klass = ainfo->attrs [i].ctor->klass;
7455 if (mono_class_has_parent (klass, attr_klass))
7462 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7469 for (i = 0; i < ainfo->num_attrs; ++i) {
7470 klass = ainfo->attrs [i].ctor->klass;
7471 if (mono_class_has_parent (klass, attr_klass)) {
7476 if (attr_index == -1)
7479 attrs = mono_custom_attrs_construct (ainfo);
7481 return mono_array_get (attrs, MonoObject*, attr_index);
7487 * mono_reflection_get_custom_attrs_info:
7488 * @obj: a reflection object handle
7490 * Return the custom attribute info for attributes defined for the
7491 * reflection handle @obj. The objects.
7494 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7497 MonoCustomAttrInfo *cinfo = NULL;
7499 klass = obj->vtable->klass;
7500 if (klass == mono_defaults.monotype_class) {
7501 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7502 klass = mono_class_from_mono_type (rtype->type);
7503 cinfo = mono_custom_attrs_from_class (klass);
7504 } else if (strcmp ("Assembly", klass->name) == 0) {
7505 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7506 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7507 } else if (strcmp ("Module", klass->name) == 0) {
7508 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7509 cinfo = mono_custom_attrs_from_module (module->image);
7510 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7511 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7512 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7513 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7514 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7515 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7516 } else if (strcmp ("MonoField", klass->name) == 0) {
7517 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7518 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7519 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7520 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7521 cinfo = mono_custom_attrs_from_method (rmethod->method);
7522 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7523 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7524 cinfo = mono_custom_attrs_from_method (rmethod->method);
7525 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7526 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7527 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7528 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7529 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7530 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7531 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7532 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7533 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7534 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7535 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7536 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7537 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7538 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7539 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7540 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7541 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7542 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7543 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7544 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7545 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7546 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7547 } else { /* handle other types here... */
7548 g_error ("get custom attrs not yet supported for %s", klass->name);
7555 * mono_reflection_get_custom_attrs_by_type:
7556 * @obj: a reflection object handle
7558 * Return an array with all the custom attributes defined of the
7559 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7560 * of that type are returned. The objects are fully build. Return NULL if a loading error
7564 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7567 MonoCustomAttrInfo *cinfo;
7569 cinfo = mono_reflection_get_custom_attrs_info (obj);
7572 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7574 result = mono_custom_attrs_construct (cinfo);
7576 mono_custom_attrs_free (cinfo);
7578 if (mono_loader_get_last_error ())
7580 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7587 * mono_reflection_get_custom_attrs:
7588 * @obj: a reflection object handle
7590 * Return an array with all the custom attributes defined of the
7591 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7595 mono_reflection_get_custom_attrs (MonoObject *obj)
7597 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7601 * mono_reflection_get_custom_attrs_data:
7602 * @obj: a reflection obj handle
7604 * Returns an array of System.Reflection.CustomAttributeData,
7605 * which include information about attributes reflected on
7606 * types loaded using the Reflection Only methods
7609 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7612 MonoCustomAttrInfo *cinfo;
7614 cinfo = mono_reflection_get_custom_attrs_info (obj);
7616 result = mono_custom_attrs_data_construct (cinfo);
7618 mono_custom_attrs_free (cinfo);
7620 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7625 static MonoReflectionType*
7626 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7628 MonoMethod *method_get_underlying_system_type;
7630 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7631 mono_class_get_method_from_name (mono_object_class (t),
7632 "get_UnderlyingSystemType",
7634 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7638 mono_reflection_type_get_handle (MonoReflectionType* t)
7643 t = mono_reflection_type_get_underlying_system_type (t);
7651 * LOCKING: Assumes the loader lock is held.
7653 static MonoMethodSignature*
7654 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7655 MonoMethodSignature *sig;
7658 count = parameters? mono_array_length (parameters): 0;
7660 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7661 sig->param_count = count;
7662 sig->sentinelpos = -1; /* FIXME */
7663 for (i = 0; i < count; ++i) {
7664 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7665 sig->params [i] = mono_reflection_type_get_handle (pt);
7671 * LOCKING: Assumes the loader lock is held.
7673 static MonoMethodSignature*
7674 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7675 MonoMethodSignature *sig;
7677 sig = parameters_to_signature (mp, ctor->parameters);
7678 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7679 sig->ret = &mono_defaults.void_class->byval_arg;
7684 * LOCKING: Assumes the loader lock is held.
7686 static MonoMethodSignature*
7687 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7688 MonoMethodSignature *sig;
7690 sig = parameters_to_signature (mp, method->parameters);
7691 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7692 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7693 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7697 static MonoMethodSignature*
7698 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7699 MonoMethodSignature *sig;
7701 sig = parameters_to_signature (NULL, method->parameters);
7702 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7703 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7704 sig->generic_param_count = 0;
7709 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7711 MonoClass *klass = mono_object_class (prop);
7712 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7713 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7714 *name = mono_string_to_utf8 (pb->name);
7715 *type = pb->type->type;
7717 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7718 *name = g_strdup (p->property->name);
7719 if (p->property->get)
7720 *type = mono_method_signature (p->property->get)->ret;
7722 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7727 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7729 MonoClass *klass = mono_object_class (field);
7730 if (strcmp (klass->name, "FieldBuilder") == 0) {
7731 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7732 *name = mono_string_to_utf8 (fb->name);
7733 *type = fb->type->type;
7735 MonoReflectionField *f = (MonoReflectionField *)field;
7736 *name = g_strdup (f->field->name);
7737 *type = f->field->type;
7742 * Encode a value in a custom attribute stream of bytes.
7743 * The value to encode is either supplied as an object in argument val
7744 * (valuetypes are boxed), or as a pointer to the data in the
7746 * @type represents the type of the value
7747 * @buffer is the start of the buffer
7748 * @p the current position in the buffer
7749 * @buflen contains the size of the buffer and is used to return the new buffer size
7750 * if this needs to be realloced.
7751 * @retbuffer and @retp return the start and the position of the buffer
7754 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7756 MonoTypeEnum simple_type;
7758 if ((p-buffer) + 10 >= *buflen) {
7761 newbuf = g_realloc (buffer, *buflen);
7762 p = newbuf + (p-buffer);
7766 argval = ((char*)arg + sizeof (MonoObject));
7767 simple_type = type->type;
7769 switch (simple_type) {
7770 case MONO_TYPE_BOOLEAN:
7775 case MONO_TYPE_CHAR:
7778 swap_with_size (p, argval, 2, 1);
7784 swap_with_size (p, argval, 4, 1);
7788 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7798 swap_with_size (p, argval, 8, 1);
7804 swap_with_size (p, argval, 8, 1);
7807 case MONO_TYPE_VALUETYPE:
7808 if (type->data.klass->enumtype) {
7809 simple_type = type->data.klass->enum_basetype->type;
7812 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7815 case MONO_TYPE_STRING: {
7822 str = mono_string_to_utf8 ((MonoString*)arg);
7823 slen = strlen (str);
7824 if ((p-buffer) + 10 + slen >= *buflen) {
7828 newbuf = g_realloc (buffer, *buflen);
7829 p = newbuf + (p-buffer);
7832 mono_metadata_encode_value (slen, p, &p);
7833 memcpy (p, str, slen);
7838 case MONO_TYPE_CLASS: {
7846 k = mono_object_class (arg);
7847 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7848 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7849 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7852 if (rt && (rtc = mono_object_class (rt)) &&
7853 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7854 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7855 arg = (MonoObject *) rt;
7858 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7861 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7862 slen = strlen (str);
7863 if ((p-buffer) + 10 + slen >= *buflen) {
7867 newbuf = g_realloc (buffer, *buflen);
7868 p = newbuf + (p-buffer);
7871 mono_metadata_encode_value (slen, p, &p);
7872 memcpy (p, str, slen);
7877 case MONO_TYPE_SZARRAY: {
7879 MonoClass *eclass, *arg_eclass;
7882 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7885 len = mono_array_length ((MonoArray*)arg);
7887 *p++ = (len >> 8) & 0xff;
7888 *p++ = (len >> 16) & 0xff;
7889 *p++ = (len >> 24) & 0xff;
7891 *retbuffer = buffer;
7892 eclass = type->data.klass;
7893 arg_eclass = mono_object_class (arg)->element_class;
7896 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7897 eclass = mono_defaults.object_class;
7899 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7900 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7901 int elsize = mono_class_array_element_size (arg_eclass);
7902 for (i = 0; i < len; ++i) {
7903 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7906 } else if (eclass->valuetype && arg_eclass->valuetype) {
7907 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7908 int elsize = mono_class_array_element_size (eclass);
7909 for (i = 0; i < len; ++i) {
7910 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7914 for (i = 0; i < len; ++i) {
7915 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7920 case MONO_TYPE_OBJECT: {
7926 * The parameter type is 'object' but the type of the actual
7927 * argument is not. So we have to add type information to the blob
7928 * too. This is completely undocumented in the spec.
7932 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7937 klass = mono_object_class (arg);
7939 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7942 } else if (klass->enumtype) {
7944 } else if (klass == mono_defaults.string_class) {
7945 simple_type = MONO_TYPE_STRING;
7948 } else if (klass->rank == 1) {
7950 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7951 /* See Partition II, Appendix B3 */
7954 *p++ = klass->element_class->byval_arg.type;
7955 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7957 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7958 *p++ = simple_type = klass->byval_arg.type;
7961 g_error ("unhandled type in custom attr");
7963 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7964 slen = strlen (str);
7965 if ((p-buffer) + 10 + slen >= *buflen) {
7969 newbuf = g_realloc (buffer, *buflen);
7970 p = newbuf + (p-buffer);
7973 mono_metadata_encode_value (slen, p, &p);
7974 memcpy (p, str, slen);
7977 simple_type = klass->enum_basetype->type;
7981 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7984 *retbuffer = buffer;
7988 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7990 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7991 char *str = type_get_qualified_name (type, NULL);
7992 int slen = strlen (str);
7996 * This seems to be optional...
7999 mono_metadata_encode_value (slen, p, &p);
8000 memcpy (p, str, slen);
8003 } else if (type->type == MONO_TYPE_OBJECT) {
8005 } else if (type->type == MONO_TYPE_CLASS) {
8006 /* it should be a type: encode_cattr_value () has the check */
8009 mono_metadata_encode_value (type->type, p, &p);
8010 if (type->type == MONO_TYPE_SZARRAY)
8011 /* See the examples in Partition VI, Annex B */
8012 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8019 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8022 /* Preallocate a large enough buffer */
8023 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8024 char *str = type_get_qualified_name (type, NULL);
8027 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8028 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8034 len += strlen (name);
8036 if ((p-buffer) + 20 + len >= *buflen) {
8040 newbuf = g_realloc (buffer, *buflen);
8041 p = newbuf + (p-buffer);
8045 encode_field_or_prop_type (type, p, &p);
8047 len = strlen (name);
8048 mono_metadata_encode_value (len, p, &p);
8049 memcpy (p, name, len);
8051 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8053 *retbuffer = buffer;
8057 * mono_reflection_get_custom_attrs_blob:
8058 * @ctor: custom attribute constructor
8059 * @ctorArgs: arguments o the constructor
8065 * Creates the blob of data that needs to be saved in the metadata and that represents
8066 * the custom attributed described by @ctor, @ctorArgs etc.
8067 * Returns: a Byte array representing the blob of data.
8070 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8073 MonoMethodSignature *sig;
8078 MONO_ARCH_SAVE_REGS;
8080 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8081 /* sig is freed later so allocate it in the heap */
8082 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8084 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8087 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8089 p = buffer = g_malloc (buflen);
8090 /* write the prolog */
8093 for (i = 0; i < sig->param_count; ++i) {
8094 arg = mono_array_get (ctorArgs, MonoObject*, i);
8095 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8099 i += mono_array_length (properties);
8101 i += mono_array_length (fields);
8103 *p++ = (i >> 8) & 0xff;
8106 for (i = 0; i < mono_array_length (properties); ++i) {
8110 prop = mono_array_get (properties, gpointer, i);
8111 get_prop_name_and_type (prop, &pname, &ptype);
8112 *p++ = 0x54; /* PROPERTY signature */
8113 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8120 for (i = 0; i < mono_array_length (fields); ++i) {
8124 field = mono_array_get (fields, gpointer, i);
8125 get_field_name_and_type (field, &fname, &ftype);
8126 *p++ = 0x53; /* FIELD signature */
8127 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8132 g_assert (p - buffer <= buflen);
8133 buflen = p - buffer;
8134 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8135 p = mono_array_addr (result, char, 0);
8136 memcpy (p, buffer, buflen);
8138 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8144 static void* reflection_info_desc = NULL;
8145 #define MOVING_GC_REGISTER(addr) do { \
8146 if (!reflection_info_desc) { \
8148 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8150 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8153 #define MOVING_GC_REGISTER(addr)
8157 * mono_reflection_setup_internal_class:
8158 * @tb: a TypeBuilder object
8160 * Creates a MonoClass that represents the TypeBuilder.
8161 * This is a trick that lets us simplify a lot of reflection code
8162 * (and will allow us to support Build and Run assemblies easier).
8165 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8167 MonoClass *klass, *parent;
8169 MONO_ARCH_SAVE_REGS;
8171 mono_loader_lock ();
8174 /* check so we can compile corlib correctly */
8175 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8176 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8177 parent = tb->parent->type->data.klass;
8179 parent = my_mono_class_from_mono_type (tb->parent->type);
8185 /* the type has already being created: it means we just have to change the parent */
8186 if (tb->type.type) {
8187 klass = mono_class_from_mono_type (tb->type.type);
8188 klass->parent = NULL;
8189 /* fool mono_class_setup_parent */
8190 klass->supertypes = NULL;
8191 mono_class_setup_parent (klass, parent);
8192 mono_class_setup_mono_type (klass);
8193 mono_loader_unlock ();
8197 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8199 klass->image = &tb->module->dynamic_image->image;
8201 klass->inited = 1; /* we lie to the runtime */
8202 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8203 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8204 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8205 klass->flags = tb->attrs;
8207 klass->element_class = klass;
8209 MOVING_GC_REGISTER (&klass->reflection_info);
8210 klass->reflection_info = tb;
8212 /* Put into cache so mono_class_get () will find it */
8213 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8215 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8216 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8218 if (parent != NULL) {
8219 mono_class_setup_parent (klass, parent);
8220 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8221 const char *old_n = klass->name;
8222 /* trick to get relative numbering right when compiling corlib */
8223 klass->name = "BuildingObject";
8224 mono_class_setup_parent (klass, mono_defaults.object_class);
8225 klass->name = old_n;
8228 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8229 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8230 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8231 klass->instance_size = sizeof (MonoObject);
8232 klass->size_inited = 1;
8233 mono_class_setup_vtable_general (klass, NULL, 0);
8236 mono_class_setup_mono_type (klass);
8238 mono_class_setup_supertypes (klass);
8241 * FIXME: handle interfaces.
8244 tb->type.type = &klass->byval_arg;
8246 if (tb->nesting_type) {
8247 g_assert (tb->nesting_type->type);
8248 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8251 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8253 mono_loader_unlock ();
8257 * mono_reflection_setup_generic_class:
8258 * @tb: a TypeBuilder object
8260 * Setup the generic class before adding the first generic parameter.
8263 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8267 MONO_ARCH_SAVE_REGS;
8269 klass = my_mono_class_from_mono_type (tb->type.type);
8270 if (tb->generic_container)
8273 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8274 tb->generic_container->owner.klass = klass;
8278 * mono_reflection_create_generic_class:
8279 * @tb: a TypeBuilder object
8281 * Creates the generic class after all generic parameters have been added.
8284 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8289 MONO_ARCH_SAVE_REGS;
8291 klass = my_mono_class_from_mono_type (tb->type.type);
8293 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8295 if (klass->generic_container || (count == 0))
8298 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8300 klass->generic_container = tb->generic_container;
8302 klass->generic_container->type_argc = count;
8303 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8305 for (i = 0; i < count; i++) {
8306 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8307 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8308 g_assert (klass->generic_container->type_params [i].owner);
8311 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8315 * mono_reflection_create_internal_class:
8316 * @tb: a TypeBuilder object
8318 * Actually create the MonoClass that is associated with the TypeBuilder.
8321 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8325 MONO_ARCH_SAVE_REGS;
8327 klass = my_mono_class_from_mono_type (tb->type.type);
8329 mono_loader_lock ();
8330 if (klass->enumtype && klass->enum_basetype == NULL) {
8331 MonoReflectionFieldBuilder *fb;
8334 g_assert (tb->fields != NULL);
8335 g_assert (mono_array_length (tb->fields) >= 1);
8337 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8339 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8340 mono_loader_unlock ();
8344 klass->enum_basetype = fb->type->type;
8345 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8346 if (!klass->element_class)
8347 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8350 * get the element_class from the current corlib.
8352 ec = default_class_from_mono_type (klass->enum_basetype);
8353 klass->instance_size = ec->instance_size;
8354 klass->size_inited = 1;
8356 * this is almost safe to do with enums and it's needed to be able
8357 * to create objects of the enum type (for use in SetConstant).
8359 /* FIXME: Does this mean enums can't have method overrides ? */
8360 mono_class_setup_vtable_general (klass, NULL, 0);
8362 mono_loader_unlock ();
8365 static MonoMarshalSpec*
8366 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8367 MonoReflectionMarshal *minfo)
8369 MonoMarshalSpec *res;
8371 res = g_new0 (MonoMarshalSpec, 1);
8372 res->native = minfo->type;
8374 switch (minfo->type) {
8375 case MONO_NATIVE_LPARRAY:
8376 res->data.array_data.elem_type = minfo->eltype;
8377 if (minfo->has_size) {
8378 res->data.array_data.param_num = minfo->param_num;
8379 res->data.array_data.num_elem = minfo->count;
8380 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8383 res->data.array_data.param_num = -1;
8384 res->data.array_data.num_elem = -1;
8385 res->data.array_data.elem_mult = -1;
8389 case MONO_NATIVE_BYVALTSTR:
8390 case MONO_NATIVE_BYVALARRAY:
8391 res->data.array_data.num_elem = minfo->count;
8394 case MONO_NATIVE_CUSTOM:
8395 if (minfo->marshaltyperef)
8396 res->data.custom_data.custom_name =
8397 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8399 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8409 MonoReflectionMarshal*
8410 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8411 MonoMarshalSpec *spec)
8413 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8414 MonoReflectionMarshal *minfo;
8417 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8418 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8419 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8420 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8423 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8424 minfo->type = spec->native;
8426 switch (minfo->type) {
8427 case MONO_NATIVE_LPARRAY:
8428 minfo->eltype = spec->data.array_data.elem_type;
8429 minfo->count = spec->data.array_data.num_elem;
8430 minfo->param_num = spec->data.array_data.param_num;
8433 case MONO_NATIVE_BYVALTSTR:
8434 case MONO_NATIVE_BYVALARRAY:
8435 minfo->count = spec->data.array_data.num_elem;
8438 case MONO_NATIVE_CUSTOM:
8439 if (spec->data.custom_data.custom_name) {
8440 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8442 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8444 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8446 if (spec->data.custom_data.cookie)
8447 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8458 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8459 ReflectionMethodBuilder *rmb,
8460 MonoMethodSignature *sig)
8463 MonoMethodNormal *pm;
8464 MonoMarshalSpec **specs;
8465 MonoReflectionMethodAux *method_aux;
8470 g_assert (!klass->generic_class);
8473 * Methods created using a MethodBuilder should have their memory allocated
8474 * inside the image mempool, while dynamic methods should have their memory
8477 dynamic = rmb->refs != NULL;
8478 mp = dynamic ? NULL : klass->image->mempool;
8480 mono_loader_lock ();
8482 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8483 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8484 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8486 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8488 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8490 pm = (MonoMethodNormal*)m;
8492 m->dynamic = dynamic;
8494 m->flags = rmb->attrs;
8495 m->iflags = rmb->iattrs;
8496 m->name = mp_string_to_utf8 (mp, rmb->name);
8499 m->skip_visibility = rmb->skip_visibility;
8501 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8503 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8504 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8507 m->signature->pinvoke = 1;
8508 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8509 m->signature->pinvoke = 1;
8511 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8513 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8514 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8516 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8518 if (klass->image->dynamic)
8519 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8521 mono_loader_unlock ();
8524 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8525 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8526 MonoMethodHeader *header;
8528 gint32 max_stack, i;
8529 gint32 num_locals = 0;
8530 gint32 num_clauses = 0;
8534 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8535 code_size = rmb->ilgen->code_len;
8536 max_stack = rmb->ilgen->max_stack;
8537 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8538 if (rmb->ilgen->ex_handlers)
8539 num_clauses = method_count_clauses (rmb->ilgen);
8542 code = mono_array_addr (rmb->code, guint8, 0);
8543 code_size = mono_array_length (rmb->code);
8544 /* we probably need to run a verifier on the code... */
8554 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8555 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8556 header->code_size = code_size;
8557 header->code = mp_g_malloc (mp, code_size);
8558 memcpy ((char*)header->code, code, code_size);
8559 header->max_stack = max_stack;
8560 header->init_locals = rmb->init_locals;
8561 header->num_locals = num_locals;
8563 for (i = 0; i < num_locals; ++i) {
8564 MonoReflectionLocalBuilder *lb =
8565 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8567 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8568 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8571 header->num_clauses = num_clauses;
8573 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8574 rmb->ilgen, num_clauses);
8577 pm->header = header;
8580 if (rmb->generic_params) {
8581 int count = mono_array_length (rmb->generic_params);
8582 MonoGenericContainer *container;
8584 m->generic_container = container = rmb->generic_container;
8585 container->type_argc = count;
8586 container->type_params = g_new0 (MonoGenericParam, count);
8587 container->owner.method = m;
8589 for (i = 0; i < count; i++) {
8590 MonoReflectionGenericParam *gp =
8591 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8593 container->type_params [i] = *gp->type.type->data.generic_param;
8596 if (klass->generic_container) {
8597 container->parent = klass->generic_container;
8598 container->context.class_inst = klass->generic_container->context.class_inst;
8600 container->context.method_inst = mono_get_shared_generic_inst (container);
8604 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8608 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8610 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8611 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8612 for (i = 0; i < rmb->nrefs; ++i)
8613 data [i + 1] = rmb->refs [i];
8618 /* Parameter info */
8621 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8622 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8623 for (i = 0; i <= m->signature->param_count; ++i) {
8624 MonoReflectionParamBuilder *pb;
8625 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8626 if ((i > 0) && (pb->attrs)) {
8627 /* Make a copy since it might point to a shared type structure */
8628 /* FIXME: Alloc this from a mempool */
8629 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8630 m->signature->params [i - 1]->attrs = pb->attrs;
8633 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8634 MonoDynamicImage *assembly;
8635 guint32 idx, def_type, len;
8639 if (!method_aux->param_defaults) {
8640 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8641 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8643 assembly = (MonoDynamicImage*)klass->image;
8644 idx = encode_constant (assembly, pb->def_value, &def_type);
8645 /* Copy the data from the blob since it might get realloc-ed */
8646 p = assembly->blob.data + idx;
8647 len = mono_metadata_decode_blob_size (p, &p2);
8649 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8650 method_aux->param_default_types [i] = def_type;
8651 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8655 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8657 if (!method_aux->param_cattr)
8658 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8659 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8665 /* Parameter marshalling */
8668 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8669 MonoReflectionParamBuilder *pb;
8670 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8671 if (pb->marshal_info) {
8673 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8674 specs [pb->position] =
8675 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8679 if (specs != NULL) {
8681 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8682 method_aux->param_marshall = specs;
8685 if (klass->image->dynamic && method_aux)
8686 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8688 mono_loader_unlock ();
8694 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8696 ReflectionMethodBuilder rmb;
8697 MonoMethodSignature *sig;
8699 mono_loader_lock ();
8700 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8701 mono_loader_unlock ();
8703 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8705 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8706 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8708 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8709 /* ilgen is no longer needed */
8717 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8719 ReflectionMethodBuilder rmb;
8720 MonoMethodSignature *sig;
8722 mono_loader_lock ();
8723 sig = method_builder_to_signature (klass->image->mempool, mb);
8724 mono_loader_unlock ();
8726 reflection_methodbuilder_from_method_builder (&rmb, mb);
8728 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8729 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8731 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8732 /* ilgen is no longer needed */
8738 static MonoClassField*
8739 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8741 MonoClassField *field;
8745 field = g_new0 (MonoClassField, 1);
8747 field->name = mono_string_to_utf8 (fb->name);
8749 /* FIXME: handle type modifiers */
8750 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8751 field->type->attrs = fb->attrs;
8753 field->type = fb->type->type;
8755 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8756 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8757 if (fb->offset != -1)
8758 field->offset = fb->offset;
8759 field->parent = klass;
8760 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8762 if (fb->def_value) {
8763 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8764 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8765 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8766 /* Copy the data from the blob since it might get realloc-ed */
8767 p = assembly->blob.data + idx;
8768 len = mono_metadata_decode_blob_size (p, &p2);
8770 field->data = g_malloc (len);
8771 memcpy ((gpointer)field->data, p, len);
8778 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8781 MonoReflectionTypeBuilder *tb = NULL;
8782 gboolean is_dynamic = FALSE;
8786 mono_loader_lock ();
8788 domain = mono_object_domain (type);
8790 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8791 tb = (MonoReflectionTypeBuilder *) type;
8794 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8795 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8796 MonoReflectionType *rgt = rgi->generic_type;
8798 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8799 tb = (MonoReflectionTypeBuilder *) rgt;
8804 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8805 if (tb && tb->generic_container)
8806 mono_reflection_create_generic_class (tb);
8808 klass = mono_class_from_mono_type (type->type);
8809 if (!klass->generic_container) {
8810 mono_loader_unlock ();
8814 if (klass->wastypebuilder) {
8815 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8820 mono_loader_unlock ();
8822 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8824 return &geninst->byval_arg;
8828 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8830 MonoGenericClass *gclass;
8831 MonoGenericInst *inst;
8833 g_assert (klass->generic_container);
8835 inst = mono_metadata_get_generic_inst (type_argc, types);
8836 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8838 return mono_generic_class_get_class (gclass);
8841 MonoReflectionMethod*
8842 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8845 MonoMethod *method, *inflated;
8846 MonoMethodInflated *imethod;
8847 MonoReflectionMethodBuilder *mb = NULL;
8848 MonoGenericContext tmp_context;
8849 MonoGenericInst *ginst;
8850 MonoType **type_argv;
8853 MONO_ARCH_SAVE_REGS;
8854 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8855 MonoReflectionTypeBuilder *tb;
8858 mb = (MonoReflectionMethodBuilder *) rmethod;
8859 tb = (MonoReflectionTypeBuilder *) mb->type;
8860 klass = mono_class_from_mono_type (tb->type.type);
8862 method = methodbuilder_to_mono_method (klass, mb);
8864 method = rmethod->method;
8867 klass = method->klass;
8869 if (method->is_inflated)
8870 method = ((MonoMethodInflated *) method)->declaring;
8872 count = mono_method_signature (method)->generic_param_count;
8873 if (count != mono_array_length (types))
8876 type_argv = g_new0 (MonoType *, count);
8877 for (i = 0; i < count; i++) {
8878 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8879 type_argv [i] = garg->type;
8881 ginst = mono_metadata_get_generic_inst (count, type_argv);
8884 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8885 tmp_context.method_inst = ginst;
8887 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8888 imethod = (MonoMethodInflated *) inflated;
8890 MOVING_GC_REGISTER (&imethod->reflection_info);
8891 imethod->reflection_info = rmethod;
8893 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8897 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8899 MonoMethodInflated *imethod;
8900 MonoGenericContext tmp_context;
8901 MonoGenericContext *context;
8904 klass = mono_class_from_mono_type (type->type.type);
8905 g_assert (klass->generic_class);
8906 context = mono_class_get_context (klass);
8908 if (method->generic_container) {
8909 g_assert (method->klass == klass->generic_class->container_class);
8911 tmp_context.class_inst = klass->generic_class->context.class_inst;
8912 tmp_context.method_inst = method->generic_container->context.method_inst;
8913 context = &tmp_context;
8916 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8917 if (method->generic_container) {
8918 MOVING_GC_REGISTER (&imethod->reflection_info);
8919 imethod->reflection_info = obj;
8921 return (MonoMethod *) imethod;
8925 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8930 gklass = mono_class_from_mono_type (type->generic_type->type);
8932 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8933 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8934 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8935 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8936 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8937 method = ((MonoReflectionMethod *) obj)->method;
8939 method = NULL; /* prevent compiler warning */
8940 g_assert_not_reached ();
8943 return inflate_mono_method (type, method, obj);
8947 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8948 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8951 MonoGenericClass *gclass;
8952 MonoDynamicGenericClass *dgclass;
8953 MonoClass *klass, *gklass;
8956 MONO_ARCH_SAVE_REGS;
8958 klass = mono_class_from_mono_type (type->type.type);
8959 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
8960 gclass = type->type.type->data.generic_class;
8962 g_assert (gclass->is_dynamic);
8963 dgclass = (MonoDynamicGenericClass *) gclass;
8965 if (dgclass->initialized)
8968 gklass = gclass->container_class;
8969 mono_class_init (gklass);
8971 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8972 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8973 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8974 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8975 dgclass->count_events = events ? mono_array_length (events) : 0;
8977 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8978 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8979 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8980 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8981 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8983 for (i = 0; i < dgclass->count_methods; i++) {
8984 MonoObject *obj = mono_array_get (methods, gpointer, i);
8986 dgclass->methods [i] = inflate_method (type, obj);
8989 for (i = 0; i < dgclass->count_ctors; i++) {
8990 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8992 dgclass->ctors [i] = inflate_method (type, obj);
8995 for (i = 0; i < dgclass->count_fields; i++) {
8996 MonoObject *obj = mono_array_get (fields, gpointer, i);
8997 MonoClassField *field;
8998 MonoInflatedField *ifield;
9000 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9001 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9002 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9003 field = ((MonoReflectionField *) obj)->field;
9005 field = NULL; /* prevent compiler warning */
9006 g_assert_not_reached ();
9009 ifield = g_new0 (MonoInflatedField, 1);
9010 ifield->generic_type = field->type;
9011 MOVING_GC_REGISTER (&ifield->reflection_info);
9012 ifield->reflection_info = obj;
9014 dgclass->fields [i] = *field;
9015 dgclass->fields [i].parent = klass;
9016 dgclass->fields [i].generic_info = ifield;
9017 dgclass->fields [i].type = mono_class_inflate_generic_type (
9018 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9021 for (i = 0; i < dgclass->count_properties; i++) {
9022 MonoObject *obj = mono_array_get (properties, gpointer, i);
9023 MonoProperty *property = &dgclass->properties [i];
9025 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9026 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9028 property->parent = klass;
9029 property->attrs = pb->attrs;
9030 property->name = mono_string_to_utf8 (pb->name);
9032 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9034 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9035 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9036 *property = *((MonoReflectionProperty *) obj)->property;
9039 property->get = inflate_mono_method (type, property->get, NULL);
9041 property->set = inflate_mono_method (type, property->set, NULL);
9043 g_assert_not_reached ();
9046 for (i = 0; i < dgclass->count_events; i++) {
9047 MonoObject *obj = mono_array_get (events, gpointer, i);
9048 MonoEvent *event = &dgclass->events [i];
9050 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9051 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9053 event->parent = klass;
9054 event->attrs = eb->attrs;
9055 event->name = mono_string_to_utf8 (eb->name);
9057 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9058 if (eb->remove_method)
9059 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9060 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9061 *event = *((MonoReflectionEvent *) obj)->event;
9064 event->add = inflate_mono_method (type, event->add, NULL);
9066 event->remove = inflate_mono_method (type, event->remove, NULL);
9068 g_assert_not_reached ();
9071 dgclass->initialized = TRUE;
9075 ensure_runtime_vtable (MonoClass *klass)
9077 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9080 if (!tb || klass->wastypebuilder)
9083 ensure_runtime_vtable (klass->parent);
9085 num = tb->ctors? mono_array_length (tb->ctors): 0;
9086 num += tb->num_methods;
9087 klass->method.count = num;
9088 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9089 num = tb->ctors? mono_array_length (tb->ctors): 0;
9090 for (i = 0; i < num; ++i)
9091 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9092 num = tb->num_methods;
9094 for (i = 0; i < num; ++i)
9095 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9097 if (tb->interfaces) {
9098 klass->interface_count = mono_array_length (tb->interfaces);
9099 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9100 for (i = 0; i < klass->interface_count; ++i) {
9101 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9102 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9106 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9107 for (i = 0; i < klass->method.count; ++i)
9108 klass->methods [i]->slot = i;
9110 mono_class_setup_interface_offsets (klass);
9114 * The generic vtable is needed even if image->run is not set since some
9115 * runtime code like ves_icall_Type_GetMethodsByName depends on
9116 * method->slot being defined.
9120 * tb->methods could not be freed since it is used for determining
9121 * overrides during dynamic vtable construction.
9126 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9128 MonoReflectionTypeBuilder *tb;
9134 g_assert (klass->image->dynamic);
9136 if (!klass->reflection_info)
9139 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9141 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9145 for (i = 0; i < tb->num_methods; ++i) {
9146 MonoReflectionMethodBuilder *mb =
9147 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9148 if (mb->override_method)
9154 *overrides = g_new0 (MonoMethod*, onum * 2);
9157 for (i = 0; i < tb->num_methods; ++i) {
9158 MonoReflectionMethodBuilder *mb =
9159 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9160 if (mb->override_method) {
9161 (*overrides) [onum * 2] =
9162 mb->override_method->method;
9163 (*overrides) [onum * 2 + 1] =
9166 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9167 g_assert (mb->override_method->method);
9168 g_assert (mb->mhandle);
9175 *num_overrides = onum;
9179 typebuilder_setup_fields (MonoClass *klass)
9181 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9182 MonoReflectionFieldBuilder *fb;
9183 MonoClassField *field;
9188 klass->field.count = tb->num_fields;
9189 klass->field.first = 0;
9191 if (!klass->field.count)
9194 klass->fields = g_new0 (MonoClassField, klass->field.count);
9196 for (i = 0; i < klass->field.count; ++i) {
9197 fb = mono_array_get (tb->fields, gpointer, i);
9198 field = &klass->fields [i];
9199 field->name = mono_string_to_utf8 (fb->name);
9201 /* FIXME: handle type modifiers */
9202 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9203 field->type->attrs = fb->attrs;
9205 field->type = fb->type->type;
9207 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9208 field->data = mono_array_addr (fb->rva_data, char, 0);
9209 if (fb->offset != -1)
9210 field->offset = fb->offset;
9211 field->parent = klass;
9213 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9215 if (fb->def_value) {
9216 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9217 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9218 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9219 /* Copy the data from the blob since it might get realloc-ed */
9220 p = assembly->blob.data + idx;
9221 len = mono_metadata_decode_blob_size (p, &p2);
9223 field->data = g_malloc (len);
9224 memcpy ((gpointer)field->data, p, len);
9227 mono_class_layout_fields (klass);
9231 typebuilder_setup_properties (MonoClass *klass)
9233 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9234 MonoReflectionPropertyBuilder *pb;
9237 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9238 klass->property.first = 0;
9240 klass->properties = g_new0 (MonoProperty, klass->property.count);
9241 for (i = 0; i < klass->property.count; ++i) {
9242 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9243 klass->properties [i].parent = klass;
9244 klass->properties [i].attrs = pb->attrs;
9245 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9247 klass->properties [i].get = pb->get_method->mhandle;
9249 klass->properties [i].set = pb->set_method->mhandle;
9251 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9255 MonoReflectionEvent *
9256 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9258 MonoEvent *event = g_new0 (MonoEvent, 1);
9262 klass = my_mono_class_from_mono_type (tb->type.type);
9264 event->parent = klass;
9265 event->attrs = eb->attrs;
9266 event->name = mono_string_to_utf8 (eb->name);
9268 event->add = eb->add_method->mhandle;
9269 if (eb->remove_method)
9270 event->remove = eb->remove_method->mhandle;
9271 if (eb->raise_method)
9272 event->raise = eb->raise_method->mhandle;
9274 if (eb->other_methods) {
9275 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9276 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9277 MonoReflectionMethodBuilder *mb =
9278 mono_array_get (eb->other_methods,
9279 MonoReflectionMethodBuilder*, j);
9280 event->other [j] = mb->mhandle;
9284 return mono_event_get_object (mono_object_domain (tb), klass, event);
9288 typebuilder_setup_events (MonoClass *klass)
9290 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9291 MonoReflectionEventBuilder *eb;
9294 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9295 klass->event.first = 0;
9297 klass->events = g_new0 (MonoEvent, klass->event.count);
9298 for (i = 0; i < klass->event.count; ++i) {
9299 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9300 klass->events [i].parent = klass;
9301 klass->events [i].attrs = eb->attrs;
9302 klass->events [i].name = mono_string_to_utf8 (eb->name);
9304 klass->events [i].add = eb->add_method->mhandle;
9305 if (eb->remove_method)
9306 klass->events [i].remove = eb->remove_method->mhandle;
9307 if (eb->raise_method)
9308 klass->events [i].raise = eb->raise_method->mhandle;
9310 if (eb->other_methods) {
9311 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9312 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9313 MonoReflectionMethodBuilder *mb =
9314 mono_array_get (eb->other_methods,
9315 MonoReflectionMethodBuilder*, j);
9316 klass->events [i].other [j] = mb->mhandle;
9323 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9327 MonoReflectionType* res;
9330 MONO_ARCH_SAVE_REGS;
9332 domain = mono_object_domain (tb);
9333 klass = my_mono_class_from_mono_type (tb->type.type);
9335 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9338 * we need to lock the domain because the lock will be taken inside
9339 * So, we need to keep the locking order correct.
9341 mono_domain_lock (domain);
9342 mono_loader_lock ();
9343 if (klass->wastypebuilder) {
9344 mono_loader_unlock ();
9345 mono_domain_unlock (domain);
9346 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9349 * Fields to set in klass:
9350 * the various flags: delegate/unicode/contextbound etc.
9352 klass->flags = tb->attrs;
9353 klass->has_cctor = 1;
9354 klass->has_finalize = 1;
9357 if (!((MonoDynamicImage*)klass->image)->run) {
9358 if (klass->generic_container) {
9359 /* FIXME: The code below can't handle generic classes */
9360 klass->wastypebuilder = TRUE;
9361 mono_loader_unlock ();
9362 mono_domain_unlock (domain);
9363 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9368 /* enums are done right away */
9369 if (!klass->enumtype)
9370 ensure_runtime_vtable (klass);
9373 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9374 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9375 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9379 /* fields and object layout */
9380 if (klass->parent) {
9381 if (!klass->parent->size_inited)
9382 mono_class_init (klass->parent);
9383 klass->instance_size = klass->parent->instance_size;
9384 klass->sizes.class_size = 0;
9385 klass->min_align = klass->parent->min_align;
9386 /* if the type has no fields we won't call the field_setup
9387 * routine which sets up klass->has_references.
9389 klass->has_references |= klass->parent->has_references;
9391 klass->instance_size = sizeof (MonoObject);
9392 klass->min_align = 1;
9395 /* FIXME: handle packing_size and instance_size */
9396 typebuilder_setup_fields (klass);
9398 typebuilder_setup_properties (klass);
9400 typebuilder_setup_events (klass);
9402 klass->wastypebuilder = TRUE;
9403 mono_loader_unlock ();
9404 mono_domain_unlock (domain);
9406 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9407 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9408 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9411 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9412 g_assert (res != (MonoReflectionType*)tb);
9418 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9420 MonoGenericParam *param;
9423 MONO_ARCH_SAVE_REGS;
9425 param = g_new0 (MonoGenericParam, 1);
9427 if (gparam->mbuilder) {
9428 if (!gparam->mbuilder->generic_container)
9429 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9430 param->owner = gparam->mbuilder->generic_container;
9431 } else if (gparam->tbuilder) {
9432 g_assert (gparam->tbuilder->generic_container);
9433 param->owner = gparam->tbuilder->generic_container;
9436 param->name = mono_string_to_utf8 (gparam->name);
9437 param->num = gparam->index;
9439 image = &gparam->tbuilder->module->dynamic_image->image;
9440 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9442 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9443 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9445 gparam->type.type = g_new0 (MonoType, 1);
9446 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9447 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9448 gparam->type.type->data.generic_param = param;
9452 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9454 MonoDynamicImage *assembly = sig->module->dynamic_image;
9455 guint32 na = mono_array_length (sig->arguments);
9460 sigbuffer_init (&buf, 32);
9462 sigbuffer_add_value (&buf, 0x07);
9463 sigbuffer_add_value (&buf, na);
9464 for (i = 0; i < na; ++i) {
9465 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9466 encode_reflection_type (assembly, type, &buf);
9469 buflen = buf.p - buf.buf;
9470 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9471 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9472 sigbuffer_free (&buf);
9478 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9480 MonoDynamicImage *assembly = sig->module->dynamic_image;
9481 guint32 na = mono_array_length (sig->arguments);
9486 sigbuffer_init (&buf, 32);
9488 sigbuffer_add_value (&buf, 0x06);
9489 for (i = 0; i < na; ++i) {
9490 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9491 encode_reflection_type (assembly, type, &buf);
9494 buflen = buf.p - buf.buf;
9495 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9496 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9497 sigbuffer_free (&buf);
9503 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9505 ReflectionMethodBuilder rmb;
9506 MonoMethodSignature *sig;
9511 sig = dynamic_method_to_signature (mb);
9513 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9516 * Resolve references.
9519 * Every second entry in the refs array is reserved for storing handle_class,
9520 * which is needed by the ldtoken implementation in the JIT.
9522 rmb.nrefs = mb->nrefs;
9523 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9524 for (i = 0; i < mb->nrefs; i += 2) {
9525 MonoClass *handle_class;
9527 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9529 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9530 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9532 * The referenced DynamicMethod should already be created by the managed
9533 * code, except in the case of circular references. In that case, we store
9534 * method in the refs array, and fix it up later when the referenced
9535 * DynamicMethod is created.
9537 if (method->mhandle) {
9538 ref = method->mhandle;
9540 /* FIXME: GC object stored in unmanaged memory */
9543 /* FIXME: GC object stored in unmanaged memory */
9544 method->referenced_by = g_slist_append (method->referenced_by, mb);
9546 handle_class = mono_defaults.methodhandle_class;
9548 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9551 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9556 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9557 rmb.refs [i + 1] = handle_class;
9560 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9562 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9564 /* Fix up refs entries pointing at us */
9565 for (l = mb->referenced_by; l; l = l->next) {
9566 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9567 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9570 g_assert (method->mhandle);
9572 data = (gpointer*)wrapper->method_data;
9573 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9574 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9575 data [i + 1] = mb->mhandle;
9578 g_slist_free (mb->referenced_by);
9582 /* ilgen is no longer needed */
9587 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9592 mono_runtime_free_method (
9593 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9597 * mono_reflection_lookup_dynamic_token:
9599 * Finish the Builder object pointed to by TOKEN and return the corresponding
9600 * runtime structure. HANDLE_CLASS is set to the class required by
9604 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context)
9606 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9609 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9612 return resolve_object (image, obj, handle_class, context);
9616 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9618 gpointer result = NULL;
9620 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9621 result = mono_string_intern ((MonoString*)obj);
9622 *handle_class = NULL;
9624 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9625 MonoReflectionType *tb = (MonoReflectionType*)obj;
9627 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9628 result = mono_class_from_mono_type (inflated);
9629 mono_metadata_free_type (inflated);
9631 result = mono_class_from_mono_type (tb->type);
9633 *handle_class = mono_defaults.typehandle_class;
9635 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9636 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9637 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9638 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9639 result = ((MonoReflectionMethod*)obj)->method;
9640 result = mono_class_inflate_generic_method (result, context);
9641 *handle_class = mono_defaults.methodhandle_class;
9643 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9644 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9645 result = mb->mhandle;
9647 /* Type is not yet created */
9648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9650 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9653 * Hopefully this has been filled in by calling CreateType() on the
9657 * TODO: This won't work if the application finishes another
9658 * TypeBuilder instance instead of this one.
9660 result = mb->mhandle;
9662 result = mono_class_inflate_generic_method (result, context);
9663 *handle_class = mono_defaults.methodhandle_class;
9664 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9665 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9667 result = cb->mhandle;
9669 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9671 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9672 result = cb->mhandle;
9674 result = mono_class_inflate_generic_method (result, context);
9675 *handle_class = mono_defaults.methodhandle_class;
9676 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9677 result = ((MonoReflectionField*)obj)->field;
9678 *handle_class = mono_defaults.fieldhandle_class;
9680 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9681 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9682 result = fb->handle;
9685 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9687 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9688 result = fb->handle;
9690 *handle_class = mono_defaults.fieldhandle_class;
9691 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9692 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9695 klass = tb->type.type->data.klass;
9696 if (klass->wastypebuilder) {
9697 /* Already created */
9701 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9702 result = tb->type.type->data.klass;
9705 *handle_class = mono_defaults.typehandle_class;
9706 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9707 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9708 MonoMethodSignature *sig;
9711 if (helper->arguments)
9712 nargs = mono_array_length (helper->arguments);
9716 sig = mono_metadata_signature_alloc (image, nargs);
9717 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9718 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9720 if (helper->call_conv == 0) /* unmanaged */
9721 sig->call_convention = helper->unmanaged_call_conv - 1;
9723 if (helper->call_conv & 0x02)
9724 sig->call_convention = MONO_CALL_VARARG;
9726 sig->call_convention = MONO_CALL_DEFAULT;
9728 sig->param_count = nargs;
9729 /* TODO: Copy type ? */
9730 sig->ret = helper->return_type->type;
9731 for (i = 0; i < nargs; ++i) {
9732 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9733 sig->params [i] = rt->type;
9737 *handle_class = NULL;
9738 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9739 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9740 /* Already created by the managed code */
9741 g_assert (method->mhandle);
9742 result = method->mhandle;
9743 *handle_class = mono_defaults.methodhandle_class;
9744 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9745 MonoReflectionType *tb = (MonoReflectionType*)obj;
9746 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9747 *handle_class = mono_defaults.typehandle_class;
9749 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9750 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9751 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9752 *handle_class = mono_defaults.typehandle_class;
9755 g_print (obj->vtable->klass->name);
9756 g_assert_not_reached ();
9762 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9763 const static guint32 declsec_flags_map[] = {
9764 0x00000000, /* empty */
9765 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9766 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9767 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9768 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9769 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9770 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9771 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9772 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9773 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9774 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9775 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9776 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9777 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9778 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9779 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9780 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9781 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9782 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9786 * Returns flags that includes all available security action associated to the handle.
9787 * @token: metadata token (either for a class or a method)
9788 * @image: image where resides the metadata.
9791 mono_declsec_get_flags (MonoImage *image, guint32 token)
9793 int index = mono_metadata_declsec_from_index (image, token);
9794 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9799 /* HasSecurity can be present for other, not specially encoded, attributes,
9800 e.g. SuppressUnmanagedCodeSecurityAttribute */
9804 for (i = index; i < t->rows; i++) {
9805 guint32 cols [MONO_DECL_SECURITY_SIZE];
9807 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9808 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9811 action = cols [MONO_DECL_SECURITY_ACTION];
9812 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9813 result |= declsec_flags_map [action];
9815 g_assert_not_reached ();
9822 * Get the security actions (in the form of flags) associated with the specified method.
9824 * @method: The method for which we want the declarative security flags.
9825 * Return the declarative security flags for the method (only).
9827 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9828 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9831 mono_declsec_flags_from_method (MonoMethod *method)
9833 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9834 /* FIXME: No cache (for the moment) */
9835 guint32 idx = mono_method_get_index (method);
9836 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9837 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9838 return mono_declsec_get_flags (method->klass->image, idx);
9844 * Get the security actions (in the form of flags) associated with the specified class.
9846 * @klass: The class for which we want the declarative security flags.
9847 * Return the declarative security flags for the class.
9849 * Note: We cache the flags inside the MonoClass structure as this will get
9850 * called very often (at least for each method).
9853 mono_declsec_flags_from_class (MonoClass *klass)
9855 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9856 if (!klass->declsec_flags) {
9857 guint32 idx = mono_metadata_token_index (klass->type_token);
9858 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9859 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9860 /* we cache the flags on classes */
9861 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9863 return klass->declsec_flags;
9869 * Get the security actions (in the form of flags) associated with the specified assembly.
9871 * @assembly: The assembly for which we want the declarative security flags.
9872 * Return the declarative security flags for the assembly.
9875 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9877 guint32 idx = 1; /* there is only one assembly */
9878 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9879 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9880 return mono_declsec_get_flags (assembly->image, idx);
9885 * Fill actions for the specific index (which may either be an encoded class token or
9886 * an encoded method token) from the metadata image.
9887 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9890 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9891 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9893 MonoBoolean result = FALSE;
9895 guint32 cols [MONO_DECL_SECURITY_SIZE];
9896 int index = mono_metadata_declsec_from_index (image, token);
9899 t = &image->tables [MONO_TABLE_DECLSECURITY];
9900 for (i = index; i < t->rows; i++) {
9901 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9903 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9906 /* if present only replace (class) permissions with method permissions */
9907 /* if empty accept either class or method permissions */
9908 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9909 if (!actions->demand.blob) {
9910 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9911 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9912 actions->demand.blob = (char*) (blob + 2);
9913 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9916 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9917 if (!actions->noncasdemand.blob) {
9918 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9919 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9920 actions->noncasdemand.blob = (char*) (blob + 2);
9921 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9924 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9925 if (!actions->demandchoice.blob) {
9926 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9927 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9928 actions->demandchoice.blob = (char*) (blob + 2);
9929 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9939 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9940 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9942 guint32 idx = mono_metadata_token_index (klass->type_token);
9943 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9944 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9945 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9949 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9950 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9952 guint32 idx = mono_method_get_index (method);
9953 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9954 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9955 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9959 * Collect all actions (that requires to generate code in mini) assigned for
9960 * the specified method.
9961 * Note: Don't use the content of actions if the function return FALSE.
9964 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9966 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9967 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9968 MonoBoolean result = FALSE;
9971 /* quick exit if no declarative security is present in the metadata */
9972 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9975 /* we want the original as the wrapper is "free" of the security informations */
9976 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
9977 method = mono_marshal_method_from_wrapper (method);
9982 /* First we look for method-level attributes */
9983 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9984 mono_class_init (method->klass);
9985 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9987 result = mono_declsec_get_method_demands_params (method, demands,
9988 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9991 /* Here we use (or create) the class declarative cache to look for demands */
9992 flags = mono_declsec_flags_from_class (method->klass);
9995 mono_class_init (method->klass);
9996 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9998 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9999 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10002 /* The boolean return value is used as a shortcut in case nothing needs to
10003 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10009 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10011 * Note: Don't use the content of actions if the function return FALSE.
10014 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10016 MonoBoolean result = FALSE;
10019 /* quick exit if no declarative security is present in the metadata */
10020 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10023 /* we want the original as the wrapper is "free" of the security informations */
10024 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10025 method = mono_marshal_method_from_wrapper (method);
10030 /* results are independant - zeroize both */
10031 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10032 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10034 /* First we look for method-level attributes */
10035 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10036 mono_class_init (method->klass);
10038 result = mono_declsec_get_method_demands_params (method, cmethod,
10039 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10042 /* Here we use (or create) the class declarative cache to look for demands */
10043 flags = mono_declsec_flags_from_class (method->klass);
10044 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10045 mono_class_init (method->klass);
10047 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10048 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10055 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10057 * @klass The inherited class - this is the class that provides the security check (attributes)
10059 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10061 * Note: Don't use the content of actions if the function return FALSE.
10064 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10066 MonoBoolean result = FALSE;
10069 /* quick exit if no declarative security is present in the metadata */
10070 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10073 /* Here we use (or create) the class declarative cache to look for demands */
10074 flags = mono_declsec_flags_from_class (klass);
10075 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10076 mono_class_init (klass);
10077 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10079 result |= mono_declsec_get_class_demands_params (klass, demands,
10080 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10087 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10089 * Note: Don't use the content of actions if the function return FALSE.
10092 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10094 /* quick exit if no declarative security is present in the metadata */
10095 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10098 /* we want the original as the wrapper is "free" of the security informations */
10099 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10100 method = mono_marshal_method_from_wrapper (method);
10105 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10106 mono_class_init (method->klass);
10107 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10109 return mono_declsec_get_method_demands_params (method, demands,
10110 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10117 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10119 guint32 cols [MONO_DECL_SECURITY_SIZE];
10123 int index = mono_metadata_declsec_from_index (image, token);
10127 t = &image->tables [MONO_TABLE_DECLSECURITY];
10128 for (i = index; i < t->rows; i++) {
10129 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10131 /* shortcut - index are ordered */
10132 if (token != cols [MONO_DECL_SECURITY_PARENT])
10135 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10136 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10137 entry->blob = (char*) (metadata + 2);
10138 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10147 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10149 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10150 guint32 idx = mono_method_get_index (method);
10151 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10152 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10153 return get_declsec_action (method->klass->image, idx, action, entry);
10159 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10162 guint32 flags = mono_declsec_flags_from_class (klass);
10163 if (declsec_flags_map [action] & flags) {
10164 guint32 idx = mono_metadata_token_index (klass->type_token);
10165 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10166 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10167 return get_declsec_action (klass->image, idx, action, entry);
10173 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10175 guint32 idx = 1; /* there is only one assembly */
10176 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10177 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10179 return get_declsec_action (assembly->image, idx, action, entry);
10183 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10185 MonoObject *res, *exc;
10187 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10188 static MonoMethod *method = NULL;
10190 if (!System_Reflection_Emit_TypeBuilder) {
10191 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10192 g_assert (System_Reflection_Emit_TypeBuilder);
10194 if (method == NULL) {
10195 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10200 * The result of mono_type_get_object () might be a System.MonoType but we
10201 * need a TypeBuilder so use klass->reflection_info.
10203 g_assert (klass->reflection_info);
10204 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10206 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10208 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10212 return *(MonoBoolean*)mono_object_unbox (res);