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 if (tb->generic_container)
2555 mono_reflection_create_generic_class (tb);
2557 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2558 g_assert (klass->generic_container);
2559 sigbuffer_add_value (&buf, klass->byval_arg.type);
2560 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2562 count = mono_array_length (tb->generic_params);
2563 sigbuffer_add_value (&buf, count);
2564 for (i = 0; i < count; i++) {
2565 MonoReflectionGenericParam *gparam;
2567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2569 encode_type (assembly, gparam->type.type, &buf);
2572 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2574 if (assembly->save) {
2575 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2576 alloc_table (table, table->rows + 1);
2577 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2578 values [MONO_TYPESPEC_SIGNATURE] = token;
2580 sigbuffer_free (&buf);
2582 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2591 MonoDynamicTable *table;
2594 guint32 token, pclass, parent, sig;
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2601 klass = mono_class_from_mono_type (fb->typeb->type);
2602 name = mono_string_to_utf8 (fb->name);
2604 sig = fieldref_encode_signature (assembly, fb->type->type);
2606 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2609 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610 parent >>= MONO_TYPEDEFORREF_BITS;
2612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2614 if (assembly->save) {
2615 alloc_table (table, table->rows + 1);
2616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619 values [MONO_MEMBERREF_SIGNATURE] = sig;
2622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2624 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2636 if (!assembly->save)
2640 g_assert (helper->type == 2);
2642 if (helper->arguments)
2643 nargs = mono_array_length (helper->arguments);
2647 size = 10 + (nargs * 10);
2649 sigbuffer_init (&buf, 32);
2651 /* Encode calling convention */
2652 /* Change Any to Standard */
2653 if ((helper->call_conv & 0x03) == 0x03)
2654 helper->call_conv = 0x01;
2655 /* explicit_this implies has_this */
2656 if (helper->call_conv & 0x40)
2657 helper->call_conv &= 0x20;
2659 if (helper->call_conv == 0) { /* Unmanaged */
2660 idx = helper->unmanaged_call_conv - 1;
2663 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2664 if (helper->call_conv & 0x02) /* varargs */
2668 sigbuffer_add_byte (&buf, idx);
2669 sigbuffer_add_value (&buf, nargs);
2670 encode_reflection_type (assembly, helper->return_type, &buf);
2671 for (i = 0; i < nargs; ++i) {
2672 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2673 encode_reflection_type (assembly, pt, &buf);
2675 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2676 sigbuffer_free (&buf);
2682 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2685 MonoDynamicTable *table;
2688 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2689 idx = table->next_idx ++;
2691 alloc_table (table, table->rows);
2692 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2694 values [MONO_STAND_ALONE_SIGNATURE] =
2695 mono_reflection_encode_sighelper (assembly, helper);
2701 reflection_cc_to_file (int call_conv) {
2702 switch (call_conv & 0x3) {
2704 case 1: return MONO_CALL_DEFAULT;
2705 case 2: return MONO_CALL_VARARG;
2707 g_assert_not_reached ();
2714 MonoMethodSignature *sig;
2720 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2725 MonoMethodSignature *sig;
2728 name = mono_string_to_utf8 (m->name);
2729 nparams = mono_array_length (m->parameters);
2730 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2732 sig->sentinelpos = -1;
2733 sig->call_convention = reflection_cc_to_file (m->call_conv);
2734 sig->param_count = nparams;
2735 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2736 for (i = 0; i < nparams; ++i) {
2737 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2738 sig->params [i] = t->type;
2741 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2743 if (strcmp (name, am->name) == 0 &&
2744 mono_metadata_type_equal (am->parent, m->parent->type) &&
2745 mono_metadata_signature_equal (am->sig, sig)) {
2748 m->table_idx = am->token & 0xffffff;
2752 am = g_new0 (ArrayMethod, 1);
2755 am->parent = m->parent->type;
2756 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2757 method_encode_signature (assembly, sig));
2758 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2759 m->table_idx = am->token & 0xffffff;
2764 * Insert into the metadata tables all the info about the TypeBuilder tb.
2765 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2768 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2770 MonoDynamicTable *table;
2772 int i, is_object = 0, is_system = 0;
2775 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2776 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2777 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2778 n = mono_string_to_utf8 (tb->name);
2779 if (strcmp (n, "Object") == 0)
2781 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2783 n = mono_string_to_utf8 (tb->nspace);
2784 if (strcmp (n, "System") == 0)
2786 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2788 if (tb->parent && !(is_system && is_object) &&
2789 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2790 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2792 values [MONO_TYPEDEF_EXTENDS] = 0;
2794 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2795 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2798 * if we have explicitlayout or sequentiallayouts, output data in the
2799 * ClassLayout table.
2801 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2802 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2803 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2805 alloc_table (table, table->rows);
2806 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2807 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2808 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2809 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2812 /* handle interfaces */
2813 if (tb->interfaces) {
2814 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2816 table->rows += mono_array_length (tb->interfaces);
2817 alloc_table (table, table->rows);
2818 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2819 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2820 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2821 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2822 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2823 values += MONO_INTERFACEIMPL_SIZE;
2829 table = &assembly->tables [MONO_TABLE_FIELD];
2830 table->rows += tb->num_fields;
2831 alloc_table (table, table->rows);
2832 for (i = 0; i < tb->num_fields; ++i)
2833 mono_image_get_field_info (
2834 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2837 /* handle constructors */
2839 table = &assembly->tables [MONO_TABLE_METHOD];
2840 table->rows += mono_array_length (tb->ctors);
2841 alloc_table (table, table->rows);
2842 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2843 mono_image_get_ctor_info (domain,
2844 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2847 /* handle methods */
2849 table = &assembly->tables [MONO_TABLE_METHOD];
2850 table->rows += tb->num_methods;
2851 alloc_table (table, table->rows);
2852 for (i = 0; i < tb->num_methods; ++i)
2853 mono_image_get_method_info (
2854 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2857 /* Do the same with properties etc.. */
2858 if (tb->events && mono_array_length (tb->events)) {
2859 table = &assembly->tables [MONO_TABLE_EVENT];
2860 table->rows += mono_array_length (tb->events);
2861 alloc_table (table, table->rows);
2862 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2864 alloc_table (table, table->rows);
2865 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2866 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2867 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2868 for (i = 0; i < mono_array_length (tb->events); ++i)
2869 mono_image_get_event_info (
2870 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2872 if (tb->properties && mono_array_length (tb->properties)) {
2873 table = &assembly->tables [MONO_TABLE_PROPERTY];
2874 table->rows += mono_array_length (tb->properties);
2875 alloc_table (table, table->rows);
2876 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2878 alloc_table (table, table->rows);
2879 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2880 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2881 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2882 for (i = 0; i < mono_array_length (tb->properties); ++i)
2883 mono_image_get_property_info (
2884 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2887 /* handle generic parameters */
2888 if (tb->generic_params) {
2889 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2890 table->rows += mono_array_length (tb->generic_params);
2891 alloc_table (table, table->rows);
2892 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2893 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2895 mono_image_get_generic_param_info (
2896 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2900 mono_image_add_decl_security (assembly,
2901 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2904 MonoDynamicTable *ntable;
2906 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2907 ntable->rows += mono_array_length (tb->subtypes);
2908 alloc_table (ntable, ntable->rows);
2909 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2911 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2912 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2914 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2915 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2916 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2917 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2918 mono_string_to_utf8 (tb->name), tb->table_idx,
2919 ntable->next_idx, ntable->rows);*/
2920 values += MONO_NESTED_CLASS_SIZE;
2927 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2931 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2933 if (!type->subtypes)
2936 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2937 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2938 collect_types (types, subtype);
2943 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2945 if ((*type1)->table_idx < (*type2)->table_idx)
2948 if ((*type1)->table_idx > (*type2)->table_idx)
2955 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2960 for (i = 0; i < mono_array_length (pinfo); ++i) {
2961 MonoReflectionParamBuilder *pb;
2962 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2965 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2970 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2973 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2975 for (i = 0; i < tb->num_fields; ++i) {
2976 MonoReflectionFieldBuilder* fb;
2977 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2978 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2982 for (i = 0; i < mono_array_length (tb->events); ++i) {
2983 MonoReflectionEventBuilder* eb;
2984 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2985 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2988 if (tb->properties) {
2989 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2990 MonoReflectionPropertyBuilder* pb;
2991 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2992 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2996 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2997 MonoReflectionCtorBuilder* cb;
2998 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2999 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3000 params_add_cattrs (assembly, cb->pinfo);
3005 for (i = 0; i < tb->num_methods; ++i) {
3006 MonoReflectionMethodBuilder* mb;
3007 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3008 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3009 params_add_cattrs (assembly, mb->pinfo);
3014 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3015 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3020 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3024 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3026 if (moduleb->global_methods) {
3027 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3028 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3030 params_add_cattrs (assembly, mb->pinfo);
3034 if (moduleb->global_fields) {
3035 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3036 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3037 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3041 if (moduleb->types) {
3042 for (i = 0; i < moduleb->num_types; ++i)
3043 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3048 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3050 MonoDynamicTable *table;
3054 char *b = blob_size;
3057 table = &assembly->tables [MONO_TABLE_FILE];
3059 alloc_table (table, table->rows);
3060 values = table->values + table->next_idx * MONO_FILE_SIZE;
3061 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3062 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3063 if (module->image->dynamic) {
3064 /* This depends on the fact that the main module is emitted last */
3065 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3066 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3069 path = g_strdup (module->image->name);
3071 mono_sha1_get_digest_from_file (path, hash);
3074 mono_metadata_encode_value (20, b, &b);
3075 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3076 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3081 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3083 MonoDynamicTable *table;
3086 table = &assembly->tables [MONO_TABLE_MODULE];
3087 mb->table_idx = table->next_idx ++;
3088 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3089 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3092 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3093 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3094 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3095 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3099 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3100 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3102 MonoDynamicTable *table;
3106 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3107 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3110 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3112 alloc_table (table, table->rows);
3113 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3115 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3116 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3117 if (klass->nested_in)
3118 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3120 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3121 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3122 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3124 res = table->next_idx;
3128 /* Emit nested types */
3129 if (klass->nested_classes) {
3132 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3133 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3140 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3141 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3146 klass = mono_class_from_mono_type (tb->type.type);
3148 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3150 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3151 parent_index, assembly);
3155 * We need to do this ourselves since klass->nested_classes is not set up.
3158 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3159 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3164 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3165 guint32 module_index, MonoDynamicImage *assembly)
3167 MonoImage *image = module->image;
3171 t = &image->tables [MONO_TABLE_TYPEDEF];
3173 for (i = 0; i < t->rows; ++i) {
3174 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3176 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3177 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3182 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3184 MonoDynamicTable *table;
3190 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3192 if (assemblyb->type_forwarders) {
3193 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3194 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3200 klass = mono_class_from_mono_type (t->type);
3202 scope = resolution_scope_from_image (assembly, klass->image);
3203 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3204 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3207 alloc_table (table, table->rows);
3208 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3210 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3211 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3212 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3213 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3214 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3219 #define align_pointer(base,p)\
3221 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3223 (p) += 4 - (__diff & 3);\
3227 compare_constants (const void *a, const void *b)
3229 const guint32 *a_values = a;
3230 const guint32 *b_values = b;
3231 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3235 compare_semantics (const void *a, const void *b)
3237 const guint32 *a_values = a;
3238 const guint32 *b_values = b;
3239 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3242 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3246 compare_custom_attrs (const void *a, const void *b)
3248 const guint32 *a_values = a;
3249 const guint32 *b_values = b;
3251 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3255 compare_field_marshal (const void *a, const void *b)
3257 const guint32 *a_values = a;
3258 const guint32 *b_values = b;
3260 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3264 compare_nested (const void *a, const void *b)
3266 const guint32 *a_values = a;
3267 const guint32 *b_values = b;
3269 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3273 compare_genericparam (const void *a, const void *b)
3275 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3276 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3278 if ((*b_entry)->owner == (*a_entry)->owner)
3280 (*a_entry)->gparam->type.type->data.generic_param->num -
3281 (*b_entry)->gparam->type.type->data.generic_param->num;
3283 return (*a_entry)->owner - (*b_entry)->owner;
3287 compare_declsecurity_attrs (const void *a, const void *b)
3289 const guint32 *a_values = a;
3290 const guint32 *b_values = b;
3292 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3296 pad_heap (MonoDynamicStream *sh)
3298 if (sh->index & 3) {
3299 int sz = 4 - (sh->index & 3);
3300 memset (sh->data + sh->index, 0, sz);
3307 MonoDynamicStream *stream;
3311 * build_compressed_metadata() fills in the blob of data that represents the
3312 * raw metadata as it will be saved in the PE file. The five streams are output
3313 * and the metadata tables are comnpressed from the guint32 array representation,
3314 * to the compressed on-disk format.
3317 build_compressed_metadata (MonoDynamicImage *assembly)
3319 MonoDynamicTable *table;
3321 guint64 valid_mask = 0;
3322 guint64 sorted_mask;
3323 guint32 heapt_size = 0;
3324 guint32 meta_size = 256; /* allow for header and other stuff */
3325 guint32 table_offset;
3326 guint32 ntables = 0;
3332 struct StreamDesc stream_desc [5];
3334 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3335 for (i = 0; i < assembly->gen_params->len; i++){
3336 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3337 write_generic_param_entry (assembly, entry);
3340 stream_desc [0].name = "#~";
3341 stream_desc [0].stream = &assembly->tstream;
3342 stream_desc [1].name = "#Strings";
3343 stream_desc [1].stream = &assembly->sheap;
3344 stream_desc [2].name = "#US";
3345 stream_desc [2].stream = &assembly->us;
3346 stream_desc [3].name = "#Blob";
3347 stream_desc [3].stream = &assembly->blob;
3348 stream_desc [4].name = "#GUID";
3349 stream_desc [4].stream = &assembly->guid;
3351 /* tables that are sorted */
3352 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3353 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3354 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3355 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3356 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3357 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3359 /* Compute table sizes */
3360 /* the MonoImage has already been created in mono_image_basic_init() */
3361 meta = &assembly->image;
3363 /* sizes should be multiple of 4 */
3364 pad_heap (&assembly->blob);
3365 pad_heap (&assembly->guid);
3366 pad_heap (&assembly->sheap);
3367 pad_heap (&assembly->us);
3369 /* Setup the info used by compute_sizes () */
3370 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3371 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3372 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3374 meta_size += assembly->blob.index;
3375 meta_size += assembly->guid.index;
3376 meta_size += assembly->sheap.index;
3377 meta_size += assembly->us.index;
3379 for (i=0; i < MONO_TABLE_NUM; ++i)
3380 meta->tables [i].rows = assembly->tables [i].rows;
3382 for (i = 0; i < MONO_TABLE_NUM; i++){
3383 if (meta->tables [i].rows == 0)
3385 valid_mask |= (guint64)1 << i;
3387 meta->tables [i].row_size = mono_metadata_compute_size (
3388 meta, i, &meta->tables [i].size_bitfield);
3389 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3391 heapt_size += 24; /* #~ header size */
3392 heapt_size += ntables * 4;
3393 /* make multiple of 4 */
3396 meta_size += heapt_size;
3397 meta->raw_metadata = g_malloc0 (meta_size);
3398 p = (unsigned char*)meta->raw_metadata;
3399 /* the metadata signature */
3400 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3401 /* version numbers and 4 bytes reserved */
3402 int16val = (guint16*)p;
3403 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3404 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3406 /* version string */
3407 int32val = (guint32*)p;
3408 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3410 memcpy (p, meta->version, strlen (meta->version));
3411 p += GUINT32_FROM_LE (*int32val);
3412 align_pointer (meta->raw_metadata, p);
3413 int16val = (guint16*)p;
3414 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3415 *int16val = GUINT16_TO_LE (5); /* number of streams */
3419 * write the stream info.
3421 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3422 table_offset += 3; table_offset &= ~3;
3424 assembly->tstream.index = heapt_size;
3425 for (i = 0; i < 5; ++i) {
3426 int32val = (guint32*)p;
3427 stream_desc [i].stream->offset = table_offset;
3428 *int32val++ = GUINT32_TO_LE (table_offset);
3429 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3430 table_offset += GUINT32_FROM_LE (*int32val);
3431 table_offset += 3; table_offset &= ~3;
3433 strcpy ((char*)p, stream_desc [i].name);
3434 p += strlen (stream_desc [i].name) + 1;
3435 align_pointer (meta->raw_metadata, p);
3438 * now copy the data, the table stream header and contents goes first.
3440 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3441 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3442 int32val = (guint32*)p;
3443 *int32val = GUINT32_TO_LE (0); /* reserved */
3446 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3447 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3448 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3449 *p++ = 2; /* version */
3452 *p++ = 1; /* version */
3456 if (meta->idx_string_wide)
3458 if (meta->idx_guid_wide)
3460 if (meta->idx_blob_wide)
3463 *p++ = 1; /* reserved */
3464 int64val = (guint64*)p;
3465 *int64val++ = GUINT64_TO_LE (valid_mask);
3466 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3468 int32val = (guint32*)p;
3469 for (i = 0; i < MONO_TABLE_NUM; i++){
3470 if (meta->tables [i].rows == 0)
3472 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3474 p = (unsigned char*)int32val;
3476 /* sort the tables that still need sorting */
3477 table = &assembly->tables [MONO_TABLE_CONSTANT];
3479 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3480 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3482 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3483 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3485 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3486 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3488 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3489 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3491 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3492 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3493 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3495 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3497 /* compress the tables */
3498 for (i = 0; i < MONO_TABLE_NUM; i++){
3501 guint32 bitfield = meta->tables [i].size_bitfield;
3502 if (!meta->tables [i].rows)
3504 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3505 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3506 meta->tables [i].base = (char*)p;
3507 for (row = 1; row <= meta->tables [i].rows; ++row) {
3508 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3509 for (col = 0; col < assembly->tables [i].columns; ++col) {
3510 switch (mono_metadata_table_size (bitfield, col)) {
3512 *p++ = values [col];
3515 *p++ = values [col] & 0xff;
3516 *p++ = (values [col] >> 8) & 0xff;
3519 *p++ = values [col] & 0xff;
3520 *p++ = (values [col] >> 8) & 0xff;
3521 *p++ = (values [col] >> 16) & 0xff;
3522 *p++ = (values [col] >> 24) & 0xff;
3525 g_assert_not_reached ();
3529 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3532 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3533 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3534 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3535 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3536 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3538 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3542 * Some tables in metadata need to be sorted according to some criteria, but
3543 * when methods and fields are first created with reflection, they may be assigned a token
3544 * that doesn't correspond to the final token they will get assigned after the sorting.
3545 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3546 * with the reflection objects that represent them. Once all the tables are set up, the
3547 * reflection objects will contains the correct table index. fixup_method() will fixup the
3548 * tokens for the method with ILGenerator @ilgen.
3551 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3552 guint32 code_idx = GPOINTER_TO_UINT (value);
3553 MonoReflectionILTokenInfo *iltoken;
3554 MonoReflectionFieldBuilder *field;
3555 MonoReflectionCtorBuilder *ctor;
3556 MonoReflectionMethodBuilder *method;
3557 MonoReflectionTypeBuilder *tb;
3558 MonoReflectionArrayMethod *am;
3560 unsigned char *target;
3562 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3563 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3564 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3565 switch (target [3]) {
3566 case MONO_TABLE_FIELD:
3567 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3568 field = (MonoReflectionFieldBuilder *)iltoken->member;
3569 idx = field->table_idx;
3570 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3571 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3572 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3574 g_assert_not_reached ();
3577 case MONO_TABLE_METHOD:
3578 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3579 method = (MonoReflectionMethodBuilder *)iltoken->member;
3580 idx = method->table_idx;
3581 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3582 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3583 idx = ctor->table_idx;
3584 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3585 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3586 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3587 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3589 g_assert_not_reached ();
3592 case MONO_TABLE_TYPEDEF:
3593 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3594 g_assert_not_reached ();
3595 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3596 idx = tb->table_idx;
3598 case MONO_TABLE_MEMBERREF:
3599 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3600 am = (MonoReflectionArrayMethod*)iltoken->member;
3601 idx = am->table_idx;
3602 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3603 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3604 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3605 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3606 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3607 g_assert (m->klass->generic_class || m->klass->generic_container);
3609 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3611 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3612 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3613 g_assert (f->generic_info);
3615 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3618 g_assert_not_reached ();
3621 case MONO_TABLE_METHODSPEC:
3622 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3623 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3624 g_assert (mono_method_signature (m)->generic_param_count);
3627 g_assert_not_reached ();
3631 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3633 target [0] = idx & 0xff;
3634 target [1] = (idx >> 8) & 0xff;
3635 target [2] = (idx >> 16) & 0xff;
3642 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3643 * value is not known when the table is emitted.
3646 fixup_cattrs (MonoDynamicImage *assembly)
3648 MonoDynamicTable *table;
3650 guint32 type, i, idx, token;
3653 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3655 for (i = 0; i < table->rows; ++i) {
3656 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3658 type = values [MONO_CUSTOM_ATTR_TYPE];
3659 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3660 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3661 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3662 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3665 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3666 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3667 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3668 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3675 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3677 MonoDynamicTable *table;
3680 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3682 alloc_table (table, table->rows);
3683 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3684 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3685 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3686 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
3687 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3692 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3694 MonoDynamicTable *table;
3698 char *b = blob_size;
3700 guint32 idx, offset;
3702 if (rsrc->filename) {
3703 name = mono_string_to_utf8 (rsrc->filename);
3704 sname = g_path_get_basename (name);
3706 table = &assembly->tables [MONO_TABLE_FILE];
3708 alloc_table (table, table->rows);
3709 values = table->values + table->next_idx * MONO_FILE_SIZE;
3710 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3711 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3714 mono_sha1_get_digest_from_file (name, hash);
3715 mono_metadata_encode_value (20, b, &b);
3716 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3717 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3719 idx = table->next_idx++;
3721 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3727 data = mono_array_addr (rsrc->data, char, 0);
3728 len = mono_array_length (rsrc->data);
3734 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3735 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3736 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3737 mono_image_add_stream_data (&assembly->resources, data, len);
3741 * The entry should be emitted into the MANIFESTRESOURCE table of
3742 * the main module, but that needs to reference the FILE table
3743 * which isn't emitted yet.
3750 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3754 set_version_from_string (MonoString *version, guint32 *values)
3756 gchar *ver, *p, *str;
3759 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3760 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3761 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3762 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3765 ver = str = mono_string_to_utf8 (version);
3766 for (i = 0; i < 4; ++i) {
3767 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3773 /* handle Revision and Build */
3783 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3787 char *b = blob_size;
3792 len = mono_array_length (pkey);
3793 mono_metadata_encode_value (len, b, &b);
3794 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3795 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
3797 assembly->public_key = g_malloc (len);
3798 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
3799 assembly->public_key_len = len;
3801 /* Special case: check for ECMA key (16 bytes) */
3802 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
3803 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3804 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3805 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3806 /* minimum key size (in 2.0) is 384 bits */
3807 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3809 /* FIXME - verifier */
3810 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3811 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3813 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3819 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3821 MonoDynamicTable *table;
3822 MonoDynamicImage *assembly;
3823 MonoReflectionAssemblyBuilder *assemblyb;
3827 guint32 module_index;
3829 assemblyb = moduleb->assemblyb;
3830 assembly = moduleb->dynamic_image;
3831 domain = mono_object_domain (assemblyb);
3833 /* Emit ASSEMBLY table */
3834 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3835 alloc_table (table, 1);
3836 values = table->values + MONO_ASSEMBLY_SIZE;
3837 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3838 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
3839 if (assemblyb->culture) {
3840 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
3842 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3844 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3845 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3846 set_version_from_string (assemblyb->version, values);
3848 /* Emit FILE + EXPORTED_TYPE table */
3850 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3852 MonoReflectionModuleBuilder *file_module =
3853 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3854 if (file_module != moduleb) {
3855 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3857 if (file_module->types) {
3858 for (j = 0; j < file_module->num_types; ++j) {
3859 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3860 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3865 if (assemblyb->loaded_modules) {
3866 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3867 MonoReflectionModule *file_module =
3868 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3869 mono_image_fill_file_table (domain, file_module, assembly);
3871 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3874 if (assemblyb->type_forwarders)
3875 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3877 /* Emit MANIFESTRESOURCE table */
3879 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3881 MonoReflectionModuleBuilder *file_module =
3882 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3883 /* The table for the main module is emitted later */
3884 if (file_module != moduleb) {
3886 if (file_module->resources) {
3887 int len = mono_array_length (file_module->resources);
3888 for (j = 0; j < len; ++j) {
3889 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3890 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3898 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3899 * for the modulebuilder @moduleb.
3900 * At the end of the process, method and field tokens are fixed up and the
3901 * on-disk compressed metadata representation is created.
3904 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3906 MonoDynamicTable *table;
3907 MonoDynamicImage *assembly;
3908 MonoReflectionAssemblyBuilder *assemblyb;
3914 assemblyb = moduleb->assemblyb;
3915 assembly = moduleb->dynamic_image;
3916 domain = mono_object_domain (assemblyb);
3918 if (assembly->text_rva)
3921 assembly->text_rva = START_TEXT_RVA;
3923 if (moduleb->is_main) {
3924 mono_image_emit_manifest (moduleb);
3927 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3928 table->rows = 1; /* .<Module> */
3930 alloc_table (table, table->rows);
3932 * Set the first entry.
3934 values = table->values + table->columns;
3935 values [MONO_TYPEDEF_FLAGS] = 0;
3936 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3937 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3938 values [MONO_TYPEDEF_EXTENDS] = 0;
3939 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3940 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3943 * handle global methods
3944 * FIXME: test what to do when global methods are defined in multiple modules.
3946 if (moduleb->global_methods) {
3947 table = &assembly->tables [MONO_TABLE_METHOD];
3948 table->rows += mono_array_length (moduleb->global_methods);
3949 alloc_table (table, table->rows);
3950 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3951 mono_image_get_method_info (
3952 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3954 if (moduleb->global_fields) {
3955 table = &assembly->tables [MONO_TABLE_FIELD];
3956 table->rows += mono_array_length (moduleb->global_fields);
3957 alloc_table (table, table->rows);
3958 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3959 mono_image_get_field_info (
3960 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3963 table = &assembly->tables [MONO_TABLE_MODULE];
3964 alloc_table (table, 1);
3965 mono_image_fill_module_table (domain, moduleb, assembly);
3967 /* Collect all types into a list sorted by their table_idx */
3968 types = g_ptr_array_new ();
3971 for (i = 0; i < moduleb->num_types; ++i) {
3972 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3973 collect_types (types, type);
3976 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3977 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3978 table->rows += types->len;
3979 alloc_table (table, table->rows);
3982 * Emit type names + namespaces at one place inside the string heap,
3983 * so load_class_names () needs to touch fewer pages.
3985 for (i = 0; i < types->len; ++i) {
3986 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3987 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
3989 for (i = 0; i < types->len; ++i) {
3990 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3991 string_heap_insert_mstring (&assembly->sheap, tb->name);
3994 for (i = 0; i < types->len; ++i) {
3995 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3996 mono_image_get_type_info (domain, type, assembly);
4000 * table->rows is already set above and in mono_image_fill_module_table.
4002 /* add all the custom attributes at the end, once all the indexes are stable */
4003 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4005 /* CAS assembly permissions */
4006 if (assemblyb->permissions_minimum)
4007 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4008 if (assemblyb->permissions_optional)
4009 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4010 if (assemblyb->permissions_refused)
4011 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4013 module_add_cattrs (assembly, moduleb);
4016 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4018 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4019 * the final tokens and don't need another fixup pass. */
4021 if (moduleb->global_methods) {
4022 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4023 MonoReflectionMethodBuilder *mb = mono_array_get (
4024 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4025 mono_image_add_methodimpl (assembly, mb);
4029 for (i = 0; i < types->len; ++i) {
4030 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4031 if (type->methods) {
4032 for (j = 0; j < type->num_methods; ++j) {
4033 MonoReflectionMethodBuilder *mb = mono_array_get (
4034 type->methods, MonoReflectionMethodBuilder*, j);
4036 mono_image_add_methodimpl (assembly, mb);
4041 g_ptr_array_free (types, TRUE);
4043 fixup_cattrs (assembly);
4047 * mono_image_insert_string:
4048 * @module: module builder object
4051 * Insert @str into the user string stream of @module.
4054 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4056 MonoDynamicImage *assembly;
4061 MONO_ARCH_SAVE_REGS;
4063 if (!module->dynamic_image)
4064 mono_image_module_basic_init (module);
4066 assembly = module->dynamic_image;
4068 if (assembly->save) {
4069 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4070 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4071 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4073 char *swapped = g_malloc (2 * mono_string_length (str));
4074 const char *p = (const char*)mono_string_chars (str);
4076 swap_with_size (swapped, p, 2, mono_string_length (str));
4077 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4081 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4083 mono_image_add_stream_data (&assembly->us, "", 1);
4085 idx = assembly->us.index ++;
4088 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4090 return MONO_TOKEN_STRING | idx;
4094 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4099 klass = obj->vtable->klass;
4100 if (strcmp (klass->name, "MonoMethod") == 0) {
4101 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4102 MonoMethodSignature *sig, *old;
4103 guint32 sig_token, parent;
4106 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4108 nargs = mono_array_length (opt_param_types);
4109 old = mono_method_signature (method);
4110 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4112 sig->hasthis = old->hasthis;
4113 sig->explicit_this = old->explicit_this;
4114 sig->call_convention = old->call_convention;
4115 sig->generic_param_count = old->generic_param_count;
4116 sig->param_count = old->param_count + nargs;
4117 sig->sentinelpos = old->param_count;
4118 sig->ret = old->ret;
4120 for (i = 0; i < old->param_count; i++)
4121 sig->params [i] = old->params [i];
4123 for (i = 0; i < nargs; i++) {
4124 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4125 sig->params [old->param_count + i] = rt->type;
4128 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4129 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4130 parent >>= MONO_TYPEDEFORREF_BITS;
4132 parent <<= MONO_MEMBERREF_PARENT_BITS;
4133 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4135 sig_token = method_encode_signature (assembly, sig);
4136 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4137 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4138 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4139 ReflectionMethodBuilder rmb;
4140 guint32 parent, sig;
4142 reflection_methodbuilder_from_method_builder (&rmb, mb);
4143 rmb.opt_types = opt_param_types;
4145 sig = method_builder_encode_signature (assembly, &rmb);
4147 parent = mono_image_create_token (assembly, obj, TRUE);
4148 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4150 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4151 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4153 token = mono_image_get_varargs_method_token (
4154 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4156 g_error ("requested method token for %s\n", klass->name);
4163 * mono_image_create_token:
4164 * @assembly: a dynamic assembly
4167 * Get a token to insert in the IL code stream for the given MemberInfo.
4168 * @obj can be one of:
4169 * ConstructorBuilder
4179 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4184 klass = obj->vtable->klass;
4185 if (strcmp (klass->name, "MethodBuilder") == 0) {
4186 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4188 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4189 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4191 token = mono_image_get_methodbuilder_token (assembly, mb);
4192 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4193 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4194 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4196 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4197 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4199 token = mono_image_get_ctorbuilder_token (assembly, mb);
4200 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4201 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4202 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4203 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4204 if (tb->generic_params) {
4205 token = mono_image_get_generic_field_token (assembly, fb);
4207 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4209 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4210 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4211 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4212 } else if (strcmp (klass->name, "MonoType") == 0) {
4213 MonoReflectionType *tb = (MonoReflectionType *)obj;
4214 MonoClass *mc = mono_class_from_mono_type (tb->type);
4215 token = mono_metadata_token_from_dor (
4216 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4217 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4218 MonoReflectionType *tb = (MonoReflectionType *)obj;
4219 token = mono_metadata_token_from_dor (
4220 mono_image_typedef_or_ref (assembly, tb->type));
4221 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4222 MonoReflectionType *tb = (MonoReflectionType *)obj;
4223 token = mono_metadata_token_from_dor (
4224 mono_image_typedef_or_ref (assembly, tb->type));
4225 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4226 strcmp (klass->name, "MonoMethod") == 0 ||
4227 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4228 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4229 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4230 if (m->method->is_inflated) {
4231 if (create_methodspec)
4232 token = mono_image_get_methodspec_token (assembly, m->method);
4234 token = mono_image_get_inflated_method_token (assembly, m->method);
4235 } else if ((m->method->klass->image == &assembly->image) &&
4236 !m->method->klass->generic_class) {
4237 static guint32 method_table_idx = 0xffffff;
4238 if (m->method->klass->wastypebuilder) {
4239 /* we use the same token as the one that was assigned
4240 * to the Methodbuilder.
4241 * FIXME: do the equivalent for Fields.
4243 token = m->method->token;
4246 * Each token should have a unique index, but the indexes are
4247 * assigned by managed code, so we don't know about them. An
4248 * easy solution is to count backwards...
4250 method_table_idx --;
4251 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4254 token = mono_image_get_methodref_token (assembly, m->method);
4256 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4257 } else if (strcmp (klass->name, "MonoField") == 0) {
4258 MonoReflectionField *f = (MonoReflectionField *)obj;
4259 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4260 static guint32 field_table_idx = 0xffffff;
4262 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4264 token = mono_image_get_fieldref_token (assembly, f);
4266 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4267 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4268 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4269 token = mono_image_get_array_token (assembly, m);
4270 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4271 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4272 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4273 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4274 MonoReflectionType *tb = (MonoReflectionType *)obj;
4275 token = mono_metadata_token_from_dor (
4276 mono_image_typedef_or_ref (assembly, tb->type));
4278 g_error ("requested token for %s\n", klass->name);
4281 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4287 guint32 import_lookup_table;
4291 guint32 import_address_table_rva;
4299 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4301 static MonoDynamicImage*
4302 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4304 static const guchar entrycode [16] = {0xff, 0x25, 0};
4305 MonoDynamicImage *image;
4308 const char *version = mono_get_runtime_info ()->runtime_version;
4311 image = GC_MALLOC (sizeof (MonoDynamicImage));
4313 image = g_new0 (MonoDynamicImage, 1);
4316 /*g_print ("created image %p\n", image);*/
4317 /* keep in sync with image.c */
4318 image->image.name = assembly_name;
4319 image->image.assembly_name = image->image.name; /* they may be different */
4320 image->image.module_name = module_name;
4321 image->image.version = g_strdup (version);
4322 image->image.md_version_major = 1;
4323 image->image.md_version_minor = 1;
4324 image->image.dynamic = TRUE;
4326 image->image.references = g_new0 (MonoAssembly*, 1);
4327 image->image.references [0] = NULL;
4329 mono_image_init (&image->image);
4331 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4332 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4333 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4334 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4335 image->handleref = g_hash_table_new (NULL, NULL);
4336 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4337 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4338 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4339 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4340 image->gen_params = g_ptr_array_new ();
4342 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4343 string_heap_init (&image->sheap);
4344 mono_image_add_stream_data (&image->us, "", 1);
4345 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4346 /* import tables... */
4347 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4348 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4349 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4350 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4351 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4352 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4353 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4354 stream_data_align (&image->code);
4356 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4358 for (i=0; i < MONO_TABLE_NUM; ++i) {
4359 image->tables [i].next_idx = 1;
4360 image->tables [i].columns = table_sizes [i];
4363 image->image.assembly = (MonoAssembly*)assembly;
4364 image->run = assembly->run;
4365 image->save = assembly->save;
4366 image->pe_kind = 0x1; /* ILOnly */
4367 image->machine = 0x14c; /* I386 */
4373 * mono_image_basic_init:
4374 * @assembly: an assembly builder object
4376 * Create the MonoImage that represents the assembly builder and setup some
4377 * of the helper hash table and the basic metadata streams.
4380 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4382 MonoDynamicAssembly *assembly;
4383 MonoDynamicImage *image;
4384 MonoDomain *domain = mono_object_domain (assemblyb);
4386 MONO_ARCH_SAVE_REGS;
4388 if (assemblyb->dynamic_assembly)
4392 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4394 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4397 assembly->assembly.ref_count = 1;
4398 assembly->assembly.dynamic = TRUE;
4399 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4400 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4401 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4402 if (assemblyb->culture)
4403 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4405 assembly->assembly.aname.culture = g_strdup ("");
4407 if (assemblyb->version) {
4408 char *vstr = mono_string_to_utf8 (assemblyb->version);
4409 char **version = g_strsplit (vstr, ".", 4);
4410 char **parts = version;
4411 assembly->assembly.aname.major = atoi (*parts++);
4412 assembly->assembly.aname.minor = atoi (*parts++);
4413 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4414 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4416 g_strfreev (version);
4419 assembly->assembly.aname.major = 0;
4420 assembly->assembly.aname.minor = 0;
4421 assembly->assembly.aname.build = 0;
4422 assembly->assembly.aname.revision = 0;
4425 assembly->run = assemblyb->access != 2;
4426 assembly->save = assemblyb->access != 1;
4428 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4429 image->initial_image = TRUE;
4430 assembly->assembly.aname.name = image->image.name;
4431 assembly->assembly.image = &image->image;
4433 mono_domain_assemblies_lock (domain);
4434 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4435 mono_domain_assemblies_unlock (domain);
4437 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4438 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4442 calc_section_size (MonoDynamicImage *assembly)
4446 /* alignment constraints */
4447 assembly->code.index += 3;
4448 assembly->code.index &= ~3;
4449 assembly->meta_size += 3;
4450 assembly->meta_size &= ~3;
4451 assembly->resources.index += 3;
4452 assembly->resources.index &= ~3;
4454 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4455 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4458 if (assembly->win32_res) {
4459 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4461 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4462 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4466 assembly->sections [MONO_SECTION_RELOC].size = 12;
4467 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4477 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4481 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4483 ResTreeNode *t1 = (ResTreeNode*)a;
4484 ResTreeNode *t2 = (ResTreeNode*)b;
4486 return t1->id - t2->id;
4490 * resource_tree_create:
4492 * Organize the resources into a resource tree.
4494 static ResTreeNode *
4495 resource_tree_create (MonoArray *win32_resources)
4497 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4501 tree = g_new0 (ResTreeNode, 1);
4503 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4504 MonoReflectionWin32Resource *win32_res =
4505 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4509 /* FIXME: BUG: this stores managed references in unmanaged memory */
4510 lang_node = g_new0 (ResTreeNode, 1);
4511 lang_node->id = win32_res->lang_id;
4512 lang_node->win32_res = win32_res;
4514 /* Create type node if neccesary */
4516 for (l = tree->children; l; l = l->next)
4517 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4518 type_node = (ResTreeNode*)l->data;
4523 type_node = g_new0 (ResTreeNode, 1);
4524 type_node->id = win32_res->res_type;
4527 * The resource types have to be sorted otherwise
4528 * Windows Explorer can't display the version information.
4530 tree->children = g_slist_insert_sorted (tree->children,
4531 type_node, resource_tree_compare_by_id);
4534 /* Create res node if neccesary */
4536 for (l = type_node->children; l; l = l->next)
4537 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4538 res_node = (ResTreeNode*)l->data;
4543 res_node = g_new0 (ResTreeNode, 1);
4544 res_node->id = win32_res->res_id;
4545 type_node->children = g_slist_append (type_node->children, res_node);
4548 res_node->children = g_slist_append (res_node->children, lang_node);
4555 * resource_tree_encode:
4557 * Encode the resource tree into the format used in the PE file.
4560 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4563 MonoPEResourceDir dir;
4564 MonoPEResourceDirEntry dir_entry;
4565 MonoPEResourceDataEntry data_entry;
4569 * For the format of the resource directory, see the article
4570 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4574 memset (&dir, 0, sizeof (dir));
4575 memset (&dir_entry, 0, sizeof (dir_entry));
4576 memset (&data_entry, 0, sizeof (data_entry));
4578 g_assert (sizeof (dir) == 16);
4579 g_assert (sizeof (dir_entry) == 8);
4580 g_assert (sizeof (data_entry) == 16);
4582 node->offset = p - begin;
4584 /* IMAGE_RESOURCE_DIRECTORY */
4585 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4587 memcpy (p, &dir, sizeof (dir));
4590 /* Reserve space for entries */
4592 p += sizeof (dir_entry) * dir.res_id_entries;
4594 /* Write children */
4595 for (l = node->children; l; l = l->next) {
4596 ResTreeNode *child = (ResTreeNode*)l->data;
4598 if (child->win32_res) {
4600 child->offset = p - begin;
4602 /* IMAGE_RESOURCE_DATA_ENTRY */
4603 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4604 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4606 memcpy (p, &data_entry, sizeof (data_entry));
4607 p += sizeof (data_entry);
4609 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4610 p += data_entry.rde_size;
4612 resource_tree_encode (child, begin, p, &p);
4616 /* IMAGE_RESOURCE_ENTRY */
4617 for (l = node->children; l; l = l->next) {
4618 ResTreeNode *child = (ResTreeNode*)l->data;
4619 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4621 dir_entry.is_dir = child->win32_res ? 0 : 1;
4622 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4624 memcpy (entries, &dir_entry, sizeof (dir_entry));
4625 entries += sizeof (dir_entry);
4632 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4637 MonoReflectionWin32Resource *win32_res;
4640 if (!assemblyb->win32_resources)
4644 * Resources are stored in a three level tree inside the PE file.
4645 * - level one contains a node for each type of resource
4646 * - level two contains a node for each resource
4647 * - level three contains a node for each instance of a resource for a
4648 * specific language.
4651 tree = resource_tree_create (assemblyb->win32_resources);
4653 /* Estimate the size of the encoded tree */
4655 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4656 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4657 size += mono_array_length (win32_res->res_data);
4659 /* Directory structure */
4660 size += mono_array_length (assemblyb->win32_resources) * 256;
4661 p = buf = g_malloc (size);
4663 resource_tree_encode (tree, p, p, &p);
4665 g_assert (p - buf <= size);
4667 assembly->win32_res = g_malloc (p - buf);
4668 assembly->win32_res_size = p - buf;
4669 memcpy (assembly->win32_res, buf, p - buf);
4675 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4677 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4680 p += sizeof (MonoPEResourceDir);
4681 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4682 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4683 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4684 if (dir_entry->is_dir) {
4685 fixup_resource_directory (res_section, child, rva);
4687 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4688 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4691 p += sizeof (MonoPEResourceDirEntry);
4696 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4699 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4700 g_error ("WriteFile returned %d\n", GetLastError ());
4704 * mono_image_create_pefile:
4705 * @mb: a module builder object
4707 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4708 * assembly->pefile where it can be easily retrieved later in chunks.
4711 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4712 MonoMSDOSHeader *msdos;
4713 MonoDotNetHeader *header;
4714 MonoSectionTable *section;
4715 MonoCLIHeader *cli_header;
4716 guint32 size, image_size, virtual_base, text_offset;
4717 guint32 header_start, section_start, file_offset, virtual_offset;
4718 MonoDynamicImage *assembly;
4719 MonoReflectionAssemblyBuilder *assemblyb;
4720 MonoDynamicStream pefile_stream = {0};
4721 MonoDynamicStream *pefile = &pefile_stream;
4723 guint32 *rva, value;
4725 static const unsigned char msheader[] = {
4726 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4727 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4728 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4729 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4730 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4731 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4732 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4733 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4736 assemblyb = mb->assemblyb;
4738 mono_image_basic_init (assemblyb);
4739 assembly = mb->dynamic_image;
4741 assembly->pe_kind = assemblyb->pe_kind;
4742 assembly->machine = assemblyb->machine;
4743 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4744 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4746 mono_image_build_metadata (mb);
4748 if (mb->is_main && assemblyb->resources) {
4749 int len = mono_array_length (assemblyb->resources);
4750 for (i = 0; i < len; ++i)
4751 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4754 if (mb->resources) {
4755 int len = mono_array_length (mb->resources);
4756 for (i = 0; i < len; ++i)
4757 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4760 build_compressed_metadata (assembly);
4763 assembly_add_win32_resources (assembly, assemblyb);
4765 nsections = calc_section_size (assembly);
4767 /* The DOS header and stub */
4768 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4769 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
4771 /* the dotnet header */
4772 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4774 /* the section tables */
4775 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4777 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4778 virtual_offset = VIRT_ALIGN;
4781 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4782 if (!assembly->sections [i].size)
4785 file_offset += FILE_ALIGN - 1;
4786 file_offset &= ~(FILE_ALIGN - 1);
4787 virtual_offset += VIRT_ALIGN - 1;
4788 virtual_offset &= ~(VIRT_ALIGN - 1);
4790 assembly->sections [i].offset = file_offset;
4791 assembly->sections [i].rva = virtual_offset;
4793 file_offset += assembly->sections [i].size;
4794 virtual_offset += assembly->sections [i].size;
4795 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4798 file_offset += FILE_ALIGN - 1;
4799 file_offset &= ~(FILE_ALIGN - 1);
4801 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4803 /* back-patch info */
4804 msdos = (MonoMSDOSHeader*)pefile->data;
4805 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4807 header = (MonoDotNetHeader*)(pefile->data + header_start);
4808 header->pesig [0] = 'P';
4809 header->pesig [1] = 'E';
4811 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4812 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4813 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4814 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4815 if (assemblyb->pekind == 1) {
4817 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4820 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4823 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4825 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4826 header->pe.pe_major = 6;
4827 header->pe.pe_minor = 0;
4828 size = assembly->sections [MONO_SECTION_TEXT].size;
4829 size += FILE_ALIGN - 1;
4830 size &= ~(FILE_ALIGN - 1);
4831 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4832 size = assembly->sections [MONO_SECTION_RSRC].size;
4833 size += FILE_ALIGN - 1;
4834 size &= ~(FILE_ALIGN - 1);
4835 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4836 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4837 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4838 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4839 /* pe_rva_entry_point always at the beginning of the text section */
4840 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4842 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4843 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4844 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4845 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4846 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4847 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4848 size = section_start;
4849 size += FILE_ALIGN - 1;
4850 size &= ~(FILE_ALIGN - 1);
4851 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4853 size += VIRT_ALIGN - 1;
4854 size &= ~(VIRT_ALIGN - 1);
4855 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4858 // Translate the PEFileKind value to the value expected by the Windows loader
4864 // PEFileKinds.Dll == 1
4865 // PEFileKinds.ConsoleApplication == 2
4866 // PEFileKinds.WindowApplication == 3
4869 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4870 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4872 if (assemblyb->pekind == 3)
4877 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4879 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4880 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4881 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4882 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4883 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4884 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4886 /* fill data directory entries */
4888 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4889 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4891 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4892 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4894 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4895 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4896 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4897 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4898 /* patch entrypoint name */
4899 if (assemblyb->pekind == 1)
4900 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4902 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4903 /* patch imported function RVA name */
4904 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4905 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4907 /* the import table */
4908 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4909 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4910 /* patch imported dll RVA name and other entries in the dir */
4911 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4912 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4913 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4914 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4915 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4916 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4918 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
4919 value = (assembly->text_rva + assembly->imp_names_offset);
4920 *p++ = (value) & 0xff;
4921 *p++ = (value >> 8) & (0xff);
4922 *p++ = (value >> 16) & (0xff);
4923 *p++ = (value >> 24) & (0xff);
4925 /* the CLI header info */
4926 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4927 cli_header->ch_size = GUINT32_FROM_LE (72);
4928 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4929 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4930 if (assemblyb->entry_point) {
4931 guint32 table_idx = 0;
4932 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4933 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4934 table_idx = methodb->table_idx;
4936 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4938 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4940 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4942 /* The embedded managed resources */
4943 text_offset = assembly->text_rva + assembly->code.index;
4944 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4945 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4946 text_offset += assembly->resources.index;
4947 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4948 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4949 text_offset += assembly->meta_size;
4950 if (assembly->strong_name_size) {
4951 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4952 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4953 text_offset += assembly->strong_name_size;
4956 /* write the section tables and section content */
4957 section = (MonoSectionTable*)(pefile->data + section_start);
4958 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4959 static const char section_names [][7] = {
4960 ".text", ".rsrc", ".reloc"
4962 if (!assembly->sections [i].size)
4964 strcpy (section->st_name, section_names [i]);
4965 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4966 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4967 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4968 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4969 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4970 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4971 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4975 checked_write_file (file, pefile->data, pefile->index);
4977 mono_dynamic_stream_reset (pefile);
4979 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4980 if (!assembly->sections [i].size)
4983 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4984 g_error ("SetFilePointer returned %d\n", GetLastError ());
4987 case MONO_SECTION_TEXT:
4988 /* patch entry point */
4989 p = (guchar*)(assembly->code.data + 2);
4990 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4991 *p++ = (value) & 0xff;
4992 *p++ = (value >> 8) & 0xff;
4993 *p++ = (value >> 16) & 0xff;
4994 *p++ = (value >> 24) & 0xff;
4996 checked_write_file (file, assembly->code.data, assembly->code.index);
4997 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4998 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4999 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5002 g_free (assembly->image.raw_metadata);
5004 case MONO_SECTION_RELOC: {
5008 guint16 type_and_offset;
5012 g_assert (sizeof (reloc) == 12);
5014 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5015 reloc.block_size = GUINT32_FROM_LE (12);
5018 * the entrypoint is always at the start of the text section
5019 * 3 is IMAGE_REL_BASED_HIGHLOW
5020 * 2 is patch_size_rva - text_rva
5022 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5025 checked_write_file (file, &reloc, sizeof (reloc));
5029 case MONO_SECTION_RSRC:
5030 if (assembly->win32_res) {
5032 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5033 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5034 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5038 g_assert_not_reached ();
5042 /* check that the file is properly padded */
5043 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5044 g_error ("SetFilePointer returned %d\n", GetLastError ());
5045 if (! SetEndOfFile (file))
5046 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5048 mono_dynamic_stream_reset (&assembly->code);
5049 mono_dynamic_stream_reset (&assembly->us);
5050 mono_dynamic_stream_reset (&assembly->blob);
5051 mono_dynamic_stream_reset (&assembly->guid);
5052 mono_dynamic_stream_reset (&assembly->sheap);
5054 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5055 g_hash_table_destroy (assembly->blob_cache);
5056 assembly->blob_cache = NULL;
5059 MonoReflectionModule *
5060 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5064 MonoImageOpenStatus status;
5065 MonoDynamicAssembly *assembly;
5066 guint32 module_count;
5067 MonoImage **new_modules;
5068 gboolean *new_modules_loaded;
5070 name = mono_string_to_utf8 (fileName);
5072 image = mono_image_open (name, &status);
5075 if (status == MONO_IMAGE_ERROR_ERRNO)
5076 exc = mono_get_exception_file_not_found (fileName);
5078 exc = mono_get_exception_bad_image_format (name);
5080 mono_raise_exception (exc);
5085 assembly = ab->dynamic_assembly;
5086 image->assembly = (MonoAssembly*)assembly;
5088 module_count = image->assembly->image->module_count;
5089 new_modules = g_new0 (MonoImage *, module_count + 1);
5090 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5092 if (image->assembly->image->modules)
5093 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5094 if (image->assembly->image->modules_loaded)
5095 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5096 new_modules [module_count] = image;
5097 new_modules_loaded [module_count] = TRUE;
5098 mono_image_addref (image);
5100 g_free (image->assembly->image->modules);
5101 image->assembly->image->modules = new_modules;
5102 image->assembly->image->modules_loaded = new_modules_loaded;
5103 image->assembly->image->module_count ++;
5105 mono_assembly_load_references (image, &status);
5107 mono_image_close (image);
5108 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5111 return mono_module_get_object (mono_domain_get (), image);
5115 * We need to return always the same object for MethodInfo, FieldInfo etc..
5116 * but we need to consider the reflected type.
5117 * type uses a different hash, since it uses custom hash/equal functions.
5122 MonoClass *refclass;
5126 reflected_equal (gconstpointer a, gconstpointer b) {
5127 const ReflectedEntry *ea = a;
5128 const ReflectedEntry *eb = b;
5130 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5134 reflected_hash (gconstpointer a) {
5135 const ReflectedEntry *ea = a;
5136 return mono_aligned_addr_hash (ea->item);
5139 #define CHECK_OBJECT(t,p,k) \
5145 mono_domain_lock (domain); \
5146 if (!domain->refobject_hash) \
5147 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5148 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5149 mono_domain_unlock (domain); \
5152 mono_domain_unlock (domain); \
5156 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5158 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5160 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5163 #define CACHE_OBJECT(t,p,o,k) \
5166 ReflectedEntry pe; \
5168 pe.refclass = (k); \
5169 mono_domain_lock (domain); \
5170 if (!domain->refobject_hash) \
5171 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5172 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5174 ReflectedEntry *e = ALLOC_REFENTRY; \
5176 e->refclass = (k); \
5177 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5180 mono_domain_unlock (domain); \
5185 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5187 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5191 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5193 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5197 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5199 MonoDynamicImage *image = moduleb->dynamic_image;
5200 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5203 MonoImage **new_modules;
5206 * FIXME: we already created an image in mono_image_basic_init (), but
5207 * we don't know which module it belongs to, since that is only
5208 * determined at assembly save time.
5210 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5211 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5213 moduleb->module.image = &image->image;
5214 moduleb->dynamic_image = image;
5215 register_module (mono_object_domain (moduleb), moduleb, image);
5217 /* register the module with the assembly */
5218 ass = ab->dynamic_assembly->assembly.image;
5219 module_count = ass->module_count;
5220 new_modules = g_new0 (MonoImage *, module_count + 1);
5223 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5224 new_modules [module_count] = &image->image;
5225 mono_image_addref (&image->image);
5227 g_free (ass->modules);
5228 ass->modules = new_modules;
5229 ass->module_count ++;
5234 * mono_assembly_get_object:
5235 * @domain: an app domain
5236 * @assembly: an assembly
5238 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5240 MonoReflectionAssembly*
5241 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5243 static MonoClass *System_Reflection_Assembly;
5244 MonoReflectionAssembly *res;
5246 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5247 if (!System_Reflection_Assembly)
5248 System_Reflection_Assembly = mono_class_from_name (
5249 mono_defaults.corlib, "System.Reflection", "Assembly");
5250 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5251 res->assembly = assembly;
5253 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5258 MonoReflectionModule*
5259 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5261 static MonoClass *System_Reflection_Module;
5262 MonoReflectionModule *res;
5265 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5266 if (!System_Reflection_Module)
5267 System_Reflection_Module = mono_class_from_name (
5268 mono_defaults.corlib, "System.Reflection", "Module");
5269 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5272 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5274 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5275 basename = g_path_get_basename (image->name);
5276 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5277 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5281 if (image->assembly->image == image) {
5282 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5286 if (image->assembly->image->modules) {
5287 for (i = 0; i < image->assembly->image->module_count; i++) {
5288 if (image->assembly->image->modules [i] == image)
5289 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5291 g_assert (res->token);
5295 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5298 MonoReflectionModule*
5299 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5301 static MonoClass *System_Reflection_Module;
5302 MonoReflectionModule *res;
5303 MonoTableInfo *table;
5304 guint32 cols [MONO_FILE_SIZE];
5306 guint32 i, name_idx;
5309 if (!System_Reflection_Module)
5310 System_Reflection_Module = mono_class_from_name (
5311 mono_defaults.corlib, "System.Reflection", "Module");
5312 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5314 table = &image->tables [MONO_TABLE_FILE];
5315 g_assert (table_index < table->rows);
5316 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5319 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5320 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5322 /* Check whenever the row has a corresponding row in the moduleref table */
5323 table = &image->tables [MONO_TABLE_MODULEREF];
5324 for (i = 0; i < table->rows; ++i) {
5325 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5326 val = mono_metadata_string_heap (image, name_idx);
5327 if (strcmp (val, name) == 0)
5328 res->image = image->modules [i];
5331 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5332 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5333 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5334 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5335 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5341 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5343 if ((t1->type != t2->type) ||
5344 (t1->byref != t2->byref))
5348 case MONO_TYPE_VOID:
5349 case MONO_TYPE_BOOLEAN:
5350 case MONO_TYPE_CHAR:
5361 case MONO_TYPE_STRING:
5364 case MONO_TYPE_OBJECT:
5365 case MONO_TYPE_TYPEDBYREF:
5367 case MONO_TYPE_VALUETYPE:
5368 case MONO_TYPE_CLASS:
5369 case MONO_TYPE_SZARRAY:
5370 return t1->data.klass == t2->data.klass;
5372 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5373 case MONO_TYPE_ARRAY:
5374 if (t1->data.array->rank != t2->data.array->rank)
5376 return t1->data.array->eklass == t2->data.array->eklass;
5377 case MONO_TYPE_GENERICINST: {
5379 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5380 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5381 if (i1->type_argc != i2->type_argc)
5383 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5384 &t2->data.generic_class->container_class->byval_arg))
5386 /* FIXME: we should probably just compare the instance pointers directly. */
5387 for (i = 0; i < i1->type_argc; ++i) {
5388 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5394 case MONO_TYPE_MVAR:
5395 return t1->data.generic_param == t2->data.generic_param;
5397 g_error ("implement type compare for %0x!", t1->type);
5405 mymono_metadata_type_hash (MonoType *t1)
5411 hash |= t1->byref << 6; /* do not collide with t1->type values */
5413 case MONO_TYPE_VALUETYPE:
5414 case MONO_TYPE_CLASS:
5415 case MONO_TYPE_SZARRAY:
5416 /* check if the distribution is good enough */
5417 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5419 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5420 case MONO_TYPE_GENERICINST: {
5422 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5423 hash += g_str_hash (t1->data.generic_class->container_class->name);
5425 for (i = 0; i < inst->type_argc; ++i) {
5426 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5435 static MonoReflectionGenericClass*
5436 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5438 static MonoClass *System_Reflection_MonoGenericClass;
5439 MonoReflectionGenericClass *res;
5440 MonoClass *klass, *gklass;
5442 if (!System_Reflection_MonoGenericClass) {
5443 System_Reflection_MonoGenericClass = mono_class_from_name (
5444 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5445 g_assert (System_Reflection_MonoGenericClass);
5448 klass = mono_class_from_mono_type (geninst);
5449 gklass = klass->generic_class->container_class;
5451 mono_class_init (klass);
5454 /* FIXME: allow unpinned later */
5455 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5457 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5460 res->type.type = geninst;
5461 if (gklass->wastypebuilder && gklass->reflection_info)
5462 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5464 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5470 verify_safe_for_managed_space (MonoType *type)
5472 switch (type->type) {
5474 case MONO_TYPE_ARRAY:
5475 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5477 return verify_safe_for_managed_space (type->data.type);
5478 case MONO_TYPE_SZARRAY:
5479 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5480 case MONO_TYPE_GENERICINST: {
5481 MonoGenericInst *inst = type->data.generic_class->inst;
5485 for (i = 0; i < inst->type_argc; ++i)
5486 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5492 case MONO_TYPE_MVAR:
5499 * mono_type_get_object:
5500 * @domain: an app domain
5503 * Return an System.MonoType object representing the type @type.
5506 mono_type_get_object (MonoDomain *domain, MonoType *type)
5508 MonoReflectionType *res;
5509 MonoClass *klass = mono_class_from_mono_type (type);
5511 mono_domain_lock (domain);
5512 if (!domain->type_hash)
5513 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
5514 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
5515 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5516 mono_domain_unlock (domain);
5519 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5520 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5521 mono_g_hash_table_insert (domain->type_hash, type, res);
5522 mono_domain_unlock (domain);
5526 if (!verify_safe_for_managed_space (type)) {
5527 mono_domain_unlock (domain);
5528 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5531 if (klass->reflection_info && !klass->wastypebuilder) {
5532 /* g_assert_not_reached (); */
5533 /* should this be considered an error condition? */
5535 mono_domain_unlock (domain);
5536 return klass->reflection_info;
5539 mono_class_init (klass);
5541 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
5543 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5546 mono_g_hash_table_insert (domain->type_hash, type, res);
5547 mono_domain_unlock (domain);
5552 * mono_method_get_object:
5553 * @domain: an app domain
5555 * @refclass: the reflected type (can be NULL)
5557 * Return an System.Reflection.MonoMethod object representing the method @method.
5559 MonoReflectionMethod*
5560 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5563 * We use the same C representation for methods and constructors, but the type
5564 * name in C# is different.
5566 static MonoClass *System_Reflection_MonoMethod = NULL;
5567 static MonoClass *System_Reflection_MonoCMethod = NULL;
5568 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
5569 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
5571 MonoReflectionMethod *ret;
5573 if (method->is_inflated) {
5574 MonoReflectionGenericMethod *gret;
5576 refclass = method->klass;
5577 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5578 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
5579 if (!System_Reflection_MonoGenericCMethod)
5580 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
5581 klass = System_Reflection_MonoGenericCMethod;
5583 if (!System_Reflection_MonoGenericMethod)
5584 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
5585 klass = System_Reflection_MonoGenericMethod;
5587 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5588 gret->method.method = method;
5589 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5590 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5591 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5595 refclass = method->klass;
5597 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5598 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
5599 if (!System_Reflection_MonoCMethod)
5600 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
5601 klass = System_Reflection_MonoCMethod;
5604 if (!System_Reflection_MonoMethod)
5605 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
5606 klass = System_Reflection_MonoMethod;
5608 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5609 ret->method = method;
5610 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5611 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5615 * mono_field_get_object:
5616 * @domain: an app domain
5620 * Return an System.Reflection.MonoField object representing the field @field
5623 MonoReflectionField*
5624 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5626 MonoReflectionField *res;
5627 static MonoClass *monofield_klass;
5629 CHECK_OBJECT (MonoReflectionField *, field, klass);
5630 if (!monofield_klass)
5631 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5632 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
5635 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5636 if (field->generic_info)
5637 res->attrs = field->generic_info->generic_type->attrs;
5639 res->attrs = field->type->attrs;
5640 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5641 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5645 * mono_property_get_object:
5646 * @domain: an app domain
5648 * @property: a property
5650 * Return an System.Reflection.MonoProperty object representing the property @property
5653 MonoReflectionProperty*
5654 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5656 MonoReflectionProperty *res;
5657 static MonoClass *monoproperty_klass;
5659 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5660 if (!monoproperty_klass)
5661 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5662 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
5664 res->property = property;
5665 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5669 * mono_event_get_object:
5670 * @domain: an app domain
5674 * Return an System.Reflection.MonoEvent object representing the event @event
5677 MonoReflectionEvent*
5678 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5680 MonoReflectionEvent *res;
5681 static MonoClass *monoevent_klass;
5683 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5684 if (!monoevent_klass)
5685 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5686 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
5689 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5693 * mono_param_get_objects:
5694 * @domain: an app domain
5697 * Return an System.Reflection.ParameterInfo array object representing the parameters
5698 * in the method @method.
5701 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5703 static MonoClass *System_Reflection_ParameterInfo;
5704 MonoArray *res = NULL;
5705 MonoReflectionMethod *member = NULL;
5706 MonoReflectionParameter *param = NULL;
5707 char **names, **blobs = NULL;
5708 guint32 *types = NULL;
5709 MonoType *type = NULL;
5710 MonoObject *dbnull = mono_get_dbnull_object (domain);
5711 MonoMarshalSpec **mspecs;
5712 MonoMethodSignature *sig;
5715 if (!System_Reflection_ParameterInfo)
5716 System_Reflection_ParameterInfo = mono_class_from_name (
5717 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5719 if (!mono_method_signature (method)->param_count)
5720 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5722 /* Note: the cache is based on the address of the signature into the method
5723 * since we already cache MethodInfos with the method as keys.
5725 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5727 sig = mono_method_signature (method);
5728 member = mono_method_get_object (domain, method, NULL);
5729 names = g_new (char *, sig->param_count);
5730 mono_method_get_param_names (method, (const char **) names);
5732 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
5733 mono_method_get_marshal_info (method, mspecs);
5735 res = mono_array_new (domain, System_Reflection_ParameterInfo, sig->param_count);
5736 for (i = 0; i < sig->param_count; ++i) {
5737 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5738 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
5739 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5740 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5741 param->PositionImpl = i;
5742 param->AttrsImpl = sig->params [i]->attrs;
5744 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5745 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5749 blobs = g_new0 (char *, sig->param_count);
5750 types = g_new0 (guint32, sig->param_count);
5751 get_default_param_value_blobs (method, blobs, types);
5754 /* Build MonoType for the type from the Constant Table */
5756 type = g_new0 (MonoType, 1);
5757 type->type = types [i];
5758 type->data.klass = NULL;
5759 if (types [i] == MONO_TYPE_CLASS)
5760 type->data.klass = mono_defaults.object_class;
5761 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
5762 /* For enums, types [i] contains the base type */
5764 type->type = MONO_TYPE_VALUETYPE;
5765 type->data.klass = mono_class_from_mono_type (sig->params [i]);
5767 type->data.klass = mono_class_from_mono_type (type);
5769 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5771 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5772 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5773 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5778 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5780 mono_array_setref (res, i, param);
5787 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5789 mono_metadata_free_marshal_spec (mspecs [i]);
5792 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5796 * mono_method_body_get_object:
5797 * @domain: an app domain
5800 * Return an System.Reflection.MethodBody object representing the method @method.
5802 MonoReflectionMethodBody*
5803 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5805 static MonoClass *System_Reflection_MethodBody = NULL;
5806 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5807 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5808 MonoReflectionMethodBody *ret;
5809 MonoMethodNormal *mn;
5810 MonoMethodHeader *header;
5811 guint32 method_rva, local_var_sig_token;
5813 unsigned char format, flags;
5816 if (!System_Reflection_MethodBody)
5817 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5818 if (!System_Reflection_LocalVariableInfo)
5819 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5820 if (!System_Reflection_ExceptionHandlingClause)
5821 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5823 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5825 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5826 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5827 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5828 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5830 mn = (MonoMethodNormal *)method;
5831 header = mono_method_get_header (method);
5833 /* Obtain local vars signature token */
5834 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5835 ptr = mono_image_rva_map (method->klass->image, method_rva);
5836 flags = *(const unsigned char *) ptr;
5837 format = flags & METHOD_HEADER_FORMAT_MASK;
5839 case METHOD_HEADER_TINY_FORMAT:
5840 case METHOD_HEADER_TINY_FORMAT1:
5841 local_var_sig_token = 0;
5843 case METHOD_HEADER_FAT_FORMAT:
5847 local_var_sig_token = read32 (ptr);
5850 g_assert_not_reached ();
5853 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5855 ret->init_locals = header->init_locals;
5856 ret->max_stack = header->max_stack;
5857 ret->local_var_sig_token = local_var_sig_token;
5858 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5859 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5862 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5863 for (i = 0; i < header->num_locals; ++i) {
5864 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5865 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5866 info->is_pinned = header->locals [i]->pinned;
5867 info->local_index = i;
5868 mono_array_setref (ret->locals, i, info);
5872 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5873 for (i = 0; i < header->num_clauses; ++i) {
5874 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5875 MonoExceptionClause *clause = &header->clauses [i];
5877 info->flags = clause->flags;
5878 info->try_offset = clause->try_offset;
5879 info->try_length = clause->try_len;
5880 info->handler_offset = clause->handler_offset;
5881 info->handler_length = clause->handler_len;
5882 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5883 info->filter_offset = clause->data.filter_offset;
5884 else if (clause->data.catch_class)
5885 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5887 mono_array_setref (ret->clauses, i, info);
5890 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5895 mono_get_dbnull_object (MonoDomain *domain)
5898 static MonoClassField *dbnull_value_field = NULL;
5900 if (!dbnull_value_field) {
5901 MonoClass *dbnull_klass;
5902 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5903 mono_class_init (dbnull_klass);
5904 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
5905 g_assert (dbnull_value_field);
5907 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5914 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5916 guint32 param_index, i, lastp, crow = 0;
5917 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5920 MonoClass *klass = method->klass;
5921 MonoImage *image = klass->image;
5922 MonoMethodSignature *methodsig = mono_method_signature (method);
5924 MonoTableInfo *constt;
5925 MonoTableInfo *methodt;
5926 MonoTableInfo *paramt;
5928 if (!methodsig->param_count)
5931 mono_class_init (klass);
5933 if (klass->image->dynamic) {
5934 MonoReflectionMethodAux *aux;
5935 if (method->is_inflated)
5936 method = ((MonoMethodInflated*)method)->declaring;
5937 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5938 if (aux && aux->param_defaults) {
5939 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5940 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5945 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5946 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5947 constt = &image->tables [MONO_TABLE_CONSTANT];
5949 idx = mono_method_get_index (method) - 1;
5950 g_assert (idx != -1);
5952 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5953 if (idx + 1 < methodt->rows)
5954 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5956 lastp = paramt->rows + 1;
5958 for (i = param_index; i < lastp; ++i) {
5961 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5962 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5964 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5967 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5972 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5973 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5974 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5981 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5986 MonoType *basetype = type;
5991 klass = mono_class_from_mono_type (type);
5992 if (klass->valuetype) {
5993 object = mono_object_new (domain, klass);
5994 retval = ((gchar *) object + sizeof (MonoObject));
5995 if (klass->enumtype)
5996 basetype = klass->enum_basetype;
6001 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6008 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6012 memset (assembly, 0, sizeof (MonoAssemblyName));
6014 assembly->culture = "";
6015 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6017 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6020 while (g_ascii_isspace (*p) || *p == ',') {
6029 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6031 assembly->major = strtoul (p, &s, 10);
6032 if (s == p || *s != '.')
6035 assembly->minor = strtoul (p, &s, 10);
6036 if (s == p || *s != '.')
6039 assembly->build = strtoul (p, &s, 10);
6040 if (s == p || *s != '.')
6043 assembly->revision = strtoul (p, &s, 10);
6047 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6049 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6050 assembly->culture = "";
6053 assembly->culture = p;
6054 while (*p && *p != ',') {
6058 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6060 if (strncmp (p, "null", 4) == 0) {
6065 while (*p && *p != ',') {
6068 len = (p - start + 1);
6069 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6070 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6071 g_strlcpy ((char*)assembly->public_key_token, start, len);
6074 while (*p && *p != ',')
6078 while (g_ascii_isspace (*p) || *p == ',') {
6092 * mono_reflection_parse_type:
6095 * Parse a type name as accepted by the GetType () method and output the info
6096 * extracted in the info structure.
6097 * the name param will be mangled, so, make a copy before passing it to this function.
6098 * The fields in info will be valid until the memory pointed to by name is valid.
6100 * See also mono_type_get_name () below.
6102 * Returns: 0 on parse error.
6105 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6106 MonoTypeNameParse *info)
6108 char *start, *p, *w, *temp, *last_point, *startn;
6109 int in_modifiers = 0;
6110 int isbyref = 0, rank, arity = 0, i;
6112 start = p = w = name;
6114 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6115 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6116 info->name = info->name_space = NULL;
6117 info->nested = NULL;
6118 info->modifiers = NULL;
6119 info->type_arguments = NULL;
6121 /* last_point separates the namespace from the name */
6127 *p = 0; /* NULL terminate the name */
6129 info->nested = g_list_append (info->nested, startn);
6130 /* we have parsed the nesting namespace + name */
6134 info->name_space = start;
6136 info->name = last_point + 1;
6138 info->name_space = (char *)"";
6157 i = strtol (p, &temp, 10);
6174 info->name_space = start;
6176 info->name = last_point + 1;
6178 info->name_space = (char *)"";
6185 if (isbyref) /* only one level allowed by the spec */
6188 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6192 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6198 info->type_arguments = g_ptr_array_new ();
6199 for (i = 0; i < arity; i++) {
6200 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6201 gboolean fqname = FALSE;
6203 g_ptr_array_add (info->type_arguments, subinfo);
6210 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6221 while (*p && (*p != ']'))
6229 if (g_ascii_isspace (*aname)) {
6236 !assembly_name_to_aname (&subinfo->assembly, aname))
6240 if (i + 1 < arity) {
6260 else if (*p != '*') /* '*' means unknown lower bound */
6266 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6277 if (g_ascii_isspace (*p)) {
6284 return 0; /* missing assembly name */
6285 if (!assembly_name_to_aname (&info->assembly, p))
6291 if (info->assembly.name)
6294 // *w = 0; /* terminate class name */
6296 if (!info->name || !*info->name)
6300 /* add other consistency checks */
6305 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6307 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6311 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6313 gboolean type_resolve = FALSE;
6315 MonoImage *rootimage = image;
6317 if (info->assembly.name) {
6318 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6320 /* then we must load the assembly ourselve - see #60439 */
6321 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6325 image = assembly->image;
6326 } else if (!image) {
6327 image = mono_defaults.corlib;
6330 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6331 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6332 image = mono_defaults.corlib;
6333 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6340 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6347 image = mono_defaults.corlib;
6350 klass = mono_class_from_name_case (image, info->name_space, info->name);
6352 klass = mono_class_from_name (image, info->name_space, info->name);
6355 for (mod = info->nested; mod; mod = mod->next) {
6358 mono_class_init (klass);
6359 nested = klass->nested_classes;
6362 klass = nested->data;
6364 if (g_strcasecmp (klass->name, mod->data) == 0)
6367 if (strcmp (klass->name, mod->data) == 0)
6371 nested = nested->next;
6378 mono_class_init (klass);
6380 if (info->type_arguments) {
6381 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6382 MonoReflectionType *the_type;
6386 for (i = 0; i < info->type_arguments->len; i++) {
6387 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6389 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
6390 if (!type_args [i]) {
6396 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6398 instance = mono_reflection_bind_generic_parameters (
6399 the_type, info->type_arguments->len, type_args);
6405 klass = mono_class_from_mono_type (instance);
6408 for (mod = info->modifiers; mod; mod = mod->next) {
6409 modval = GPOINTER_TO_UINT (mod->data);
6410 if (!modval) { /* byref: must be last modifier */
6411 return &klass->this_arg;
6412 } else if (modval == -1) {
6413 klass = mono_ptr_class_get (&klass->byval_arg);
6414 } else { /* array rank */
6415 klass = mono_array_class_get (klass, modval);
6417 mono_class_init (klass);
6420 return &klass->byval_arg;
6424 * mono_reflection_get_type:
6425 * @image: a metadata context
6426 * @info: type description structure
6427 * @ignorecase: flag for case-insensitive string compares
6428 * @type_resolve: whenever type resolve was already tried
6430 * Build a MonoType from the type description in @info.
6435 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
6436 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
6440 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
6442 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
6446 g_assert (assembly->dynamic);
6448 /* Enumerate all modules */
6451 if (abuilder->modules) {
6452 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6453 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6454 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
6460 if (!type && abuilder->loaded_modules) {
6461 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6462 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6463 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
6473 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6476 MonoReflectionAssembly *assembly;
6480 if (image && image->dynamic)
6481 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
6483 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
6486 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6493 *type_resolve = TRUE;
6496 /* Reconstruct the type name */
6497 fullName = g_string_new ("");
6498 if (info->name_space && (info->name_space [0] != '\0'))
6499 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6501 g_string_printf (fullName, info->name);
6502 for (mod = info->nested; mod; mod = mod->next)
6503 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6505 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6507 if (assembly->assembly->dynamic)
6508 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
6510 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
6513 g_string_free (fullName, TRUE);
6518 mono_reflection_free_type_info (MonoTypeNameParse *info)
6520 g_list_free (info->modifiers);
6521 g_list_free (info->nested);
6523 if (info->type_arguments) {
6526 for (i = 0; i < info->type_arguments->len; i++) {
6527 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6529 mono_reflection_free_type_info (subinfo);
6530 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
6534 g_ptr_array_free (info->type_arguments, TRUE);
6539 * mono_reflection_type_from_name:
6541 * @image: a metadata context (can be NULL).
6543 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6544 * it defaults to get the type from @image or, if @image is NULL or loading
6545 * from it fails, uses corlib.
6549 mono_reflection_type_from_name (char *name, MonoImage *image)
6551 MonoType *type = NULL;
6552 MonoTypeNameParse info;
6555 /* Make a copy since parse_type modifies its argument */
6556 tmp = g_strdup (name);
6558 /*g_print ("requested type %s\n", str);*/
6559 if (mono_reflection_parse_type (tmp, &info)) {
6560 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6564 mono_reflection_free_type_info (&info);
6569 * mono_reflection_get_token:
6571 * Return the metadata token of OBJ which should be an object
6572 * representing a metadata element.
6575 mono_reflection_get_token (MonoObject *obj)
6580 klass = obj->vtable->klass;
6582 if (strcmp (klass->name, "MethodBuilder") == 0) {
6583 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6585 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6586 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6587 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6589 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6590 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6591 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6592 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6593 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6594 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6595 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6596 } else if (strcmp (klass->name, "MonoType") == 0) {
6597 MonoReflectionType *tb = (MonoReflectionType *)obj;
6598 token = mono_class_from_mono_type (tb->type)->type_token;
6599 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6600 strcmp (klass->name, "MonoMethod") == 0 ||
6601 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6602 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6603 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6604 if (m->method->is_inflated) {
6605 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6606 return inflated->declaring->token;
6608 token = m->method->token;
6610 } else if (strcmp (klass->name, "MonoField") == 0) {
6611 MonoReflectionField *f = (MonoReflectionField*)obj;
6613 if (f->field->generic_info && f->field->generic_info->reflection_info)
6614 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6616 token = mono_class_get_field_token (f->field);
6617 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6618 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6620 token = mono_class_get_property_token (p->property);
6621 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6622 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6624 token = mono_class_get_event_token (p->event);
6625 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6626 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6628 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6629 } else if (strcmp (klass->name, "Module") == 0) {
6630 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6633 } else if (strcmp (klass->name, "Assembly") == 0) {
6634 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6636 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6637 MonoException *ex = mono_get_exception_not_implemented (msg);
6639 mono_raise_exception (ex);
6646 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6648 int slen, type = t->type;
6649 MonoClass *tklass = t->data.klass;
6655 case MONO_TYPE_BOOLEAN: {
6656 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6661 case MONO_TYPE_CHAR:
6663 case MONO_TYPE_I2: {
6664 guint16 *val = g_malloc (sizeof (guint16));
6669 #if SIZEOF_VOID_P == 4
6675 case MONO_TYPE_I4: {
6676 guint32 *val = g_malloc (sizeof (guint32));
6681 #if SIZEOF_VOID_P == 8
6682 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6686 case MONO_TYPE_I8: {
6687 guint64 *val = g_malloc (sizeof (guint64));
6692 case MONO_TYPE_R8: {
6693 double *val = g_malloc (sizeof (double));
6698 case MONO_TYPE_VALUETYPE:
6699 if (t->data.klass->enumtype) {
6700 type = t->data.klass->enum_basetype->type;
6703 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6706 case MONO_TYPE_STRING:
6707 if (*p == (char)0xFF) {
6711 slen = mono_metadata_decode_value (p, &p);
6713 return mono_string_new_len (mono_domain_get (), p, slen);
6714 case MONO_TYPE_CLASS: {
6717 if (*p == (char)0xFF) {
6722 slen = mono_metadata_decode_value (p, &p);
6723 n = g_memdup (p, slen + 1);
6725 t = mono_reflection_type_from_name (n, image);
6727 g_warning ("Cannot load type '%s'", n);
6731 return mono_type_get_object (mono_domain_get (), t);
6735 case MONO_TYPE_OBJECT: {
6738 MonoClass *subc = NULL;
6743 } else if (subt == 0x0E) {
6744 type = MONO_TYPE_STRING;
6746 } else if (subt == 0x1D) {
6747 MonoType simple_type = {{0}};
6752 /* See Partition II, Appendix B3 */
6753 etype = MONO_TYPE_OBJECT;
6754 type = MONO_TYPE_SZARRAY;
6755 simple_type.type = etype;
6756 tklass = mono_class_from_mono_type (&simple_type);
6758 } else if (subt == 0x55) {
6761 slen = mono_metadata_decode_value (p, &p);
6762 n = g_memdup (p, slen + 1);
6764 t = mono_reflection_type_from_name (n, image);
6766 g_error ("Cannot load type '%s'", n);
6769 subc = mono_class_from_mono_type (t);
6770 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6771 MonoType simple_type = {{0}};
6772 simple_type.type = subt;
6773 subc = mono_class_from_mono_type (&simple_type);
6775 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6777 val = load_cattr_value (image, &subc->byval_arg, p, end);
6778 obj = mono_object_new (mono_domain_get (), subc);
6779 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6783 case MONO_TYPE_SZARRAY: {
6785 guint32 i, alen, basetype;
6788 if (alen == 0xffffffff) {
6792 arr = mono_array_new (mono_domain_get(), tklass, alen);
6793 basetype = tklass->byval_arg.type;
6794 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
6795 basetype = tklass->enum_basetype->type;
6800 case MONO_TYPE_BOOLEAN:
6801 for (i = 0; i < alen; i++) {
6802 MonoBoolean val = *p++;
6803 mono_array_set (arr, MonoBoolean, i, val);
6806 case MONO_TYPE_CHAR:
6809 for (i = 0; i < alen; i++) {
6810 guint16 val = read16 (p);
6811 mono_array_set (arr, guint16, i, val);
6818 for (i = 0; i < alen; i++) {
6819 guint32 val = read32 (p);
6820 mono_array_set (arr, guint32, i, val);
6825 for (i = 0; i < alen; i++) {
6828 mono_array_set (arr, double, i, val);
6834 for (i = 0; i < alen; i++) {
6835 guint64 val = read64 (p);
6836 mono_array_set (arr, guint64, i, val);
6840 case MONO_TYPE_CLASS:
6841 case MONO_TYPE_OBJECT:
6842 case MONO_TYPE_STRING:
6843 for (i = 0; i < alen; i++) {
6844 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6845 mono_array_setref (arr, i, item);
6849 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
6855 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6861 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6863 static MonoClass *klass;
6864 static MonoMethod *ctor;
6866 void *params [2], *unboxed;
6869 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6871 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6873 params [0] = mono_type_get_object (mono_domain_get (), t);
6875 retval = mono_object_new (mono_domain_get (), klass);
6876 unboxed = mono_object_unbox (retval);
6877 mono_runtime_invoke (ctor, unboxed, params, NULL);
6883 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6885 static MonoClass *klass;
6886 static MonoMethod *ctor;
6888 void *unboxed, *params [2];
6891 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6893 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6896 params [1] = typedarg;
6897 retval = mono_object_new (mono_domain_get (), klass);
6898 unboxed = mono_object_unbox (retval);
6899 mono_runtime_invoke (ctor, unboxed, params, NULL);
6905 type_is_reference (MonoType *type)
6907 switch (type->type) {
6908 case MONO_TYPE_BOOLEAN:
6909 case MONO_TYPE_CHAR:
6922 case MONO_TYPE_VALUETYPE:
6930 free_param_data (MonoMethodSignature *sig, void **params) {
6932 for (i = 0; i < sig->param_count; ++i) {
6933 if (!type_is_reference (sig->params [i]))
6934 g_free (params [i]);
6939 * Find the field index in the metadata FieldDef table.
6942 find_field_index (MonoClass *klass, MonoClassField *field) {
6945 for (i = 0; i < klass->field.count; ++i) {
6946 if (field == &klass->fields [i])
6947 return klass->field.first + 1 + i;
6953 * Find the property index in the metadata Property table.
6956 find_property_index (MonoClass *klass, MonoProperty *property) {
6959 for (i = 0; i < klass->property.count; ++i) {
6960 if (property == &klass->properties [i])
6961 return klass->property.first + 1 + i;
6967 * Find the event index in the metadata Event table.
6970 find_event_index (MonoClass *klass, MonoEvent *event) {
6973 for (i = 0; i < klass->event.count; ++i) {
6974 if (event == &klass->events [i])
6975 return klass->event.first + 1 + i;
6981 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
6983 const char *p = (const char*)data;
6985 guint32 i, j, num_named;
6989 mono_class_init (method->klass);
6992 attr = mono_object_new (mono_domain_get (), method->klass);
6993 mono_runtime_invoke (method, attr, NULL, NULL);
6997 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7000 /*g_print ("got attr %s\n", method->klass->name);*/
7002 /* Allocate using alloca so it gets GC tracking */
7003 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7007 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7008 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7012 attr = mono_object_new (mono_domain_get (), method->klass);
7013 mono_runtime_invoke (method, attr, params, NULL);
7014 free_param_data (method->signature, params);
7015 num_named = read16 (named);
7017 for (j = 0; j < num_named; j++) {
7019 char *name, named_type, data_type;
7020 named_type = *named++;
7021 data_type = *named++; /* type of data */
7022 if (data_type == MONO_TYPE_SZARRAY)
7023 data_type = *named++;
7024 if (data_type == MONO_TYPE_ENUM) {
7027 type_len = mono_metadata_decode_blob_size (named, &named);
7028 type_name = g_malloc (type_len + 1);
7029 memcpy (type_name, named, type_len);
7030 type_name [type_len] = 0;
7032 /* FIXME: lookup the type and check type consistency */
7035 name_len = mono_metadata_decode_blob_size (named, &named);
7036 name = g_malloc (name_len + 1);
7037 memcpy (name, named, name_len);
7038 name [name_len] = 0;
7040 if (named_type == 0x53) {
7041 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7042 void *val = load_cattr_value (image, field->type, named, &named);
7043 mono_field_set_value (attr, field, val);
7044 if (!type_is_reference (field->type))
7046 } else if (named_type == 0x54) {
7049 MonoType *prop_type;
7051 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7052 /* can we have more that 1 arg in a custom attr named property? */
7053 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7054 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7055 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7056 mono_property_set_value (prop, attr, pparams, NULL);
7057 if (!type_is_reference (prop_type))
7058 g_free (pparams [0]);
7067 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7069 MonoArray *typedargs, *namedargs;
7070 MonoClass *attrklass;
7071 static MonoMethod *ctor;
7074 const char *p = (const char*)data;
7076 guint32 i, j, num_named;
7079 mono_class_init (method->klass);
7082 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7084 domain = mono_domain_get ();
7086 /* This is for Attributes with no parameters */
7087 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7088 params [0] = mono_method_get_object (domain, method, NULL);
7089 params [1] = params [2] = NULL;
7090 mono_runtime_invoke (method, attr, params, NULL);
7094 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7097 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7101 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7102 MonoObject *obj, *typedarg;
7105 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7106 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7107 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7108 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7109 mono_array_setref (typedargs, i, typedarg);
7111 if (!type_is_reference (mono_method_signature (method)->params [i]))
7116 num_named = read16 (named);
7117 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7119 attrklass = method->klass;
7120 for (j = 0; j < num_named; j++) {
7122 char *name, named_type, data_type;
7123 named_type = *named++;
7124 data_type = *named++; /* type of data */
7125 if (data_type == MONO_TYPE_SZARRAY)
7126 data_type = *named++;
7127 if (data_type == MONO_TYPE_ENUM) {
7130 type_len = mono_metadata_decode_blob_size (named, &named);
7131 type_name = g_malloc (type_len + 1);
7132 memcpy (type_name, named, type_len);
7133 type_name [type_len] = 0;
7135 /* FIXME: lookup the type and check type consistency */
7138 name_len = mono_metadata_decode_blob_size (named, &named);
7139 name = g_malloc (name_len + 1);
7140 memcpy (name, named, name_len);
7141 name [name_len] = 0;
7143 if (named_type == 0x53) {
7144 MonoObject *obj, *typedarg, *namedarg;
7145 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7146 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7148 minfo = mono_field_get_object (domain, NULL, field);
7149 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7150 typedarg = create_cattr_typed_arg (field->type, obj);
7151 namedarg = create_cattr_named_arg (minfo, typedarg);
7152 mono_array_setref (namedargs, j, namedarg);
7153 if (!type_is_reference (field->type))
7155 } else if (named_type == 0x54) {
7156 MonoObject *obj, *typedarg, *namedarg;
7157 MonoType *prop_type;
7159 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7161 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7162 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7163 minfo = mono_property_get_object (domain, NULL, prop);
7164 val = load_cattr_value (image, prop_type, named, &named);
7165 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7166 typedarg = create_cattr_typed_arg (prop_type, obj);
7167 namedarg = create_cattr_named_arg (minfo, typedarg);
7168 mono_array_setref (namedargs, j, namedarg);
7169 if (!type_is_reference (prop_type))
7174 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7175 params [0] = mono_method_get_object (domain, method, NULL);
7176 params [1] = typedargs;
7177 params [2] = namedargs;
7178 mono_runtime_invoke (ctor, attr, params, NULL);
7183 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7189 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7190 for (i = 0; i < cinfo->num_attrs; ++i) {
7191 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7192 mono_array_setref (result, i, attr);
7198 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7205 for (i = 0; i < cinfo->num_attrs; ++i) {
7206 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7210 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7212 for (i = 0; i < cinfo->num_attrs; ++i) {
7213 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7214 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7215 mono_array_setref (result, n, attr);
7223 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7229 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7230 for (i = 0; i < cinfo->num_attrs; ++i) {
7231 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7232 mono_array_setref (result, i, attr);
7238 * mono_custom_attrs_from_index:
7240 * Returns: NULL if no attributes are found or if a loading error occurs.
7243 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7245 guint32 mtoken, i, len;
7246 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7248 MonoCustomAttrInfo *ainfo;
7249 GList *tmp, *list = NULL;
7252 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7254 i = mono_metadata_custom_attrs_from_index (image, idx);
7258 while (i < ca->rows) {
7259 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7261 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7264 len = g_list_length (list);
7267 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7268 ainfo->num_attrs = len;
7269 ainfo->image = image;
7270 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7271 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7272 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7273 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7274 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7275 mtoken |= MONO_TOKEN_METHOD_DEF;
7277 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7278 mtoken |= MONO_TOKEN_MEMBER_REF;
7281 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7284 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7285 if (!ainfo->attrs [i].ctor) {
7286 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7291 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7292 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7293 ainfo->attrs [i].data = (guchar*)data;
7301 mono_custom_attrs_from_method (MonoMethod *method)
7303 MonoCustomAttrInfo *cinfo;
7306 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (method)))
7308 idx = mono_method_get_index (method);
7309 idx <<= MONO_CUSTOM_ATTR_BITS;
7310 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7311 return mono_custom_attrs_from_index (method->klass->image, idx);
7315 mono_custom_attrs_from_class (MonoClass *klass)
7317 MonoCustomAttrInfo *cinfo;
7320 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (klass)))
7322 idx = mono_metadata_token_index (klass->type_token);
7323 idx <<= MONO_CUSTOM_ATTR_BITS;
7324 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7325 return mono_custom_attrs_from_index (klass->image, idx);
7329 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7331 MonoCustomAttrInfo *cinfo;
7334 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (assembly)))
7336 idx = 1; /* there is only one assembly */
7337 idx <<= MONO_CUSTOM_ATTR_BITS;
7338 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7339 return mono_custom_attrs_from_index (assembly->image, idx);
7342 static MonoCustomAttrInfo*
7343 mono_custom_attrs_from_module (MonoImage *image)
7345 MonoCustomAttrInfo *cinfo;
7348 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (image)))
7350 idx = 1; /* there is only one module */
7351 idx <<= MONO_CUSTOM_ATTR_BITS;
7352 idx |= MONO_CUSTOM_ATTR_MODULE;
7353 return mono_custom_attrs_from_index (image, idx);
7357 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7359 MonoCustomAttrInfo *cinfo;
7362 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (property)))
7364 idx = find_property_index (klass, property);
7365 idx <<= MONO_CUSTOM_ATTR_BITS;
7366 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7367 return mono_custom_attrs_from_index (klass->image, idx);
7371 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7373 MonoCustomAttrInfo *cinfo;
7376 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (event)))
7378 idx = find_event_index (klass, event);
7379 idx <<= MONO_CUSTOM_ATTR_BITS;
7380 idx |= MONO_CUSTOM_ATTR_EVENT;
7381 return mono_custom_attrs_from_index (klass->image, idx);
7385 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7387 MonoCustomAttrInfo *cinfo;
7390 if (dynamic_custom_attrs && (cinfo = lookup_custom_attr (field)))
7392 idx = find_field_index (klass, field);
7393 idx <<= MONO_CUSTOM_ATTR_BITS;
7394 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7395 return mono_custom_attrs_from_index (klass->image, idx);
7399 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7402 guint32 i, idx, method_index;
7403 guint32 param_list, param_last, param_pos, found;
7405 MonoReflectionMethodAux *aux;
7407 if (method->klass->image->dynamic) {
7408 MonoCustomAttrInfo *res, *ainfo;
7411 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7412 if (!aux || !aux->param_cattr)
7415 /* Need to copy since it will be freed later */
7416 ainfo = aux->param_cattr [param];
7417 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
7418 res = g_malloc0 (size);
7419 memcpy (res, ainfo, size);
7423 image = method->klass->image;
7424 method_index = mono_method_get_index (method);
7425 ca = &image->tables [MONO_TABLE_METHOD];
7427 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7428 if (method_index == ca->rows) {
7429 ca = &image->tables [MONO_TABLE_PARAM];
7430 param_last = ca->rows + 1;
7432 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7433 ca = &image->tables [MONO_TABLE_PARAM];
7436 for (i = param_list; i < param_last; ++i) {
7437 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7438 if (param_pos == param) {
7446 idx <<= MONO_CUSTOM_ATTR_BITS;
7447 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7448 return mono_custom_attrs_from_index (image, idx);
7452 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7456 for (i = 0; i < ainfo->num_attrs; ++i) {
7457 klass = ainfo->attrs [i].ctor->klass;
7458 if (mono_class_has_parent (klass, attr_klass))
7465 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7472 for (i = 0; i < ainfo->num_attrs; ++i) {
7473 klass = ainfo->attrs [i].ctor->klass;
7474 if (mono_class_has_parent (klass, attr_klass)) {
7479 if (attr_index == -1)
7482 attrs = mono_custom_attrs_construct (ainfo);
7484 return mono_array_get (attrs, MonoObject*, attr_index);
7490 * mono_reflection_get_custom_attrs_info:
7491 * @obj: a reflection object handle
7493 * Return the custom attribute info for attributes defined for the
7494 * reflection handle @obj. The objects.
7497 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7500 MonoCustomAttrInfo *cinfo = NULL;
7502 klass = obj->vtable->klass;
7503 if (klass == mono_defaults.monotype_class) {
7504 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7505 klass = mono_class_from_mono_type (rtype->type);
7506 cinfo = mono_custom_attrs_from_class (klass);
7507 } else if (strcmp ("Assembly", klass->name) == 0) {
7508 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7509 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7510 } else if (strcmp ("Module", klass->name) == 0) {
7511 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7512 cinfo = mono_custom_attrs_from_module (module->image);
7513 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7514 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7515 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7516 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7517 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7518 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7519 } else if (strcmp ("MonoField", klass->name) == 0) {
7520 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7521 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7522 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7523 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7524 cinfo = mono_custom_attrs_from_method (rmethod->method);
7525 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7526 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7527 cinfo = mono_custom_attrs_from_method (rmethod->method);
7528 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7529 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7530 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7531 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7532 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7533 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7534 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7535 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7537 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7538 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7539 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7540 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7541 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7542 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7543 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7544 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7545 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7546 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7547 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7548 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7549 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7550 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
7551 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
7552 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
7553 } else { /* handle other types here... */
7554 g_error ("get custom attrs not yet supported for %s", klass->name);
7561 * mono_reflection_get_custom_attrs_by_type:
7562 * @obj: a reflection object handle
7564 * Return an array with all the custom attributes defined of the
7565 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7566 * of that type are returned. The objects are fully build. Return NULL if a loading error
7570 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7573 MonoCustomAttrInfo *cinfo;
7575 cinfo = mono_reflection_get_custom_attrs_info (obj);
7578 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7580 result = mono_custom_attrs_construct (cinfo);
7582 mono_custom_attrs_free (cinfo);
7584 if (mono_loader_get_last_error ())
7586 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
7593 * mono_reflection_get_custom_attrs:
7594 * @obj: a reflection object handle
7596 * Return an array with all the custom attributes defined of the
7597 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
7601 mono_reflection_get_custom_attrs (MonoObject *obj)
7603 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7607 * mono_reflection_get_custom_attrs_data:
7608 * @obj: a reflection obj handle
7610 * Returns an array of System.Reflection.CustomAttributeData,
7611 * which include information about attributes reflected on
7612 * types loaded using the Reflection Only methods
7615 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7618 MonoCustomAttrInfo *cinfo;
7620 cinfo = mono_reflection_get_custom_attrs_info (obj);
7622 result = mono_custom_attrs_data_construct (cinfo);
7624 mono_custom_attrs_free (cinfo);
7626 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
7631 static MonoReflectionType*
7632 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
7634 MonoMethod *method_get_underlying_system_type;
7636 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
7637 mono_class_get_method_from_name (mono_object_class (t),
7638 "get_UnderlyingSystemType",
7640 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
7644 mono_reflection_type_get_handle (MonoReflectionType* t)
7649 t = mono_reflection_type_get_underlying_system_type (t);
7657 * LOCKING: Assumes the loader lock is held.
7659 static MonoMethodSignature*
7660 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
7661 MonoMethodSignature *sig;
7664 count = parameters? mono_array_length (parameters): 0;
7666 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7667 sig->param_count = count;
7668 sig->sentinelpos = -1; /* FIXME */
7669 for (i = 0; i < count; ++i) {
7670 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7671 sig->params [i] = mono_reflection_type_get_handle (pt);
7677 * LOCKING: Assumes the loader lock is held.
7679 static MonoMethodSignature*
7680 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
7681 MonoMethodSignature *sig;
7683 sig = parameters_to_signature (mp, ctor->parameters);
7684 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7685 sig->ret = &mono_defaults.void_class->byval_arg;
7690 * LOCKING: Assumes the loader lock is held.
7692 static MonoMethodSignature*
7693 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
7694 MonoMethodSignature *sig;
7696 sig = parameters_to_signature (mp, method->parameters);
7697 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7698 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7699 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7703 static MonoMethodSignature*
7704 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7705 MonoMethodSignature *sig;
7707 sig = parameters_to_signature (NULL, method->parameters);
7708 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7709 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7710 sig->generic_param_count = 0;
7715 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7717 MonoClass *klass = mono_object_class (prop);
7718 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7719 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7720 *name = mono_string_to_utf8 (pb->name);
7721 *type = pb->type->type;
7723 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7724 *name = g_strdup (p->property->name);
7725 if (p->property->get)
7726 *type = mono_method_signature (p->property->get)->ret;
7728 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7733 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7735 MonoClass *klass = mono_object_class (field);
7736 if (strcmp (klass->name, "FieldBuilder") == 0) {
7737 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7738 *name = mono_string_to_utf8 (fb->name);
7739 *type = fb->type->type;
7741 MonoReflectionField *f = (MonoReflectionField *)field;
7742 *name = g_strdup (f->field->name);
7743 *type = f->field->type;
7748 * Encode a value in a custom attribute stream of bytes.
7749 * The value to encode is either supplied as an object in argument val
7750 * (valuetypes are boxed), or as a pointer to the data in the
7752 * @type represents the type of the value
7753 * @buffer is the start of the buffer
7754 * @p the current position in the buffer
7755 * @buflen contains the size of the buffer and is used to return the new buffer size
7756 * if this needs to be realloced.
7757 * @retbuffer and @retp return the start and the position of the buffer
7760 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7762 MonoTypeEnum simple_type;
7764 if ((p-buffer) + 10 >= *buflen) {
7767 newbuf = g_realloc (buffer, *buflen);
7768 p = newbuf + (p-buffer);
7772 argval = ((char*)arg + sizeof (MonoObject));
7773 simple_type = type->type;
7775 switch (simple_type) {
7776 case MONO_TYPE_BOOLEAN:
7781 case MONO_TYPE_CHAR:
7784 swap_with_size (p, argval, 2, 1);
7790 swap_with_size (p, argval, 4, 1);
7794 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
7804 swap_with_size (p, argval, 8, 1);
7810 swap_with_size (p, argval, 8, 1);
7813 case MONO_TYPE_VALUETYPE:
7814 if (type->data.klass->enumtype) {
7815 simple_type = type->data.klass->enum_basetype->type;
7818 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7821 case MONO_TYPE_STRING: {
7828 str = mono_string_to_utf8 ((MonoString*)arg);
7829 slen = strlen (str);
7830 if ((p-buffer) + 10 + slen >= *buflen) {
7834 newbuf = g_realloc (buffer, *buflen);
7835 p = newbuf + (p-buffer);
7838 mono_metadata_encode_value (slen, p, &p);
7839 memcpy (p, str, slen);
7844 case MONO_TYPE_CLASS: {
7852 k = mono_object_class (arg);
7853 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7854 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
7855 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
7858 if (rt && (rtc = mono_object_class (rt)) &&
7859 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
7860 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
7861 arg = (MonoObject *) rt;
7864 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
7867 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7868 slen = strlen (str);
7869 if ((p-buffer) + 10 + slen >= *buflen) {
7873 newbuf = g_realloc (buffer, *buflen);
7874 p = newbuf + (p-buffer);
7877 mono_metadata_encode_value (slen, p, &p);
7878 memcpy (p, str, slen);
7883 case MONO_TYPE_SZARRAY: {
7885 MonoClass *eclass, *arg_eclass;
7888 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7891 len = mono_array_length ((MonoArray*)arg);
7893 *p++ = (len >> 8) & 0xff;
7894 *p++ = (len >> 16) & 0xff;
7895 *p++ = (len >> 24) & 0xff;
7897 *retbuffer = buffer;
7898 eclass = type->data.klass;
7899 arg_eclass = mono_object_class (arg)->element_class;
7902 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7903 eclass = mono_defaults.object_class;
7905 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7906 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7907 int elsize = mono_class_array_element_size (arg_eclass);
7908 for (i = 0; i < len; ++i) {
7909 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7912 } else if (eclass->valuetype && arg_eclass->valuetype) {
7913 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7914 int elsize = mono_class_array_element_size (eclass);
7915 for (i = 0; i < len; ++i) {
7916 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7920 for (i = 0; i < len; ++i) {
7921 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7926 case MONO_TYPE_OBJECT: {
7932 * The parameter type is 'object' but the type of the actual
7933 * argument is not. So we have to add type information to the blob
7934 * too. This is completely undocumented in the spec.
7938 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7943 klass = mono_object_class (arg);
7945 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7948 } else if (klass->enumtype) {
7950 } else if (klass == mono_defaults.string_class) {
7951 simple_type = MONO_TYPE_STRING;
7954 } else if (klass->rank == 1) {
7956 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
7957 /* See Partition II, Appendix B3 */
7960 *p++ = klass->element_class->byval_arg.type;
7961 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
7963 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7964 *p++ = simple_type = klass->byval_arg.type;
7967 g_error ("unhandled type in custom attr");
7969 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7970 slen = strlen (str);
7971 if ((p-buffer) + 10 + slen >= *buflen) {
7975 newbuf = g_realloc (buffer, *buflen);
7976 p = newbuf + (p-buffer);
7979 mono_metadata_encode_value (slen, p, &p);
7980 memcpy (p, str, slen);
7983 simple_type = klass->enum_basetype->type;
7987 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7990 *retbuffer = buffer;
7994 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
7996 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7997 char *str = type_get_qualified_name (type, NULL);
7998 int slen = strlen (str);
8002 * This seems to be optional...
8005 mono_metadata_encode_value (slen, p, &p);
8006 memcpy (p, str, slen);
8009 } else if (type->type == MONO_TYPE_OBJECT) {
8011 } else if (type->type == MONO_TYPE_CLASS) {
8012 /* it should be a type: encode_cattr_value () has the check */
8015 mono_metadata_encode_value (type->type, p, &p);
8016 if (type->type == MONO_TYPE_SZARRAY)
8017 /* See the examples in Partition VI, Annex B */
8018 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8025 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8028 /* Preallocate a large enough buffer */
8029 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8030 char *str = type_get_qualified_name (type, NULL);
8033 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8034 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8040 len += strlen (name);
8042 if ((p-buffer) + 20 + len >= *buflen) {
8046 newbuf = g_realloc (buffer, *buflen);
8047 p = newbuf + (p-buffer);
8051 encode_field_or_prop_type (type, p, &p);
8053 len = strlen (name);
8054 mono_metadata_encode_value (len, p, &p);
8055 memcpy (p, name, len);
8057 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8059 *retbuffer = buffer;
8063 * mono_reflection_get_custom_attrs_blob:
8064 * @ctor: custom attribute constructor
8065 * @ctorArgs: arguments o the constructor
8071 * Creates the blob of data that needs to be saved in the metadata and that represents
8072 * the custom attributed described by @ctor, @ctorArgs etc.
8073 * Returns: a Byte array representing the blob of data.
8076 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8079 MonoMethodSignature *sig;
8084 MONO_ARCH_SAVE_REGS;
8086 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8087 /* sig is freed later so allocate it in the heap */
8088 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8090 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8093 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8095 p = buffer = g_malloc (buflen);
8096 /* write the prolog */
8099 for (i = 0; i < sig->param_count; ++i) {
8100 arg = mono_array_get (ctorArgs, MonoObject*, i);
8101 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8105 i += mono_array_length (properties);
8107 i += mono_array_length (fields);
8109 *p++ = (i >> 8) & 0xff;
8112 for (i = 0; i < mono_array_length (properties); ++i) {
8116 prop = mono_array_get (properties, gpointer, i);
8117 get_prop_name_and_type (prop, &pname, &ptype);
8118 *p++ = 0x54; /* PROPERTY signature */
8119 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8126 for (i = 0; i < mono_array_length (fields); ++i) {
8130 field = mono_array_get (fields, gpointer, i);
8131 get_field_name_and_type (field, &fname, &ftype);
8132 *p++ = 0x53; /* FIELD signature */
8133 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8138 g_assert (p - buffer <= buflen);
8139 buflen = p - buffer;
8140 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8141 p = mono_array_addr (result, char, 0);
8142 memcpy (p, buffer, buflen);
8144 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8150 static void* reflection_info_desc = NULL;
8151 #define MOVING_GC_REGISTER(addr) do { \
8152 if (!reflection_info_desc) { \
8154 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8156 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8159 #define MOVING_GC_REGISTER(addr)
8163 * mono_reflection_setup_internal_class:
8164 * @tb: a TypeBuilder object
8166 * Creates a MonoClass that represents the TypeBuilder.
8167 * This is a trick that lets us simplify a lot of reflection code
8168 * (and will allow us to support Build and Run assemblies easier).
8171 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8173 MonoClass *klass, *parent;
8175 MONO_ARCH_SAVE_REGS;
8177 mono_loader_lock ();
8180 /* check so we can compile corlib correctly */
8181 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8182 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8183 parent = tb->parent->type->data.klass;
8185 parent = my_mono_class_from_mono_type (tb->parent->type);
8191 /* the type has already being created: it means we just have to change the parent */
8192 if (tb->type.type) {
8193 klass = mono_class_from_mono_type (tb->type.type);
8194 klass->parent = NULL;
8195 /* fool mono_class_setup_parent */
8196 klass->supertypes = NULL;
8197 mono_class_setup_parent (klass, parent);
8198 mono_class_setup_mono_type (klass);
8199 mono_loader_unlock ();
8203 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8205 klass->image = &tb->module->dynamic_image->image;
8207 klass->inited = 1; /* we lie to the runtime */
8208 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8209 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8210 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8211 klass->flags = tb->attrs;
8213 klass->element_class = klass;
8215 MOVING_GC_REGISTER (&klass->reflection_info);
8216 klass->reflection_info = tb;
8218 /* Put into cache so mono_class_get () will find it */
8219 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8221 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8222 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8224 if (parent != NULL) {
8225 mono_class_setup_parent (klass, parent);
8226 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8227 const char *old_n = klass->name;
8228 /* trick to get relative numbering right when compiling corlib */
8229 klass->name = "BuildingObject";
8230 mono_class_setup_parent (klass, mono_defaults.object_class);
8231 klass->name = old_n;
8234 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8235 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8236 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8237 klass->instance_size = sizeof (MonoObject);
8238 klass->size_inited = 1;
8239 mono_class_setup_vtable_general (klass, NULL, 0);
8242 mono_class_setup_mono_type (klass);
8244 mono_class_setup_supertypes (klass);
8247 * FIXME: handle interfaces.
8250 tb->type.type = &klass->byval_arg;
8252 if (tb->nesting_type) {
8253 g_assert (tb->nesting_type->type);
8254 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8257 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8259 mono_loader_unlock ();
8263 * mono_reflection_setup_generic_class:
8264 * @tb: a TypeBuilder object
8266 * Setup the generic class before adding the first generic parameter.
8269 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8273 MONO_ARCH_SAVE_REGS;
8275 klass = my_mono_class_from_mono_type (tb->type.type);
8276 if (tb->generic_container)
8279 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8280 tb->generic_container->owner.klass = klass;
8284 * mono_reflection_create_generic_class:
8285 * @tb: a TypeBuilder object
8287 * Creates the generic class after all generic parameters have been added.
8290 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8295 MONO_ARCH_SAVE_REGS;
8297 klass = my_mono_class_from_mono_type (tb->type.type);
8299 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8301 if (klass->generic_container || (count == 0))
8304 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8306 klass->generic_container = tb->generic_container;
8308 klass->generic_container->type_argc = count;
8309 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8311 for (i = 0; i < count; i++) {
8312 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8313 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8314 g_assert (klass->generic_container->type_params [i].owner);
8317 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8321 * mono_reflection_create_internal_class:
8322 * @tb: a TypeBuilder object
8324 * Actually create the MonoClass that is associated with the TypeBuilder.
8327 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8331 MONO_ARCH_SAVE_REGS;
8333 klass = my_mono_class_from_mono_type (tb->type.type);
8335 mono_loader_lock ();
8336 if (klass->enumtype && klass->enum_basetype == NULL) {
8337 MonoReflectionFieldBuilder *fb;
8340 g_assert (tb->fields != NULL);
8341 g_assert (mono_array_length (tb->fields) >= 1);
8343 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8345 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
8346 mono_loader_unlock ();
8350 klass->enum_basetype = fb->type->type;
8351 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8352 if (!klass->element_class)
8353 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8356 * get the element_class from the current corlib.
8358 ec = default_class_from_mono_type (klass->enum_basetype);
8359 klass->instance_size = ec->instance_size;
8360 klass->size_inited = 1;
8362 * this is almost safe to do with enums and it's needed to be able
8363 * to create objects of the enum type (for use in SetConstant).
8365 /* FIXME: Does this mean enums can't have method overrides ? */
8366 mono_class_setup_vtable_general (klass, NULL, 0);
8368 mono_loader_unlock ();
8371 static MonoMarshalSpec*
8372 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8373 MonoReflectionMarshal *minfo)
8375 MonoMarshalSpec *res;
8377 res = g_new0 (MonoMarshalSpec, 1);
8378 res->native = minfo->type;
8380 switch (minfo->type) {
8381 case MONO_NATIVE_LPARRAY:
8382 res->data.array_data.elem_type = minfo->eltype;
8383 if (minfo->has_size) {
8384 res->data.array_data.param_num = minfo->param_num;
8385 res->data.array_data.num_elem = minfo->count;
8386 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8389 res->data.array_data.param_num = -1;
8390 res->data.array_data.num_elem = -1;
8391 res->data.array_data.elem_mult = -1;
8395 case MONO_NATIVE_BYVALTSTR:
8396 case MONO_NATIVE_BYVALARRAY:
8397 res->data.array_data.num_elem = minfo->count;
8400 case MONO_NATIVE_CUSTOM:
8401 if (minfo->marshaltyperef)
8402 res->data.custom_data.custom_name =
8403 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8405 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8415 MonoReflectionMarshal*
8416 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8417 MonoMarshalSpec *spec)
8419 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8420 MonoReflectionMarshal *minfo;
8423 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8424 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8425 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8426 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8429 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8430 minfo->type = spec->native;
8432 switch (minfo->type) {
8433 case MONO_NATIVE_LPARRAY:
8434 minfo->eltype = spec->data.array_data.elem_type;
8435 minfo->count = spec->data.array_data.num_elem;
8436 minfo->param_num = spec->data.array_data.param_num;
8439 case MONO_NATIVE_BYVALTSTR:
8440 case MONO_NATIVE_BYVALARRAY:
8441 minfo->count = spec->data.array_data.num_elem;
8444 case MONO_NATIVE_CUSTOM:
8445 if (spec->data.custom_data.custom_name) {
8446 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8448 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8450 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8452 if (spec->data.custom_data.cookie)
8453 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8464 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8465 ReflectionMethodBuilder *rmb,
8466 MonoMethodSignature *sig)
8469 MonoMethodNormal *pm;
8470 MonoMarshalSpec **specs;
8471 MonoReflectionMethodAux *method_aux;
8476 g_assert (!klass->generic_class);
8479 * Methods created using a MethodBuilder should have their memory allocated
8480 * inside the image mempool, while dynamic methods should have their memory
8483 dynamic = rmb->refs != NULL;
8484 mp = dynamic ? NULL : klass->image->mempool;
8486 mono_loader_lock ();
8488 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8489 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8490 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
8492 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
8494 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
8496 pm = (MonoMethodNormal*)m;
8498 m->dynamic = dynamic;
8500 m->flags = rmb->attrs;
8501 m->iflags = rmb->iattrs;
8502 m->name = mp_string_to_utf8 (mp, rmb->name);
8505 m->skip_visibility = rmb->skip_visibility;
8507 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8509 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8510 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8513 m->signature->pinvoke = 1;
8514 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8515 m->signature->pinvoke = 1;
8517 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8519 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
8520 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
8522 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8524 if (klass->image->dynamic)
8525 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8527 mono_loader_unlock ();
8530 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8531 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8532 MonoMethodHeader *header;
8534 gint32 max_stack, i;
8535 gint32 num_locals = 0;
8536 gint32 num_clauses = 0;
8540 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8541 code_size = rmb->ilgen->code_len;
8542 max_stack = rmb->ilgen->max_stack;
8543 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8544 if (rmb->ilgen->ex_handlers)
8545 num_clauses = method_count_clauses (rmb->ilgen);
8548 code = mono_array_addr (rmb->code, guint8, 0);
8549 code_size = mono_array_length (rmb->code);
8550 /* we probably need to run a verifier on the code... */
8560 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
8561 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8562 header->code_size = code_size;
8563 header->code = mp_g_malloc (mp, code_size);
8564 memcpy ((char*)header->code, code, code_size);
8565 header->max_stack = max_stack;
8566 header->init_locals = rmb->init_locals;
8567 header->num_locals = num_locals;
8569 for (i = 0; i < num_locals; ++i) {
8570 MonoReflectionLocalBuilder *lb =
8571 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8573 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
8574 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8577 header->num_clauses = num_clauses;
8579 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8580 rmb->ilgen, num_clauses);
8583 pm->header = header;
8586 if (rmb->generic_params) {
8587 int count = mono_array_length (rmb->generic_params);
8588 MonoGenericContainer *container;
8590 m->generic_container = container = rmb->generic_container;
8591 container->type_argc = count;
8592 container->type_params = g_new0 (MonoGenericParam, count);
8593 container->is_method = TRUE;
8594 container->owner.method = m;
8596 for (i = 0; i < count; i++) {
8597 MonoReflectionGenericParam *gp =
8598 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8600 container->type_params [i] = *gp->type.type->data.generic_param;
8603 if (klass->generic_container) {
8604 container->parent = klass->generic_container;
8605 container->context.class_inst = klass->generic_container->context.class_inst;
8607 container->context.method_inst = mono_get_shared_generic_inst (container);
8611 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8615 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8617 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
8618 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8619 for (i = 0; i < rmb->nrefs; ++i)
8620 data [i + 1] = rmb->refs [i];
8625 /* Parameter info */
8628 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8629 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
8630 for (i = 0; i <= m->signature->param_count; ++i) {
8631 MonoReflectionParamBuilder *pb;
8632 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8633 if ((i > 0) && (pb->attrs)) {
8634 /* Make a copy since it might point to a shared type structure */
8635 /* FIXME: Alloc this from a mempool */
8636 m->signature->params [i - 1] = mono_metadata_type_dup (NULL, m->signature->params [i - 1]);
8637 m->signature->params [i - 1]->attrs = pb->attrs;
8640 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8641 MonoDynamicImage *assembly;
8642 guint32 idx, def_type, len;
8646 if (!method_aux->param_defaults) {
8647 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
8648 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
8650 assembly = (MonoDynamicImage*)klass->image;
8651 idx = encode_constant (assembly, pb->def_value, &def_type);
8652 /* Copy the data from the blob since it might get realloc-ed */
8653 p = assembly->blob.data + idx;
8654 len = mono_metadata_decode_blob_size (p, &p2);
8656 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
8657 method_aux->param_default_types [i] = def_type;
8658 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8662 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
8664 if (!method_aux->param_cattr)
8665 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
8666 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8672 /* Parameter marshalling */
8675 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8676 MonoReflectionParamBuilder *pb;
8677 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8678 if (pb->marshal_info) {
8680 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
8681 specs [pb->position] =
8682 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8686 if (specs != NULL) {
8688 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
8689 method_aux->param_marshall = specs;
8692 if (klass->image->dynamic && method_aux)
8693 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8695 mono_loader_unlock ();
8701 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8703 ReflectionMethodBuilder rmb;
8704 MonoMethodSignature *sig;
8707 /* Can happen if this was called from inflate_method () earlier */
8710 mono_loader_lock ();
8711 sig = ctor_builder_to_signature (klass->image->mempool, mb);
8712 mono_loader_unlock ();
8714 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8716 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8717 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8719 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8720 /* ilgen is no longer needed */
8728 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8730 ReflectionMethodBuilder rmb;
8731 MonoMethodSignature *sig;
8734 /* Can happen if this was called from inflate_method () earlier */
8737 mono_loader_lock ();
8738 sig = method_builder_to_signature (klass->image->mempool, mb);
8739 mono_loader_unlock ();
8741 reflection_methodbuilder_from_method_builder (&rmb, mb);
8743 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8744 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8746 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8747 /* ilgen is no longer needed */
8753 static MonoClassField*
8754 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8756 MonoClassField *field;
8760 field = g_new0 (MonoClassField, 1);
8762 field->name = mono_string_to_utf8 (fb->name);
8764 /* FIXME: handle type modifiers */
8765 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8766 field->type->attrs = fb->attrs;
8768 field->type = fb->type->type;
8770 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8771 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8772 if (fb->offset != -1)
8773 field->offset = fb->offset;
8774 field->parent = klass;
8775 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8777 if (fb->def_value) {
8778 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8779 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8780 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8781 /* Copy the data from the blob since it might get realloc-ed */
8782 p = assembly->blob.data + idx;
8783 len = mono_metadata_decode_blob_size (p, &p2);
8785 field->data = g_malloc (len);
8786 memcpy ((gpointer)field->data, p, len);
8793 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8796 MonoReflectionTypeBuilder *tb = NULL;
8797 gboolean is_dynamic = FALSE;
8801 mono_loader_lock ();
8803 domain = mono_object_domain (type);
8805 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8806 tb = (MonoReflectionTypeBuilder *) type;
8809 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8810 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8811 MonoReflectionType *rgt = rgi->generic_type;
8813 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8814 tb = (MonoReflectionTypeBuilder *) rgt;
8819 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
8820 if (tb && tb->generic_container)
8821 mono_reflection_create_generic_class (tb);
8823 klass = mono_class_from_mono_type (type->type);
8824 if (!klass->generic_container) {
8825 mono_loader_unlock ();
8829 if (klass->wastypebuilder) {
8830 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8835 mono_loader_unlock ();
8837 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
8839 return &geninst->byval_arg;
8843 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
8845 MonoGenericClass *gclass;
8846 MonoGenericInst *inst;
8848 g_assert (klass->generic_container);
8850 inst = mono_metadata_get_generic_inst (type_argc, types);
8851 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
8853 return mono_generic_class_get_class (gclass);
8856 MonoReflectionMethod*
8857 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8860 MonoMethod *method, *inflated;
8861 MonoMethodInflated *imethod;
8862 MonoReflectionMethodBuilder *mb = NULL;
8863 MonoGenericContext tmp_context;
8864 MonoGenericInst *ginst;
8865 MonoType **type_argv;
8868 MONO_ARCH_SAVE_REGS;
8869 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8870 MonoReflectionTypeBuilder *tb;
8873 mb = (MonoReflectionMethodBuilder *) rmethod;
8874 tb = (MonoReflectionTypeBuilder *) mb->type;
8875 klass = mono_class_from_mono_type (tb->type.type);
8877 method = methodbuilder_to_mono_method (klass, mb);
8879 method = rmethod->method;
8882 klass = method->klass;
8884 if (method->is_inflated)
8885 method = ((MonoMethodInflated *) method)->declaring;
8887 count = mono_method_signature (method)->generic_param_count;
8888 if (count != mono_array_length (types))
8891 type_argv = g_new0 (MonoType *, count);
8892 for (i = 0; i < count; i++) {
8893 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8894 type_argv [i] = garg->type;
8896 ginst = mono_metadata_get_generic_inst (count, type_argv);
8899 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
8900 tmp_context.method_inst = ginst;
8902 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8903 imethod = (MonoMethodInflated *) inflated;
8905 MOVING_GC_REGISTER (&imethod->reflection_info);
8906 imethod->reflection_info = rmethod;
8908 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8912 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8914 MonoMethodInflated *imethod;
8915 MonoGenericContext tmp_context;
8916 MonoGenericContext *context;
8919 klass = mono_class_from_mono_type (type->type.type);
8920 g_assert (klass->generic_class);
8921 context = mono_class_get_context (klass);
8923 if (method->generic_container) {
8924 g_assert (method->klass == klass->generic_class->container_class);
8926 tmp_context.class_inst = klass->generic_class->context.class_inst;
8927 tmp_context.method_inst = method->generic_container->context.method_inst;
8928 context = &tmp_context;
8931 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
8932 if (method->generic_container) {
8933 MOVING_GC_REGISTER (&imethod->reflection_info);
8934 imethod->reflection_info = obj;
8936 return (MonoMethod *) imethod;
8940 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8945 gklass = mono_class_from_mono_type (type->generic_type->type);
8947 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8948 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8949 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8950 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8951 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8952 method = ((MonoReflectionMethod *) obj)->method;
8954 method = NULL; /* prevent compiler warning */
8955 g_assert_not_reached ();
8958 return inflate_mono_method (type, method, obj);
8962 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8963 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8966 MonoGenericClass *gclass;
8967 MonoDynamicGenericClass *dgclass;
8968 MonoClass *klass, *gklass;
8971 MONO_ARCH_SAVE_REGS;
8973 klass = mono_class_from_mono_type (type->type.type);
8974 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
8975 gclass = type->type.type->data.generic_class;
8977 g_assert (gclass->is_dynamic);
8978 dgclass = (MonoDynamicGenericClass *) gclass;
8980 if (dgclass->initialized)
8983 gklass = gclass->container_class;
8984 mono_class_init (gklass);
8986 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8987 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8988 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8989 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8990 dgclass->count_events = events ? mono_array_length (events) : 0;
8992 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8993 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8994 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8995 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8996 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8998 for (i = 0; i < dgclass->count_methods; i++) {
8999 MonoObject *obj = mono_array_get (methods, gpointer, i);
9001 dgclass->methods [i] = inflate_method (type, obj);
9004 for (i = 0; i < dgclass->count_ctors; i++) {
9005 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9007 dgclass->ctors [i] = inflate_method (type, obj);
9010 for (i = 0; i < dgclass->count_fields; i++) {
9011 MonoObject *obj = mono_array_get (fields, gpointer, i);
9012 MonoClassField *field;
9013 MonoInflatedField *ifield;
9015 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9016 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9017 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9018 field = ((MonoReflectionField *) obj)->field;
9020 field = NULL; /* prevent compiler warning */
9021 g_assert_not_reached ();
9024 ifield = g_new0 (MonoInflatedField, 1);
9025 ifield->generic_type = field->type;
9026 MOVING_GC_REGISTER (&ifield->reflection_info);
9027 ifield->reflection_info = obj;
9029 dgclass->fields [i] = *field;
9030 dgclass->fields [i].parent = klass;
9031 dgclass->fields [i].generic_info = ifield;
9032 dgclass->fields [i].type = mono_class_inflate_generic_type (
9033 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9036 for (i = 0; i < dgclass->count_properties; i++) {
9037 MonoObject *obj = mono_array_get (properties, gpointer, i);
9038 MonoProperty *property = &dgclass->properties [i];
9040 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9041 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9043 property->parent = klass;
9044 property->attrs = pb->attrs;
9045 property->name = mono_string_to_utf8 (pb->name);
9047 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9049 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9050 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9051 *property = *((MonoReflectionProperty *) obj)->property;
9054 property->get = inflate_mono_method (type, property->get, NULL);
9056 property->set = inflate_mono_method (type, property->set, NULL);
9058 g_assert_not_reached ();
9061 for (i = 0; i < dgclass->count_events; i++) {
9062 MonoObject *obj = mono_array_get (events, gpointer, i);
9063 MonoEvent *event = &dgclass->events [i];
9065 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9066 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9068 event->parent = klass;
9069 event->attrs = eb->attrs;
9070 event->name = mono_string_to_utf8 (eb->name);
9072 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9073 if (eb->remove_method)
9074 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9075 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9076 *event = *((MonoReflectionEvent *) obj)->event;
9079 event->add = inflate_mono_method (type, event->add, NULL);
9081 event->remove = inflate_mono_method (type, event->remove, NULL);
9083 g_assert_not_reached ();
9086 dgclass->initialized = TRUE;
9090 ensure_runtime_vtable (MonoClass *klass)
9092 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9095 if (!tb || klass->wastypebuilder)
9098 ensure_runtime_vtable (klass->parent);
9100 num = tb->ctors? mono_array_length (tb->ctors): 0;
9101 num += tb->num_methods;
9102 klass->method.count = num;
9103 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9104 num = tb->ctors? mono_array_length (tb->ctors): 0;
9105 for (i = 0; i < num; ++i)
9106 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9107 num = tb->num_methods;
9109 for (i = 0; i < num; ++i)
9110 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9112 if (tb->interfaces) {
9113 klass->interface_count = mono_array_length (tb->interfaces);
9114 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9115 for (i = 0; i < klass->interface_count; ++i) {
9116 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9117 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9121 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9122 for (i = 0; i < klass->method.count; ++i)
9123 klass->methods [i]->slot = i;
9125 mono_class_setup_interface_offsets (klass);
9129 * The generic vtable is needed even if image->run is not set since some
9130 * runtime code like ves_icall_Type_GetMethodsByName depends on
9131 * method->slot being defined.
9135 * tb->methods could not be freed since it is used for determining
9136 * overrides during dynamic vtable construction.
9141 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9143 MonoReflectionTypeBuilder *tb;
9149 g_assert (klass->image->dynamic);
9151 if (!klass->reflection_info)
9154 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9156 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9160 for (i = 0; i < tb->num_methods; ++i) {
9161 MonoReflectionMethodBuilder *mb =
9162 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9163 if (mb->override_method)
9169 *overrides = g_new0 (MonoMethod*, onum * 2);
9172 for (i = 0; i < tb->num_methods; ++i) {
9173 MonoReflectionMethodBuilder *mb =
9174 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9175 if (mb->override_method) {
9176 (*overrides) [onum * 2] =
9177 mb->override_method->method;
9178 (*overrides) [onum * 2 + 1] =
9181 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9182 g_assert (mb->override_method->method);
9183 g_assert (mb->mhandle);
9190 *num_overrides = onum;
9194 typebuilder_setup_fields (MonoClass *klass)
9196 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9197 MonoReflectionFieldBuilder *fb;
9198 MonoClassField *field;
9203 klass->field.count = tb->num_fields;
9204 klass->field.first = 0;
9206 if (!klass->field.count)
9209 klass->fields = g_new0 (MonoClassField, klass->field.count);
9211 for (i = 0; i < klass->field.count; ++i) {
9212 fb = mono_array_get (tb->fields, gpointer, i);
9213 field = &klass->fields [i];
9214 field->name = mono_string_to_utf8 (fb->name);
9216 /* FIXME: handle type modifiers */
9217 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9218 field->type->attrs = fb->attrs;
9220 field->type = fb->type->type;
9222 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9223 field->data = mono_array_addr (fb->rva_data, char, 0);
9224 if (fb->offset != -1)
9225 field->offset = fb->offset;
9226 field->parent = klass;
9228 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9230 if (fb->def_value) {
9231 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9232 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9233 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9234 /* Copy the data from the blob since it might get realloc-ed */
9235 p = assembly->blob.data + idx;
9236 len = mono_metadata_decode_blob_size (p, &p2);
9238 field->data = g_malloc (len);
9239 memcpy ((gpointer)field->data, p, len);
9242 mono_class_layout_fields (klass);
9246 typebuilder_setup_properties (MonoClass *klass)
9248 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9249 MonoReflectionPropertyBuilder *pb;
9252 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9253 klass->property.first = 0;
9255 klass->properties = g_new0 (MonoProperty, klass->property.count);
9256 for (i = 0; i < klass->property.count; ++i) {
9257 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9258 klass->properties [i].parent = klass;
9259 klass->properties [i].attrs = pb->attrs;
9260 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9262 klass->properties [i].get = pb->get_method->mhandle;
9264 klass->properties [i].set = pb->set_method->mhandle;
9266 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9270 MonoReflectionEvent *
9271 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9273 MonoEvent *event = g_new0 (MonoEvent, 1);
9277 klass = my_mono_class_from_mono_type (tb->type.type);
9279 event->parent = klass;
9280 event->attrs = eb->attrs;
9281 event->name = mono_string_to_utf8 (eb->name);
9283 event->add = eb->add_method->mhandle;
9284 if (eb->remove_method)
9285 event->remove = eb->remove_method->mhandle;
9286 if (eb->raise_method)
9287 event->raise = eb->raise_method->mhandle;
9289 if (eb->other_methods) {
9290 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9291 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9292 MonoReflectionMethodBuilder *mb =
9293 mono_array_get (eb->other_methods,
9294 MonoReflectionMethodBuilder*, j);
9295 event->other [j] = mb->mhandle;
9299 return mono_event_get_object (mono_object_domain (tb), klass, event);
9303 typebuilder_setup_events (MonoClass *klass)
9305 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9306 MonoReflectionEventBuilder *eb;
9309 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9310 klass->event.first = 0;
9312 klass->events = g_new0 (MonoEvent, klass->event.count);
9313 for (i = 0; i < klass->event.count; ++i) {
9314 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9315 klass->events [i].parent = klass;
9316 klass->events [i].attrs = eb->attrs;
9317 klass->events [i].name = mono_string_to_utf8 (eb->name);
9319 klass->events [i].add = eb->add_method->mhandle;
9320 if (eb->remove_method)
9321 klass->events [i].remove = eb->remove_method->mhandle;
9322 if (eb->raise_method)
9323 klass->events [i].raise = eb->raise_method->mhandle;
9325 if (eb->other_methods) {
9326 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9327 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9328 MonoReflectionMethodBuilder *mb =
9329 mono_array_get (eb->other_methods,
9330 MonoReflectionMethodBuilder*, j);
9331 klass->events [i].other [j] = mb->mhandle;
9338 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9342 MonoReflectionType* res;
9345 MONO_ARCH_SAVE_REGS;
9347 domain = mono_object_domain (tb);
9348 klass = my_mono_class_from_mono_type (tb->type.type);
9350 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9353 * we need to lock the domain because the lock will be taken inside
9354 * So, we need to keep the locking order correct.
9356 mono_domain_lock (domain);
9357 mono_loader_lock ();
9358 if (klass->wastypebuilder) {
9359 mono_loader_unlock ();
9360 mono_domain_unlock (domain);
9361 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9364 * Fields to set in klass:
9365 * the various flags: delegate/unicode/contextbound etc.
9367 klass->flags = tb->attrs;
9368 klass->has_cctor = 1;
9369 klass->has_finalize = 1;
9372 if (!((MonoDynamicImage*)klass->image)->run) {
9373 if (klass->generic_container) {
9374 /* FIXME: The code below can't handle generic classes */
9375 klass->wastypebuilder = TRUE;
9376 mono_loader_unlock ();
9377 mono_domain_unlock (domain);
9378 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9383 /* enums are done right away */
9384 if (!klass->enumtype)
9385 ensure_runtime_vtable (klass);
9388 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9389 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9390 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9394 /* fields and object layout */
9395 if (klass->parent) {
9396 if (!klass->parent->size_inited)
9397 mono_class_init (klass->parent);
9398 klass->instance_size = klass->parent->instance_size;
9399 klass->sizes.class_size = 0;
9400 klass->min_align = klass->parent->min_align;
9401 /* if the type has no fields we won't call the field_setup
9402 * routine which sets up klass->has_references.
9404 klass->has_references |= klass->parent->has_references;
9406 klass->instance_size = sizeof (MonoObject);
9407 klass->min_align = 1;
9410 /* FIXME: handle packing_size and instance_size */
9411 typebuilder_setup_fields (klass);
9413 typebuilder_setup_properties (klass);
9415 typebuilder_setup_events (klass);
9417 klass->wastypebuilder = TRUE;
9418 mono_loader_unlock ();
9419 mono_domain_unlock (domain);
9421 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
9422 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
9423 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
9426 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9427 g_assert (res != (MonoReflectionType*)tb);
9433 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9435 MonoGenericParam *param;
9438 MONO_ARCH_SAVE_REGS;
9440 param = g_new0 (MonoGenericParam, 1);
9442 if (gparam->mbuilder) {
9443 if (!gparam->mbuilder->generic_container)
9444 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9445 param->owner = gparam->mbuilder->generic_container;
9446 } else if (gparam->tbuilder) {
9447 g_assert (gparam->tbuilder->generic_container);
9448 param->owner = gparam->tbuilder->generic_container;
9451 param->name = mono_string_to_utf8 (gparam->name);
9452 param->num = gparam->index;
9454 image = &gparam->tbuilder->module->dynamic_image->image;
9455 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9457 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
9458 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9460 gparam->type.type = g_new0 (MonoType, 1);
9461 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9462 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9463 gparam->type.type->data.generic_param = param;
9467 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9469 MonoDynamicImage *assembly = sig->module->dynamic_image;
9470 guint32 na = mono_array_length (sig->arguments);
9475 sigbuffer_init (&buf, 32);
9477 sigbuffer_add_value (&buf, 0x07);
9478 sigbuffer_add_value (&buf, na);
9479 for (i = 0; i < na; ++i) {
9480 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9481 encode_reflection_type (assembly, type, &buf);
9484 buflen = buf.p - buf.buf;
9485 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9486 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9487 sigbuffer_free (&buf);
9493 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9495 MonoDynamicImage *assembly = sig->module->dynamic_image;
9496 guint32 na = mono_array_length (sig->arguments);
9501 sigbuffer_init (&buf, 32);
9503 sigbuffer_add_value (&buf, 0x06);
9504 for (i = 0; i < na; ++i) {
9505 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9506 encode_reflection_type (assembly, type, &buf);
9509 buflen = buf.p - buf.buf;
9510 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9511 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
9512 sigbuffer_free (&buf);
9518 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9520 ReflectionMethodBuilder rmb;
9521 MonoMethodSignature *sig;
9526 sig = dynamic_method_to_signature (mb);
9528 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9531 * Resolve references.
9534 * Every second entry in the refs array is reserved for storing handle_class,
9535 * which is needed by the ldtoken implementation in the JIT.
9537 rmb.nrefs = mb->nrefs;
9538 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9539 for (i = 0; i < mb->nrefs; i += 2) {
9540 MonoClass *handle_class;
9542 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
9544 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9545 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9547 * The referenced DynamicMethod should already be created by the managed
9548 * code, except in the case of circular references. In that case, we store
9549 * method in the refs array, and fix it up later when the referenced
9550 * DynamicMethod is created.
9552 if (method->mhandle) {
9553 ref = method->mhandle;
9555 /* FIXME: GC object stored in unmanaged memory */
9558 /* FIXME: GC object stored in unmanaged memory */
9559 method->referenced_by = g_slist_append (method->referenced_by, mb);
9561 handle_class = mono_defaults.methodhandle_class;
9563 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
9566 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9571 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
9572 rmb.refs [i + 1] = handle_class;
9575 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
9577 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9579 /* Fix up refs entries pointing at us */
9580 for (l = mb->referenced_by; l; l = l->next) {
9581 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
9582 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
9585 g_assert (method->mhandle);
9587 data = (gpointer*)wrapper->method_data;
9588 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
9589 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
9590 data [i + 1] = mb->mhandle;
9593 g_slist_free (mb->referenced_by);
9597 /* ilgen is no longer needed */
9602 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
9607 mono_runtime_free_method (
9608 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
9612 * mono_reflection_lookup_dynamic_token:
9614 * Finish the Builder object pointed to by TOKEN and return the corresponding
9615 * runtime structure. HANDLE_CLASS is set to the class required by
9619 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class, MonoGenericContext *context)
9621 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9624 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9627 return resolve_object (image, obj, handle_class, context);
9631 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
9633 gpointer result = NULL;
9635 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9636 result = mono_string_intern ((MonoString*)obj);
9637 *handle_class = NULL;
9639 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9640 MonoReflectionType *tb = (MonoReflectionType*)obj;
9642 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
9643 result = mono_class_from_mono_type (inflated);
9644 mono_metadata_free_type (inflated);
9646 result = mono_class_from_mono_type (tb->type);
9648 *handle_class = mono_defaults.typehandle_class;
9650 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9651 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9652 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9653 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9654 result = ((MonoReflectionMethod*)obj)->method;
9655 result = mono_class_inflate_generic_method (result, context);
9656 *handle_class = mono_defaults.methodhandle_class;
9658 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9659 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9660 result = mb->mhandle;
9662 /* Type is not yet created */
9663 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9665 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9668 * Hopefully this has been filled in by calling CreateType() on the
9672 * TODO: This won't work if the application finishes another
9673 * TypeBuilder instance instead of this one.
9675 result = mb->mhandle;
9677 result = mono_class_inflate_generic_method (result, context);
9678 *handle_class = mono_defaults.methodhandle_class;
9679 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9680 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9682 result = cb->mhandle;
9684 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9686 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9687 result = cb->mhandle;
9689 result = mono_class_inflate_generic_method (result, context);
9690 *handle_class = mono_defaults.methodhandle_class;
9691 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9692 result = ((MonoReflectionField*)obj)->field;
9693 *handle_class = mono_defaults.fieldhandle_class;
9695 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9696 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9697 result = fb->handle;
9700 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9702 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9703 result = fb->handle;
9706 if (fb->handle && fb->handle->parent->generic_container) {
9707 MonoClass *klass = fb->handle->parent;
9708 MonoClass *inflated = mono_class_from_mono_type (mono_class_inflate_generic_type (&klass->byval_arg, context));
9710 result = mono_class_get_field_from_name (inflated, fb->handle->name);
9713 *handle_class = mono_defaults.fieldhandle_class;
9714 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9715 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9718 klass = tb->type.type->data.klass;
9719 if (klass->wastypebuilder) {
9720 /* Already created */
9724 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9725 result = tb->type.type->data.klass;
9728 *handle_class = mono_defaults.typehandle_class;
9729 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9730 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9731 MonoMethodSignature *sig;
9734 if (helper->arguments)
9735 nargs = mono_array_length (helper->arguments);
9739 sig = mono_metadata_signature_alloc (image, nargs);
9740 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9741 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9743 if (helper->call_conv == 0) /* unmanaged */
9744 sig->call_convention = helper->unmanaged_call_conv - 1;
9746 if (helper->call_conv & 0x02)
9747 sig->call_convention = MONO_CALL_VARARG;
9749 sig->call_convention = MONO_CALL_DEFAULT;
9751 sig->param_count = nargs;
9752 /* TODO: Copy type ? */
9753 sig->ret = helper->return_type->type;
9754 for (i = 0; i < nargs; ++i) {
9755 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9756 sig->params [i] = rt->type;
9760 *handle_class = NULL;
9761 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
9762 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
9763 /* Already created by the managed code */
9764 g_assert (method->mhandle);
9765 result = method->mhandle;
9766 *handle_class = mono_defaults.methodhandle_class;
9767 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
9768 MonoReflectionType *tb = (MonoReflectionType*)obj;
9769 result = mono_class_from_mono_type (mono_class_inflate_generic_type (tb->type, context));
9770 *handle_class = mono_defaults.typehandle_class;
9772 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
9773 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
9774 result = mono_class_from_mono_type (mono_class_inflate_generic_type (ref->type.type, context));
9775 *handle_class = mono_defaults.typehandle_class;
9778 g_print (obj->vtable->klass->name);
9779 g_assert_not_reached ();
9785 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9786 const static guint32 declsec_flags_map[] = {
9787 0x00000000, /* empty */
9788 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9789 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9790 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9791 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9792 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9793 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9794 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9795 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9796 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9797 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9798 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9799 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9800 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9801 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9802 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9803 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9804 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9805 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9809 * Returns flags that includes all available security action associated to the handle.
9810 * @token: metadata token (either for a class or a method)
9811 * @image: image where resides the metadata.
9814 mono_declsec_get_flags (MonoImage *image, guint32 token)
9816 int index = mono_metadata_declsec_from_index (image, token);
9817 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9822 /* HasSecurity can be present for other, not specially encoded, attributes,
9823 e.g. SuppressUnmanagedCodeSecurityAttribute */
9827 for (i = index; i < t->rows; i++) {
9828 guint32 cols [MONO_DECL_SECURITY_SIZE];
9830 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9831 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9834 action = cols [MONO_DECL_SECURITY_ACTION];
9835 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9836 result |= declsec_flags_map [action];
9838 g_assert_not_reached ();
9845 * Get the security actions (in the form of flags) associated with the specified method.
9847 * @method: The method for which we want the declarative security flags.
9848 * Return the declarative security flags for the method (only).
9850 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9851 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9854 mono_declsec_flags_from_method (MonoMethod *method)
9856 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9857 /* FIXME: No cache (for the moment) */
9858 guint32 idx = mono_method_get_index (method);
9859 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9860 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9861 return mono_declsec_get_flags (method->klass->image, idx);
9867 * Get the security actions (in the form of flags) associated with the specified class.
9869 * @klass: The class for which we want the declarative security flags.
9870 * Return the declarative security flags for the class.
9872 * Note: We cache the flags inside the MonoClass structure as this will get
9873 * called very often (at least for each method).
9876 mono_declsec_flags_from_class (MonoClass *klass)
9878 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9879 if (!klass->declsec_flags) {
9880 guint32 idx = mono_metadata_token_index (klass->type_token);
9881 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9882 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9883 /* we cache the flags on classes */
9884 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9886 return klass->declsec_flags;
9892 * Get the security actions (in the form of flags) associated with the specified assembly.
9894 * @assembly: The assembly for which we want the declarative security flags.
9895 * Return the declarative security flags for the assembly.
9898 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9900 guint32 idx = 1; /* there is only one assembly */
9901 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9902 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9903 return mono_declsec_get_flags (assembly->image, idx);
9908 * Fill actions for the specific index (which may either be an encoded class token or
9909 * an encoded method token) from the metadata image.
9910 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9913 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9914 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9916 MonoBoolean result = FALSE;
9918 guint32 cols [MONO_DECL_SECURITY_SIZE];
9919 int index = mono_metadata_declsec_from_index (image, token);
9922 t = &image->tables [MONO_TABLE_DECLSECURITY];
9923 for (i = index; i < t->rows; i++) {
9924 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9926 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9929 /* if present only replace (class) permissions with method permissions */
9930 /* if empty accept either class or method permissions */
9931 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9932 if (!actions->demand.blob) {
9933 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9934 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9935 actions->demand.blob = (char*) (blob + 2);
9936 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9939 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9940 if (!actions->noncasdemand.blob) {
9941 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9942 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9943 actions->noncasdemand.blob = (char*) (blob + 2);
9944 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9947 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9948 if (!actions->demandchoice.blob) {
9949 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9950 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9951 actions->demandchoice.blob = (char*) (blob + 2);
9952 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9962 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9963 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9965 guint32 idx = mono_metadata_token_index (klass->type_token);
9966 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9967 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9968 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9972 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9973 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9975 guint32 idx = mono_method_get_index (method);
9976 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9977 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9978 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9982 * Collect all actions (that requires to generate code in mini) assigned for
9983 * the specified method.
9984 * Note: Don't use the content of actions if the function return FALSE.
9987 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9989 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9990 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9991 MonoBoolean result = FALSE;
9994 /* quick exit if no declarative security is present in the metadata */
9995 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9998 /* we want the original as the wrapper is "free" of the security informations */
9999 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10000 method = mono_marshal_method_from_wrapper (method);
10005 /* First we look for method-level attributes */
10006 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10007 mono_class_init (method->klass);
10008 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10010 result = mono_declsec_get_method_demands_params (method, demands,
10011 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10014 /* Here we use (or create) the class declarative cache to look for demands */
10015 flags = mono_declsec_flags_from_class (method->klass);
10016 if (flags & mask) {
10018 mono_class_init (method->klass);
10019 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10021 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10022 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10025 /* The boolean return value is used as a shortcut in case nothing needs to
10026 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10032 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10034 * Note: Don't use the content of actions if the function return FALSE.
10037 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10039 MonoBoolean result = FALSE;
10042 /* quick exit if no declarative security is present in the metadata */
10043 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10046 /* we want the original as the wrapper is "free" of the security informations */
10047 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10048 method = mono_marshal_method_from_wrapper (method);
10053 /* results are independant - zeroize both */
10054 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
10055 memset (klass, 0, sizeof (MonoDeclSecurityActions));
10057 /* First we look for method-level attributes */
10058 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10059 mono_class_init (method->klass);
10061 result = mono_declsec_get_method_demands_params (method, cmethod,
10062 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10065 /* Here we use (or create) the class declarative cache to look for demands */
10066 flags = mono_declsec_flags_from_class (method->klass);
10067 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
10068 mono_class_init (method->klass);
10070 result |= mono_declsec_get_class_demands_params (method->klass, klass,
10071 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10078 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10080 * @klass The inherited class - this is the class that provides the security check (attributes)
10082 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10084 * Note: Don't use the content of actions if the function return FALSE.
10087 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10089 MonoBoolean result = FALSE;
10092 /* quick exit if no declarative security is present in the metadata */
10093 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10096 /* Here we use (or create) the class declarative cache to look for demands */
10097 flags = mono_declsec_flags_from_class (klass);
10098 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10099 mono_class_init (klass);
10100 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10102 result |= mono_declsec_get_class_demands_params (klass, demands,
10103 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10110 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10112 * Note: Don't use the content of actions if the function return FALSE.
10115 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10117 /* quick exit if no declarative security is present in the metadata */
10118 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10121 /* we want the original as the wrapper is "free" of the security informations */
10122 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10123 method = mono_marshal_method_from_wrapper (method);
10128 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10129 mono_class_init (method->klass);
10130 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10132 return mono_declsec_get_method_demands_params (method, demands,
10133 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10140 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10142 guint32 cols [MONO_DECL_SECURITY_SIZE];
10146 int index = mono_metadata_declsec_from_index (image, token);
10150 t = &image->tables [MONO_TABLE_DECLSECURITY];
10151 for (i = index; i < t->rows; i++) {
10152 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10154 /* shortcut - index are ordered */
10155 if (token != cols [MONO_DECL_SECURITY_PARENT])
10158 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10159 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10160 entry->blob = (char*) (metadata + 2);
10161 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10170 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10172 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10173 guint32 idx = mono_method_get_index (method);
10174 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10175 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10176 return get_declsec_action (method->klass->image, idx, action, entry);
10182 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10185 guint32 flags = mono_declsec_flags_from_class (klass);
10186 if (declsec_flags_map [action] & flags) {
10187 guint32 idx = mono_metadata_token_index (klass->type_token);
10188 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10189 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10190 return get_declsec_action (klass->image, idx, action, entry);
10196 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10198 guint32 idx = 1; /* there is only one assembly */
10199 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10200 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10202 return get_declsec_action (assembly->image, idx, action, entry);
10206 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10208 MonoObject *res, *exc;
10210 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10211 static MonoMethod *method = NULL;
10213 if (!System_Reflection_Emit_TypeBuilder) {
10214 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10215 g_assert (System_Reflection_Emit_TypeBuilder);
10217 if (method == NULL) {
10218 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10223 * The result of mono_type_get_object () might be a System.MonoType but we
10224 * need a TypeBuilder so use klass->reflection_info.
10226 g_assert (klass->reflection_info);
10227 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10229 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10231 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10235 return *(MonoBoolean*)mono_object_unbox (res);