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/utils/mono-membar.h"
13 #include "mono/metadata/reflection.h"
14 #include "mono/metadata/tabledefs.h"
15 #include "mono/metadata/metadata-internals.h"
16 #include <mono/metadata/profiler-private.h>
17 #include "mono/metadata/class-internals.h"
18 #include "mono/metadata/gc-internal.h"
19 #include "mono/metadata/tokentype.h"
20 #include "mono/metadata/domain-internals.h"
21 #include "mono/metadata/opcodes.h"
22 #include "mono/metadata/assembly.h"
23 #include "mono/metadata/object-internals.h"
24 #include <mono/metadata/exception.h>
25 #include <mono/metadata/marshal.h>
26 #include <mono/metadata/security-manager.h>
35 #include "mono-endian.h"
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/mempool-internals.h>
45 #define TEXT_OFFSET 512
46 #define CLI_H_SIZE 136
47 #define FILE_ALIGN 512
48 #define VIRT_ALIGN 8192
49 #define START_TEXT_RVA 0x00002000
52 MonoReflectionILGen *ilgen;
53 MonoReflectionType *rtype;
54 MonoArray *parameters;
55 MonoArray *generic_params;
56 MonoGenericContainer *generic_container;
62 guint32 *table_idx; /* note: it's a pointer */
66 MonoBoolean init_locals;
67 MonoBoolean skip_visibility;
68 MonoArray *return_modreq;
69 MonoArray *return_modopt;
70 MonoArray *param_modreq;
71 MonoArray *param_modopt;
72 MonoArray *permissions;
77 int charset, extra_flags, native_cc;
78 MonoString *dll, *dllentry;
79 } ReflectionMethodBuilder;
83 MonoReflectionGenericParam *gparam;
84 } GenericParamTableEntry;
86 const unsigned char table_sizes [MONO_TABLE_NUM] = {
96 MONO_INTERFACEIMPL_SIZE,
97 MONO_MEMBERREF_SIZE, /* 0x0A */
99 MONO_CUSTOM_ATTR_SIZE,
100 MONO_FIELD_MARSHAL_SIZE,
101 MONO_DECL_SECURITY_SIZE,
102 MONO_CLASS_LAYOUT_SIZE,
103 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
104 MONO_STAND_ALONE_SIGNATURE_SIZE,
108 MONO_PROPERTY_MAP_SIZE,
111 MONO_METHOD_SEMA_SIZE,
112 MONO_METHODIMPL_SIZE,
113 MONO_MODULEREF_SIZE, /* 0x1A */
119 MONO_ASSEMBLY_SIZE, /* 0x20 */
120 MONO_ASSEMBLY_PROCESSOR_SIZE,
121 MONO_ASSEMBLYOS_SIZE,
122 MONO_ASSEMBLYREF_SIZE,
123 MONO_ASSEMBLYREFPROC_SIZE,
124 MONO_ASSEMBLYREFOS_SIZE,
128 MONO_NESTED_CLASS_SIZE,
130 MONO_GENERICPARAM_SIZE, /* 0x2A */
131 MONO_METHODSPEC_SIZE,
132 MONO_GENPARCONSTRAINT_SIZE
136 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
137 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
138 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
139 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
140 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
141 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
142 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
143 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
144 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
145 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
146 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
147 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
148 static void ensure_runtime_vtable (MonoClass *klass);
149 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
150 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
151 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
152 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
153 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
154 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
157 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
158 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
159 static CRITICAL_SECTION reflection_mutex;
162 mono_reflection_init (void)
164 InitializeCriticalSection (&reflection_mutex);
168 sigbuffer_init (SigBuffer *buf, int size)
170 buf->buf = g_malloc (size);
172 buf->end = buf->buf + size;
176 sigbuffer_make_room (SigBuffer *buf, int size)
178 if (buf->end - buf->p < size) {
179 int new_size = buf->end - buf->buf + size + 32;
180 char *p = g_realloc (buf->buf, new_size);
181 size = buf->p - buf->buf;
184 buf->end = buf->buf + new_size;
189 sigbuffer_add_value (SigBuffer *buf, guint32 val)
191 sigbuffer_make_room (buf, 6);
192 mono_metadata_encode_value (val, buf->p, &buf->p);
196 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
198 sigbuffer_make_room (buf, 1);
204 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
206 sigbuffer_make_room (buf, size);
207 memcpy (buf->p, p, size);
212 sigbuffer_free (SigBuffer *buf)
220 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
224 mp_g_malloc (MonoMemPool *mp, guint size)
227 return mono_mempool_alloc (mp, size);
229 return g_malloc (size);
235 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
239 mp_g_malloc0 (MonoMemPool *mp, guint size)
242 return mono_mempool_alloc0 (mp, size);
244 return g_malloc0 (size);
250 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
251 * memory from the C heap.
254 mp_string_to_utf8 (MonoMemPool *mp, MonoString *s)
257 return mono_string_to_utf8_mp (mp, s);
259 return mono_string_to_utf8 (s);
262 #define mp_g_new(mp,struct_type, n_structs) \
263 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
265 #define mp_g_new0(mp,struct_type, n_structs) \
266 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
269 alloc_table (MonoDynamicTable *table, guint nrows)
272 g_assert (table->columns);
273 if (nrows + 1 >= table->alloc_rows) {
274 while (nrows + 1 >= table->alloc_rows) {
275 if (table->alloc_rows == 0)
276 table->alloc_rows = 16;
278 table->alloc_rows *= 2;
281 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
286 make_room_in_stream (MonoDynamicStream *stream, int size)
288 if (size <= stream->alloc_size)
291 while (stream->alloc_size <= size) {
292 if (stream->alloc_size < 4096)
293 stream->alloc_size = 4096;
295 stream->alloc_size *= 2;
298 stream->data = g_realloc (stream->data, stream->alloc_size);
302 string_heap_insert (MonoDynamicStream *sh, const char *str)
306 gpointer oldkey, oldval;
308 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
309 return GPOINTER_TO_UINT (oldval);
311 len = strlen (str) + 1;
314 make_room_in_stream (sh, idx + len);
317 * We strdup the string even if we already copy them in sh->data
318 * so that the string pointers in the hash remain valid even if
319 * we need to realloc sh->data. We may want to avoid that later.
321 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
322 memcpy (sh->data + idx, str, len);
328 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
330 char *name = mono_string_to_utf8 (str);
332 idx = string_heap_insert (sh, name);
338 string_heap_init (MonoDynamicStream *sh)
341 sh->alloc_size = 4096;
342 sh->data = g_malloc (4096);
343 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
344 string_heap_insert (sh, "");
348 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
352 make_room_in_stream (stream, stream->index + len);
353 memcpy (stream->data + stream->index, data, len);
355 stream->index += len;
357 * align index? Not without adding an additional param that controls it since
358 * we may store a blob value in pieces.
364 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
368 make_room_in_stream (stream, stream->index + len);
369 memset (stream->data + stream->index, 0, len);
371 stream->index += len;
376 stream_data_align (MonoDynamicStream *stream)
379 guint32 count = stream->index % 4;
381 /* we assume the stream data will be aligned */
383 mono_image_add_stream_data (stream, buf, 4 - count);
387 mono_blob_entry_hash (const char* str)
391 len = mono_metadata_decode_blob_size (str, &str);
395 for (str += 1; str < end; str++)
396 h = (h << 5) - h + *str;
404 mono_blob_entry_equal (const char *str1, const char *str2) {
408 len = mono_metadata_decode_blob_size (str1, &end1);
409 len2 = mono_metadata_decode_blob_size (str2, &end2);
412 return memcmp (end1, end2, len) == 0;
416 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
420 gpointer oldkey, oldval;
422 copy = g_malloc (s1+s2);
423 memcpy (copy, b1, s1);
424 memcpy (copy + s1, b2, s2);
425 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
427 idx = GPOINTER_TO_UINT (oldval);
429 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
430 mono_image_add_stream_data (&assembly->blob, b2, s2);
431 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
437 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
441 guint32 size = buf->p - buf->buf;
443 g_assert (size <= (buf->end - buf->buf));
444 mono_metadata_encode_value (size, b, &b);
445 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
449 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
450 * dest may be misaligned.
453 swap_with_size (char *dest, const char* val, int len, int nelem) {
454 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
457 for (elem = 0; elem < nelem; ++elem) {
483 g_assert_not_reached ();
489 memcpy (dest, val, len * nelem);
494 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
498 guint32 idx = 0, len;
500 len = str->length * 2;
501 mono_metadata_encode_value (len, b, &b);
502 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
504 char *swapped = g_malloc (2 * mono_string_length (str));
505 const char *p = (const char*)mono_string_chars (str);
507 swap_with_size (swapped, p, 2, mono_string_length (str));
508 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
512 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
517 /* modified version needed to handle building corlib */
519 my_mono_class_from_mono_type (MonoType *type) {
520 switch (type->type) {
521 case MONO_TYPE_ARRAY:
523 case MONO_TYPE_SZARRAY:
524 case MONO_TYPE_GENERICINST:
525 return mono_class_from_mono_type (type);
528 g_assert (type->data.generic_param->pklass);
529 return type->data.generic_param->pklass;
531 /* should be always valid when we reach this case... */
532 return type->data.klass;
537 default_class_from_mono_type (MonoType *type)
539 switch (type->type) {
540 case MONO_TYPE_OBJECT:
541 return mono_defaults.object_class;
543 return mono_defaults.void_class;
544 case MONO_TYPE_BOOLEAN:
545 return mono_defaults.boolean_class;
547 return mono_defaults.char_class;
549 return mono_defaults.sbyte_class;
551 return mono_defaults.byte_class;
553 return mono_defaults.int16_class;
555 return mono_defaults.uint16_class;
557 return mono_defaults.int32_class;
559 return mono_defaults.uint32_class;
561 return mono_defaults.int_class;
563 return mono_defaults.uint_class;
565 return mono_defaults.int64_class;
567 return mono_defaults.uint64_class;
569 return mono_defaults.single_class;
571 return mono_defaults.double_class;
572 case MONO_TYPE_STRING:
573 return mono_defaults.string_class;
575 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
576 g_assert_not_reached ();
583 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
586 MonoGenericInst *class_inst;
591 class_inst = gclass->context.class_inst;
593 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
594 klass = gclass->container_class;
595 sigbuffer_add_value (buf, klass->byval_arg.type);
596 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
598 sigbuffer_add_value (buf, class_inst->type_argc);
599 for (i = 0; i < class_inst->type_argc; ++i)
600 encode_type (assembly, class_inst->type_argv [i], buf);
605 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
608 g_assert_not_reached ();
613 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
617 case MONO_TYPE_BOOLEAN:
631 case MONO_TYPE_STRING:
632 case MONO_TYPE_OBJECT:
633 case MONO_TYPE_TYPEDBYREF:
634 sigbuffer_add_value (buf, type->type);
637 sigbuffer_add_value (buf, type->type);
638 encode_type (assembly, type->data.type, buf);
640 case MONO_TYPE_SZARRAY:
641 sigbuffer_add_value (buf, type->type);
642 encode_type (assembly, &type->data.klass->byval_arg, buf);
644 case MONO_TYPE_VALUETYPE:
645 case MONO_TYPE_CLASS: {
646 MonoClass *k = mono_class_from_mono_type (type);
648 if (k->generic_container) {
649 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
650 encode_generic_class (assembly, gclass, buf);
653 * Make sure we use the correct type.
655 sigbuffer_add_value (buf, k->byval_arg.type);
657 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
658 * otherwise two typerefs could point to the same type, leading to
659 * verification errors.
661 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
665 case MONO_TYPE_ARRAY:
666 sigbuffer_add_value (buf, type->type);
667 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
668 sigbuffer_add_value (buf, type->data.array->rank);
669 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
670 sigbuffer_add_value (buf, 0);
672 case MONO_TYPE_GENERICINST:
673 encode_generic_class (assembly, type->data.generic_class, buf);
677 sigbuffer_add_value (buf, type->type);
678 sigbuffer_add_value (buf, type->data.generic_param->num);
681 g_error ("need to encode type %x", type->type);
686 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
689 sigbuffer_add_value (buf, MONO_TYPE_VOID);
694 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
695 encode_type (assembly, type->type, buf);
699 g_assert_not_reached ();
704 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
709 for (i = 0; i < mono_array_length (modreq); ++i) {
710 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
711 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
712 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
716 for (i = 0; i < mono_array_length (modopt); ++i) {
717 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
718 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
719 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
725 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
729 guint32 nparams = sig->param_count;
735 sigbuffer_init (&buf, 32);
737 * FIXME: vararg, explicit_this, differenc call_conv values...
739 idx = sig->call_convention;
741 idx |= 0x20; /* hasthis */
742 if (sig->generic_param_count)
743 idx |= 0x10; /* generic */
744 sigbuffer_add_byte (&buf, idx);
745 if (sig->generic_param_count)
746 sigbuffer_add_value (&buf, sig->generic_param_count);
747 sigbuffer_add_value (&buf, nparams);
748 encode_type (assembly, sig->ret, &buf);
749 for (i = 0; i < nparams; ++i) {
750 if (i == sig->sentinelpos)
751 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
752 encode_type (assembly, sig->params [i], &buf);
754 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
755 sigbuffer_free (&buf);
760 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
763 * FIXME: reuse code from method_encode_signature().
767 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
768 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
769 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
772 sigbuffer_init (&buf, 32);
773 /* LAMESPEC: all the call conv spec is foobared */
774 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
775 if (mb->call_conv & 2)
776 idx |= 0x5; /* vararg */
777 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
778 idx |= 0x20; /* hasthis */
780 idx |= 0x10; /* generic */
781 sigbuffer_add_byte (&buf, idx);
783 sigbuffer_add_value (&buf, ngparams);
784 sigbuffer_add_value (&buf, nparams + notypes);
785 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
786 encode_reflection_type (assembly, mb->rtype, &buf);
787 for (i = 0; i < nparams; ++i) {
788 MonoArray *modreq = NULL;
789 MonoArray *modopt = NULL;
790 MonoReflectionType *pt;
792 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
793 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
794 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
795 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
796 encode_custom_modifiers (assembly, modreq, modopt, &buf);
797 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
798 encode_reflection_type (assembly, pt, &buf);
801 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
802 for (i = 0; i < notypes; ++i) {
803 MonoReflectionType *pt;
805 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
806 encode_reflection_type (assembly, pt, &buf);
809 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
810 sigbuffer_free (&buf);
815 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
817 MonoDynamicTable *table;
819 guint32 idx, sig_idx;
820 guint nl = mono_array_length (ilgen->locals);
824 sigbuffer_init (&buf, 32);
825 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
826 idx = table->next_idx ++;
828 alloc_table (table, table->rows);
829 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
831 sigbuffer_add_value (&buf, 0x07);
832 sigbuffer_add_value (&buf, nl);
833 for (i = 0; i < nl; ++i) {
834 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
837 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
839 encode_reflection_type (assembly, lb->type, &buf);
841 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
842 sigbuffer_free (&buf);
844 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
850 method_count_clauses (MonoReflectionILGen *ilgen)
852 guint32 num_clauses = 0;
855 MonoILExceptionInfo *ex_info;
856 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
857 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
858 if (ex_info->handlers)
859 num_clauses += mono_array_length (ex_info->handlers);
867 static MonoExceptionClause*
868 method_encode_clauses (MonoMemPool *mp, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
870 MonoExceptionClause *clauses;
871 MonoExceptionClause *clause;
872 MonoILExceptionInfo *ex_info;
873 MonoILExceptionBlock *ex_block;
874 guint32 finally_start;
875 int i, j, clause_index;;
877 clauses = mp_g_new0 (mp, MonoExceptionClause, num_clauses);
880 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
881 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
882 finally_start = ex_info->start + ex_info->len;
883 if (!ex_info->handlers)
885 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
886 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
887 clause = &(clauses [clause_index]);
889 clause->flags = ex_block->type;
890 clause->try_offset = ex_info->start;
892 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
893 clause->try_len = finally_start - ex_info->start;
895 clause->try_len = ex_info->len;
896 clause->handler_offset = ex_block->start;
897 clause->handler_len = ex_block->len;
898 if (ex_block->extype) {
899 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
901 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
902 clause->data.filter_offset = ex_block->filter_offset;
904 clause->data.filter_offset = 0;
906 finally_start = ex_block->start + ex_block->len;
916 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
922 gint32 num_locals = 0;
923 gint32 num_exception = 0;
926 char fat_header [12];
929 guint32 local_sig = 0;
930 guint32 header_size = 12;
933 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
934 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
938 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
940 code = mb->ilgen->code;
941 code_size = mb->ilgen->code_len;
942 max_stack = mb->ilgen->max_stack;
943 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
944 if (mb->ilgen->ex_handlers)
945 num_exception = method_count_clauses (mb->ilgen);
949 char *name = mono_string_to_utf8 (mb->name);
950 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
951 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
954 mono_raise_exception (exception);
957 code_size = mono_array_length (code);
958 max_stack = 8; /* we probably need to run a verifier on the code... */
961 stream_data_align (&assembly->code);
963 /* check for exceptions, maxstack, locals */
964 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
966 if (code_size < 64 && !(code_size & 1)) {
967 flags = (code_size << 2) | 0x2;
968 } else if (code_size < 32 && (code_size & 1)) {
969 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
973 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
974 /* add to the fixup todo list */
975 if (mb->ilgen && mb->ilgen->num_token_fixups)
976 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
977 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
978 return assembly->text_rva + idx;
982 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
984 * FIXME: need to set also the header size in fat_flags.
985 * (and more sects and init locals flags)
989 fat_flags |= METHOD_HEADER_MORE_SECTS;
991 fat_flags |= METHOD_HEADER_INIT_LOCALS;
992 fat_header [0] = fat_flags;
993 fat_header [1] = (header_size / 4 ) << 4;
994 short_value = GUINT16_TO_LE (max_stack);
995 memcpy (fat_header + 2, &short_value, 2);
996 int_value = GUINT32_TO_LE (code_size);
997 memcpy (fat_header + 4, &int_value, 4);
998 int_value = GUINT32_TO_LE (local_sig);
999 memcpy (fat_header + 8, &int_value, 4);
1000 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1001 /* add to the fixup todo list */
1002 if (mb->ilgen && mb->ilgen->num_token_fixups)
1003 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1005 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1006 if (num_exception) {
1007 unsigned char sheader [4];
1008 MonoILExceptionInfo * ex_info;
1009 MonoILExceptionBlock * ex_block;
1012 stream_data_align (&assembly->code);
1013 /* always use fat format for now */
1014 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1015 num_exception *= 6 * sizeof (guint32);
1016 num_exception += 4; /* include the size of the header */
1017 sheader [1] = num_exception & 0xff;
1018 sheader [2] = (num_exception >> 8) & 0xff;
1019 sheader [3] = (num_exception >> 16) & 0xff;
1020 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1021 /* fat header, so we are already aligned */
1023 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1024 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1025 if (ex_info->handlers) {
1026 int finally_start = ex_info->start + ex_info->len;
1027 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1029 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1031 val = GUINT32_TO_LE (ex_block->type);
1032 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1034 val = GUINT32_TO_LE (ex_info->start);
1035 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1036 /* need fault, too, probably */
1037 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1038 val = GUINT32_TO_LE (finally_start - ex_info->start);
1040 val = GUINT32_TO_LE (ex_info->len);
1041 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1042 /* handler offset */
1043 val = GUINT32_TO_LE (ex_block->start);
1044 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1046 val = GUINT32_TO_LE (ex_block->len);
1047 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1048 finally_start = ex_block->start + ex_block->len;
1049 if (ex_block->extype) {
1050 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1052 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1053 val = ex_block->filter_offset;
1057 val = GUINT32_TO_LE (val);
1058 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1059 /*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",
1060 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);*/
1063 g_error ("No clauses for ex info block %d", i);
1067 return assembly->text_rva + idx;
1071 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1074 MonoDynamicTable *table;
1077 table = &assembly->tables [table_idx];
1079 g_assert (col < table->columns);
1081 values = table->values + table->columns;
1082 for (i = 1; i <= table->rows; ++i) {
1083 if (values [col] == token)
1085 values += table->columns;
1091 * LOCKING: Acquires the loader lock.
1093 static MonoCustomAttrInfo*
1094 lookup_custom_attr (MonoImage *image, gpointer member)
1096 MonoCustomAttrInfo* res;
1098 mono_loader_lock ();
1099 res = mono_property_hash_lookup (image->property_hash, member, MONO_PROP_DYNAMIC_CATTR);
1100 mono_loader_unlock ();
1105 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1109 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1111 /* FIXME: Need to do more checks */
1112 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1113 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1115 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1122 static MonoCustomAttrInfo*
1123 mono_custom_attrs_from_builders (MonoMemPool *mp, MonoImage *image, MonoArray *cattrs)
1125 int i, index, count, not_visible;
1126 MonoCustomAttrInfo *ainfo;
1127 MonoReflectionCustomAttr *cattr;
1131 /* FIXME: check in assembly the Run flag is set */
1133 count = mono_array_length (cattrs);
1135 /* Skip nonpublic attributes since MS.NET seems to do the same */
1136 /* FIXME: This needs to be done more globally */
1138 for (i = 0; i < count; ++i) {
1139 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1140 if (!custom_attr_visible (image, cattr))
1143 count -= not_visible;
1145 ainfo = mp_g_malloc0 (mp, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1147 ainfo->image = image;
1148 ainfo->num_attrs = count;
1149 ainfo->cached = mp != NULL;
1151 mono_loader_lock ();
1152 for (i = 0; i < count; ++i) {
1153 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1154 if (custom_attr_visible (image, cattr)) {
1155 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1156 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1157 ainfo->attrs [index].ctor = cattr->ctor->method;
1158 ainfo->attrs [index].data = saved;
1159 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1163 mono_loader_unlock ();
1169 * LOCKING: Acquires the loader lock.
1172 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1174 MonoCustomAttrInfo *ainfo, *tmp;
1176 if (!cattrs || !mono_array_length (cattrs))
1179 ainfo = mono_custom_attrs_from_builders (image->mempool, image, cattrs);
1180 mono_loader_lock ();
1181 tmp = mono_property_hash_lookup (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR);
1183 mono_custom_attrs_free (tmp);
1184 mono_property_hash_insert (image->property_hash, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1185 mono_loader_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, 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 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1374 rmb->ilgen = mb->ilgen;
1375 rmb->rtype = mb->rtype;
1376 rmb->parameters = mb->parameters;
1377 rmb->generic_params = mb->generic_params;
1378 rmb->generic_container = mb->generic_container;
1379 rmb->opt_types = NULL;
1380 rmb->pinfo = mb->pinfo;
1381 rmb->attrs = mb->attrs;
1382 rmb->iattrs = mb->iattrs;
1383 rmb->call_conv = mb->call_conv;
1384 rmb->code = mb->code;
1385 rmb->type = mb->type;
1386 rmb->name = mb->name;
1387 rmb->table_idx = &mb->table_idx;
1388 rmb->init_locals = mb->init_locals;
1389 rmb->skip_visibility = FALSE;
1390 rmb->return_modreq = mb->return_modreq;
1391 rmb->return_modopt = mb->return_modopt;
1392 rmb->param_modreq = mb->param_modreq;
1393 rmb->param_modopt = mb->param_modopt;
1394 rmb->permissions = mb->permissions;
1395 rmb->mhandle = mb->mhandle;
1400 rmb->charset = mb->charset;
1401 rmb->extra_flags = mb->extra_flags;
1402 rmb->native_cc = mb->native_cc;
1403 rmb->dllentry = mb->dllentry;
1409 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1411 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1413 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1415 rmb->ilgen = mb->ilgen;
1416 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1417 rmb->parameters = mb->parameters;
1418 rmb->generic_params = NULL;
1419 rmb->generic_container = NULL;
1420 rmb->opt_types = NULL;
1421 rmb->pinfo = mb->pinfo;
1422 rmb->attrs = mb->attrs;
1423 rmb->iattrs = mb->iattrs;
1424 rmb->call_conv = mb->call_conv;
1426 rmb->type = mb->type;
1427 rmb->name = mono_string_new (mono_domain_get (), name);
1428 rmb->table_idx = &mb->table_idx;
1429 rmb->init_locals = mb->init_locals;
1430 rmb->skip_visibility = FALSE;
1431 rmb->return_modreq = NULL;
1432 rmb->return_modopt = NULL;
1433 rmb->param_modreq = mb->param_modreq;
1434 rmb->param_modopt = mb->param_modopt;
1435 rmb->permissions = mb->permissions;
1436 rmb->mhandle = mb->mhandle;
1442 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1444 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1446 rmb->ilgen = mb->ilgen;
1447 rmb->rtype = mb->rtype;
1448 rmb->parameters = mb->parameters;
1449 rmb->generic_params = NULL;
1450 rmb->generic_container = NULL;
1451 rmb->opt_types = NULL;
1453 rmb->attrs = mb->attrs;
1455 rmb->call_conv = mb->call_conv;
1457 rmb->type = (MonoObject *) mb->owner;
1458 rmb->name = mb->name;
1459 rmb->table_idx = NULL;
1460 rmb->init_locals = mb->init_locals;
1461 rmb->skip_visibility = mb->skip_visibility;
1462 rmb->return_modreq = NULL;
1463 rmb->return_modopt = NULL;
1464 rmb->param_modreq = NULL;
1465 rmb->param_modopt = NULL;
1466 rmb->permissions = NULL;
1467 rmb->mhandle = mb->mhandle;
1473 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1475 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1476 MonoDynamicTable *table;
1480 if (!mb->override_method)
1483 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1485 alloc_table (table, table->rows);
1486 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1487 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1488 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1490 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1491 switch (mono_metadata_token_table (tok)) {
1492 case MONO_TABLE_MEMBERREF:
1493 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1495 case MONO_TABLE_METHOD:
1496 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1499 g_assert_not_reached ();
1501 values [MONO_METHODIMPL_DECLARATION] = tok;
1505 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1507 MonoDynamicTable *table;
1509 ReflectionMethodBuilder rmb;
1512 reflection_methodbuilder_from_method_builder (&rmb, mb);
1514 mono_image_basic_method (&rmb, assembly);
1515 mb->table_idx = *rmb.table_idx;
1517 if (mb->dll) { /* It's a P/Invoke method */
1519 /* map CharSet values to on-disk values */
1520 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1521 int extra_flags = mb->extra_flags;
1522 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1524 alloc_table (table, table->rows);
1525 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1527 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1528 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1530 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1532 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1533 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1534 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1535 table = &assembly->tables [MONO_TABLE_MODULEREF];
1537 alloc_table (table, table->rows);
1538 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1539 values [MONO_IMPLMAP_SCOPE] = table->rows;
1543 if (mb->generic_params) {
1544 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1545 table->rows += mono_array_length (mb->generic_params);
1546 alloc_table (table, table->rows);
1547 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1548 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1550 mono_image_get_generic_param_info (
1551 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1558 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1560 ReflectionMethodBuilder rmb;
1562 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1564 mono_image_basic_method (&rmb, assembly);
1565 mb->table_idx = *rmb.table_idx;
1569 type_get_fully_qualified_name (MonoType *type)
1571 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1575 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1579 klass = my_mono_class_from_mono_type (type);
1581 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1582 ta = klass->image->assembly;
1583 if (ta->dynamic || (ta == ass)) {
1584 if (klass->generic_class || klass->generic_container)
1585 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1588 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1595 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1600 if (!assembly->save)
1603 sigbuffer_init (&buf, 32);
1605 sigbuffer_add_value (&buf, 0x06);
1606 /* encode custom attributes before the type */
1607 /* FIXME: This should probably go in encode_type () */
1608 if (type->num_mods) {
1609 for (i = 0; i < type->num_mods; ++i) {
1610 if (type->modifiers [i].required)
1611 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1613 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1614 sigbuffer_add_value (&buf, type->modifiers [i].token);
1617 encode_type (assembly, type, &buf);
1618 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1619 sigbuffer_free (&buf);
1624 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1629 sigbuffer_init (&buf, 32);
1631 sigbuffer_add_value (&buf, 0x06);
1632 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1633 /* encode custom attributes before the type */
1634 encode_reflection_type (assembly, fb->type, &buf);
1635 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1636 sigbuffer_free (&buf);
1641 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1642 char blob_size [64];
1643 char *b = blob_size;
1646 guint32 idx = 0, len = 0, dummy = 0;
1648 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1649 guint32 fpa_double [2];
1654 p = buf = g_malloc (64);
1656 *ret_type = MONO_TYPE_CLASS;
1658 box_val = (char*)&dummy;
1660 box_val = ((char*)val) + sizeof (MonoObject);
1661 *ret_type = val->vtable->klass->byval_arg.type;
1664 switch (*ret_type) {
1665 case MONO_TYPE_BOOLEAN:
1670 case MONO_TYPE_CHAR:
1687 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1688 fpa_p = (guint32*)box_val;
1689 fpa_double [0] = fpa_p [1];
1690 fpa_double [1] = fpa_p [0];
1691 box_val = (char*)fpa_double;
1695 case MONO_TYPE_VALUETYPE:
1696 if (val->vtable->klass->enumtype) {
1697 *ret_type = val->vtable->klass->enum_basetype->type;
1700 g_error ("we can't encode valuetypes");
1701 case MONO_TYPE_CLASS:
1703 case MONO_TYPE_STRING: {
1704 MonoString *str = (MonoString*)val;
1705 /* there is no signature */
1706 len = str->length * 2;
1707 mono_metadata_encode_value (len, b, &b);
1708 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1710 char *swapped = g_malloc (2 * mono_string_length (str));
1711 const char *p = (const char*)mono_string_chars (str);
1713 swap_with_size (swapped, p, 2, mono_string_length (str));
1714 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1718 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1724 case MONO_TYPE_GENERICINST:
1725 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1728 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1731 /* there is no signature */
1732 mono_metadata_encode_value (len, b, &b);
1733 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1734 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1735 swap_with_size (blob_size, box_val, len, 1);
1736 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1746 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1751 sigbuffer_init (&buf, 32);
1753 sigbuffer_add_value (&buf, minfo->type);
1755 switch (minfo->type) {
1756 case MONO_NATIVE_BYVALTSTR:
1757 case MONO_NATIVE_BYVALARRAY:
1758 sigbuffer_add_value (&buf, minfo->count);
1760 case MONO_NATIVE_LPARRAY:
1761 if (minfo->eltype || minfo->has_size) {
1762 sigbuffer_add_value (&buf, minfo->eltype);
1763 if (minfo->has_size) {
1764 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1765 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1767 /* LAMESPEC: ElemMult is undocumented */
1768 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1772 case MONO_NATIVE_CUSTOM:
1774 str = mono_string_to_utf8 (minfo->guid);
1776 sigbuffer_add_value (&buf, len);
1777 sigbuffer_add_mem (&buf, str, len);
1780 sigbuffer_add_value (&buf, 0);
1782 /* native type name */
1783 sigbuffer_add_value (&buf, 0);
1784 /* custom marshaler type name */
1785 if (minfo->marshaltype || minfo->marshaltyperef) {
1786 if (minfo->marshaltyperef)
1787 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1789 str = mono_string_to_utf8 (minfo->marshaltype);
1791 sigbuffer_add_value (&buf, len);
1792 sigbuffer_add_mem (&buf, str, len);
1795 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1796 sigbuffer_add_value (&buf, 0);
1798 if (minfo->mcookie) {
1799 str = mono_string_to_utf8 (minfo->mcookie);
1801 sigbuffer_add_value (&buf, len);
1802 sigbuffer_add_mem (&buf, str, len);
1805 sigbuffer_add_value (&buf, 0);
1811 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1812 sigbuffer_free (&buf);
1817 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1819 MonoDynamicTable *table;
1822 /* maybe this fixup should be done in the C# code */
1823 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1824 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1825 table = &assembly->tables [MONO_TABLE_FIELD];
1826 fb->table_idx = table->next_idx ++;
1827 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1828 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1829 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1830 values [MONO_FIELD_FLAGS] = fb->attrs;
1831 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1833 if (fb->offset != -1) {
1834 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1836 alloc_table (table, table->rows);
1837 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1838 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1839 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1841 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1842 guint32 field_type = 0;
1843 table = &assembly->tables [MONO_TABLE_CONSTANT];
1845 alloc_table (table, table->rows);
1846 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1847 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1848 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1849 values [MONO_CONSTANT_TYPE] = field_type;
1850 values [MONO_CONSTANT_PADDING] = 0;
1852 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1854 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1856 alloc_table (table, table->rows);
1857 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1858 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1860 * We store it in the code section because it's simpler for now.
1863 if (mono_array_length (fb->rva_data) >= 10)
1864 stream_data_align (&assembly->code);
1865 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1867 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1868 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1870 if (fb->marshal_info) {
1871 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1873 alloc_table (table, table->rows);
1874 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1875 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1876 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1881 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1884 guint32 nparams = 0;
1885 MonoReflectionMethodBuilder *mb = fb->get_method;
1886 MonoReflectionMethodBuilder *smb = fb->set_method;
1889 if (mb && mb->parameters)
1890 nparams = mono_array_length (mb->parameters);
1891 if (!mb && smb && smb->parameters)
1892 nparams = mono_array_length (smb->parameters) - 1;
1893 sigbuffer_init (&buf, 32);
1894 sigbuffer_add_byte (&buf, 0x08);
1895 sigbuffer_add_value (&buf, nparams);
1897 encode_reflection_type (assembly, mb->rtype, &buf);
1898 for (i = 0; i < nparams; ++i) {
1899 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1900 encode_reflection_type (assembly, pt, &buf);
1902 } else if (smb && smb->parameters) {
1903 /* the property type is the last param */
1904 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1905 for (i = 0; i < nparams; ++i) {
1906 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1907 encode_reflection_type (assembly, pt, &buf);
1910 encode_reflection_type (assembly, fb->type, &buf);
1913 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1914 sigbuffer_free (&buf);
1919 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1921 MonoDynamicTable *table;
1923 guint num_methods = 0;
1927 * we need to set things in the following tables:
1928 * PROPERTYMAP (info already filled in _get_type_info ())
1929 * PROPERTY (rows already preallocated in _get_type_info ())
1930 * METHOD (method info already done with the generic method code)
1933 table = &assembly->tables [MONO_TABLE_PROPERTY];
1934 pb->table_idx = table->next_idx ++;
1935 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1936 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1937 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1938 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1940 /* FIXME: we still don't handle 'other' methods */
1941 if (pb->get_method) num_methods ++;
1942 if (pb->set_method) num_methods ++;
1944 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1945 table->rows += num_methods;
1946 alloc_table (table, table->rows);
1948 if (pb->get_method) {
1949 semaidx = table->next_idx ++;
1950 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1951 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1952 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1953 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1955 if (pb->set_method) {
1956 semaidx = table->next_idx ++;
1957 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1958 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1959 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1960 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1965 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1967 MonoDynamicTable *table;
1969 guint num_methods = 0;
1973 * we need to set things in the following tables:
1974 * EVENTMAP (info already filled in _get_type_info ())
1975 * EVENT (rows already preallocated in _get_type_info ())
1976 * METHOD (method info already done with the generic method code)
1979 table = &assembly->tables [MONO_TABLE_EVENT];
1980 eb->table_idx = table->next_idx ++;
1981 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1982 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1983 values [MONO_EVENT_FLAGS] = eb->attrs;
1984 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1987 * FIXME: we still don't handle 'other' methods
1989 if (eb->add_method) num_methods ++;
1990 if (eb->remove_method) num_methods ++;
1991 if (eb->raise_method) num_methods ++;
1993 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1994 table->rows += num_methods;
1995 alloc_table (table, table->rows);
1997 if (eb->add_method) {
1998 semaidx = table->next_idx ++;
1999 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2000 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2001 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2002 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2004 if (eb->remove_method) {
2005 semaidx = table->next_idx ++;
2006 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2007 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2008 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2009 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2011 if (eb->raise_method) {
2012 semaidx = table->next_idx ++;
2013 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2014 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2015 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2016 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2021 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2023 MonoDynamicTable *table;
2024 guint32 num_constraints, i;
2028 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2029 num_constraints = gparam->iface_constraints ?
2030 mono_array_length (gparam->iface_constraints) : 0;
2031 table->rows += num_constraints;
2032 if (gparam->base_type)
2034 alloc_table (table, table->rows);
2036 if (gparam->base_type) {
2037 table_idx = table->next_idx ++;
2038 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2040 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2041 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2042 assembly, gparam->base_type->type);
2045 for (i = 0; i < num_constraints; i++) {
2046 MonoReflectionType *constraint = mono_array_get (
2047 gparam->iface_constraints, gpointer, i);
2049 table_idx = table->next_idx ++;
2050 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2052 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2053 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2054 assembly, constraint->type);
2059 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2061 GenericParamTableEntry *entry;
2064 * The GenericParam table must be sorted according to the `owner' field.
2065 * We need to do this sorting prior to writing the GenericParamConstraint
2066 * table, since we have to use the final GenericParam table indices there
2067 * and they must also be sorted.
2070 entry = g_new0 (GenericParamTableEntry, 1);
2071 entry->owner = owner;
2073 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2074 MONO_GC_REGISTER_ROOT (entry->gparam);
2076 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2078 g_ptr_array_add (assembly->gen_params, entry);
2082 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2084 MonoDynamicTable *table;
2085 MonoGenericParam *param;
2089 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2090 table_idx = table->next_idx ++;
2091 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2093 param = entry->gparam->type.type->data.generic_param;
2095 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2096 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2097 values [MONO_GENERICPARAM_NUMBER] = param->num;
2098 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2100 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2102 encode_constraints (entry->gparam, table_idx, assembly);
2106 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2108 MonoDynamicTable *table;
2111 guint32 cols [MONO_ASSEMBLY_SIZE];
2115 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2118 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2119 table = &assembly->tables [MONO_TABLE_MODULEREF];
2120 token = table->next_idx ++;
2122 alloc_table (table, table->rows);
2123 values = table->values + token * MONO_MODULEREF_SIZE;
2124 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2126 token <<= MONO_RESOLTION_SCOPE_BITS;
2127 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2128 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2133 if (image->assembly->dynamic)
2135 memset (cols, 0, sizeof (cols));
2137 /* image->assembly->image is the manifest module */
2138 image = image->assembly->image;
2139 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2142 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2143 token = table->next_idx ++;
2145 alloc_table (table, table->rows);
2146 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2147 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2148 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2149 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2150 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2151 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2152 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2153 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2154 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2156 if (strcmp ("", image->assembly->aname.culture)) {
2157 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2158 image->assembly->aname.culture);
2161 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2162 guchar pubtoken [9];
2164 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2165 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2167 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2169 token <<= MONO_RESOLTION_SCOPE_BITS;
2170 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2171 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2176 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2178 MonoDynamicTable *table;
2183 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2186 sigbuffer_init (&buf, 32);
2187 switch (type->type) {
2188 case MONO_TYPE_FNPTR:
2190 case MONO_TYPE_SZARRAY:
2191 case MONO_TYPE_ARRAY:
2193 case MONO_TYPE_MVAR:
2194 case MONO_TYPE_GENERICINST:
2195 encode_type (assembly, type, &buf);
2197 case MONO_TYPE_CLASS:
2198 case MONO_TYPE_VALUETYPE: {
2199 MonoClass *k = mono_class_from_mono_type (type);
2200 if (!k || !k->generic_container) {
2201 sigbuffer_free (&buf);
2204 encode_type (assembly, type, &buf);
2208 sigbuffer_free (&buf);
2212 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2213 if (assembly->save) {
2214 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2215 alloc_table (table, table->rows + 1);
2216 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2217 values [MONO_TYPESPEC_SIGNATURE] = token;
2219 sigbuffer_free (&buf);
2221 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2222 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2228 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2230 MonoDynamicTable *table;
2232 guint32 token, scope, enclosing;
2235 /* if the type requires a typespec, we must try that first*/
2236 if (try_typespec && (token = create_typespec (assembly, type)))
2238 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2241 klass = my_mono_class_from_mono_type (type);
2243 klass = mono_class_from_mono_type (type);
2246 * If it's in the same module and not a generic type parameter:
2248 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2249 (type->type != MONO_TYPE_MVAR)) {
2250 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2251 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2252 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2256 if (klass->nested_in) {
2257 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2258 /* get the typeref idx of the enclosing type */
2259 enclosing >>= MONO_TYPEDEFORREF_BITS;
2260 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2262 scope = resolution_scope_from_image (assembly, klass->image);
2264 table = &assembly->tables [MONO_TABLE_TYPEREF];
2265 if (assembly->save) {
2266 alloc_table (table, table->rows + 1);
2267 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2268 values [MONO_TYPEREF_SCOPE] = scope;
2269 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2270 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2272 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2273 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2275 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2280 * Despite the name, we handle also TypeSpec (with the above helper).
2283 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2285 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2289 * Insert a memberef row into the metadata: the token that point to the memberref
2290 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2291 * mono_image_get_fieldref_token()).
2292 * The sig param is an index to an already built signature.
2295 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2297 MonoDynamicTable *table;
2299 guint32 token, pclass;
2302 parent = mono_image_typedef_or_ref (assembly, type);
2303 switch (parent & MONO_TYPEDEFORREF_MASK) {
2304 case MONO_TYPEDEFORREF_TYPEREF:
2305 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2307 case MONO_TYPEDEFORREF_TYPESPEC:
2308 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2310 case MONO_TYPEDEFORREF_TYPEDEF:
2311 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2314 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2317 /* extract the index */
2318 parent >>= MONO_TYPEDEFORREF_BITS;
2320 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2322 if (assembly->save) {
2323 alloc_table (table, table->rows + 1);
2324 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2325 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2326 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2327 values [MONO_MEMBERREF_SIGNATURE] = sig;
2330 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2337 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2340 MonoMethodSignature *sig;
2342 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2347 * A methodref signature can't contain an unmanaged calling convention.
2349 sig = mono_metadata_signature_dup (mono_method_signature (method));
2350 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2351 sig->call_convention = MONO_CALL_DEFAULT;
2352 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2353 method->name, method_encode_signature (assembly, sig));
2355 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2360 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2363 ReflectionMethodBuilder rmb;
2366 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2370 name = mono_string_to_utf8 (method->name);
2371 reflection_methodbuilder_from_method_builder (&rmb, method);
2374 * A methodref signature can't contain an unmanaged calling convention.
2375 * Since some flags are encoded as part of call_conv, we need to check against it.
2377 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2378 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2379 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2380 name, method_builder_encode_signature (assembly, &rmb));
2383 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2388 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2389 const gchar *name, guint32 sig)
2391 MonoDynamicTable *table;
2395 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2397 if (assembly->save) {
2398 alloc_table (table, table->rows + 1);
2399 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2400 values [MONO_MEMBERREF_CLASS] = original;
2401 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2402 values [MONO_MEMBERREF_SIGNATURE] = sig;
2405 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2412 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2416 guint32 nparams = mono_array_length (mb->generic_params);
2419 if (!assembly->save)
2422 sigbuffer_init (&buf, 32);
2424 sigbuffer_add_value (&buf, 0xa);
2425 sigbuffer_add_value (&buf, nparams);
2427 for (i = 0; i < nparams; i++) {
2428 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2429 sigbuffer_add_value (&buf, i);
2432 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2433 sigbuffer_free (&buf);
2438 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2440 MonoDynamicTable *table;
2442 guint32 token, mtoken = 0;
2444 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2448 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2450 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2451 switch (mono_metadata_token_table (mtoken)) {
2452 case MONO_TABLE_MEMBERREF:
2453 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2455 case MONO_TABLE_METHOD:
2456 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2459 g_assert_not_reached ();
2462 if (assembly->save) {
2463 alloc_table (table, table->rows + 1);
2464 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2465 values [MONO_METHODSPEC_METHOD] = mtoken;
2466 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2469 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2472 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2477 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2481 if (mb->generic_params && create_methodspec)
2482 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2488 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2489 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2494 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2497 ReflectionMethodBuilder rmb;
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2504 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2506 name = mono_string_to_utf8 (rmb.name);
2507 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2508 name, method_builder_encode_signature (assembly, &rmb));
2511 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2516 is_field_on_inst (MonoClassField *field)
2518 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2522 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2525 get_field_on_inst_generic_type (MonoClassField *field)
2527 MonoDynamicGenericClass *dgclass;
2530 g_assert (is_field_on_inst (field));
2532 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2533 field_index = field - dgclass->fields;
2535 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2536 return dgclass->field_generic_types [field_index];
2540 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2544 MonoClassField *field;
2546 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2549 g_assert (f->field->parent);
2552 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2553 int index = field - field->parent->fields;
2554 type = field->parent->generic_class->container_class->fields [index].type;
2556 if (is_field_on_inst (f->field))
2557 type = get_field_on_inst_generic_type (f->field);
2559 type = f->field->type;
2561 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2562 f->field->name, fieldref_encode_signature (assembly, type));
2563 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2568 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2572 MonoGenericClass *gclass;
2573 MonoDynamicGenericClass *dgclass;
2574 MonoReflectionFieldBuilder *fb = f->fb;
2577 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2580 klass = mono_class_from_mono_type (f->inst->type.type);
2581 gclass = f->inst->type.type->data.generic_class;
2582 g_assert (gclass->is_dynamic);
2583 dgclass = (MonoDynamicGenericClass *) gclass;
2585 name = mono_string_to_utf8 (fb->name);
2586 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2587 field_encode_signature (assembly, fb));
2589 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2594 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2598 MonoGenericClass *gclass;
2599 MonoDynamicGenericClass *dgclass;
2600 MonoReflectionCtorBuilder *cb = c->cb;
2601 ReflectionMethodBuilder rmb;
2604 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2606 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2609 klass = mono_class_from_mono_type (c->inst->type.type);
2610 gclass = c->inst->type.type->data.generic_class;
2611 g_assert (gclass->is_dynamic);
2612 dgclass = (MonoDynamicGenericClass *) gclass;
2614 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2616 name = mono_string_to_utf8 (rmb.name);
2618 sig = method_builder_encode_signature (assembly, &rmb);
2620 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2623 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2628 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2632 MonoGenericClass *gclass;
2633 MonoReflectionMethodBuilder *mb = m->mb;
2634 ReflectionMethodBuilder rmb;
2637 if (create_methodspec && mb->generic_params)
2639 g_assert_not_reached ();
2641 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2644 klass = mono_class_from_mono_type (m->inst->type.type);
2645 gclass = m->inst->type.type->data.generic_class;
2646 g_assert (gclass->is_dynamic);
2648 reflection_methodbuilder_from_method_builder (&rmb, mb);
2650 name = mono_string_to_utf8 (rmb.name);
2652 sig = method_builder_encode_signature (assembly, &rmb);
2654 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2657 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2662 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2666 guint32 nparams = context->method_inst->type_argc;
2669 if (!assembly->save)
2672 sigbuffer_init (&buf, 32);
2674 * FIXME: vararg, explicit_this, differenc call_conv values...
2676 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2677 sigbuffer_add_value (&buf, nparams);
2679 for (i = 0; i < nparams; i++)
2680 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2682 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2683 sigbuffer_free (&buf);
2688 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2690 MonoDynamicTable *table;
2692 guint32 token, mtoken = 0, sig;
2693 MonoMethodInflated *imethod;
2694 MonoMethod *declaring;
2696 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2698 g_assert (method->is_inflated);
2699 imethod = (MonoMethodInflated *) method;
2700 declaring = imethod->declaring;
2702 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2703 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2705 if (!mono_method_signature (declaring)->generic_param_count)
2708 switch (mono_metadata_token_table (mtoken)) {
2709 case MONO_TABLE_MEMBERREF:
2710 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2712 case MONO_TABLE_METHOD:
2713 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2716 g_assert_not_reached ();
2719 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2721 if (assembly->save) {
2722 alloc_table (table, table->rows + 1);
2723 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2724 values [MONO_METHODSPEC_METHOD] = mtoken;
2725 values [MONO_METHODSPEC_SIGNATURE] = sig;
2728 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2735 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2737 MonoMethodInflated *imethod;
2740 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2744 g_assert (method->is_inflated);
2745 imethod = (MonoMethodInflated *) method;
2747 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2748 token = method_encode_methodspec (assembly, method);
2750 guint32 sig = method_encode_signature (
2751 assembly, mono_method_signature (imethod->declaring));
2752 token = mono_image_get_memberref_token (
2753 assembly, &method->klass->byval_arg, method->name, sig);
2756 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2761 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2763 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2766 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2767 token = mono_image_get_memberref_token (
2768 assembly, &m->klass->byval_arg, m->name, sig);
2774 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2776 MonoDynamicTable *table;
2784 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2785 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2786 * Because of this, we must not insert it into the `typeref' hash table.
2789 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2793 sigbuffer_init (&buf, 32);
2795 g_assert (tb->generic_params);
2796 klass = mono_class_from_mono_type (tb->type.type);
2798 if (tb->generic_container)
2799 mono_reflection_create_generic_class (tb);
2801 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2802 g_assert (klass->generic_container);
2803 sigbuffer_add_value (&buf, klass->byval_arg.type);
2804 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2806 count = mono_array_length (tb->generic_params);
2807 sigbuffer_add_value (&buf, count);
2808 for (i = 0; i < count; i++) {
2809 MonoReflectionGenericParam *gparam;
2811 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2813 encode_type (assembly, gparam->type.type, &buf);
2816 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2818 if (assembly->save) {
2819 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2820 alloc_table (table, table->rows + 1);
2821 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2822 values [MONO_TYPESPEC_SIGNATURE] = token;
2824 sigbuffer_free (&buf);
2826 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2827 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2833 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2836 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2838 int i, count, len, pos;
2843 count += mono_array_length (modreq);
2845 count += mono_array_length (modopt);
2848 return mono_metadata_type_dup (NULL, type);
2850 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2852 memcpy (t, type, len);
2854 t->num_mods = count;
2857 for (i = 0; i < mono_array_length (modreq); ++i) {
2858 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
2859 t->modifiers [pos].required = 1;
2860 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2865 for (i = 0; i < mono_array_length (modopt); ++i) {
2866 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
2867 t->modifiers [pos].required = 0;
2868 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2877 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2879 MonoDynamicTable *table;
2881 MonoType *custom = NULL;
2883 guint32 token, pclass, parent, sig;
2886 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2890 klass = mono_class_from_mono_type (fb->typeb->type);
2891 name = mono_string_to_utf8 (fb->name);
2893 /* fb->type does not include the custom modifiers */
2894 /* FIXME: We should do this in one place when a fieldbuilder is created */
2895 if (fb->modreq || fb->modopt) {
2896 custom = add_custom_modifiers (assembly, fb->type->type, fb->modreq, fb->modopt);
2897 sig = fieldref_encode_signature (assembly, custom);
2900 sig = fieldref_encode_signature (assembly, fb->type->type);
2903 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2904 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2906 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2907 parent >>= MONO_TYPEDEFORREF_BITS;
2909 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2911 if (assembly->save) {
2912 alloc_table (table, table->rows + 1);
2913 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2914 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2915 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2916 values [MONO_MEMBERREF_SIGNATURE] = sig;
2919 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2921 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2927 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2934 if (!assembly->save)
2937 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2938 g_assert (helper->type == 2);
2940 if (helper->arguments)
2941 nargs = mono_array_length (helper->arguments);
2945 size = 10 + (nargs * 10);
2947 sigbuffer_init (&buf, 32);
2949 /* Encode calling convention */
2950 /* Change Any to Standard */
2951 if ((helper->call_conv & 0x03) == 0x03)
2952 helper->call_conv = 0x01;
2953 /* explicit_this implies has_this */
2954 if (helper->call_conv & 0x40)
2955 helper->call_conv &= 0x20;
2957 if (helper->call_conv == 0) { /* Unmanaged */
2958 idx = helper->unmanaged_call_conv - 1;
2961 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2962 if (helper->call_conv & 0x02) /* varargs */
2966 sigbuffer_add_byte (&buf, idx);
2967 sigbuffer_add_value (&buf, nargs);
2968 encode_reflection_type (assembly, helper->return_type, &buf);
2969 for (i = 0; i < nargs; ++i) {
2970 MonoArray *modreqs = NULL;
2971 MonoArray *modopts = NULL;
2972 MonoReflectionType *pt;
2974 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
2975 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
2976 if (helper->modopts && (i < mono_array_length (helper->modopts)))
2977 modopts = mono_array_get (helper->modopts, MonoArray*, i);
2979 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
2980 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2981 encode_reflection_type (assembly, pt, &buf);
2983 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2984 sigbuffer_free (&buf);
2990 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2993 MonoDynamicTable *table;
2996 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2997 idx = table->next_idx ++;
2999 alloc_table (table, table->rows);
3000 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3002 values [MONO_STAND_ALONE_SIGNATURE] =
3003 mono_reflection_encode_sighelper (assembly, helper);
3009 reflection_cc_to_file (int call_conv) {
3010 switch (call_conv & 0x3) {
3012 case 1: return MONO_CALL_DEFAULT;
3013 case 2: return MONO_CALL_VARARG;
3015 g_assert_not_reached ();
3022 MonoMethodSignature *sig;
3028 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3033 MonoMethodSignature *sig;
3036 name = mono_string_to_utf8 (m->name);
3037 nparams = mono_array_length (m->parameters);
3038 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3040 sig->sentinelpos = -1;
3041 sig->call_convention = reflection_cc_to_file (m->call_conv);
3042 sig->param_count = nparams;
3043 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3044 for (i = 0; i < nparams; ++i) {
3045 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
3046 sig->params [i] = t->type;
3049 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3051 if (strcmp (name, am->name) == 0 &&
3052 mono_metadata_type_equal (am->parent, m->parent->type) &&
3053 mono_metadata_signature_equal (am->sig, sig)) {
3056 m->table_idx = am->token & 0xffffff;
3060 am = g_new0 (ArrayMethod, 1);
3063 am->parent = m->parent->type;
3064 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3065 method_encode_signature (assembly, sig));
3066 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3067 m->table_idx = am->token & 0xffffff;
3072 * Insert into the metadata tables all the info about the TypeBuilder tb.
3073 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3076 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3078 MonoDynamicTable *table;
3080 int i, is_object = 0, is_system = 0;
3083 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3084 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3085 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3086 n = mono_string_to_utf8 (tb->name);
3087 if (strcmp (n, "Object") == 0)
3089 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3091 n = mono_string_to_utf8 (tb->nspace);
3092 if (strcmp (n, "System") == 0)
3094 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3096 if (tb->parent && !(is_system && is_object) &&
3097 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3098 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
3100 values [MONO_TYPEDEF_EXTENDS] = 0;
3102 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3103 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3106 * if we have explicitlayout or sequentiallayouts, output data in the
3107 * ClassLayout table.
3109 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3110 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3111 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3113 alloc_table (table, table->rows);
3114 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3115 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3116 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3117 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3120 /* handle interfaces */
3121 if (tb->interfaces) {
3122 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3124 table->rows += mono_array_length (tb->interfaces);
3125 alloc_table (table, table->rows);
3126 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3127 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3128 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3129 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3130 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3131 values += MONO_INTERFACEIMPL_SIZE;
3137 table = &assembly->tables [MONO_TABLE_FIELD];
3138 table->rows += tb->num_fields;
3139 alloc_table (table, table->rows);
3140 for (i = 0; i < tb->num_fields; ++i)
3141 mono_image_get_field_info (
3142 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3145 /* handle constructors */
3147 table = &assembly->tables [MONO_TABLE_METHOD];
3148 table->rows += mono_array_length (tb->ctors);
3149 alloc_table (table, table->rows);
3150 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3151 mono_image_get_ctor_info (domain,
3152 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3155 /* handle methods */
3157 table = &assembly->tables [MONO_TABLE_METHOD];
3158 table->rows += tb->num_methods;
3159 alloc_table (table, table->rows);
3160 for (i = 0; i < tb->num_methods; ++i)
3161 mono_image_get_method_info (
3162 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3165 /* Do the same with properties etc.. */
3166 if (tb->events && mono_array_length (tb->events)) {
3167 table = &assembly->tables [MONO_TABLE_EVENT];
3168 table->rows += mono_array_length (tb->events);
3169 alloc_table (table, table->rows);
3170 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3172 alloc_table (table, table->rows);
3173 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3174 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3175 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3176 for (i = 0; i < mono_array_length (tb->events); ++i)
3177 mono_image_get_event_info (
3178 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3180 if (tb->properties && mono_array_length (tb->properties)) {
3181 table = &assembly->tables [MONO_TABLE_PROPERTY];
3182 table->rows += mono_array_length (tb->properties);
3183 alloc_table (table, table->rows);
3184 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3186 alloc_table (table, table->rows);
3187 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3188 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3189 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3190 for (i = 0; i < mono_array_length (tb->properties); ++i)
3191 mono_image_get_property_info (
3192 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3195 /* handle generic parameters */
3196 if (tb->generic_params) {
3197 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3198 table->rows += mono_array_length (tb->generic_params);
3199 alloc_table (table, table->rows);
3200 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3201 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3203 mono_image_get_generic_param_info (
3204 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3208 mono_image_add_decl_security (assembly,
3209 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3212 MonoDynamicTable *ntable;
3214 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3215 ntable->rows += mono_array_length (tb->subtypes);
3216 alloc_table (ntable, ntable->rows);
3217 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3219 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3220 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3222 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3223 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3224 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3225 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3226 mono_string_to_utf8 (tb->name), tb->table_idx,
3227 ntable->next_idx, ntable->rows);*/
3228 values += MONO_NESTED_CLASS_SIZE;
3235 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3239 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3241 if (!type->subtypes)
3244 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3245 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3246 collect_types (types, subtype);
3251 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3253 if ((*type1)->table_idx < (*type2)->table_idx)
3256 if ((*type1)->table_idx > (*type2)->table_idx)
3263 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3268 for (i = 0; i < mono_array_length (pinfo); ++i) {
3269 MonoReflectionParamBuilder *pb;
3270 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3273 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3278 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3281 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3283 for (i = 0; i < tb->num_fields; ++i) {
3284 MonoReflectionFieldBuilder* fb;
3285 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3286 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3290 for (i = 0; i < mono_array_length (tb->events); ++i) {
3291 MonoReflectionEventBuilder* eb;
3292 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3293 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3296 if (tb->properties) {
3297 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3298 MonoReflectionPropertyBuilder* pb;
3299 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3300 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3304 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3305 MonoReflectionCtorBuilder* cb;
3306 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3307 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3308 params_add_cattrs (assembly, cb->pinfo);
3313 for (i = 0; i < tb->num_methods; ++i) {
3314 MonoReflectionMethodBuilder* mb;
3315 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3316 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3317 params_add_cattrs (assembly, mb->pinfo);
3322 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3323 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3328 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3332 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3334 if (moduleb->global_methods) {
3335 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3336 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3337 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3338 params_add_cattrs (assembly, mb->pinfo);
3342 if (moduleb->global_fields) {
3343 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3344 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3345 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3349 if (moduleb->types) {
3350 for (i = 0; i < moduleb->num_types; ++i)
3351 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3356 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3358 MonoDynamicTable *table;
3362 char *b = blob_size;
3365 table = &assembly->tables [MONO_TABLE_FILE];
3367 alloc_table (table, table->rows);
3368 values = table->values + table->next_idx * MONO_FILE_SIZE;
3369 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3370 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3371 if (module->image->dynamic) {
3372 /* This depends on the fact that the main module is emitted last */
3373 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3374 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3377 path = g_strdup (module->image->name);
3379 mono_sha1_get_digest_from_file (path, hash);
3382 mono_metadata_encode_value (20, b, &b);
3383 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3384 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3389 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3391 MonoDynamicTable *table;
3394 table = &assembly->tables [MONO_TABLE_MODULE];
3395 mb->table_idx = table->next_idx ++;
3396 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3397 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3400 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3401 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3402 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3403 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3407 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3408 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3410 MonoDynamicTable *table;
3414 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3415 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3418 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3420 alloc_table (table, table->rows);
3421 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3423 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3424 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3425 if (klass->nested_in)
3426 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3428 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3429 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3430 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3432 res = table->next_idx;
3436 /* Emit nested types */
3437 if (klass->nested_classes) {
3440 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3441 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3448 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3449 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3454 klass = mono_class_from_mono_type (tb->type.type);
3456 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3458 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3459 parent_index, assembly);
3463 * We need to do this ourselves since klass->nested_classes is not set up.
3466 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3467 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3472 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3473 guint32 module_index, MonoDynamicImage *assembly)
3475 MonoImage *image = module->image;
3479 t = &image->tables [MONO_TABLE_TYPEDEF];
3481 for (i = 0; i < t->rows; ++i) {
3482 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3484 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3485 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3490 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3492 MonoDynamicTable *table;
3498 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3500 if (assemblyb->type_forwarders) {
3501 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3502 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3508 klass = mono_class_from_mono_type (t->type);
3510 scope = resolution_scope_from_image (assembly, klass->image);
3511 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3512 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3515 alloc_table (table, table->rows);
3516 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3518 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3519 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3520 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3521 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3522 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3529 #define align_pointer(base,p)\
3531 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3533 (p) += 4 - (__diff & 3);\
3537 compare_constants (const void *a, const void *b)
3539 const guint32 *a_values = a;
3540 const guint32 *b_values = b;
3541 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3545 compare_semantics (const void *a, const void *b)
3547 const guint32 *a_values = a;
3548 const guint32 *b_values = b;
3549 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3552 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3556 compare_custom_attrs (const void *a, const void *b)
3558 const guint32 *a_values = a;
3559 const guint32 *b_values = b;
3561 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3565 compare_field_marshal (const void *a, const void *b)
3567 const guint32 *a_values = a;
3568 const guint32 *b_values = b;
3570 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3574 compare_nested (const void *a, const void *b)
3576 const guint32 *a_values = a;
3577 const guint32 *b_values = b;
3579 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3583 compare_genericparam (const void *a, const void *b)
3585 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3586 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3588 if ((*b_entry)->owner == (*a_entry)->owner)
3590 (*a_entry)->gparam->type.type->data.generic_param->num -
3591 (*b_entry)->gparam->type.type->data.generic_param->num;
3593 return (*a_entry)->owner - (*b_entry)->owner;
3597 compare_declsecurity_attrs (const void *a, const void *b)
3599 const guint32 *a_values = a;
3600 const guint32 *b_values = b;
3602 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3606 compare_interface_impl (const void *a, const void *b)
3608 const guint32 *a_values = a;
3609 const guint32 *b_values = b;
3611 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3615 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3619 pad_heap (MonoDynamicStream *sh)
3621 if (sh->index & 3) {
3622 int sz = 4 - (sh->index & 3);
3623 memset (sh->data + sh->index, 0, sz);
3630 MonoDynamicStream *stream;
3634 * build_compressed_metadata() fills in the blob of data that represents the
3635 * raw metadata as it will be saved in the PE file. The five streams are output
3636 * and the metadata tables are comnpressed from the guint32 array representation,
3637 * to the compressed on-disk format.
3640 build_compressed_metadata (MonoDynamicImage *assembly)
3642 MonoDynamicTable *table;
3644 guint64 valid_mask = 0;
3645 guint64 sorted_mask;
3646 guint32 heapt_size = 0;
3647 guint32 meta_size = 256; /* allow for header and other stuff */
3648 guint32 table_offset;
3649 guint32 ntables = 0;
3655 struct StreamDesc stream_desc [5];
3657 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3658 for (i = 0; i < assembly->gen_params->len; i++){
3659 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3660 write_generic_param_entry (assembly, entry);
3663 stream_desc [0].name = "#~";
3664 stream_desc [0].stream = &assembly->tstream;
3665 stream_desc [1].name = "#Strings";
3666 stream_desc [1].stream = &assembly->sheap;
3667 stream_desc [2].name = "#US";
3668 stream_desc [2].stream = &assembly->us;
3669 stream_desc [3].name = "#Blob";
3670 stream_desc [3].stream = &assembly->blob;
3671 stream_desc [4].name = "#GUID";
3672 stream_desc [4].stream = &assembly->guid;
3674 /* tables that are sorted */
3675 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3676 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3677 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3678 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3679 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3680 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3681 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3683 /* Compute table sizes */
3684 /* the MonoImage has already been created in mono_image_basic_init() */
3685 meta = &assembly->image;
3687 /* sizes should be multiple of 4 */
3688 pad_heap (&assembly->blob);
3689 pad_heap (&assembly->guid);
3690 pad_heap (&assembly->sheap);
3691 pad_heap (&assembly->us);
3693 /* Setup the info used by compute_sizes () */
3694 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3695 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3696 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3698 meta_size += assembly->blob.index;
3699 meta_size += assembly->guid.index;
3700 meta_size += assembly->sheap.index;
3701 meta_size += assembly->us.index;
3703 for (i=0; i < MONO_TABLE_NUM; ++i)
3704 meta->tables [i].rows = assembly->tables [i].rows;
3706 for (i = 0; i < MONO_TABLE_NUM; i++){
3707 if (meta->tables [i].rows == 0)
3709 valid_mask |= (guint64)1 << i;
3711 meta->tables [i].row_size = mono_metadata_compute_size (
3712 meta, i, &meta->tables [i].size_bitfield);
3713 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3715 heapt_size += 24; /* #~ header size */
3716 heapt_size += ntables * 4;
3717 /* make multiple of 4 */
3720 meta_size += heapt_size;
3721 meta->raw_metadata = g_malloc0 (meta_size);
3722 p = (unsigned char*)meta->raw_metadata;
3723 /* the metadata signature */
3724 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3725 /* version numbers and 4 bytes reserved */
3726 int16val = (guint16*)p;
3727 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3728 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3730 /* version string */
3731 int32val = (guint32*)p;
3732 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3734 memcpy (p, meta->version, strlen (meta->version));
3735 p += GUINT32_FROM_LE (*int32val);
3736 align_pointer (meta->raw_metadata, p);
3737 int16val = (guint16*)p;
3738 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3739 *int16val = GUINT16_TO_LE (5); /* number of streams */
3743 * write the stream info.
3745 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3746 table_offset += 3; table_offset &= ~3;
3748 assembly->tstream.index = heapt_size;
3749 for (i = 0; i < 5; ++i) {
3750 int32val = (guint32*)p;
3751 stream_desc [i].stream->offset = table_offset;
3752 *int32val++ = GUINT32_TO_LE (table_offset);
3753 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3754 table_offset += GUINT32_FROM_LE (*int32val);
3755 table_offset += 3; table_offset &= ~3;
3757 strcpy ((char*)p, stream_desc [i].name);
3758 p += strlen (stream_desc [i].name) + 1;
3759 align_pointer (meta->raw_metadata, p);
3762 * now copy the data, the table stream header and contents goes first.
3764 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3765 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3766 int32val = (guint32*)p;
3767 *int32val = GUINT32_TO_LE (0); /* reserved */
3770 if (mono_framework_version () > 1) {
3771 *p++ = 2; /* version */
3774 *p++ = 1; /* version */
3778 if (meta->idx_string_wide)
3780 if (meta->idx_guid_wide)
3782 if (meta->idx_blob_wide)
3785 *p++ = 1; /* reserved */
3786 int64val = (guint64*)p;
3787 *int64val++ = GUINT64_TO_LE (valid_mask);
3788 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3790 int32val = (guint32*)p;
3791 for (i = 0; i < MONO_TABLE_NUM; i++){
3792 if (meta->tables [i].rows == 0)
3794 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3796 p = (unsigned char*)int32val;
3798 /* sort the tables that still need sorting */
3799 table = &assembly->tables [MONO_TABLE_CONSTANT];
3801 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3802 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3804 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3805 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3807 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3808 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3810 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3811 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3813 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3814 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3815 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3817 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3818 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3820 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3822 /* compress the tables */
3823 for (i = 0; i < MONO_TABLE_NUM; i++){
3826 guint32 bitfield = meta->tables [i].size_bitfield;
3827 if (!meta->tables [i].rows)
3829 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3830 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3831 meta->tables [i].base = (char*)p;
3832 for (row = 1; row <= meta->tables [i].rows; ++row) {
3833 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3834 for (col = 0; col < assembly->tables [i].columns; ++col) {
3835 switch (mono_metadata_table_size (bitfield, col)) {
3837 *p++ = values [col];
3840 *p++ = values [col] & 0xff;
3841 *p++ = (values [col] >> 8) & 0xff;
3844 *p++ = values [col] & 0xff;
3845 *p++ = (values [col] >> 8) & 0xff;
3846 *p++ = (values [col] >> 16) & 0xff;
3847 *p++ = (values [col] >> 24) & 0xff;
3850 g_assert_not_reached ();
3854 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3857 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3858 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3859 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3860 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3861 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3863 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3867 * Some tables in metadata need to be sorted according to some criteria, but
3868 * when methods and fields are first created with reflection, they may be assigned a token
3869 * that doesn't correspond to the final token they will get assigned after the sorting.
3870 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3871 * with the reflection objects that represent them. Once all the tables are set up, the
3872 * reflection objects will contains the correct table index. fixup_method() will fixup the
3873 * tokens for the method with ILGenerator @ilgen.
3876 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3878 guint32 code_idx = GPOINTER_TO_UINT (value);
3879 MonoReflectionILTokenInfo *iltoken;
3880 MonoReflectionFieldBuilder *field;
3881 MonoReflectionCtorBuilder *ctor;
3882 MonoReflectionMethodBuilder *method;
3883 MonoReflectionTypeBuilder *tb;
3884 MonoReflectionArrayMethod *am;
3886 unsigned char *target;
3888 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3889 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3890 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3891 switch (target [3]) {
3892 case MONO_TABLE_FIELD:
3893 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3894 field = (MonoReflectionFieldBuilder *)iltoken->member;
3895 idx = field->table_idx;
3896 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3897 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3898 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3900 g_assert_not_reached ();
3903 case MONO_TABLE_METHOD:
3904 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3905 method = (MonoReflectionMethodBuilder *)iltoken->member;
3906 idx = method->table_idx;
3907 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3908 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3909 idx = ctor->table_idx;
3910 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3911 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3912 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3913 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3915 g_assert_not_reached ();
3918 case MONO_TABLE_TYPEDEF:
3919 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3920 g_assert_not_reached ();
3921 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3922 idx = tb->table_idx;
3924 case MONO_TABLE_MEMBERREF:
3925 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3926 am = (MonoReflectionArrayMethod*)iltoken->member;
3927 idx = am->table_idx;
3928 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3929 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3930 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3931 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3932 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3933 g_assert (m->klass->generic_class || m->klass->generic_container);
3935 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3937 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3938 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3939 g_assert (is_field_on_inst (f));
3941 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3942 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3944 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3946 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3948 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3951 g_assert_not_reached ();
3954 case MONO_TABLE_METHODSPEC:
3955 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3956 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3957 g_assert (mono_method_signature (m)->generic_param_count);
3959 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3962 g_assert_not_reached ();
3966 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3968 target [0] = idx & 0xff;
3969 target [1] = (idx >> 8) & 0xff;
3970 target [2] = (idx >> 16) & 0xff;
3977 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3978 * value is not known when the table is emitted.
3981 fixup_cattrs (MonoDynamicImage *assembly)
3983 MonoDynamicTable *table;
3985 guint32 type, i, idx, token;
3988 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3990 for (i = 0; i < table->rows; ++i) {
3991 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3993 type = values [MONO_CUSTOM_ATTR_TYPE];
3994 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3995 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3996 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3997 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4000 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4001 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4002 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4003 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4010 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4012 MonoDynamicTable *table;
4015 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4017 alloc_table (table, table->rows);
4018 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4019 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4020 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4021 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4022 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4027 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4029 MonoDynamicTable *table;
4033 char *b = blob_size;
4035 guint32 idx, offset;
4037 if (rsrc->filename) {
4038 name = mono_string_to_utf8 (rsrc->filename);
4039 sname = g_path_get_basename (name);
4041 table = &assembly->tables [MONO_TABLE_FILE];
4043 alloc_table (table, table->rows);
4044 values = table->values + table->next_idx * MONO_FILE_SIZE;
4045 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4046 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4049 mono_sha1_get_digest_from_file (name, hash);
4050 mono_metadata_encode_value (20, b, &b);
4051 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4052 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4054 idx = table->next_idx++;
4056 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4062 data = mono_array_addr (rsrc->data, char, 0);
4063 len = mono_array_length (rsrc->data);
4069 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4070 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4071 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4072 mono_image_add_stream_data (&assembly->resources, data, len);
4076 * The entry should be emitted into the MANIFESTRESOURCE table of
4077 * the main module, but that needs to reference the FILE table
4078 * which isn't emitted yet.
4085 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4089 set_version_from_string (MonoString *version, guint32 *values)
4091 gchar *ver, *p, *str;
4094 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4095 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4096 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4097 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4100 ver = str = mono_string_to_utf8 (version);
4101 for (i = 0; i < 4; ++i) {
4102 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4108 /* handle Revision and Build */
4118 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4122 char *b = blob_size;
4127 len = mono_array_length (pkey);
4128 mono_metadata_encode_value (len, b, &b);
4129 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4130 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4132 assembly->public_key = g_malloc (len);
4133 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4134 assembly->public_key_len = len;
4136 /* Special case: check for ECMA key (16 bytes) */
4137 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4138 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4139 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4140 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4141 /* minimum key size (in 2.0) is 384 bits */
4142 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4144 /* FIXME - verifier */
4145 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4146 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4148 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4154 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4156 MonoDynamicTable *table;
4157 MonoDynamicImage *assembly;
4158 MonoReflectionAssemblyBuilder *assemblyb;
4162 guint32 module_index;
4164 assemblyb = moduleb->assemblyb;
4165 assembly = moduleb->dynamic_image;
4166 domain = mono_object_domain (assemblyb);
4168 /* Emit ASSEMBLY table */
4169 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4170 alloc_table (table, 1);
4171 values = table->values + MONO_ASSEMBLY_SIZE;
4172 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4173 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4174 if (assemblyb->culture) {
4175 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4177 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4179 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4180 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4181 set_version_from_string (assemblyb->version, values);
4183 /* Emit FILE + EXPORTED_TYPE table */
4185 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4187 MonoReflectionModuleBuilder *file_module =
4188 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4189 if (file_module != moduleb) {
4190 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4192 if (file_module->types) {
4193 for (j = 0; j < file_module->num_types; ++j) {
4194 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4195 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4200 if (assemblyb->loaded_modules) {
4201 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4202 MonoReflectionModule *file_module =
4203 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4204 mono_image_fill_file_table (domain, file_module, assembly);
4206 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4209 if (assemblyb->type_forwarders)
4210 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4212 /* Emit MANIFESTRESOURCE table */
4214 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4216 MonoReflectionModuleBuilder *file_module =
4217 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4218 /* The table for the main module is emitted later */
4219 if (file_module != moduleb) {
4221 if (file_module->resources) {
4222 int len = mono_array_length (file_module->resources);
4223 for (j = 0; j < len; ++j) {
4224 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4225 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4232 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4235 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4236 * for the modulebuilder @moduleb.
4237 * At the end of the process, method and field tokens are fixed up and the
4238 * on-disk compressed metadata representation is created.
4241 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4243 MonoDynamicTable *table;
4244 MonoDynamicImage *assembly;
4245 MonoReflectionAssemblyBuilder *assemblyb;
4251 assemblyb = moduleb->assemblyb;
4252 assembly = moduleb->dynamic_image;
4253 domain = mono_object_domain (assemblyb);
4255 if (assembly->text_rva)
4258 assembly->text_rva = START_TEXT_RVA;
4260 if (moduleb->is_main) {
4261 mono_image_emit_manifest (moduleb);
4264 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4265 table->rows = 1; /* .<Module> */
4267 alloc_table (table, table->rows);
4269 * Set the first entry.
4271 values = table->values + table->columns;
4272 values [MONO_TYPEDEF_FLAGS] = 0;
4273 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4274 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4275 values [MONO_TYPEDEF_EXTENDS] = 0;
4276 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4277 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4280 * handle global methods
4281 * FIXME: test what to do when global methods are defined in multiple modules.
4283 if (moduleb->global_methods) {
4284 table = &assembly->tables [MONO_TABLE_METHOD];
4285 table->rows += mono_array_length (moduleb->global_methods);
4286 alloc_table (table, table->rows);
4287 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4288 mono_image_get_method_info (
4289 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4291 if (moduleb->global_fields) {
4292 table = &assembly->tables [MONO_TABLE_FIELD];
4293 table->rows += mono_array_length (moduleb->global_fields);
4294 alloc_table (table, table->rows);
4295 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4296 mono_image_get_field_info (
4297 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4300 table = &assembly->tables [MONO_TABLE_MODULE];
4301 alloc_table (table, 1);
4302 mono_image_fill_module_table (domain, moduleb, assembly);
4304 /* Collect all types into a list sorted by their table_idx */
4305 types = g_ptr_array_new ();
4308 for (i = 0; i < moduleb->num_types; ++i) {
4309 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4310 collect_types (types, type);
4313 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4314 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4315 table->rows += types->len;
4316 alloc_table (table, table->rows);
4319 * Emit type names + namespaces at one place inside the string heap,
4320 * so load_class_names () needs to touch fewer pages.
4322 for (i = 0; i < types->len; ++i) {
4323 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4324 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4326 for (i = 0; i < types->len; ++i) {
4327 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4328 string_heap_insert_mstring (&assembly->sheap, tb->name);
4331 for (i = 0; i < types->len; ++i) {
4332 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4333 mono_image_get_type_info (domain, type, assembly);
4337 * table->rows is already set above and in mono_image_fill_module_table.
4339 /* add all the custom attributes at the end, once all the indexes are stable */
4340 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4342 /* CAS assembly permissions */
4343 if (assemblyb->permissions_minimum)
4344 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4345 if (assemblyb->permissions_optional)
4346 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4347 if (assemblyb->permissions_refused)
4348 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4350 module_add_cattrs (assembly, moduleb);
4353 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4355 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4356 * the final tokens and don't need another fixup pass. */
4358 if (moduleb->global_methods) {
4359 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4360 MonoReflectionMethodBuilder *mb = mono_array_get (
4361 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4362 mono_image_add_methodimpl (assembly, mb);
4366 for (i = 0; i < types->len; ++i) {
4367 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4368 if (type->methods) {
4369 for (j = 0; j < type->num_methods; ++j) {
4370 MonoReflectionMethodBuilder *mb = mono_array_get (
4371 type->methods, MonoReflectionMethodBuilder*, j);
4373 mono_image_add_methodimpl (assembly, mb);
4378 g_ptr_array_free (types, TRUE);
4380 fixup_cattrs (assembly);
4383 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4386 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4388 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4391 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4393 #ifndef DISABLE_REFLECTION_EMIT
4396 * mono_image_insert_string:
4397 * @module: module builder object
4400 * Insert @str into the user string stream of @module.
4403 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4405 MonoDynamicImage *assembly;
4410 MONO_ARCH_SAVE_REGS;
4412 if (!module->dynamic_image)
4413 mono_image_module_basic_init (module);
4415 assembly = module->dynamic_image;
4417 if (assembly->save) {
4418 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4419 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4420 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4422 char *swapped = g_malloc (2 * mono_string_length (str));
4423 const char *p = (const char*)mono_string_chars (str);
4425 swap_with_size (swapped, p, 2, mono_string_length (str));
4426 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4430 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4432 mono_image_add_stream_data (&assembly->us, "", 1);
4434 idx = assembly->us.index ++;
4437 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4439 return MONO_TOKEN_STRING | idx;
4443 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4448 klass = obj->vtable->klass;
4449 if (strcmp (klass->name, "MonoMethod") == 0) {
4450 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4451 MonoMethodSignature *sig, *old;
4452 guint32 sig_token, parent;
4455 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4457 nargs = mono_array_length (opt_param_types);
4458 old = mono_method_signature (method);
4459 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4461 sig->hasthis = old->hasthis;
4462 sig->explicit_this = old->explicit_this;
4463 sig->call_convention = old->call_convention;
4464 sig->generic_param_count = old->generic_param_count;
4465 sig->param_count = old->param_count + nargs;
4466 sig->sentinelpos = old->param_count;
4467 sig->ret = old->ret;
4469 for (i = 0; i < old->param_count; i++)
4470 sig->params [i] = old->params [i];
4472 for (i = 0; i < nargs; i++) {
4473 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4474 sig->params [old->param_count + i] = rt->type;
4477 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4478 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4479 parent >>= MONO_TYPEDEFORREF_BITS;
4481 parent <<= MONO_MEMBERREF_PARENT_BITS;
4482 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4484 sig_token = method_encode_signature (assembly, sig);
4485 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4486 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4487 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4488 ReflectionMethodBuilder rmb;
4489 guint32 parent, sig;
4492 reflection_methodbuilder_from_method_builder (&rmb, mb);
4493 rmb.opt_types = opt_param_types;
4495 sig = method_builder_encode_signature (assembly, &rmb);
4497 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4498 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4500 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4501 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4503 name = mono_string_to_utf8 (rmb.name);
4504 token = mono_image_get_varargs_method_token (
4505 assembly, parent, name, sig);
4508 g_error ("requested method token for %s\n", klass->name);
4515 * mono_image_create_token:
4516 * @assembly: a dynamic assembly
4518 * @register_token: Whenever to register the token in the assembly->tokens hash.
4520 * Get a token to insert in the IL code stream for the given MemberInfo.
4521 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4522 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4526 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4527 gboolean create_methodspec, gboolean register_token)
4532 klass = obj->vtable->klass;
4533 if (strcmp (klass->name, "MethodBuilder") == 0) {
4534 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4537 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4538 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4540 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4541 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4542 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4543 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4544 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4546 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4547 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4549 token = mono_image_get_ctorbuilder_token (assembly, mb);
4550 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4551 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4552 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4553 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4554 if (tb->generic_params) {
4555 token = mono_image_get_generic_field_token (assembly, fb);
4557 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4559 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4560 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4561 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4562 } else if (strcmp (klass->name, "MonoType") == 0) {
4563 MonoReflectionType *tb = (MonoReflectionType *)obj;
4564 MonoClass *mc = mono_class_from_mono_type (tb->type);
4565 token = mono_metadata_token_from_dor (
4566 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4567 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4568 MonoReflectionType *tb = (MonoReflectionType *)obj;
4569 token = mono_metadata_token_from_dor (
4570 mono_image_typedef_or_ref (assembly, tb->type));
4571 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4572 MonoReflectionType *tb = (MonoReflectionType *)obj;
4573 token = mono_metadata_token_from_dor (
4574 mono_image_typedef_or_ref (assembly, tb->type));
4575 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4576 strcmp (klass->name, "MonoMethod") == 0 ||
4577 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4578 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4579 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4580 if (m->method->is_inflated) {
4581 if (create_methodspec)
4582 token = mono_image_get_methodspec_token (assembly, m->method);
4584 token = mono_image_get_inflated_method_token (assembly, m->method);
4585 } else if ((m->method->klass->image == &assembly->image) &&
4586 !m->method->klass->generic_class) {
4587 static guint32 method_table_idx = 0xffffff;
4588 if (m->method->klass->wastypebuilder) {
4589 /* we use the same token as the one that was assigned
4590 * to the Methodbuilder.
4591 * FIXME: do the equivalent for Fields.
4593 token = m->method->token;
4596 * Each token should have a unique index, but the indexes are
4597 * assigned by managed code, so we don't know about them. An
4598 * easy solution is to count backwards...
4600 method_table_idx --;
4601 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4604 token = mono_image_get_methodref_token (assembly, m->method);
4606 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4607 } else if (strcmp (klass->name, "MonoField") == 0) {
4608 MonoReflectionField *f = (MonoReflectionField *)obj;
4609 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4610 static guint32 field_table_idx = 0xffffff;
4612 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4614 token = mono_image_get_fieldref_token (assembly, f);
4616 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4617 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4618 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4619 token = mono_image_get_array_token (assembly, m);
4620 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4621 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4622 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4623 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4624 MonoReflectionType *tb = (MonoReflectionType *)obj;
4625 token = mono_metadata_token_from_dor (
4626 mono_image_typedef_or_ref (assembly, tb->type));
4627 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4628 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4629 token = mono_image_get_field_on_inst_token (assembly, f);
4630 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4631 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4632 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4633 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4634 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4635 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4637 g_error ("requested token for %s\n", klass->name);
4641 mono_image_register_token (assembly, token, obj);
4647 * mono_image_register_token:
4649 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4650 * the Module.ResolveXXXToken () methods to work.
4653 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4655 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4657 /* There could be multiple MethodInfo objects with the same token */
4658 //g_assert (prev == obj);
4660 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4664 #endif /* DISABLE_REFLECTION_EMIT */
4667 guint32 import_lookup_table;
4671 guint32 import_address_table_rva;
4679 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4681 static MonoDynamicImage*
4682 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4684 static const guchar entrycode [16] = {0xff, 0x25, 0};
4685 MonoDynamicImage *image;
4688 const char *version;
4690 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4691 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4693 version = mono_get_runtime_info ()->runtime_version;
4696 image = GC_MALLOC (sizeof (MonoDynamicImage));
4698 image = g_new0 (MonoDynamicImage, 1);
4701 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4703 /*g_print ("created image %p\n", image);*/
4704 /* keep in sync with image.c */
4705 image->image.name = assembly_name;
4706 image->image.assembly_name = image->image.name; /* they may be different */
4707 image->image.module_name = module_name;
4708 image->image.version = g_strdup (version);
4709 image->image.md_version_major = 1;
4710 image->image.md_version_minor = 1;
4711 image->image.dynamic = TRUE;
4713 image->image.references = g_new0 (MonoAssembly*, 1);
4714 image->image.references [0] = NULL;
4716 mono_image_init (&image->image);
4718 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4719 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4720 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4721 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4722 image->handleref = g_hash_table_new (NULL, NULL);
4723 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4724 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4725 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4726 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4727 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4728 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4729 image->gen_params = g_ptr_array_new ();
4731 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4732 string_heap_init (&image->sheap);
4733 mono_image_add_stream_data (&image->us, "", 1);
4734 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4735 /* import tables... */
4736 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4737 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4738 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4739 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4740 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4741 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4742 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4743 stream_data_align (&image->code);
4745 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4747 for (i=0; i < MONO_TABLE_NUM; ++i) {
4748 image->tables [i].next_idx = 1;
4749 image->tables [i].columns = table_sizes [i];
4752 image->image.assembly = (MonoAssembly*)assembly;
4753 image->run = assembly->run;
4754 image->save = assembly->save;
4755 image->pe_kind = 0x1; /* ILOnly */
4756 image->machine = 0x14c; /* I386 */
4758 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4764 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4770 mono_dynamic_image_free (MonoDynamicImage *image)
4772 MonoDynamicImage *di = image;
4777 mono_g_hash_table_destroy (di->methodspec);
4779 g_hash_table_destroy (di->typespec);
4781 g_hash_table_destroy (di->typeref);
4783 g_hash_table_destroy (di->handleref);
4785 mono_g_hash_table_destroy (di->tokens);
4786 if (di->generic_def_objects)
4787 mono_g_hash_table_destroy (di->generic_def_objects);
4788 if (di->blob_cache) {
4789 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4790 g_hash_table_destroy (di->blob_cache);
4792 for (list = di->array_methods; list; list = list->next) {
4793 ArrayMethod *am = (ArrayMethod *)list->data;
4798 g_list_free (di->array_methods);
4799 if (di->gen_params) {
4800 for (i = 0; i < di->gen_params->len; i++) {
4801 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4802 if (entry->gparam->type.type) {
4803 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4804 g_free ((char*)param->name);
4806 g_free (entry->gparam->type.type);
4810 g_ptr_array_free (di->gen_params, TRUE);
4812 if (di->token_fixups)
4813 mono_g_hash_table_destroy (di->token_fixups);
4814 if (di->method_to_table_idx)
4815 g_hash_table_destroy (di->method_to_table_idx);
4816 if (di->field_to_table_idx)
4817 g_hash_table_destroy (di->field_to_table_idx);
4818 if (di->method_aux_hash)
4819 g_hash_table_destroy (di->method_aux_hash);
4820 g_free (di->strong_name);
4821 g_free (di->win32_res);
4823 g_free (di->public_key);
4825 /*g_print ("string heap destroy for image %p\n", di);*/
4826 mono_dynamic_stream_reset (&di->sheap);
4827 mono_dynamic_stream_reset (&di->code);
4828 mono_dynamic_stream_reset (&di->resources);
4829 mono_dynamic_stream_reset (&di->us);
4830 mono_dynamic_stream_reset (&di->blob);
4831 mono_dynamic_stream_reset (&di->tstream);
4832 mono_dynamic_stream_reset (&di->guid);
4833 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4834 g_free (di->tables [i].values);
4838 #ifndef DISABLE_REFLECTION_EMIT
4841 * mono_image_basic_init:
4842 * @assembly: an assembly builder object
4844 * Create the MonoImage that represents the assembly builder and setup some
4845 * of the helper hash table and the basic metadata streams.
4848 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4850 MonoDynamicAssembly *assembly;
4851 MonoDynamicImage *image;
4852 MonoDomain *domain = mono_object_domain (assemblyb);
4854 MONO_ARCH_SAVE_REGS;
4856 if (assemblyb->dynamic_assembly)
4860 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4862 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4865 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4867 assembly->assembly.ref_count = 1;
4868 assembly->assembly.dynamic = TRUE;
4869 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4870 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4871 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4872 if (assemblyb->culture)
4873 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4875 assembly->assembly.aname.culture = g_strdup ("");
4877 if (assemblyb->version) {
4878 char *vstr = mono_string_to_utf8 (assemblyb->version);
4879 char **version = g_strsplit (vstr, ".", 4);
4880 char **parts = version;
4881 assembly->assembly.aname.major = atoi (*parts++);
4882 assembly->assembly.aname.minor = atoi (*parts++);
4883 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4884 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4886 g_strfreev (version);
4889 assembly->assembly.aname.major = 0;
4890 assembly->assembly.aname.minor = 0;
4891 assembly->assembly.aname.build = 0;
4892 assembly->assembly.aname.revision = 0;
4895 assembly->run = assemblyb->access != 2;
4896 assembly->save = assemblyb->access != 1;
4898 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4899 image->initial_image = TRUE;
4900 assembly->assembly.aname.name = image->image.name;
4901 assembly->assembly.image = &image->image;
4903 mono_domain_assemblies_lock (domain);
4904 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4905 mono_domain_assemblies_unlock (domain);
4907 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4909 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4911 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4914 #endif /* DISABLE_REFLECTION_EMIT */
4917 calc_section_size (MonoDynamicImage *assembly)
4921 /* alignment constraints */
4922 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4923 g_assert ((assembly->code.index % 4) == 0);
4924 assembly->meta_size += 3;
4925 assembly->meta_size &= ~3;
4926 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4927 g_assert ((assembly->resources.index % 4) == 0);
4929 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4930 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4933 if (assembly->win32_res) {
4934 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4936 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4937 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4941 assembly->sections [MONO_SECTION_RELOC].size = 12;
4942 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4952 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4956 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4958 ResTreeNode *t1 = (ResTreeNode*)a;
4959 ResTreeNode *t2 = (ResTreeNode*)b;
4961 return t1->id - t2->id;
4965 * resource_tree_create:
4967 * Organize the resources into a resource tree.
4969 static ResTreeNode *
4970 resource_tree_create (MonoArray *win32_resources)
4972 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4976 tree = g_new0 (ResTreeNode, 1);
4978 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4979 MonoReflectionWin32Resource *win32_res =
4980 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4984 /* FIXME: BUG: this stores managed references in unmanaged memory */
4985 lang_node = g_new0 (ResTreeNode, 1);
4986 lang_node->id = win32_res->lang_id;
4987 lang_node->win32_res = win32_res;
4989 /* Create type node if neccesary */
4991 for (l = tree->children; l; l = l->next)
4992 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4993 type_node = (ResTreeNode*)l->data;
4998 type_node = g_new0 (ResTreeNode, 1);
4999 type_node->id = win32_res->res_type;
5002 * The resource types have to be sorted otherwise
5003 * Windows Explorer can't display the version information.
5005 tree->children = g_slist_insert_sorted (tree->children,
5006 type_node, resource_tree_compare_by_id);
5009 /* Create res node if neccesary */
5011 for (l = type_node->children; l; l = l->next)
5012 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5013 res_node = (ResTreeNode*)l->data;
5018 res_node = g_new0 (ResTreeNode, 1);
5019 res_node->id = win32_res->res_id;
5020 type_node->children = g_slist_append (type_node->children, res_node);
5023 res_node->children = g_slist_append (res_node->children, lang_node);
5030 * resource_tree_encode:
5032 * Encode the resource tree into the format used in the PE file.
5035 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5038 MonoPEResourceDir dir;
5039 MonoPEResourceDirEntry dir_entry;
5040 MonoPEResourceDataEntry data_entry;
5042 guint32 res_id_entries;
5045 * For the format of the resource directory, see the article
5046 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5050 memset (&dir, 0, sizeof (dir));
5051 memset (&dir_entry, 0, sizeof (dir_entry));
5052 memset (&data_entry, 0, sizeof (data_entry));
5054 g_assert (sizeof (dir) == 16);
5055 g_assert (sizeof (dir_entry) == 8);
5056 g_assert (sizeof (data_entry) == 16);
5058 node->offset = p - begin;
5060 /* IMAGE_RESOURCE_DIRECTORY */
5061 res_id_entries = g_slist_length (node->children);
5062 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5064 memcpy (p, &dir, sizeof (dir));
5067 /* Reserve space for entries */
5069 p += sizeof (dir_entry) * res_id_entries;
5071 /* Write children */
5072 for (l = node->children; l; l = l->next) {
5073 ResTreeNode *child = (ResTreeNode*)l->data;
5075 if (child->win32_res) {
5078 child->offset = p - begin;
5080 /* IMAGE_RESOURCE_DATA_ENTRY */
5081 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5082 size = mono_array_length (child->win32_res->res_data);
5083 data_entry.rde_size = GUINT32_TO_LE (size);
5085 memcpy (p, &data_entry, sizeof (data_entry));
5086 p += sizeof (data_entry);
5088 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5091 resource_tree_encode (child, begin, p, &p);
5095 /* IMAGE_RESOURCE_ENTRY */
5096 for (l = node->children; l; l = l->next) {
5097 ResTreeNode *child = (ResTreeNode*)l->data;
5099 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5100 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5102 memcpy (entries, &dir_entry, sizeof (dir_entry));
5103 entries += sizeof (dir_entry);
5110 resource_tree_free (ResTreeNode * node)
5113 for (list = node->children; list; list = list->next)
5114 resource_tree_free ((ResTreeNode*)list->data);
5115 g_slist_free(node->children);
5120 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5125 MonoReflectionWin32Resource *win32_res;
5128 if (!assemblyb->win32_resources)
5132 * Resources are stored in a three level tree inside the PE file.
5133 * - level one contains a node for each type of resource
5134 * - level two contains a node for each resource
5135 * - level three contains a node for each instance of a resource for a
5136 * specific language.
5139 tree = resource_tree_create (assemblyb->win32_resources);
5141 /* Estimate the size of the encoded tree */
5143 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5144 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5145 size += mono_array_length (win32_res->res_data);
5147 /* Directory structure */
5148 size += mono_array_length (assemblyb->win32_resources) * 256;
5149 p = buf = g_malloc (size);
5151 resource_tree_encode (tree, p, p, &p);
5153 g_assert (p - buf <= size);
5155 assembly->win32_res = g_malloc (p - buf);
5156 assembly->win32_res_size = p - buf;
5157 memcpy (assembly->win32_res, buf, p - buf);
5160 resource_tree_free (tree);
5164 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5166 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5169 p += sizeof (MonoPEResourceDir);
5170 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5171 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5172 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5173 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5174 fixup_resource_directory (res_section, child, rva);
5176 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5177 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5180 p += sizeof (MonoPEResourceDirEntry);
5185 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5188 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5189 g_error ("WriteFile returned %d\n", GetLastError ());
5192 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5195 * mono_image_create_pefile:
5196 * @mb: a module builder object
5198 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5199 * assembly->pefile where it can be easily retrieved later in chunks.
5202 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5204 MonoMSDOSHeader *msdos;
5205 MonoDotNetHeader *header;
5206 MonoSectionTable *section;
5207 MonoCLIHeader *cli_header;
5208 guint32 size, image_size, virtual_base, text_offset;
5209 guint32 header_start, section_start, file_offset, virtual_offset;
5210 MonoDynamicImage *assembly;
5211 MonoReflectionAssemblyBuilder *assemblyb;
5212 MonoDynamicStream pefile_stream = {0};
5213 MonoDynamicStream *pefile = &pefile_stream;
5215 guint32 *rva, value;
5217 static const unsigned char msheader[] = {
5218 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5219 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5222 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5223 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5224 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5225 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5228 assemblyb = mb->assemblyb;
5230 mono_image_basic_init (assemblyb);
5231 assembly = mb->dynamic_image;
5233 assembly->pe_kind = assemblyb->pe_kind;
5234 assembly->machine = assemblyb->machine;
5235 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5236 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5238 mono_image_build_metadata (mb);
5240 if (mb->is_main && assemblyb->resources) {
5241 int len = mono_array_length (assemblyb->resources);
5242 for (i = 0; i < len; ++i)
5243 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5246 if (mb->resources) {
5247 int len = mono_array_length (mb->resources);
5248 for (i = 0; i < len; ++i)
5249 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5252 build_compressed_metadata (assembly);
5255 assembly_add_win32_resources (assembly, assemblyb);
5257 nsections = calc_section_size (assembly);
5259 /* The DOS header and stub */
5260 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5261 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5263 /* the dotnet header */
5264 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5266 /* the section tables */
5267 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5269 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5270 virtual_offset = VIRT_ALIGN;
5273 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5274 if (!assembly->sections [i].size)
5277 file_offset += FILE_ALIGN - 1;
5278 file_offset &= ~(FILE_ALIGN - 1);
5279 virtual_offset += VIRT_ALIGN - 1;
5280 virtual_offset &= ~(VIRT_ALIGN - 1);
5282 assembly->sections [i].offset = file_offset;
5283 assembly->sections [i].rva = virtual_offset;
5285 file_offset += assembly->sections [i].size;
5286 virtual_offset += assembly->sections [i].size;
5287 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5290 file_offset += FILE_ALIGN - 1;
5291 file_offset &= ~(FILE_ALIGN - 1);
5293 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5295 /* back-patch info */
5296 msdos = (MonoMSDOSHeader*)pefile->data;
5297 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5299 header = (MonoDotNetHeader*)(pefile->data + header_start);
5300 header->pesig [0] = 'P';
5301 header->pesig [1] = 'E';
5303 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5304 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5305 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5306 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5307 if (assemblyb->pekind == 1) {
5309 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5312 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5315 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5317 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5318 header->pe.pe_major = 6;
5319 header->pe.pe_minor = 0;
5320 size = assembly->sections [MONO_SECTION_TEXT].size;
5321 size += FILE_ALIGN - 1;
5322 size &= ~(FILE_ALIGN - 1);
5323 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5324 size = assembly->sections [MONO_SECTION_RSRC].size;
5325 size += FILE_ALIGN - 1;
5326 size &= ~(FILE_ALIGN - 1);
5327 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5328 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5329 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5330 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5331 /* pe_rva_entry_point always at the beginning of the text section */
5332 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5334 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5335 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5336 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5337 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5338 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5339 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5340 size = section_start;
5341 size += FILE_ALIGN - 1;
5342 size &= ~(FILE_ALIGN - 1);
5343 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5345 size += VIRT_ALIGN - 1;
5346 size &= ~(VIRT_ALIGN - 1);
5347 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5350 // Translate the PEFileKind value to the value expected by the Windows loader
5356 // PEFileKinds.Dll == 1
5357 // PEFileKinds.ConsoleApplication == 2
5358 // PEFileKinds.WindowApplication == 3
5361 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5362 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5364 if (assemblyb->pekind == 3)
5369 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5371 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5372 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5373 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5374 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5375 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5376 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5378 /* fill data directory entries */
5380 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5381 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5383 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5384 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5386 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5387 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5388 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5389 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5390 /* patch entrypoint name */
5391 if (assemblyb->pekind == 1)
5392 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5394 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5395 /* patch imported function RVA name */
5396 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5397 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5399 /* the import table */
5400 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5401 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5402 /* patch imported dll RVA name and other entries in the dir */
5403 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5404 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5405 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5406 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5407 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5408 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5410 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5411 value = (assembly->text_rva + assembly->imp_names_offset);
5412 *p++ = (value) & 0xff;
5413 *p++ = (value >> 8) & (0xff);
5414 *p++ = (value >> 16) & (0xff);
5415 *p++ = (value >> 24) & (0xff);
5417 /* the CLI header info */
5418 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5419 cli_header->ch_size = GUINT32_FROM_LE (72);
5420 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5421 if (mono_framework_version () > 1)
5422 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5424 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5425 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5426 if (assemblyb->entry_point) {
5427 guint32 table_idx = 0;
5428 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5429 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5430 table_idx = methodb->table_idx;
5432 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5434 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5436 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5438 /* The embedded managed resources */
5439 text_offset = assembly->text_rva + assembly->code.index;
5440 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5441 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5442 text_offset += assembly->resources.index;
5443 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5444 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5445 text_offset += assembly->meta_size;
5446 if (assembly->strong_name_size) {
5447 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5448 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5449 text_offset += assembly->strong_name_size;
5452 /* write the section tables and section content */
5453 section = (MonoSectionTable*)(pefile->data + section_start);
5454 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5455 static const char section_names [][7] = {
5456 ".text", ".rsrc", ".reloc"
5458 if (!assembly->sections [i].size)
5460 strcpy (section->st_name, section_names [i]);
5461 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5462 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5463 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5464 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5465 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5466 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5467 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5471 checked_write_file (file, pefile->data, pefile->index);
5473 mono_dynamic_stream_reset (pefile);
5475 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5476 if (!assembly->sections [i].size)
5479 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5480 g_error ("SetFilePointer returned %d\n", GetLastError ());
5483 case MONO_SECTION_TEXT:
5484 /* patch entry point */
5485 p = (guchar*)(assembly->code.data + 2);
5486 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5487 *p++ = (value) & 0xff;
5488 *p++ = (value >> 8) & 0xff;
5489 *p++ = (value >> 16) & 0xff;
5490 *p++ = (value >> 24) & 0xff;
5492 checked_write_file (file, assembly->code.data, assembly->code.index);
5493 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5494 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5495 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5498 g_free (assembly->image.raw_metadata);
5500 case MONO_SECTION_RELOC: {
5504 guint16 type_and_offset;
5508 g_assert (sizeof (reloc) == 12);
5510 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5511 reloc.block_size = GUINT32_FROM_LE (12);
5514 * the entrypoint is always at the start of the text section
5515 * 3 is IMAGE_REL_BASED_HIGHLOW
5516 * 2 is patch_size_rva - text_rva
5518 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5521 checked_write_file (file, &reloc, sizeof (reloc));
5525 case MONO_SECTION_RSRC:
5526 if (assembly->win32_res) {
5528 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5529 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5530 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5534 g_assert_not_reached ();
5538 /* check that the file is properly padded */
5539 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5540 g_error ("SetFilePointer returned %d\n", GetLastError ());
5541 if (! SetEndOfFile (file))
5542 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5544 mono_dynamic_stream_reset (&assembly->code);
5545 mono_dynamic_stream_reset (&assembly->us);
5546 mono_dynamic_stream_reset (&assembly->blob);
5547 mono_dynamic_stream_reset (&assembly->guid);
5548 mono_dynamic_stream_reset (&assembly->sheap);
5550 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5551 g_hash_table_destroy (assembly->blob_cache);
5552 assembly->blob_cache = NULL;
5555 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5558 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5560 g_assert_not_reached ();
5563 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5565 #ifndef DISABLE_REFLECTION_EMIT
5567 MonoReflectionModule *
5568 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5572 MonoImageOpenStatus status;
5573 MonoDynamicAssembly *assembly;
5574 guint32 module_count;
5575 MonoImage **new_modules;
5576 gboolean *new_modules_loaded;
5578 name = mono_string_to_utf8 (fileName);
5580 image = mono_image_open (name, &status);
5583 if (status == MONO_IMAGE_ERROR_ERRNO)
5584 exc = mono_get_exception_file_not_found (fileName);
5586 exc = mono_get_exception_bad_image_format (name);
5588 mono_raise_exception (exc);
5593 assembly = ab->dynamic_assembly;
5594 image->assembly = (MonoAssembly*)assembly;
5596 module_count = image->assembly->image->module_count;
5597 new_modules = g_new0 (MonoImage *, module_count + 1);
5598 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5600 if (image->assembly->image->modules)
5601 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5602 if (image->assembly->image->modules_loaded)
5603 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5604 new_modules [module_count] = image;
5605 new_modules_loaded [module_count] = TRUE;
5606 mono_image_addref (image);
5608 g_free (image->assembly->image->modules);
5609 image->assembly->image->modules = new_modules;
5610 image->assembly->image->modules_loaded = new_modules_loaded;
5611 image->assembly->image->module_count ++;
5613 mono_assembly_load_references (image, &status);
5615 mono_image_close (image);
5616 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5619 return mono_module_get_object (mono_domain_get (), image);
5622 #endif /* DISABLE_REFLECTION_EMIT */
5625 * We need to return always the same object for MethodInfo, FieldInfo etc..
5626 * but we need to consider the reflected type.
5627 * type uses a different hash, since it uses custom hash/equal functions.
5632 MonoClass *refclass;
5636 reflected_equal (gconstpointer a, gconstpointer b) {
5637 const ReflectedEntry *ea = a;
5638 const ReflectedEntry *eb = b;
5640 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5644 reflected_hash (gconstpointer a) {
5645 const ReflectedEntry *ea = a;
5646 return mono_aligned_addr_hash (ea->item);
5649 #define CHECK_OBJECT(t,p,k) \
5655 mono_domain_lock (domain); \
5656 if (!domain->refobject_hash) \
5657 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5658 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5659 mono_domain_unlock (domain); \
5662 mono_domain_unlock (domain); \
5665 #ifndef HAVE_NULL_GC
5666 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5668 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5671 #define CACHE_OBJECT(t,p,o,k) \
5674 ReflectedEntry pe; \
5676 pe.refclass = (k); \
5677 mono_domain_lock (domain); \
5678 if (!domain->refobject_hash) \
5679 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5680 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5682 ReflectedEntry *e = ALLOC_REFENTRY; \
5684 e->refclass = (k); \
5685 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5688 mono_domain_unlock (domain); \
5693 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5695 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5699 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5701 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5704 #ifndef DISABLE_REFLECTION_EMIT
5707 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5709 MonoDynamicImage *image = moduleb->dynamic_image;
5710 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5713 MonoImage **new_modules;
5716 * FIXME: we already created an image in mono_image_basic_init (), but
5717 * we don't know which module it belongs to, since that is only
5718 * determined at assembly save time.
5720 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5721 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5723 moduleb->module.image = &image->image;
5724 moduleb->dynamic_image = image;
5725 register_module (mono_object_domain (moduleb), moduleb, image);
5727 /* register the module with the assembly */
5728 ass = ab->dynamic_assembly->assembly.image;
5729 module_count = ass->module_count;
5730 new_modules = g_new0 (MonoImage *, module_count + 1);
5733 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5734 new_modules [module_count] = &image->image;
5735 mono_image_addref (&image->image);
5737 g_free (ass->modules);
5738 ass->modules = new_modules;
5739 ass->module_count ++;
5746 * mono_assembly_get_object:
5747 * @domain: an app domain
5748 * @assembly: an assembly
5750 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5752 MonoReflectionAssembly*
5753 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5755 static MonoClass *System_Reflection_Assembly;
5756 MonoReflectionAssembly *res;
5758 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5759 if (!System_Reflection_Assembly)
5760 System_Reflection_Assembly = mono_class_from_name (
5761 mono_defaults.corlib, "System.Reflection", "Assembly");
5762 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5763 res->assembly = assembly;
5765 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5770 MonoReflectionModule*
5771 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5773 static MonoClass *System_Reflection_Module;
5774 MonoReflectionModule *res;
5777 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5778 if (!System_Reflection_Module)
5779 System_Reflection_Module = mono_class_from_name (
5780 mono_defaults.corlib, "System.Reflection", "Module");
5781 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5784 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5786 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5787 basename = g_path_get_basename (image->name);
5788 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5789 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5793 if (image->assembly->image == image) {
5794 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5798 if (image->assembly->image->modules) {
5799 for (i = 0; i < image->assembly->image->module_count; i++) {
5800 if (image->assembly->image->modules [i] == image)
5801 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5803 g_assert (res->token);
5807 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5810 MonoReflectionModule*
5811 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5813 static MonoClass *System_Reflection_Module;
5814 MonoReflectionModule *res;
5815 MonoTableInfo *table;
5816 guint32 cols [MONO_FILE_SIZE];
5818 guint32 i, name_idx;
5821 if (!System_Reflection_Module)
5822 System_Reflection_Module = mono_class_from_name (
5823 mono_defaults.corlib, "System.Reflection", "Module");
5824 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5826 table = &image->tables [MONO_TABLE_FILE];
5827 g_assert (table_index < table->rows);
5828 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5831 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5832 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5834 /* Check whenever the row has a corresponding row in the moduleref table */
5835 table = &image->tables [MONO_TABLE_MODULEREF];
5836 for (i = 0; i < table->rows; ++i) {
5837 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5838 val = mono_metadata_string_heap (image, name_idx);
5839 if (strcmp (val, name) == 0)
5840 res->image = image->modules [i];
5843 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5844 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5845 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5846 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5847 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5853 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5855 if ((t1->type != t2->type) ||
5856 (t1->byref != t2->byref))
5860 case MONO_TYPE_VOID:
5861 case MONO_TYPE_BOOLEAN:
5862 case MONO_TYPE_CHAR:
5873 case MONO_TYPE_STRING:
5876 case MONO_TYPE_OBJECT:
5877 case MONO_TYPE_TYPEDBYREF:
5879 case MONO_TYPE_VALUETYPE:
5880 case MONO_TYPE_CLASS:
5881 case MONO_TYPE_SZARRAY:
5882 return t1->data.klass == t2->data.klass;
5884 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5885 case MONO_TYPE_ARRAY:
5886 if (t1->data.array->rank != t2->data.array->rank)
5888 return t1->data.array->eklass == t2->data.array->eklass;
5889 case MONO_TYPE_GENERICINST: {
5891 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5892 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5893 if (i1->type_argc != i2->type_argc)
5895 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5896 &t2->data.generic_class->container_class->byval_arg))
5898 /* FIXME: we should probably just compare the instance pointers directly. */
5899 for (i = 0; i < i1->type_argc; ++i) {
5900 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5906 case MONO_TYPE_MVAR:
5907 return t1->data.generic_param == t2->data.generic_param;
5909 g_error ("implement type compare for %0x!", t1->type);
5917 mymono_metadata_type_hash (MonoType *t1)
5923 hash |= t1->byref << 6; /* do not collide with t1->type values */
5925 case MONO_TYPE_VALUETYPE:
5926 case MONO_TYPE_CLASS:
5927 case MONO_TYPE_SZARRAY:
5928 /* check if the distribution is good enough */
5929 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5931 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5932 case MONO_TYPE_GENERICINST: {
5934 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
5935 hash += g_str_hash (t1->data.generic_class->container_class->name);
5937 for (i = 0; i < inst->type_argc; ++i) {
5938 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5947 static MonoReflectionGenericClass*
5948 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5950 static MonoClass *System_Reflection_MonoGenericClass;
5951 MonoReflectionGenericClass *res;
5952 MonoClass *klass, *gklass;
5954 if (!System_Reflection_MonoGenericClass) {
5955 System_Reflection_MonoGenericClass = mono_class_from_name (
5956 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5957 g_assert (System_Reflection_MonoGenericClass);
5960 klass = mono_class_from_mono_type (geninst);
5961 gklass = klass->generic_class->container_class;
5963 mono_class_init (klass);
5966 /* FIXME: allow unpinned later */
5967 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
5969 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5972 res->type.type = geninst;
5973 g_assert (gklass->reflection_info);
5974 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
5975 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5981 verify_safe_for_managed_space (MonoType *type)
5983 switch (type->type) {
5985 case MONO_TYPE_ARRAY:
5986 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5988 return verify_safe_for_managed_space (type->data.type);
5989 case MONO_TYPE_SZARRAY:
5990 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5991 case MONO_TYPE_GENERICINST: {
5992 MonoGenericInst *inst = type->data.generic_class->inst;
5996 for (i = 0; i < inst->type_argc; ++i)
5997 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6003 case MONO_TYPE_MVAR:
6010 * mono_type_get_object:
6011 * @domain: an app domain
6014 * Return an System.MonoType object representing the type @type.
6017 mono_type_get_object (MonoDomain *domain, MonoType *type)
6019 MonoReflectionType *res;
6020 MonoClass *klass = mono_class_from_mono_type (type);
6022 /*we must avoid using @type as it might have come
6023 * from a mono_metadata_type_dup and the caller
6024 * expects that is can be freed.
6025 * Using the right type from
6027 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6030 * If the vtable of the given class was already created, we can use
6031 * the MonoType from there and avoid all locking and hash table lookups.
6033 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6034 * that the resulting object is diferent.
6036 if (type == &klass->byval_arg && !klass->image->dynamic) {
6037 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6038 if (vtable && vtable->type)
6039 return vtable->type;
6042 mono_domain_lock (domain);
6043 if (!domain->type_hash)
6044 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6045 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6046 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6047 mono_domain_unlock (domain);
6050 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6051 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6052 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6053 mono_g_hash_table_insert (domain->type_hash, type, res);
6054 mono_domain_unlock (domain);
6058 if (!verify_safe_for_managed_space (type)) {
6059 mono_domain_unlock (domain);
6060 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6063 if (klass->reflection_info && !klass->wastypebuilder) {
6064 /* g_assert_not_reached (); */
6065 /* should this be considered an error condition? */
6067 mono_domain_unlock (domain);
6068 return klass->reflection_info;
6071 // FIXME: Get rid of this, do it in the icalls for Type
6072 mono_class_init (klass);
6074 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6076 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6079 mono_g_hash_table_insert (domain->type_hash, type, res);
6080 mono_domain_unlock (domain);
6085 * mono_method_get_object:
6086 * @domain: an app domain
6088 * @refclass: the reflected type (can be NULL)
6090 * Return an System.Reflection.MonoMethod object representing the method @method.
6092 MonoReflectionMethod*
6093 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6096 * We use the same C representation for methods and constructors, but the type
6097 * name in C# is different.
6099 static MonoClass *System_Reflection_MonoMethod = NULL;
6100 static MonoClass *System_Reflection_MonoCMethod = NULL;
6101 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6102 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6104 MonoReflectionMethod *ret;
6107 * Don't let static RGCTX invoke wrappers get into
6108 * MonoReflectionMethods.
6110 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6111 method = mono_marshal_method_from_wrapper (method);
6113 if (method->is_inflated) {
6114 MonoReflectionGenericMethod *gret;
6116 refclass = method->klass;
6117 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6118 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6119 if (!System_Reflection_MonoGenericCMethod)
6120 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6121 klass = System_Reflection_MonoGenericCMethod;
6123 if (!System_Reflection_MonoGenericMethod)
6124 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6125 klass = System_Reflection_MonoGenericMethod;
6127 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6128 gret->method.method = method;
6129 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6130 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6131 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6135 refclass = method->klass;
6137 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6138 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6139 if (!System_Reflection_MonoCMethod)
6140 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6141 klass = System_Reflection_MonoCMethod;
6144 if (!System_Reflection_MonoMethod)
6145 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6146 klass = System_Reflection_MonoMethod;
6148 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6149 ret->method = method;
6150 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6151 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6155 * mono_field_get_object:
6156 * @domain: an app domain
6160 * Return an System.Reflection.MonoField object representing the field @field
6163 MonoReflectionField*
6164 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6166 MonoReflectionField *res;
6167 static MonoClass *monofield_klass;
6169 CHECK_OBJECT (MonoReflectionField *, field, klass);
6170 if (!monofield_klass)
6171 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6172 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6175 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
6176 if (is_field_on_inst (field))
6177 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6179 res->attrs = field->type->attrs;
6180 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6181 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6185 * mono_property_get_object:
6186 * @domain: an app domain
6188 * @property: a property
6190 * Return an System.Reflection.MonoProperty object representing the property @property
6193 MonoReflectionProperty*
6194 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6196 MonoReflectionProperty *res;
6197 static MonoClass *monoproperty_klass;
6199 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6200 if (!monoproperty_klass)
6201 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6202 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6204 res->property = property;
6205 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6209 * mono_event_get_object:
6210 * @domain: an app domain
6214 * Return an System.Reflection.MonoEvent object representing the event @event
6217 MonoReflectionEvent*
6218 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6220 MonoReflectionEvent *res;
6221 static MonoClass *monoevent_klass;
6223 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6224 if (!monoevent_klass)
6225 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6226 res = (MonoReflectionEvent *)mono_object_new (domain, monoevent_klass);
6229 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6233 * mono_get_reflection_missing_object:
6234 * @domain: Domain where the object lives
6236 * Returns the System.Reflection.Missing.Value singleton object
6237 * (of type System.Reflection.Missing).
6239 * Used as the value for ParameterInfo.DefaultValue when Optional
6243 mono_get_reflection_missing_object (MonoDomain *domain)
6246 static MonoClassField *missing_value_field = NULL;
6248 if (!missing_value_field) {
6249 MonoClass *missing_klass;
6250 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6251 mono_class_init (missing_klass);
6252 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6253 g_assert (missing_value_field);
6255 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6261 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6264 *dbnull = mono_get_dbnull_object (domain);
6269 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6271 if (!*reflection_missing)
6272 *reflection_missing = mono_get_reflection_missing_object (domain);
6273 return *reflection_missing;
6277 * mono_param_get_objects:
6278 * @domain: an app domain
6281 * Return an System.Reflection.ParameterInfo array object representing the parameters
6282 * in the method @method.
6285 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6287 static MonoClass *System_Reflection_ParameterInfo;
6288 static MonoClass *System_Reflection_ParameterInfo_array;
6289 MonoArray *res = NULL;
6290 MonoReflectionMethod *member = NULL;
6291 MonoReflectionParameter *param = NULL;
6292 char **names, **blobs = NULL;
6293 guint32 *types = NULL;
6294 MonoType *type = NULL;
6295 MonoObject *dbnull = NULL;
6296 MonoObject *missing = NULL;
6297 MonoMarshalSpec **mspecs;
6298 MonoMethodSignature *sig;
6299 MonoVTable *pinfo_vtable;
6302 if (!System_Reflection_ParameterInfo_array) {
6305 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6306 mono_memory_barrier ();
6307 System_Reflection_ParameterInfo = klass;
6309 klass = mono_array_class_get (klass, 1);
6310 mono_memory_barrier ();
6311 System_Reflection_ParameterInfo_array = klass;
6314 if (!mono_method_signature (method)->param_count)
6315 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6317 /* Note: the cache is based on the address of the signature into the method
6318 * since we already cache MethodInfos with the method as keys.
6320 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
6322 sig = mono_method_signature (method);
6323 member = mono_method_get_object (domain, method, NULL);
6324 names = g_new (char *, sig->param_count);
6325 mono_method_get_param_names (method, (const char **) names);
6327 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6328 mono_method_get_marshal_info (method, mspecs);
6330 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6331 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6332 for (i = 0; i < sig->param_count; ++i) {
6333 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6334 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6335 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6336 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6337 param->PositionImpl = i;
6338 param->AttrsImpl = sig->params [i]->attrs;
6340 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6341 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6342 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6344 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6348 blobs = g_new0 (char *, sig->param_count);
6349 types = g_new0 (guint32, sig->param_count);
6350 get_default_param_value_blobs (method, blobs, types);
6353 /* Build MonoType for the type from the Constant Table */
6355 type = g_new0 (MonoType, 1);
6356 type->type = types [i];
6357 type->data.klass = NULL;
6358 if (types [i] == MONO_TYPE_CLASS)
6359 type->data.klass = mono_defaults.object_class;
6360 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6361 /* For enums, types [i] contains the base type */
6363 type->type = MONO_TYPE_VALUETYPE;
6364 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6366 type->data.klass = mono_class_from_mono_type (type);
6368 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6370 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6371 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6372 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6373 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6375 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6381 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6383 mono_array_setref (res, i, param);
6390 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6392 mono_metadata_free_marshal_spec (mspecs [i]);
6395 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
6399 * mono_method_body_get_object:
6400 * @domain: an app domain
6403 * Return an System.Reflection.MethodBody object representing the method @method.
6405 MonoReflectionMethodBody*
6406 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6408 static MonoClass *System_Reflection_MethodBody = NULL;
6409 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6410 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6411 MonoReflectionMethodBody *ret;
6412 MonoMethodNormal *mn;
6413 MonoMethodHeader *header;
6414 guint32 method_rva, local_var_sig_token;
6416 unsigned char format, flags;
6419 if (!System_Reflection_MethodBody)
6420 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6421 if (!System_Reflection_LocalVariableInfo)
6422 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6423 if (!System_Reflection_ExceptionHandlingClause)
6424 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6426 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6428 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6429 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6430 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6431 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6433 mn = (MonoMethodNormal *)method;
6434 header = mono_method_get_header (method);
6436 /* Obtain local vars signature token */
6437 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6438 ptr = mono_image_rva_map (method->klass->image, method_rva);
6439 flags = *(const unsigned char *) ptr;
6440 format = flags & METHOD_HEADER_FORMAT_MASK;
6442 case METHOD_HEADER_TINY_FORMAT:
6443 case METHOD_HEADER_TINY_FORMAT1:
6444 local_var_sig_token = 0;
6446 case METHOD_HEADER_FAT_FORMAT:
6450 local_var_sig_token = read32 (ptr);
6453 g_assert_not_reached ();
6456 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6458 ret->init_locals = header->init_locals;
6459 ret->max_stack = header->max_stack;
6460 ret->local_var_sig_token = local_var_sig_token;
6461 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
6462 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6465 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6466 for (i = 0; i < header->num_locals; ++i) {
6467 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6468 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6469 info->is_pinned = header->locals [i]->pinned;
6470 info->local_index = i;
6471 mono_array_setref (ret->locals, i, info);
6475 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6476 for (i = 0; i < header->num_clauses; ++i) {
6477 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6478 MonoExceptionClause *clause = &header->clauses [i];
6480 info->flags = clause->flags;
6481 info->try_offset = clause->try_offset;
6482 info->try_length = clause->try_len;
6483 info->handler_offset = clause->handler_offset;
6484 info->handler_length = clause->handler_len;
6485 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6486 info->filter_offset = clause->data.filter_offset;
6487 else if (clause->data.catch_class)
6488 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6490 mono_array_setref (ret->clauses, i, info);
6493 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6498 * mono_get_dbnull_object:
6499 * @domain: Domain where the object lives
6501 * Returns the System.DBNull.Value singleton object
6503 * Used as the value for ParameterInfo.DefaultValue
6506 mono_get_dbnull_object (MonoDomain *domain)
6509 static MonoClassField *dbnull_value_field = NULL;
6511 if (!dbnull_value_field) {
6512 MonoClass *dbnull_klass;
6513 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6514 mono_class_init (dbnull_klass);
6515 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6516 g_assert (dbnull_value_field);
6518 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6524 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6526 guint32 param_index, i, lastp, crow = 0;
6527 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6530 MonoClass *klass = method->klass;
6531 MonoImage *image = klass->image;
6532 MonoMethodSignature *methodsig = mono_method_signature (method);
6534 MonoTableInfo *constt;
6535 MonoTableInfo *methodt;
6536 MonoTableInfo *paramt;
6538 if (!methodsig->param_count)
6541 mono_class_init (klass);
6543 if (klass->image->dynamic) {
6544 MonoReflectionMethodAux *aux;
6545 if (method->is_inflated)
6546 method = ((MonoMethodInflated*)method)->declaring;
6547 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6548 if (aux && aux->param_defaults) {
6549 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6550 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6555 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6556 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6557 constt = &image->tables [MONO_TABLE_CONSTANT];
6559 idx = mono_method_get_index (method) - 1;
6560 g_assert (idx != -1);
6562 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6563 if (idx + 1 < methodt->rows)
6564 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6566 lastp = paramt->rows + 1;
6568 for (i = param_index; i < lastp; ++i) {
6571 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6572 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6574 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6577 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6582 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6583 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6584 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6591 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6596 MonoType *basetype = type;
6601 klass = mono_class_from_mono_type (type);
6602 if (klass->valuetype) {
6603 object = mono_object_new (domain, klass);
6604 retval = ((gchar *) object + sizeof (MonoObject));
6605 if (klass->enumtype)
6606 basetype = klass->enum_basetype;
6611 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6618 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6622 memset (assembly, 0, sizeof (MonoAssemblyName));
6624 assembly->culture = "";
6625 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6627 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6630 while (g_ascii_isspace (*p) || *p == ',') {
6639 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6641 assembly->major = strtoul (p, &s, 10);
6642 if (s == p || *s != '.')
6645 assembly->minor = strtoul (p, &s, 10);
6646 if (s == p || *s != '.')
6649 assembly->build = strtoul (p, &s, 10);
6650 if (s == p || *s != '.')
6653 assembly->revision = strtoul (p, &s, 10);
6657 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6659 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6660 assembly->culture = "";
6663 assembly->culture = p;
6664 while (*p && *p != ',') {
6668 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6670 if (strncmp (p, "null", 4) == 0) {
6675 while (*p && *p != ',') {
6678 len = (p - start + 1);
6679 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6680 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6681 g_strlcpy ((char*)assembly->public_key_token, start, len);
6684 while (*p && *p != ',')
6688 while (g_ascii_isspace (*p) || *p == ',') {
6702 * mono_reflection_parse_type:
6705 * Parse a type name as accepted by the GetType () method and output the info
6706 * extracted in the info structure.
6707 * the name param will be mangled, so, make a copy before passing it to this function.
6708 * The fields in info will be valid until the memory pointed to by name is valid.
6710 * See also mono_type_get_name () below.
6712 * Returns: 0 on parse error.
6715 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6716 MonoTypeNameParse *info)
6718 char *start, *p, *w, *temp, *last_point, *startn;
6719 int in_modifiers = 0;
6720 int isbyref = 0, rank, arity = 0, i;
6722 start = p = w = name;
6724 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6725 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6726 info->name = info->name_space = NULL;
6727 info->nested = NULL;
6728 info->modifiers = NULL;
6729 info->type_arguments = NULL;
6731 /* last_point separates the namespace from the name */
6737 *p = 0; /* NULL terminate the name */
6739 info->nested = g_list_append (info->nested, startn);
6740 /* we have parsed the nesting namespace + name */
6744 info->name_space = start;
6746 info->name = last_point + 1;
6748 info->name_space = (char *)"";
6767 i = strtol (p, &temp, 10);
6784 info->name_space = start;
6786 info->name = last_point + 1;
6788 info->name_space = (char *)"";
6795 if (isbyref) /* only one level allowed by the spec */
6798 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6802 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6808 info->type_arguments = g_ptr_array_new ();
6809 for (i = 0; i < arity; i++) {
6810 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6811 gboolean fqname = FALSE;
6813 g_ptr_array_add (info->type_arguments, subinfo);
6820 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6831 while (*p && (*p != ']'))
6839 if (g_ascii_isspace (*aname)) {
6846 !assembly_name_to_aname (&subinfo->assembly, aname))
6850 if (i + 1 < arity) {
6870 else if (*p == '*') /* '*' means unknown lower bound */
6871 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6878 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6889 if (g_ascii_isspace (*p)) {
6896 return 0; /* missing assembly name */
6897 if (!assembly_name_to_aname (&info->assembly, p))
6903 if (info->assembly.name)
6906 // *w = 0; /* terminate class name */
6908 if (!info->name || !*info->name)
6912 /* add other consistency checks */
6917 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6919 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6923 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6925 gboolean type_resolve = FALSE;
6927 MonoImage *rootimage = image;
6929 if (info->assembly.name) {
6930 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6931 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
6933 * This could happen in the AOT compiler case when the search hook is not
6936 assembly = image->assembly;
6938 /* then we must load the assembly ourselve - see #60439 */
6939 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6943 image = assembly->image;
6944 } else if (!image) {
6945 image = mono_defaults.corlib;
6948 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6949 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6950 image = mono_defaults.corlib;
6951 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
6958 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6963 gboolean bounded = FALSE;
6966 image = mono_defaults.corlib;
6969 klass = mono_class_from_name_case (image, info->name_space, info->name);
6971 klass = mono_class_from_name (image, info->name_space, info->name);
6974 for (mod = info->nested; mod; mod = mod->next) {
6975 gpointer iter = NULL;
6979 mono_class_init (parent);
6981 while ((klass = mono_class_get_nested_types (parent, &iter))) {
6983 if (g_strcasecmp (klass->name, mod->data) == 0)
6986 if (strcmp (klass->name, mod->data) == 0)
6995 mono_class_init (klass);
6997 if (info->type_arguments) {
6998 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6999 MonoReflectionType *the_type;
7003 for (i = 0; i < info->type_arguments->len; i++) {
7004 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7006 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7007 if (!type_args [i]) {
7013 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7015 instance = mono_reflection_bind_generic_parameters (
7016 the_type, info->type_arguments->len, type_args);
7022 klass = mono_class_from_mono_type (instance);
7025 for (mod = info->modifiers; mod; mod = mod->next) {
7026 modval = GPOINTER_TO_UINT (mod->data);
7027 if (!modval) { /* byref: must be last modifier */
7028 return &klass->this_arg;
7029 } else if (modval == -1) {
7030 klass = mono_ptr_class_get (&klass->byval_arg);
7031 } else if (modval == -2) {
7033 } else { /* array rank */
7034 klass = mono_bounded_array_class_get (klass, modval, bounded);
7036 mono_class_init (klass);
7039 return &klass->byval_arg;
7043 * mono_reflection_get_type:
7044 * @image: a metadata context
7045 * @info: type description structure
7046 * @ignorecase: flag for case-insensitive string compares
7047 * @type_resolve: whenever type resolve was already tried
7049 * Build a MonoType from the type description in @info.
7054 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7055 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7059 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7061 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7065 g_assert (assembly->dynamic);
7067 /* Enumerate all modules */
7070 if (abuilder->modules) {
7071 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7072 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7073 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7079 if (!type && abuilder->loaded_modules) {
7080 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7081 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7082 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7092 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7095 MonoReflectionAssembly *assembly;
7099 if (image && image->dynamic)
7100 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7102 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7105 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7112 *type_resolve = TRUE;
7115 /* Reconstruct the type name */
7116 fullName = g_string_new ("");
7117 if (info->name_space && (info->name_space [0] != '\0'))
7118 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7120 g_string_printf (fullName, info->name);
7121 for (mod = info->nested; mod; mod = mod->next)
7122 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7124 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7126 if (assembly->assembly->dynamic)
7127 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7129 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7132 g_string_free (fullName, TRUE);
7137 mono_reflection_free_type_info (MonoTypeNameParse *info)
7139 g_list_free (info->modifiers);
7140 g_list_free (info->nested);
7142 if (info->type_arguments) {
7145 for (i = 0; i < info->type_arguments->len; i++) {
7146 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7148 mono_reflection_free_type_info (subinfo);
7149 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7153 g_ptr_array_free (info->type_arguments, TRUE);
7158 * mono_reflection_type_from_name:
7160 * @image: a metadata context (can be NULL).
7162 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7163 * it defaults to get the type from @image or, if @image is NULL or loading
7164 * from it fails, uses corlib.
7168 mono_reflection_type_from_name (char *name, MonoImage *image)
7170 MonoType *type = NULL;
7171 MonoTypeNameParse info;
7174 /* Make a copy since parse_type modifies its argument */
7175 tmp = g_strdup (name);
7177 /*g_print ("requested type %s\n", str);*/
7178 if (mono_reflection_parse_type (tmp, &info)) {
7179 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7183 mono_reflection_free_type_info (&info);
7188 * mono_reflection_get_token:
7190 * Return the metadata token of OBJ which should be an object
7191 * representing a metadata element.
7194 mono_reflection_get_token (MonoObject *obj)
7199 klass = obj->vtable->klass;
7201 if (strcmp (klass->name, "MethodBuilder") == 0) {
7202 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7204 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7205 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7206 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7208 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7209 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7210 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7212 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7213 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7214 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7215 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7216 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7217 } else if (strcmp (klass->name, "MonoType") == 0) {
7218 MonoReflectionType *tb = (MonoReflectionType *)obj;
7219 token = mono_class_from_mono_type (tb->type)->type_token;
7220 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7221 strcmp (klass->name, "MonoMethod") == 0 ||
7222 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7223 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7224 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7225 if (m->method->is_inflated) {
7226 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7227 return inflated->declaring->token;
7229 token = m->method->token;
7231 } else if (strcmp (klass->name, "MonoField") == 0) {
7232 MonoReflectionField *f = (MonoReflectionField*)obj;
7234 if (is_field_on_inst (f->field)) {
7235 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7236 int field_index = f->field - dgclass->fields;
7239 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7240 obj = dgclass->field_objects [field_index];
7241 return mono_reflection_get_token (obj);
7243 token = mono_class_get_field_token (f->field);
7244 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7245 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7247 token = mono_class_get_property_token (p->property);
7248 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7249 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
7251 token = mono_class_get_event_token (p->event);
7252 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7253 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7255 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7256 } else if (strcmp (klass->name, "Module") == 0) {
7257 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7260 } else if (strcmp (klass->name, "Assembly") == 0) {
7261 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7263 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7264 MonoException *ex = mono_get_exception_not_implemented (msg);
7266 mono_raise_exception (ex);
7273 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7275 int slen, type = t->type;
7276 MonoClass *tklass = t->data.klass;
7282 case MONO_TYPE_BOOLEAN: {
7283 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7288 case MONO_TYPE_CHAR:
7290 case MONO_TYPE_I2: {
7291 guint16 *val = g_malloc (sizeof (guint16));
7296 #if SIZEOF_VOID_P == 4
7302 case MONO_TYPE_I4: {
7303 guint32 *val = g_malloc (sizeof (guint32));
7308 #if SIZEOF_VOID_P == 8
7309 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7313 case MONO_TYPE_I8: {
7314 guint64 *val = g_malloc (sizeof (guint64));
7319 case MONO_TYPE_R8: {
7320 double *val = g_malloc (sizeof (double));
7325 case MONO_TYPE_VALUETYPE:
7326 if (t->data.klass->enumtype) {
7327 type = t->data.klass->enum_basetype->type;
7330 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7333 case MONO_TYPE_STRING:
7334 if (*p == (char)0xFF) {
7338 slen = mono_metadata_decode_value (p, &p);
7340 return mono_string_new_len (mono_domain_get (), p, slen);
7341 case MONO_TYPE_CLASS: {
7344 if (*p == (char)0xFF) {
7349 slen = mono_metadata_decode_value (p, &p);
7350 n = g_memdup (p, slen + 1);
7352 t = mono_reflection_type_from_name (n, image);
7354 g_warning ("Cannot load type '%s'", n);
7358 return mono_type_get_object (mono_domain_get (), t);
7362 case MONO_TYPE_OBJECT: {
7365 MonoClass *subc = NULL;
7370 } else if (subt == 0x0E) {
7371 type = MONO_TYPE_STRING;
7373 } else if (subt == 0x1D) {
7374 MonoType simple_type = {{0}};
7379 /* See Partition II, Appendix B3 */
7380 etype = MONO_TYPE_OBJECT;
7381 type = MONO_TYPE_SZARRAY;
7382 simple_type.type = etype;
7383 tklass = mono_class_from_mono_type (&simple_type);
7385 } else if (subt == 0x55) {
7388 slen = mono_metadata_decode_value (p, &p);
7389 n = g_memdup (p, slen + 1);
7391 t = mono_reflection_type_from_name (n, image);
7393 g_error ("Cannot load type '%s'", n);
7396 subc = mono_class_from_mono_type (t);
7397 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7398 MonoType simple_type = {{0}};
7399 simple_type.type = subt;
7400 subc = mono_class_from_mono_type (&simple_type);
7402 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7404 val = load_cattr_value (image, &subc->byval_arg, p, end);
7405 obj = mono_object_new (mono_domain_get (), subc);
7406 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7410 case MONO_TYPE_SZARRAY: {
7412 guint32 i, alen, basetype;
7415 if (alen == 0xffffffff) {
7419 arr = mono_array_new (mono_domain_get(), tklass, alen);
7420 basetype = tklass->byval_arg.type;
7421 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7422 basetype = tklass->enum_basetype->type;
7427 case MONO_TYPE_BOOLEAN:
7428 for (i = 0; i < alen; i++) {
7429 MonoBoolean val = *p++;
7430 mono_array_set (arr, MonoBoolean, i, val);
7433 case MONO_TYPE_CHAR:
7436 for (i = 0; i < alen; i++) {
7437 guint16 val = read16 (p);
7438 mono_array_set (arr, guint16, i, val);
7445 for (i = 0; i < alen; i++) {
7446 guint32 val = read32 (p);
7447 mono_array_set (arr, guint32, i, val);
7452 for (i = 0; i < alen; i++) {
7455 mono_array_set (arr, double, i, val);
7461 for (i = 0; i < alen; i++) {
7462 guint64 val = read64 (p);
7463 mono_array_set (arr, guint64, i, val);
7467 case MONO_TYPE_CLASS:
7468 case MONO_TYPE_OBJECT:
7469 case MONO_TYPE_STRING:
7470 for (i = 0; i < alen; i++) {
7471 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7472 mono_array_setref (arr, i, item);
7476 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7482 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7488 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7490 static MonoClass *klass;
7491 static MonoMethod *ctor;
7493 void *params [2], *unboxed;
7496 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7498 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7500 params [0] = mono_type_get_object (mono_domain_get (), t);
7502 retval = mono_object_new (mono_domain_get (), klass);
7503 unboxed = mono_object_unbox (retval);
7504 mono_runtime_invoke (ctor, unboxed, params, NULL);
7510 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7512 static MonoClass *klass;
7513 static MonoMethod *ctor;
7515 void *unboxed, *params [2];
7518 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7520 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7523 params [1] = typedarg;
7524 retval = mono_object_new (mono_domain_get (), klass);
7525 unboxed = mono_object_unbox (retval);
7526 mono_runtime_invoke (ctor, unboxed, params, NULL);
7532 type_is_reference (MonoType *type)
7534 switch (type->type) {
7535 case MONO_TYPE_BOOLEAN:
7536 case MONO_TYPE_CHAR:
7549 case MONO_TYPE_VALUETYPE:
7557 free_param_data (MonoMethodSignature *sig, void **params) {
7559 for (i = 0; i < sig->param_count; ++i) {
7560 if (!type_is_reference (sig->params [i]))
7561 g_free (params [i]);
7566 * Find the field index in the metadata FieldDef table.
7569 find_field_index (MonoClass *klass, MonoClassField *field) {
7572 for (i = 0; i < klass->field.count; ++i) {
7573 if (field == &klass->fields [i])
7574 return klass->field.first + 1 + i;
7580 * Find the property index in the metadata Property table.
7583 find_property_index (MonoClass *klass, MonoProperty *property) {
7586 for (i = 0; i < klass->property.count; ++i) {
7587 if (property == &klass->properties [i])
7588 return klass->property.first + 1 + i;
7594 * Find the event index in the metadata Event table.
7597 find_event_index (MonoClass *klass, MonoEvent *event) {
7600 for (i = 0; i < klass->event.count; ++i) {
7601 if (event == &klass->events [i])
7602 return klass->event.first + 1 + i;
7608 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7610 const char *p = (const char*)data;
7612 guint32 i, j, num_named;
7616 mono_class_init (method->klass);
7619 attr = mono_object_new (mono_domain_get (), method->klass);
7620 mono_runtime_invoke (method, attr, NULL, NULL);
7624 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7627 /*g_print ("got attr %s\n", method->klass->name);*/
7629 /* Allocate using alloca so it gets GC tracking */
7630 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
7634 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7635 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7639 attr = mono_object_new (mono_domain_get (), method->klass);
7640 mono_runtime_invoke (method, attr, params, NULL);
7641 free_param_data (method->signature, params);
7642 num_named = read16 (named);
7644 for (j = 0; j < num_named; j++) {
7646 char *name, named_type, data_type;
7647 named_type = *named++;
7648 data_type = *named++; /* type of data */
7649 if (data_type == MONO_TYPE_SZARRAY)
7650 data_type = *named++;
7651 if (data_type == MONO_TYPE_ENUM) {
7654 type_len = mono_metadata_decode_blob_size (named, &named);
7655 type_name = g_malloc (type_len + 1);
7656 memcpy (type_name, named, type_len);
7657 type_name [type_len] = 0;
7659 /* FIXME: lookup the type and check type consistency */
7662 name_len = mono_metadata_decode_blob_size (named, &named);
7663 name = g_malloc (name_len + 1);
7664 memcpy (name, named, name_len);
7665 name [name_len] = 0;
7667 if (named_type == 0x53) {
7668 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7669 void *val = load_cattr_value (image, field->type, named, &named);
7670 mono_field_set_value (attr, field, val);
7671 if (!type_is_reference (field->type))
7673 } else if (named_type == 0x54) {
7676 MonoType *prop_type;
7678 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7679 /* can we have more that 1 arg in a custom attr named property? */
7680 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7681 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7682 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7683 mono_property_set_value (prop, attr, pparams, NULL);
7684 if (!type_is_reference (prop_type))
7685 g_free (pparams [0]);
7694 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7696 MonoArray *typedargs, *namedargs;
7697 MonoClass *attrklass;
7698 static MonoMethod *ctor;
7701 const char *p = (const char*)data;
7703 guint32 i, j, num_named;
7706 mono_class_init (method->klass);
7709 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7711 domain = mono_domain_get ();
7713 /* This is for Attributes with no parameters */
7714 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7715 params [0] = mono_method_get_object (domain, method, NULL);
7716 params [1] = params [2] = NULL;
7717 mono_runtime_invoke (method, attr, params, NULL);
7721 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7724 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7728 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7729 MonoObject *obj, *typedarg;
7732 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7733 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7734 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7735 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7736 mono_array_setref (typedargs, i, typedarg);
7738 if (!type_is_reference (mono_method_signature (method)->params [i]))
7743 num_named = read16 (named);
7744 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7746 attrklass = method->klass;
7747 for (j = 0; j < num_named; j++) {
7749 char *name, named_type, data_type;
7750 named_type = *named++;
7751 data_type = *named++; /* type of data */
7752 if (data_type == MONO_TYPE_SZARRAY)
7753 data_type = *named++;
7754 if (data_type == MONO_TYPE_ENUM) {
7757 type_len = mono_metadata_decode_blob_size (named, &named);
7758 type_name = g_malloc (type_len + 1);
7759 memcpy (type_name, named, type_len);
7760 type_name [type_len] = 0;
7762 /* FIXME: lookup the type and check type consistency */
7765 name_len = mono_metadata_decode_blob_size (named, &named);
7766 name = g_malloc (name_len + 1);
7767 memcpy (name, named, name_len);
7768 name [name_len] = 0;
7770 if (named_type == 0x53) {
7771 MonoObject *obj, *typedarg, *namedarg;
7772 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7773 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7775 minfo = mono_field_get_object (domain, NULL, field);
7776 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7777 typedarg = create_cattr_typed_arg (field->type, obj);
7778 namedarg = create_cattr_named_arg (minfo, typedarg);
7779 mono_array_setref (namedargs, j, namedarg);
7780 if (!type_is_reference (field->type))
7782 } else if (named_type == 0x54) {
7783 MonoObject *obj, *typedarg, *namedarg;
7784 MonoType *prop_type;
7786 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7788 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7789 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7790 minfo = mono_property_get_object (domain, NULL, prop);
7791 val = load_cattr_value (image, prop_type, named, &named);
7792 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7793 typedarg = create_cattr_typed_arg (prop_type, obj);
7794 namedarg = create_cattr_named_arg (minfo, typedarg);
7795 mono_array_setref (namedargs, j, namedarg);
7796 if (!type_is_reference (prop_type))
7801 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7802 params [0] = mono_method_get_object (domain, method, NULL);
7803 params [1] = typedargs;
7804 params [2] = namedargs;
7805 mono_runtime_invoke (ctor, attr, params, NULL);
7810 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7816 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7817 for (i = 0; i < cinfo->num_attrs; ++i) {
7818 if (!cinfo->attrs [i].ctor)
7819 /* The cattr type is not finished yet */
7820 /* We should include the type name but cinfo doesn't contain it */
7821 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7822 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7823 mono_array_setref (result, i, attr);
7829 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7836 for (i = 0; i < cinfo->num_attrs; ++i) {
7837 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7841 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, n);
7843 for (i = 0; i < cinfo->num_attrs; ++i) {
7844 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7845 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7846 mono_array_setref (result, n, attr);
7854 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7860 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7861 for (i = 0; i < cinfo->num_attrs; ++i) {
7862 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7863 mono_array_setref (result, i, attr);
7869 * mono_custom_attrs_from_index:
7871 * Returns: NULL if no attributes are found or if a loading error occurs.
7874 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7876 guint32 mtoken, i, len;
7877 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7879 MonoCustomAttrInfo *ainfo;
7880 GList *tmp, *list = NULL;
7883 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7885 i = mono_metadata_custom_attrs_from_index (image, idx);
7889 while (i < ca->rows) {
7890 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7892 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7895 len = g_list_length (list);
7898 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7899 ainfo->num_attrs = len;
7900 ainfo->image = image;
7901 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7902 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7903 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7904 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7905 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7906 mtoken |= MONO_TOKEN_METHOD_DEF;
7908 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7909 mtoken |= MONO_TOKEN_MEMBER_REF;
7912 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7915 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7916 if (!ainfo->attrs [i].ctor) {
7917 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7922 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7923 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7924 ainfo->attrs [i].data = (guchar*)data;
7932 mono_custom_attrs_from_method (MonoMethod *method)
7937 * An instantiated method has the same cattrs as the generic method definition.
7939 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
7940 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
7942 if (method->is_inflated)
7943 method = ((MonoMethodInflated *) method)->declaring;
7945 if (method->dynamic || method->klass->image->dynamic)
7946 return lookup_custom_attr (method->klass->image, method);
7948 idx = mono_method_get_index (method);
7949 idx <<= MONO_CUSTOM_ATTR_BITS;
7950 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7951 return mono_custom_attrs_from_index (method->klass->image, idx);
7955 mono_custom_attrs_from_class (MonoClass *klass)
7959 if (klass->generic_class)
7960 klass = klass->generic_class->container_class;
7962 if (klass->image->dynamic)
7963 return lookup_custom_attr (klass->image, klass);
7965 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
7966 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
7967 idx <<= MONO_CUSTOM_ATTR_BITS;
7968 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
7970 idx = mono_metadata_token_index (klass->type_token);
7971 idx <<= MONO_CUSTOM_ATTR_BITS;
7972 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7974 return mono_custom_attrs_from_index (klass->image, idx);
7978 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7982 if (assembly->image->dynamic)
7983 return lookup_custom_attr (assembly->image, assembly);
7984 idx = 1; /* there is only one assembly */
7985 idx <<= MONO_CUSTOM_ATTR_BITS;
7986 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7987 return mono_custom_attrs_from_index (assembly->image, idx);
7990 static MonoCustomAttrInfo*
7991 mono_custom_attrs_from_module (MonoImage *image)
7996 return lookup_custom_attr (image, image);
7997 idx = 1; /* there is only one module */
7998 idx <<= MONO_CUSTOM_ATTR_BITS;
7999 idx |= MONO_CUSTOM_ATTR_MODULE;
8000 return mono_custom_attrs_from_index (image, idx);
8004 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8008 if (klass->image->dynamic) {
8009 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8010 return lookup_custom_attr (klass->image, property);
8012 idx = find_property_index (klass, property);
8013 idx <<= MONO_CUSTOM_ATTR_BITS;
8014 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8015 return mono_custom_attrs_from_index (klass->image, idx);
8019 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8023 if (klass->image->dynamic) {
8024 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8025 return lookup_custom_attr (klass->image, event);
8027 idx = find_event_index (klass, event);
8028 idx <<= MONO_CUSTOM_ATTR_BITS;
8029 idx |= MONO_CUSTOM_ATTR_EVENT;
8030 return mono_custom_attrs_from_index (klass->image, idx);
8034 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8037 if (klass->image->dynamic) {
8038 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8039 return lookup_custom_attr (klass->image, field);
8041 idx = find_field_index (klass, field);
8042 idx <<= MONO_CUSTOM_ATTR_BITS;
8043 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8044 return mono_custom_attrs_from_index (klass->image, idx);
8048 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8051 guint32 i, idx, method_index;
8052 guint32 param_list, param_last, param_pos, found;
8054 MonoReflectionMethodAux *aux;
8057 * An instantiated method has the same cattrs as the generic method definition.
8059 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8060 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8062 if (method->is_inflated)
8063 method = ((MonoMethodInflated *) method)->declaring;
8065 if (method->klass->image->dynamic) {
8066 MonoCustomAttrInfo *res, *ainfo;
8069 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8070 if (!aux || !aux->param_cattr)
8073 /* Need to copy since it will be freed later */
8074 ainfo = aux->param_cattr [param];
8075 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8076 res = g_malloc0 (size);
8077 memcpy (res, ainfo, size);
8081 image = method->klass->image;
8082 method_index = mono_method_get_index (method);
8083 ca = &image->tables [MONO_TABLE_METHOD];
8085 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8086 if (method_index == ca->rows) {
8087 ca = &image->tables [MONO_TABLE_PARAM];
8088 param_last = ca->rows + 1;
8090 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8091 ca = &image->tables [MONO_TABLE_PARAM];
8094 for (i = param_list; i < param_last; ++i) {
8095 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8096 if (param_pos == param) {
8104 idx <<= MONO_CUSTOM_ATTR_BITS;
8105 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8106 return mono_custom_attrs_from_index (image, idx);
8110 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8114 for (i = 0; i < ainfo->num_attrs; ++i) {
8115 klass = ainfo->attrs [i].ctor->klass;
8116 if (mono_class_has_parent (klass, attr_klass))
8123 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8130 for (i = 0; i < ainfo->num_attrs; ++i) {
8131 klass = ainfo->attrs [i].ctor->klass;
8132 if (mono_class_has_parent (klass, attr_klass)) {
8137 if (attr_index == -1)
8140 attrs = mono_custom_attrs_construct (ainfo);
8142 return mono_array_get (attrs, MonoObject*, attr_index);
8148 * mono_reflection_get_custom_attrs_info:
8149 * @obj: a reflection object handle
8151 * Return the custom attribute info for attributes defined for the
8152 * reflection handle @obj. The objects.
8155 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8158 MonoCustomAttrInfo *cinfo = NULL;
8160 klass = obj->vtable->klass;
8161 if (klass == mono_defaults.monotype_class) {
8162 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8163 klass = mono_class_from_mono_type (rtype->type);
8164 cinfo = mono_custom_attrs_from_class (klass);
8165 } else if (strcmp ("Assembly", klass->name) == 0) {
8166 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8167 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8168 } else if (strcmp ("Module", klass->name) == 0) {
8169 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8170 cinfo = mono_custom_attrs_from_module (module->image);
8171 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8172 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8173 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8174 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8175 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
8176 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8177 } else if (strcmp ("MonoField", klass->name) == 0) {
8178 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8179 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8180 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8181 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8182 cinfo = mono_custom_attrs_from_method (rmethod->method);
8183 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8184 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8185 cinfo = mono_custom_attrs_from_method (rmethod->method);
8186 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8187 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8188 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8189 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8190 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8191 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8192 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8193 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8194 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8195 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8196 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8197 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8198 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8199 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8200 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8201 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8202 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8203 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8204 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8205 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8206 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8207 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8208 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8209 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8210 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8211 } else { /* handle other types here... */
8212 g_error ("get custom attrs not yet supported for %s", klass->name);
8219 * mono_reflection_get_custom_attrs_by_type:
8220 * @obj: a reflection object handle
8222 * Return an array with all the custom attributes defined of the
8223 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8224 * of that type are returned. The objects are fully build. Return NULL if a loading error
8228 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8231 MonoCustomAttrInfo *cinfo;
8233 cinfo = mono_reflection_get_custom_attrs_info (obj);
8236 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8238 result = mono_custom_attrs_construct (cinfo);
8240 mono_custom_attrs_free (cinfo);
8242 if (mono_loader_get_last_error ())
8244 result = mono_array_new (mono_domain_get (), mono_defaults.attribute_class, 0);
8251 * mono_reflection_get_custom_attrs:
8252 * @obj: a reflection object handle
8254 * Return an array with all the custom attributes defined of the
8255 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8259 mono_reflection_get_custom_attrs (MonoObject *obj)
8261 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8265 * mono_reflection_get_custom_attrs_data:
8266 * @obj: a reflection obj handle
8268 * Returns an array of System.Reflection.CustomAttributeData,
8269 * which include information about attributes reflected on
8270 * types loaded using the Reflection Only methods
8273 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8276 MonoCustomAttrInfo *cinfo;
8278 cinfo = mono_reflection_get_custom_attrs_info (obj);
8280 result = mono_custom_attrs_data_construct (cinfo);
8282 mono_custom_attrs_free (cinfo);
8284 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8289 static MonoReflectionType*
8290 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8292 MonoMethod *method_get_underlying_system_type;
8294 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8295 mono_class_get_method_from_name (mono_object_class (t),
8296 "get_UnderlyingSystemType",
8298 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8302 mono_reflection_type_get_handle (MonoReflectionType* t)
8307 t = mono_reflection_type_get_underlying_system_type (t);
8315 * LOCKING: Assumes the loader lock is held.
8317 static MonoMethodSignature*
8318 parameters_to_signature (MonoMemPool *mp, MonoArray *parameters) {
8319 MonoMethodSignature *sig;
8322 count = parameters? mono_array_length (parameters): 0;
8324 sig = mp_g_malloc0 (mp, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8325 sig->param_count = count;
8326 sig->sentinelpos = -1; /* FIXME */
8327 for (i = 0; i < count; ++i) {
8328 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
8329 sig->params [i] = mono_reflection_type_get_handle (pt);
8335 * LOCKING: Assumes the loader lock is held.
8337 static MonoMethodSignature*
8338 ctor_builder_to_signature (MonoMemPool *mp, MonoReflectionCtorBuilder *ctor) {
8339 MonoMethodSignature *sig;
8341 sig = parameters_to_signature (mp, ctor->parameters);
8342 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8343 sig->ret = &mono_defaults.void_class->byval_arg;
8348 * LOCKING: Assumes the loader lock is held.
8350 static MonoMethodSignature*
8351 method_builder_to_signature (MonoMemPool *mp, MonoReflectionMethodBuilder *method) {
8352 MonoMethodSignature *sig;
8354 sig = parameters_to_signature (mp, method->parameters);
8355 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8356 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8357 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8361 static MonoMethodSignature*
8362 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8363 MonoMethodSignature *sig;
8365 sig = parameters_to_signature (NULL, method->parameters);
8366 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8367 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8368 sig->generic_param_count = 0;
8373 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8375 MonoClass *klass = mono_object_class (prop);
8376 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8377 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8378 *name = mono_string_to_utf8 (pb->name);
8379 *type = pb->type->type;
8381 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8382 *name = g_strdup (p->property->name);
8383 if (p->property->get)
8384 *type = mono_method_signature (p->property->get)->ret;
8386 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8391 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8393 MonoClass *klass = mono_object_class (field);
8394 if (strcmp (klass->name, "FieldBuilder") == 0) {
8395 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8396 *name = mono_string_to_utf8 (fb->name);
8397 *type = fb->type->type;
8399 MonoReflectionField *f = (MonoReflectionField *)field;
8400 *name = g_strdup (f->field->name);
8401 *type = f->field->type;
8406 * Encode a value in a custom attribute stream of bytes.
8407 * The value to encode is either supplied as an object in argument val
8408 * (valuetypes are boxed), or as a pointer to the data in the
8410 * @type represents the type of the value
8411 * @buffer is the start of the buffer
8412 * @p the current position in the buffer
8413 * @buflen contains the size of the buffer and is used to return the new buffer size
8414 * if this needs to be realloced.
8415 * @retbuffer and @retp return the start and the position of the buffer
8418 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8420 MonoTypeEnum simple_type;
8422 if ((p-buffer) + 10 >= *buflen) {
8425 newbuf = g_realloc (buffer, *buflen);
8426 p = newbuf + (p-buffer);
8430 argval = ((char*)arg + sizeof (MonoObject));
8431 simple_type = type->type;
8433 switch (simple_type) {
8434 case MONO_TYPE_BOOLEAN:
8439 case MONO_TYPE_CHAR:
8442 swap_with_size (p, argval, 2, 1);
8448 swap_with_size (p, argval, 4, 1);
8452 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8462 swap_with_size (p, argval, 8, 1);
8468 swap_with_size (p, argval, 8, 1);
8471 case MONO_TYPE_VALUETYPE:
8472 if (type->data.klass->enumtype) {
8473 simple_type = type->data.klass->enum_basetype->type;
8476 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8479 case MONO_TYPE_STRING: {
8486 str = mono_string_to_utf8 ((MonoString*)arg);
8487 slen = strlen (str);
8488 if ((p-buffer) + 10 + slen >= *buflen) {
8492 newbuf = g_realloc (buffer, *buflen);
8493 p = newbuf + (p-buffer);
8496 mono_metadata_encode_value (slen, p, &p);
8497 memcpy (p, str, slen);
8502 case MONO_TYPE_CLASS: {
8510 k = mono_object_class (arg);
8511 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8512 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8513 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8516 if (rt && (rtc = mono_object_class (rt)) &&
8517 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8518 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8519 arg = (MonoObject *) rt;
8522 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8525 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8526 slen = strlen (str);
8527 if ((p-buffer) + 10 + slen >= *buflen) {
8531 newbuf = g_realloc (buffer, *buflen);
8532 p = newbuf + (p-buffer);
8535 mono_metadata_encode_value (slen, p, &p);
8536 memcpy (p, str, slen);
8541 case MONO_TYPE_SZARRAY: {
8543 MonoClass *eclass, *arg_eclass;
8546 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8549 len = mono_array_length ((MonoArray*)arg);
8551 *p++ = (len >> 8) & 0xff;
8552 *p++ = (len >> 16) & 0xff;
8553 *p++ = (len >> 24) & 0xff;
8555 *retbuffer = buffer;
8556 eclass = type->data.klass;
8557 arg_eclass = mono_object_class (arg)->element_class;
8560 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8561 eclass = mono_defaults.object_class;
8563 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8564 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8565 int elsize = mono_class_array_element_size (arg_eclass);
8566 for (i = 0; i < len; ++i) {
8567 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8570 } else if (eclass->valuetype && arg_eclass->valuetype) {
8571 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8572 int elsize = mono_class_array_element_size (eclass);
8573 for (i = 0; i < len; ++i) {
8574 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8578 for (i = 0; i < len; ++i) {
8579 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8584 case MONO_TYPE_OBJECT: {
8590 * The parameter type is 'object' but the type of the actual
8591 * argument is not. So we have to add type information to the blob
8592 * too. This is completely undocumented in the spec.
8596 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8601 klass = mono_object_class (arg);
8603 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8606 } else if (klass->enumtype) {
8608 } else if (klass == mono_defaults.string_class) {
8609 simple_type = MONO_TYPE_STRING;
8612 } else if (klass->rank == 1) {
8614 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8615 /* See Partition II, Appendix B3 */
8618 *p++ = klass->element_class->byval_arg.type;
8619 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8621 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8622 *p++ = simple_type = klass->byval_arg.type;
8625 g_error ("unhandled type in custom attr");
8627 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8628 slen = strlen (str);
8629 if ((p-buffer) + 10 + slen >= *buflen) {
8633 newbuf = g_realloc (buffer, *buflen);
8634 p = newbuf + (p-buffer);
8637 mono_metadata_encode_value (slen, p, &p);
8638 memcpy (p, str, slen);
8641 simple_type = klass->enum_basetype->type;
8645 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8648 *retbuffer = buffer;
8652 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8654 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8655 char *str = type_get_qualified_name (type, NULL);
8656 int slen = strlen (str);
8660 * This seems to be optional...
8663 mono_metadata_encode_value (slen, p, &p);
8664 memcpy (p, str, slen);
8667 } else if (type->type == MONO_TYPE_OBJECT) {
8669 } else if (type->type == MONO_TYPE_CLASS) {
8670 /* it should be a type: encode_cattr_value () has the check */
8673 mono_metadata_encode_value (type->type, p, &p);
8674 if (type->type == MONO_TYPE_SZARRAY)
8675 /* See the examples in Partition VI, Annex B */
8676 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8683 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8686 /* Preallocate a large enough buffer */
8687 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8688 char *str = type_get_qualified_name (type, NULL);
8691 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8692 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8698 len += strlen (name);
8700 if ((p-buffer) + 20 + len >= *buflen) {
8704 newbuf = g_realloc (buffer, *buflen);
8705 p = newbuf + (p-buffer);
8709 encode_field_or_prop_type (type, p, &p);
8711 len = strlen (name);
8712 mono_metadata_encode_value (len, p, &p);
8713 memcpy (p, name, len);
8715 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8717 *retbuffer = buffer;
8720 #ifndef DISABLE_REFLECTION_EMIT
8723 * mono_reflection_get_custom_attrs_blob:
8724 * @ctor: custom attribute constructor
8725 * @ctorArgs: arguments o the constructor
8731 * Creates the blob of data that needs to be saved in the metadata and that represents
8732 * the custom attributed described by @ctor, @ctorArgs etc.
8733 * Returns: a Byte array representing the blob of data.
8736 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8739 MonoMethodSignature *sig;
8744 MONO_ARCH_SAVE_REGS;
8746 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8747 /* sig is freed later so allocate it in the heap */
8748 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8750 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8753 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8755 p = buffer = g_malloc (buflen);
8756 /* write the prolog */
8759 for (i = 0; i < sig->param_count; ++i) {
8760 arg = mono_array_get (ctorArgs, MonoObject*, i);
8761 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8765 i += mono_array_length (properties);
8767 i += mono_array_length (fields);
8769 *p++ = (i >> 8) & 0xff;
8772 for (i = 0; i < mono_array_length (properties); ++i) {
8776 prop = mono_array_get (properties, gpointer, i);
8777 get_prop_name_and_type (prop, &pname, &ptype);
8778 *p++ = 0x54; /* PROPERTY signature */
8779 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8786 for (i = 0; i < mono_array_length (fields); ++i) {
8790 field = mono_array_get (fields, gpointer, i);
8791 get_field_name_and_type (field, &fname, &ftype);
8792 *p++ = 0x53; /* FIELD signature */
8793 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8798 g_assert (p - buffer <= buflen);
8799 buflen = p - buffer;
8800 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8801 p = mono_array_addr (result, char, 0);
8802 memcpy (p, buffer, buflen);
8804 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8810 static void* reflection_info_desc = NULL;
8811 #define MOVING_GC_REGISTER(addr) do { \
8812 if (!reflection_info_desc) { \
8814 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
8816 mono_gc_register_root ((addr), sizeof (gpointer), reflection_info_desc); \
8819 #define MOVING_GC_REGISTER(addr)
8823 * mono_reflection_setup_internal_class:
8824 * @tb: a TypeBuilder object
8826 * Creates a MonoClass that represents the TypeBuilder.
8827 * This is a trick that lets us simplify a lot of reflection code
8828 * (and will allow us to support Build and Run assemblies easier).
8831 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8833 MonoClass *klass, *parent;
8835 MONO_ARCH_SAVE_REGS;
8837 mono_loader_lock ();
8840 /* check so we can compile corlib correctly */
8841 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8842 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8843 parent = tb->parent->type->data.klass;
8845 parent = my_mono_class_from_mono_type (tb->parent->type);
8851 /* the type has already being created: it means we just have to change the parent */
8852 if (tb->type.type) {
8853 klass = mono_class_from_mono_type (tb->type.type);
8854 klass->parent = NULL;
8855 /* fool mono_class_setup_parent */
8856 klass->supertypes = NULL;
8857 mono_class_setup_parent (klass, parent);
8858 mono_class_setup_mono_type (klass);
8859 mono_loader_unlock ();
8863 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8865 klass->image = &tb->module->dynamic_image->image;
8867 klass->inited = 1; /* we lie to the runtime */
8868 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8869 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8870 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8871 klass->flags = tb->attrs;
8873 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8875 klass->element_class = klass;
8877 MOVING_GC_REGISTER (&klass->reflection_info);
8878 klass->reflection_info = tb;
8880 /* Put into cache so mono_class_get () will find it */
8881 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8883 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8884 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8886 if (parent != NULL) {
8887 mono_class_setup_parent (klass, parent);
8888 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8889 const char *old_n = klass->name;
8890 /* trick to get relative numbering right when compiling corlib */
8891 klass->name = "BuildingObject";
8892 mono_class_setup_parent (klass, mono_defaults.object_class);
8893 klass->name = old_n;
8896 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8897 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8898 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8899 klass->instance_size = sizeof (MonoObject);
8900 klass->size_inited = 1;
8901 mono_class_setup_vtable_general (klass, NULL, 0);
8904 mono_class_setup_mono_type (klass);
8906 mono_class_setup_supertypes (klass);
8909 * FIXME: handle interfaces.
8912 tb->type.type = &klass->byval_arg;
8914 if (tb->nesting_type) {
8915 g_assert (tb->nesting_type->type);
8916 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8919 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8921 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
8923 mono_loader_unlock ();
8927 * mono_reflection_setup_generic_class:
8928 * @tb: a TypeBuilder object
8930 * Setup the generic class before adding the first generic parameter.
8933 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8937 MONO_ARCH_SAVE_REGS;
8939 klass = my_mono_class_from_mono_type (tb->type.type);
8940 if (tb->generic_container)
8943 tb->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8944 tb->generic_container->owner.klass = klass;
8948 * mono_reflection_create_generic_class:
8949 * @tb: a TypeBuilder object
8951 * Creates the generic class after all generic parameters have been added.
8954 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8959 MONO_ARCH_SAVE_REGS;
8961 klass = my_mono_class_from_mono_type (tb->type.type);
8963 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8965 if (klass->generic_container || (count == 0))
8968 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
8970 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
8972 klass->generic_container->owner.klass = klass;
8973 klass->generic_container->type_argc = count;
8974 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
8976 for (i = 0; i < count; i++) {
8977 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8978 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8979 /*Make sure we are a diferent type instance */
8980 klass->generic_container->type_params [i].owner = klass->generic_container;
8981 klass->generic_container->type_params [i].pklass = NULL;
8983 g_assert (klass->generic_container->type_params [i].owner);
8986 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
8990 * mono_reflection_create_internal_class:
8991 * @tb: a TypeBuilder object
8993 * Actually create the MonoClass that is associated with the TypeBuilder.
8996 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9000 MONO_ARCH_SAVE_REGS;
9002 klass = my_mono_class_from_mono_type (tb->type.type);
9004 mono_loader_lock ();
9005 if (klass->enumtype && klass->enum_basetype == NULL) {
9006 MonoReflectionFieldBuilder *fb;
9009 g_assert (tb->fields != NULL);
9010 g_assert (mono_array_length (tb->fields) >= 1);
9012 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9014 if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
9015 mono_loader_unlock ();
9019 klass->enum_basetype = fb->type->type;
9020 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
9021 if (!klass->element_class)
9022 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
9025 * get the element_class from the current corlib.
9027 ec = default_class_from_mono_type (klass->enum_basetype);
9028 klass->instance_size = ec->instance_size;
9029 klass->size_inited = 1;
9031 * this is almost safe to do with enums and it's needed to be able
9032 * to create objects of the enum type (for use in SetConstant).
9034 /* FIXME: Does this mean enums can't have method overrides ? */
9035 mono_class_setup_vtable_general (klass, NULL, 0);
9037 mono_loader_unlock ();
9040 #endif /* DISABLE_REFLECTION_EMIT */
9042 static MonoMarshalSpec*
9043 mono_marshal_spec_from_builder (MonoMemPool *mp, MonoAssembly *assembly,
9044 MonoReflectionMarshal *minfo)
9046 MonoMarshalSpec *res;
9048 res = mp_g_new0 (mp, MonoMarshalSpec, 1);
9049 res->native = minfo->type;
9051 switch (minfo->type) {
9052 case MONO_NATIVE_LPARRAY:
9053 res->data.array_data.elem_type = minfo->eltype;
9054 if (minfo->has_size) {
9055 res->data.array_data.param_num = minfo->param_num;
9056 res->data.array_data.num_elem = minfo->count;
9057 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9060 res->data.array_data.param_num = -1;
9061 res->data.array_data.num_elem = -1;
9062 res->data.array_data.elem_mult = -1;
9066 case MONO_NATIVE_BYVALTSTR:
9067 case MONO_NATIVE_BYVALARRAY:
9068 res->data.array_data.num_elem = minfo->count;
9071 case MONO_NATIVE_CUSTOM:
9072 if (minfo->marshaltyperef)
9073 res->data.custom_data.custom_name =
9074 type_get_fully_qualified_name (minfo->marshaltyperef->type);
9076 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9086 MonoReflectionMarshal*
9087 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9088 MonoMarshalSpec *spec)
9090 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9091 MonoReflectionMarshal *minfo;
9094 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9095 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9096 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9097 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9100 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9101 minfo->type = spec->native;
9103 switch (minfo->type) {
9104 case MONO_NATIVE_LPARRAY:
9105 minfo->eltype = spec->data.array_data.elem_type;
9106 minfo->count = spec->data.array_data.num_elem;
9107 minfo->param_num = spec->data.array_data.param_num;
9110 case MONO_NATIVE_BYVALTSTR:
9111 case MONO_NATIVE_BYVALARRAY:
9112 minfo->count = spec->data.array_data.num_elem;
9115 case MONO_NATIVE_CUSTOM:
9116 if (spec->data.custom_data.custom_name) {
9117 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9119 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9121 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9123 if (spec->data.custom_data.cookie)
9124 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9135 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9136 ReflectionMethodBuilder *rmb,
9137 MonoMethodSignature *sig)
9140 MonoMethodNormal *pm;
9141 MonoMarshalSpec **specs;
9142 MonoReflectionMethodAux *method_aux;
9148 * Methods created using a MethodBuilder should have their memory allocated
9149 * inside the image mempool, while dynamic methods should have their memory
9152 dynamic = rmb->refs != NULL;
9153 mp = dynamic ? NULL : klass->image->mempool;
9156 g_assert (!klass->generic_class);
9158 mono_loader_lock ();
9160 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9161 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9162 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodPInvoke, 1);
9164 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodWrapper, 1);
9166 m = (MonoMethod *)mp_g_new0 (mp, MonoMethodNormal, 1);
9168 pm = (MonoMethodNormal*)m;
9170 m->dynamic = dynamic;
9172 m->flags = rmb->attrs;
9173 m->iflags = rmb->iattrs;
9174 m->name = mp_string_to_utf8 (mp, rmb->name);
9177 m->skip_visibility = rmb->skip_visibility;
9179 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9181 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9182 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9185 m->signature->pinvoke = 1;
9186 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9187 m->signature->pinvoke = 1;
9189 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9191 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_mp (mp, rmb->dllentry) : mono_mempool_strdup (mp, m->name);
9192 method_aux->dll = mono_string_to_utf8_mp (mp, rmb->dll);
9194 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9196 if (klass->image->dynamic)
9197 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9199 mono_loader_unlock ();
9202 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9203 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9204 MonoMethodHeader *header;
9206 gint32 max_stack, i;
9207 gint32 num_locals = 0;
9208 gint32 num_clauses = 0;
9212 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9213 code_size = rmb->ilgen->code_len;
9214 max_stack = rmb->ilgen->max_stack;
9215 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9216 if (rmb->ilgen->ex_handlers)
9217 num_clauses = method_count_clauses (rmb->ilgen);
9220 code = mono_array_addr (rmb->code, guint8, 0);
9221 code_size = mono_array_length (rmb->code);
9222 /* we probably need to run a verifier on the code... */
9232 header = mp_g_malloc0 (mp, sizeof (MonoMethodHeader) +
9233 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9234 header->code_size = code_size;
9235 header->code = mp_g_malloc (mp, code_size);
9236 memcpy ((char*)header->code, code, code_size);
9237 header->max_stack = max_stack;
9238 header->init_locals = rmb->init_locals;
9239 header->num_locals = num_locals;
9241 for (i = 0; i < num_locals; ++i) {
9242 MonoReflectionLocalBuilder *lb =
9243 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9245 header->locals [i] = mp_g_new0 (mp, MonoType, 1);
9246 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
9249 header->num_clauses = num_clauses;
9251 header->clauses = method_encode_clauses (mp, (MonoDynamicImage*)klass->image,
9252 rmb->ilgen, num_clauses);
9255 pm->header = header;
9258 if (rmb->generic_params) {
9259 int count = mono_array_length (rmb->generic_params);
9260 MonoGenericContainer *container;
9262 container = rmb->generic_container;
9264 m->is_generic = TRUE;
9265 mono_method_set_generic_container (m, container);
9267 container->type_argc = count;
9268 container->type_params = mp_g_new0 (mp, MonoGenericParam, count);
9269 container->owner.method = m;
9271 for (i = 0; i < count; i++) {
9272 MonoReflectionGenericParam *gp =
9273 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9275 container->type_params [i] = *gp->type.type->data.generic_param;
9278 if (klass->generic_container) {
9279 container->parent = klass->generic_container;
9280 container->context.class_inst = klass->generic_container->context.class_inst;
9282 container->context.method_inst = mono_get_shared_generic_inst (container);
9286 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9290 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9292 mw->method_data = data = mp_g_new (mp, gpointer, rmb->nrefs + 1);
9293 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9294 for (i = 0; i < rmb->nrefs; ++i)
9295 data [i + 1] = rmb->refs [i];
9300 /* Parameter info */
9303 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9304 method_aux->param_names = mp_g_new0 (mp, char *, mono_method_signature (m)->param_count + 1);
9305 for (i = 0; i <= m->signature->param_count; ++i) {
9306 MonoReflectionParamBuilder *pb;
9307 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9308 if ((i > 0) && (pb->attrs)) {
9309 /* Make a copy since it might point to a shared type structure */
9310 m->signature->params [i - 1] = mono_metadata_type_dup (mp, m->signature->params [i - 1]);
9311 m->signature->params [i - 1]->attrs = pb->attrs;
9314 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9315 MonoDynamicImage *assembly;
9316 guint32 idx, def_type, len;
9320 if (!method_aux->param_defaults) {
9321 method_aux->param_defaults = mp_g_new0 (mp, guint8*, m->signature->param_count + 1);
9322 method_aux->param_default_types = mp_g_new0 (mp, guint32, m->signature->param_count + 1);
9324 assembly = (MonoDynamicImage*)klass->image;
9325 idx = encode_constant (assembly, pb->def_value, &def_type);
9326 /* Copy the data from the blob since it might get realloc-ed */
9327 p = assembly->blob.data + idx;
9328 len = mono_metadata_decode_blob_size (p, &p2);
9330 method_aux->param_defaults [i] = mp_g_malloc (mp, len);
9331 method_aux->param_default_types [i] = def_type;
9332 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9336 method_aux->param_names [i] = mp_string_to_utf8 (mp, pb->name);
9338 if (!method_aux->param_cattr)
9339 method_aux->param_cattr = mp_g_new0 (mp, MonoCustomAttrInfo*, m->signature->param_count + 1);
9340 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (mp, klass->image, pb->cattrs);
9346 /* Parameter marshalling */
9349 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9350 MonoReflectionParamBuilder *pb;
9351 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9352 if (pb->marshal_info) {
9354 specs = mp_g_new0 (mp, MonoMarshalSpec*, sig->param_count + 1);
9355 specs [pb->position] =
9356 mono_marshal_spec_from_builder (mp, klass->image->assembly, pb->marshal_info);
9360 if (specs != NULL) {
9362 method_aux = mp_g_new0 (mp, MonoReflectionMethodAux, 1);
9363 method_aux->param_marshall = specs;
9366 if (klass->image->dynamic && method_aux)
9367 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9369 mono_loader_unlock ();
9375 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9377 ReflectionMethodBuilder rmb;
9378 MonoMethodSignature *sig;
9380 mono_loader_lock ();
9381 sig = ctor_builder_to_signature (klass->image->mempool, mb);
9382 mono_loader_unlock ();
9384 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9386 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9387 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9389 /* If we are in a generic class, we might be called multiple times from inflate_method */
9390 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9391 /* ilgen is no longer needed */
9399 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9401 ReflectionMethodBuilder rmb;
9402 MonoMethodSignature *sig;
9404 mono_loader_lock ();
9405 sig = method_builder_to_signature (klass->image->mempool, mb);
9406 mono_loader_unlock ();
9408 reflection_methodbuilder_from_method_builder (&rmb, mb);
9410 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9411 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9413 /* If we are in a generic class, we might be called multiple times from inflate_method */
9414 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9415 /* ilgen is no longer needed */
9421 static MonoClassField*
9422 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9424 MonoClassField *field;
9429 field = g_new0 (MonoClassField, 1);
9431 field->name = mono_string_to_utf8 (fb->name);
9432 if (fb->attrs || fb->modreq || fb->modopt) {
9433 field->type = mono_metadata_type_dup (NULL, fb->type->type);
9434 field->type->attrs = fb->attrs;
9436 g_assert (klass->image->dynamic);
9437 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9438 g_free (field->type);
9439 field->type = custom;
9441 field->type = fb->type->type;
9443 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9444 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
9445 if (fb->offset != -1)
9446 field->offset = fb->offset;
9447 field->parent = klass;
9448 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9450 if (fb->def_value) {
9451 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9452 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9453 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9454 /* Copy the data from the blob since it might get realloc-ed */
9455 p = assembly->blob.data + idx;
9456 len = mono_metadata_decode_blob_size (p, &p2);
9458 field->data = g_malloc (len);
9459 memcpy ((gpointer)field->data, p, len);
9466 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9469 MonoReflectionTypeBuilder *tb = NULL;
9470 gboolean is_dynamic = FALSE;
9474 mono_loader_lock ();
9476 domain = mono_object_domain (type);
9478 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9479 tb = (MonoReflectionTypeBuilder *) type;
9482 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9483 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9485 tb = rgi->generic_type;
9489 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9490 if (tb && tb->generic_container)
9491 mono_reflection_create_generic_class (tb);
9493 klass = mono_class_from_mono_type (type->type);
9494 if (!klass->generic_container) {
9495 mono_loader_unlock ();
9499 if (klass->wastypebuilder) {
9500 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9505 mono_loader_unlock ();
9507 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9509 return &geninst->byval_arg;
9513 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9515 MonoGenericClass *gclass;
9516 MonoGenericInst *inst;
9518 g_assert (klass->generic_container);
9520 inst = mono_metadata_get_generic_inst (type_argc, types);
9521 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9523 return mono_generic_class_get_class (gclass);
9526 MonoReflectionMethod*
9527 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9530 MonoMethod *method, *inflated;
9531 MonoMethodInflated *imethod;
9532 MonoReflectionMethodBuilder *mb = NULL;
9533 MonoGenericContext tmp_context;
9534 MonoGenericInst *ginst;
9535 MonoType **type_argv;
9538 MONO_ARCH_SAVE_REGS;
9540 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9541 #ifndef DISABLE_REFLECTION_EMIT
9542 MonoReflectionTypeBuilder *tb;
9545 mb = (MonoReflectionMethodBuilder *) rmethod;
9546 tb = (MonoReflectionTypeBuilder *) mb->type;
9547 klass = mono_class_from_mono_type (tb->type.type);
9549 method = methodbuilder_to_mono_method (klass, mb);
9551 g_assert_not_reached ();
9555 method = rmethod->method;
9558 klass = method->klass;
9560 if (method->is_inflated)
9561 method = ((MonoMethodInflated *) method)->declaring;
9563 count = mono_method_signature (method)->generic_param_count;
9564 if (count != mono_array_length (types))
9567 type_argv = g_new0 (MonoType *, count);
9568 for (i = 0; i < count; i++) {
9569 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9570 type_argv [i] = garg->type;
9572 ginst = mono_metadata_get_generic_inst (count, type_argv);
9575 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9576 tmp_context.method_inst = ginst;
9578 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9579 imethod = (MonoMethodInflated *) inflated;
9581 if (method->klass->image->dynamic) {
9582 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9584 * This table maps metadata structures representing inflated methods/fields
9585 * to the reflection objects representing their generic definitions.
9587 mono_loader_lock ();
9588 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9589 mono_loader_unlock ();
9592 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9595 #ifndef DISABLE_REFLECTION_EMIT
9598 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9600 MonoMethodInflated *imethod;
9601 MonoGenericContext *context;
9605 * With generic code sharing the klass might not be inflated.
9606 * This can happen because classes inflated with their own
9607 * type arguments are "normalized" to the uninflated class.
9609 if (!klass->generic_class)
9612 context = mono_class_get_context (klass);
9614 if (klass->method.count) {
9615 /* Find the already created inflated method */
9616 for (i = 0; i < klass->method.count; ++i) {
9617 g_assert (klass->methods [i]->is_inflated);
9618 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9621 g_assert (i < klass->method.count);
9622 imethod = (MonoMethodInflated*)klass->methods [i];
9624 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9627 if (method->is_generic && method->klass->image->dynamic) {
9628 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9630 mono_loader_lock ();
9631 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9632 mono_loader_unlock ();
9634 return (MonoMethod *) imethod;
9638 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9643 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9645 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9646 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9647 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9649 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9650 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9651 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9652 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9653 method = ((MonoReflectionMethod *) obj)->method;
9655 method = NULL; /* prevent compiler warning */
9656 g_assert_not_reached ();
9659 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9662 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9664 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9665 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9668 MonoGenericClass *gclass;
9669 MonoDynamicGenericClass *dgclass;
9670 MonoClass *klass, *gklass;
9673 MONO_ARCH_SAVE_REGS;
9675 klass = mono_class_from_mono_type (type->type.type);
9676 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9677 gclass = type->type.type->data.generic_class;
9679 g_assert (gclass->is_dynamic);
9680 dgclass = (MonoDynamicGenericClass *) gclass;
9682 if (dgclass->initialized)
9685 gklass = gclass->container_class;
9686 mono_class_init (gklass);
9688 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9689 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9690 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9691 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9692 dgclass->count_events = events ? mono_array_length (events) : 0;
9694 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9695 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9696 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9697 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9698 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9699 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9700 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9702 for (i = 0; i < dgclass->count_methods; i++) {
9703 MonoObject *obj = mono_array_get (methods, gpointer, i);
9705 dgclass->methods [i] = inflate_method (type, obj);
9708 for (i = 0; i < dgclass->count_ctors; i++) {
9709 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9711 dgclass->ctors [i] = inflate_method (type, obj);
9714 for (i = 0; i < dgclass->count_fields; i++) {
9715 MonoObject *obj = mono_array_get (fields, gpointer, i);
9716 MonoClassField *field, *inflated_field = NULL;
9718 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9719 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9720 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9721 field = ((MonoReflectionField *) obj)->field;
9723 field = NULL; /* prevent compiler warning */
9724 g_assert_not_reached ();
9727 dgclass->fields [i] = *field;
9728 dgclass->fields [i].parent = klass;
9729 dgclass->fields [i].type = mono_class_inflate_generic_type (
9730 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9731 dgclass->field_generic_types [i] = field->type;
9732 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9733 dgclass->field_objects [i] = obj;
9735 if (inflated_field) {
9736 g_free ((char*)inflated_field->data);
9737 g_free (inflated_field);
9739 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9743 for (i = 0; i < dgclass->count_properties; i++) {
9744 MonoObject *obj = mono_array_get (properties, gpointer, i);
9745 MonoProperty *property = &dgclass->properties [i];
9747 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9748 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9750 property->parent = klass;
9751 property->attrs = pb->attrs;
9752 property->name = mono_string_to_utf8 (pb->name);
9754 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9756 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9757 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9758 *property = *((MonoReflectionProperty *) obj)->property;
9759 property->name = g_strdup (property->name);
9762 property->get = inflate_mono_method (klass, property->get, NULL);
9764 property->set = inflate_mono_method (klass, property->set, NULL);
9766 g_assert_not_reached ();
9769 for (i = 0; i < dgclass->count_events; i++) {
9770 MonoObject *obj = mono_array_get (events, gpointer, i);
9771 MonoEvent *event = &dgclass->events [i];
9773 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9774 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9776 event->parent = klass;
9777 event->attrs = eb->attrs;
9778 event->name = mono_string_to_utf8 (eb->name);
9780 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9781 if (eb->remove_method)
9782 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9783 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9784 *event = *((MonoReflectionEvent *) obj)->event;
9785 event->name = g_strdup (event->name);
9788 event->add = inflate_mono_method (klass, event->add, NULL);
9790 event->remove = inflate_mono_method (klass, event->remove, NULL);
9792 g_assert_not_reached ();
9795 dgclass->initialized = TRUE;
9799 ensure_runtime_vtable (MonoClass *klass)
9801 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9804 if (!tb || klass->wastypebuilder)
9807 ensure_runtime_vtable (klass->parent);
9809 num = tb->ctors? mono_array_length (tb->ctors): 0;
9810 num += tb->num_methods;
9811 klass->method.count = num;
9812 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9813 num = tb->ctors? mono_array_length (tb->ctors): 0;
9814 for (i = 0; i < num; ++i)
9815 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9816 num = tb->num_methods;
9818 for (i = 0; i < num; ++i)
9819 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9821 if (tb->interfaces) {
9822 klass->interface_count = mono_array_length (tb->interfaces);
9823 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9824 for (i = 0; i < klass->interface_count; ++i) {
9825 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9826 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9830 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9831 for (i = 0; i < klass->method.count; ++i)
9832 klass->methods [i]->slot = i;
9834 mono_class_setup_interface_offsets (klass);
9838 * The generic vtable is needed even if image->run is not set since some
9839 * runtime code like ves_icall_Type_GetMethodsByName depends on
9840 * method->slot being defined.
9844 * tb->methods could not be freed since it is used for determining
9845 * overrides during dynamic vtable construction.
9850 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9852 MonoReflectionTypeBuilder *tb;
9858 g_assert (klass->image->dynamic);
9860 if (!klass->reflection_info)
9863 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9865 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9869 for (i = 0; i < tb->num_methods; ++i) {
9870 MonoReflectionMethodBuilder *mb =
9871 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9872 if (mb->override_method)
9878 *overrides = g_new0 (MonoMethod*, onum * 2);
9881 for (i = 0; i < tb->num_methods; ++i) {
9882 MonoReflectionMethodBuilder *mb =
9883 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9884 if (mb->override_method) {
9885 (*overrides) [onum * 2] =
9886 mb->override_method->method;
9887 (*overrides) [onum * 2 + 1] =
9890 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9891 g_assert (mb->override_method->method);
9892 g_assert (mb->mhandle);
9899 *num_overrides = onum;
9903 typebuilder_setup_fields (MonoClass *klass)
9905 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9906 MonoReflectionFieldBuilder *fb;
9907 MonoClassField *field;
9908 MonoMemPool *mp = klass->image->mempool;
9911 guint32 len, idx, real_size = 0;
9913 klass->field.count = tb->num_fields;
9914 klass->field.first = 0;
9916 if (tb->class_size) {
9917 g_assert ((tb->packing_size & 0xfffffff0) == 0);
9918 klass->packing_size = tb->packing_size;
9919 real_size = klass->instance_size + tb->class_size;
9922 if (!klass->field.count) {
9923 klass->instance_size = MAX (klass->instance_size, real_size);
9927 klass->fields = mp_g_new0 (mp, MonoClassField, klass->field.count);
9929 for (i = 0; i < klass->field.count; ++i) {
9930 fb = mono_array_get (tb->fields, gpointer, i);
9931 field = &klass->fields [i];
9932 field->name = mp_string_to_utf8 (mp, fb->name);
9934 field->type = mono_metadata_type_dup (mp, fb->type->type);
9935 field->type->attrs = fb->attrs;
9937 field->type = fb->type->type;
9939 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9940 field->data = mono_array_addr (fb->rva_data, char, 0);
9941 if (fb->offset != -1)
9942 field->offset = fb->offset;
9943 field->parent = klass;
9945 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9947 if (fb->def_value) {
9948 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9949 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9950 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9951 /* Copy the data from the blob since it might get realloc-ed */
9952 p = assembly->blob.data + idx;
9953 len = mono_metadata_decode_blob_size (p, &p2);
9955 field->data = mono_mempool_alloc (mp, len);
9956 memcpy ((gpointer)field->data, p, len);
9960 klass->instance_size = MAX (klass->instance_size, real_size);
9961 mono_class_layout_fields (klass);
9965 typebuilder_setup_properties (MonoClass *klass)
9967 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9968 MonoReflectionPropertyBuilder *pb;
9969 MonoMemPool *mp = klass->image->mempool;
9972 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9973 klass->property.first = 0;
9975 klass->properties = mp_g_new0 (mp, MonoProperty, klass->property.count);
9976 for (i = 0; i < klass->property.count; ++i) {
9977 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9978 klass->properties [i].parent = klass;
9979 klass->properties [i].attrs = pb->attrs;
9980 klass->properties [i].name = mp_string_to_utf8 (mp, pb->name);
9982 klass->properties [i].get = pb->get_method->mhandle;
9984 klass->properties [i].set = pb->set_method->mhandle;
9986 mono_save_custom_attrs (klass->image, &klass->properties [i], pb->cattrs);
9990 MonoReflectionEvent *
9991 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9993 MonoEvent *event = g_new0 (MonoEvent, 1);
9997 klass = my_mono_class_from_mono_type (tb->type.type);
9999 event->parent = klass;
10000 event->attrs = eb->attrs;
10001 event->name = mono_string_to_utf8 (eb->name);
10002 if (eb->add_method)
10003 event->add = eb->add_method->mhandle;
10004 if (eb->remove_method)
10005 event->remove = eb->remove_method->mhandle;
10006 if (eb->raise_method)
10007 event->raise = eb->raise_method->mhandle;
10009 if (eb->other_methods) {
10010 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10011 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10012 MonoReflectionMethodBuilder *mb =
10013 mono_array_get (eb->other_methods,
10014 MonoReflectionMethodBuilder*, j);
10015 event->other [j] = mb->mhandle;
10019 return mono_event_get_object (mono_object_domain (tb), klass, event);
10023 typebuilder_setup_events (MonoClass *klass)
10025 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10026 MonoReflectionEventBuilder *eb;
10027 MonoMemPool *mp = klass->image->mempool;
10030 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
10031 klass->event.first = 0;
10033 klass->events = mp_g_new0 (mp, MonoEvent, klass->event.count);
10034 for (i = 0; i < klass->event.count; ++i) {
10035 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10036 klass->events [i].parent = klass;
10037 klass->events [i].attrs = eb->attrs;
10038 klass->events [i].name = mp_string_to_utf8 (mp, eb->name);
10039 if (eb->add_method)
10040 klass->events [i].add = eb->add_method->mhandle;
10041 if (eb->remove_method)
10042 klass->events [i].remove = eb->remove_method->mhandle;
10043 if (eb->raise_method)
10044 klass->events [i].raise = eb->raise_method->mhandle;
10046 if (eb->other_methods) {
10047 klass->events [i].other = mp_g_new0 (mp, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10048 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10049 MonoReflectionMethodBuilder *mb =
10050 mono_array_get (eb->other_methods,
10051 MonoReflectionMethodBuilder*, j);
10052 klass->events [i].other [j] = mb->mhandle;
10055 mono_save_custom_attrs (klass->image, &klass->events [i], eb->cattrs);
10060 remove_instantiations_of (gpointer key,
10062 gpointer user_data)
10064 MonoType *type = (MonoType*)key;
10065 MonoClass *klass = (MonoClass*)user_data;
10067 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10073 MonoReflectionType*
10074 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10077 MonoDomain* domain;
10078 MonoReflectionType* res;
10081 MONO_ARCH_SAVE_REGS;
10083 domain = mono_object_domain (tb);
10084 klass = my_mono_class_from_mono_type (tb->type.type);
10086 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10089 * we need to lock the domain because the lock will be taken inside
10090 * So, we need to keep the locking order correct.
10092 mono_domain_lock (domain);
10093 mono_loader_lock ();
10094 if (klass->wastypebuilder) {
10095 mono_loader_unlock ();
10096 mono_domain_unlock (domain);
10097 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10100 * Fields to set in klass:
10101 * the various flags: delegate/unicode/contextbound etc.
10103 klass->flags = tb->attrs;
10104 klass->has_cctor = 1;
10105 klass->has_finalize = 1;
10108 if (!((MonoDynamicImage*)klass->image)->run) {
10109 if (klass->generic_container) {
10110 /* FIXME: The code below can't handle generic classes */
10111 klass->wastypebuilder = TRUE;
10112 mono_loader_unlock ();
10113 mono_domain_unlock (domain);
10114 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10119 /* enums are done right away */
10120 if (!klass->enumtype)
10121 ensure_runtime_vtable (klass);
10123 if (tb->subtypes) {
10124 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10125 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10126 klass->nested_classes = g_list_prepend_mempool (klass->image->mempool, klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
10130 klass->nested_classes_inited = TRUE;
10132 /* fields and object layout */
10133 if (klass->parent) {
10134 if (!klass->parent->size_inited)
10135 mono_class_init (klass->parent);
10136 klass->instance_size = klass->parent->instance_size;
10137 klass->sizes.class_size = 0;
10138 klass->min_align = klass->parent->min_align;
10139 /* if the type has no fields we won't call the field_setup
10140 * routine which sets up klass->has_references.
10142 klass->has_references |= klass->parent->has_references;
10144 klass->instance_size = sizeof (MonoObject);
10145 klass->min_align = 1;
10148 /* FIXME: handle packing_size and instance_size */
10149 typebuilder_setup_fields (klass);
10151 typebuilder_setup_properties (klass);
10153 typebuilder_setup_events (klass);
10155 klass->wastypebuilder = TRUE;
10158 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10159 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10160 * we want to return normal System.MonoType objects, so clear these out from the cache.
10162 if (domain->type_hash && klass->generic_container)
10163 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10165 mono_loader_unlock ();
10166 mono_domain_unlock (domain);
10168 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10169 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10170 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10173 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10174 g_assert (res != (MonoReflectionType*)tb);
10180 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10182 MonoGenericParam *param;
10185 MONO_ARCH_SAVE_REGS;
10187 param = g_new0 (MonoGenericParam, 1);
10189 if (gparam->mbuilder) {
10190 if (!gparam->mbuilder->generic_container) {
10191 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10192 MonoClass *klass = my_mono_class_from_mono_type (tb->type.type);
10193 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10194 gparam->mbuilder->generic_container->is_method = TRUE;
10196 param->owner = gparam->mbuilder->generic_container;
10197 } else if (gparam->tbuilder) {
10198 g_assert (gparam->tbuilder->generic_container);
10199 param->owner = gparam->tbuilder->generic_container;
10202 param->name = mono_string_to_utf8 (gparam->name);
10203 param->num = gparam->index;
10205 image = &gparam->tbuilder->module->dynamic_image->image;
10206 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10208 MOVING_GC_REGISTER (¶m->pklass->reflection_info);
10209 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10211 gparam->type.type = g_new0 (MonoType, 1);
10212 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
10213 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
10214 gparam->type.type->data.generic_param = param;
10218 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10220 MonoDynamicImage *assembly = sig->module->dynamic_image;
10221 guint32 na = mono_array_length (sig->arguments);
10226 sigbuffer_init (&buf, 32);
10228 sigbuffer_add_value (&buf, 0x07);
10229 sigbuffer_add_value (&buf, na);
10230 for (i = 0; i < na; ++i) {
10231 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10232 encode_reflection_type (assembly, type, &buf);
10235 buflen = buf.p - buf.buf;
10236 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10237 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10238 sigbuffer_free (&buf);
10244 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10246 MonoDynamicImage *assembly = sig->module->dynamic_image;
10247 guint32 na = mono_array_length (sig->arguments);
10252 sigbuffer_init (&buf, 32);
10254 sigbuffer_add_value (&buf, 0x06);
10255 for (i = 0; i < na; ++i) {
10256 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
10257 encode_reflection_type (assembly, type, &buf);
10260 buflen = buf.p - buf.buf;
10261 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10262 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10263 sigbuffer_free (&buf);
10269 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10271 ReflectionMethodBuilder rmb;
10272 MonoMethodSignature *sig;
10277 sig = dynamic_method_to_signature (mb);
10279 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10282 * Resolve references.
10285 * Every second entry in the refs array is reserved for storing handle_class,
10286 * which is needed by the ldtoken implementation in the JIT.
10288 rmb.nrefs = mb->nrefs;
10289 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10290 for (i = 0; i < mb->nrefs; i += 2) {
10291 MonoClass *handle_class;
10293 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10295 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10296 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10298 * The referenced DynamicMethod should already be created by the managed
10299 * code, except in the case of circular references. In that case, we store
10300 * method in the refs array, and fix it up later when the referenced
10301 * DynamicMethod is created.
10303 if (method->mhandle) {
10304 ref = method->mhandle;
10306 /* FIXME: GC object stored in unmanaged memory */
10309 /* FIXME: GC object stored in unmanaged memory */
10310 method->referenced_by = g_slist_append (method->referenced_by, mb);
10312 handle_class = mono_defaults.methodhandle_class;
10314 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10317 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
10322 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10323 rmb.refs [i + 1] = handle_class;
10326 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10328 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10330 /* Fix up refs entries pointing at us */
10331 for (l = mb->referenced_by; l; l = l->next) {
10332 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10333 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10336 g_assert (method->mhandle);
10338 data = (gpointer*)wrapper->method_data;
10339 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10340 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10341 data [i + 1] = mb->mhandle;
10344 g_slist_free (mb->referenced_by);
10348 /* ilgen is no longer needed */
10352 #endif /* DISABLE_REFLECTION_EMIT */
10355 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10360 mono_runtime_free_method (
10361 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10366 * mono_reflection_is_valid_dynamic_token:
10368 * Returns TRUE if token is valid.
10372 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10374 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10377 #ifndef DISABLE_REFLECTION_EMIT
10380 * mono_reflection_lookup_dynamic_token:
10382 * Finish the Builder object pointed to by TOKEN and return the corresponding
10383 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10384 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10388 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10390 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10394 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10397 g_assert_not_reached ();
10403 handle_class = &klass;
10404 return resolve_object (image, obj, handle_class, context);
10408 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10410 gpointer result = NULL;
10412 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10413 result = mono_string_intern ((MonoString*)obj);
10414 *handle_class = NULL;
10416 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10417 MonoReflectionType *tb = (MonoReflectionType*)obj;
10419 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10420 result = mono_class_from_mono_type (inflated);
10421 mono_metadata_free_type (inflated);
10423 result = mono_class_from_mono_type (tb->type);
10425 *handle_class = mono_defaults.typehandle_class;
10427 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10428 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10429 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10430 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10431 result = ((MonoReflectionMethod*)obj)->method;
10433 result = mono_class_inflate_generic_method (result, context);
10434 *handle_class = mono_defaults.methodhandle_class;
10436 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10437 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10438 result = mb->mhandle;
10440 /* Type is not yet created */
10441 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10443 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10446 * Hopefully this has been filled in by calling CreateType() on the
10450 * TODO: This won't work if the application finishes another
10451 * TypeBuilder instance instead of this one.
10453 result = mb->mhandle;
10456 result = mono_class_inflate_generic_method (result, context);
10457 *handle_class = mono_defaults.methodhandle_class;
10458 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10459 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10461 result = cb->mhandle;
10463 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10465 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10466 result = cb->mhandle;
10469 result = mono_class_inflate_generic_method (result, context);
10470 *handle_class = mono_defaults.methodhandle_class;
10471 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10472 result = ((MonoReflectionField*)obj)->field;
10473 *handle_class = mono_defaults.fieldhandle_class;
10475 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10476 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10477 result = fb->handle;
10480 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10482 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10483 result = fb->handle;
10486 if (fb->handle && fb->handle->parent->generic_container) {
10487 MonoClass *klass = fb->handle->parent;
10488 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10489 MonoClass *inflated = mono_class_from_mono_type (type);
10491 result = mono_class_get_field_from_name (inflated, fb->handle->name);
10493 mono_metadata_free_type (type);
10495 *handle_class = mono_defaults.fieldhandle_class;
10496 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10497 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10500 klass = tb->type.type->data.klass;
10501 if (klass->wastypebuilder) {
10502 /* Already created */
10506 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10507 result = tb->type.type->data.klass;
10510 *handle_class = mono_defaults.typehandle_class;
10511 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10512 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10513 MonoMethodSignature *sig;
10516 if (helper->arguments)
10517 nargs = mono_array_length (helper->arguments);
10521 sig = mono_metadata_signature_alloc (image, nargs);
10522 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10523 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10525 if (helper->call_conv == 0) /* unmanaged */
10526 sig->call_convention = helper->unmanaged_call_conv - 1;
10528 if (helper->call_conv & 0x02)
10529 sig->call_convention = MONO_CALL_VARARG;
10531 sig->call_convention = MONO_CALL_DEFAULT;
10533 sig->param_count = nargs;
10534 /* TODO: Copy type ? */
10535 sig->ret = helper->return_type->type;
10536 for (i = 0; i < nargs; ++i) {
10537 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
10538 sig->params [i] = rt->type;
10542 *handle_class = NULL;
10543 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10544 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10545 /* Already created by the managed code */
10546 g_assert (method->mhandle);
10547 result = method->mhandle;
10548 *handle_class = mono_defaults.methodhandle_class;
10549 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10550 MonoReflectionType *tb = (MonoReflectionType*)obj;
10551 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10552 result = mono_class_from_mono_type (type);
10553 *handle_class = mono_defaults.typehandle_class;
10555 mono_metadata_free_type (type);
10556 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10557 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10558 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10559 result = mono_class_from_mono_type (type);
10560 *handle_class = mono_defaults.typehandle_class;
10562 mono_metadata_free_type (type);
10563 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10564 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10565 MonoClass *inflated;
10568 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10569 inflated = mono_class_from_mono_type (type);
10571 g_assert (f->fb->handle);
10572 result = mono_class_get_field_from_name (inflated, f->fb->handle->name);
10574 mono_metadata_free_type (type);
10575 *handle_class = mono_defaults.fieldhandle_class;
10576 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10577 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10578 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10579 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10580 g_assert (c->cb->mhandle);
10581 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10582 *handle_class = mono_defaults.methodhandle_class;
10583 mono_metadata_free_type (type);
10584 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10585 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10586 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10587 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10588 g_assert (m->mb->mhandle);
10589 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10590 *handle_class = mono_defaults.methodhandle_class;
10591 mono_metadata_free_type (type);
10593 g_print (obj->vtable->klass->name);
10594 g_assert_not_reached ();
10599 #else /* DISABLE_REFLECTION_EMIT */
10602 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10604 g_assert_not_reached ();
10609 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10611 g_assert_not_reached ();
10615 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10617 g_assert_not_reached ();
10621 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10623 g_assert_not_reached ();
10627 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10629 g_assert_not_reached ();
10633 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10635 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10639 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10641 g_assert_not_reached ();
10644 MonoReflectionModule *
10645 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10647 g_assert_not_reached ();
10652 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10654 g_assert_not_reached ();
10659 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10661 g_assert_not_reached ();
10666 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10667 gboolean create_methodspec, gboolean register_token)
10669 g_assert_not_reached ();
10674 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10679 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10680 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10683 g_assert_not_reached ();
10687 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10690 *num_overrides = 0;
10693 MonoReflectionEvent *
10694 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10696 g_assert_not_reached ();
10700 MonoReflectionType*
10701 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10703 g_assert_not_reached ();
10708 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10710 g_assert_not_reached ();
10714 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10716 g_assert_not_reached ();
10721 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10723 g_assert_not_reached ();
10728 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10733 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10738 #endif /* DISABLE_REFLECTION_EMIT */
10740 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10741 const static guint32 declsec_flags_map[] = {
10742 0x00000000, /* empty */
10743 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10744 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10745 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10746 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10747 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10748 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10749 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10750 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10751 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10752 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10753 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10754 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10755 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10756 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10757 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10758 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10759 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10760 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10764 * Returns flags that includes all available security action associated to the handle.
10765 * @token: metadata token (either for a class or a method)
10766 * @image: image where resides the metadata.
10769 mono_declsec_get_flags (MonoImage *image, guint32 token)
10771 int index = mono_metadata_declsec_from_index (image, token);
10772 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
10773 guint32 result = 0;
10777 /* HasSecurity can be present for other, not specially encoded, attributes,
10778 e.g. SuppressUnmanagedCodeSecurityAttribute */
10782 for (i = index; i < t->rows; i++) {
10783 guint32 cols [MONO_DECL_SECURITY_SIZE];
10785 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10786 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10789 action = cols [MONO_DECL_SECURITY_ACTION];
10790 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
10791 result |= declsec_flags_map [action];
10793 g_assert_not_reached ();
10800 * Get the security actions (in the form of flags) associated with the specified method.
10802 * @method: The method for which we want the declarative security flags.
10803 * Return the declarative security flags for the method (only).
10805 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10806 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10809 mono_declsec_flags_from_method (MonoMethod *method)
10811 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10812 /* FIXME: No cache (for the moment) */
10813 guint32 idx = mono_method_get_index (method);
10814 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10815 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10816 return mono_declsec_get_flags (method->klass->image, idx);
10822 * Get the security actions (in the form of flags) associated with the specified class.
10824 * @klass: The class for which we want the declarative security flags.
10825 * Return the declarative security flags for the class.
10827 * Note: We cache the flags inside the MonoClass structure as this will get
10828 * called very often (at least for each method).
10831 mono_declsec_flags_from_class (MonoClass *klass)
10833 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
10834 if (!klass->declsec_flags) {
10835 guint32 idx = mono_metadata_token_index (klass->type_token);
10836 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10837 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10838 /* we cache the flags on classes */
10839 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
10841 return klass->declsec_flags;
10847 * Get the security actions (in the form of flags) associated with the specified assembly.
10849 * @assembly: The assembly for which we want the declarative security flags.
10850 * Return the declarative security flags for the assembly.
10853 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
10855 guint32 idx = 1; /* there is only one assembly */
10856 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10857 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10858 return mono_declsec_get_flags (assembly->image, idx);
10863 * Fill actions for the specific index (which may either be an encoded class token or
10864 * an encoded method token) from the metadata image.
10865 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10868 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
10869 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10871 MonoBoolean result = FALSE;
10873 guint32 cols [MONO_DECL_SECURITY_SIZE];
10874 int index = mono_metadata_declsec_from_index (image, token);
10877 t = &image->tables [MONO_TABLE_DECLSECURITY];
10878 for (i = index; i < t->rows; i++) {
10879 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10881 if (cols [MONO_DECL_SECURITY_PARENT] != token)
10884 /* if present only replace (class) permissions with method permissions */
10885 /* if empty accept either class or method permissions */
10886 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
10887 if (!actions->demand.blob) {
10888 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10889 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10890 actions->demand.blob = (char*) (blob + 2);
10891 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
10894 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
10895 if (!actions->noncasdemand.blob) {
10896 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10897 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10898 actions->noncasdemand.blob = (char*) (blob + 2);
10899 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
10902 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
10903 if (!actions->demandchoice.blob) {
10904 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10905 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
10906 actions->demandchoice.blob = (char*) (blob + 2);
10907 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
10917 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
10918 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10920 guint32 idx = mono_metadata_token_index (klass->type_token);
10921 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10922 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10923 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
10927 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
10928 guint32 id_std, guint32 id_noncas, guint32 id_choice)
10930 guint32 idx = mono_method_get_index (method);
10931 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10932 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10933 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
10937 * Collect all actions (that requires to generate code in mini) assigned for
10938 * the specified method.
10939 * Note: Don't use the content of actions if the function return FALSE.
10942 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
10944 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
10945 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
10946 MonoBoolean result = FALSE;
10949 /* quick exit if no declarative security is present in the metadata */
10950 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10953 /* we want the original as the wrapper is "free" of the security informations */
10954 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
10955 method = mono_marshal_method_from_wrapper (method);
10960 /* First we look for method-level attributes */
10961 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10962 mono_class_init (method->klass);
10963 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10965 result = mono_declsec_get_method_demands_params (method, demands,
10966 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10969 /* Here we use (or create) the class declarative cache to look for demands */
10970 flags = mono_declsec_flags_from_class (method->klass);
10971 if (flags & mask) {
10973 mono_class_init (method->klass);
10974 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10976 result |= mono_declsec_get_class_demands_params (method->klass, demands,
10977 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
10980 /* The boolean return value is used as a shortcut in case nothing needs to
10981 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
10987 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
10989 * Note: Don't use the content of actions if the function return FALSE.
10992 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
10994 MonoBoolean result = FALSE;
10997 /* quick exit if no declarative security is present in the metadata */
10998 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11001 /* we want the original as the wrapper is "free" of the security informations */
11002 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11003 method = mono_marshal_method_from_wrapper (method);
11008 /* results are independant - zeroize both */
11009 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11010 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11012 /* First we look for method-level attributes */
11013 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11014 mono_class_init (method->klass);
11016 result = mono_declsec_get_method_demands_params (method, cmethod,
11017 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11020 /* Here we use (or create) the class declarative cache to look for demands */
11021 flags = mono_declsec_flags_from_class (method->klass);
11022 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11023 mono_class_init (method->klass);
11025 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11026 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11033 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11035 * @klass The inherited class - this is the class that provides the security check (attributes)
11037 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11039 * Note: Don't use the content of actions if the function return FALSE.
11042 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11044 MonoBoolean result = FALSE;
11047 /* quick exit if no declarative security is present in the metadata */
11048 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11051 /* Here we use (or create) the class declarative cache to look for demands */
11052 flags = mono_declsec_flags_from_class (klass);
11053 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11054 mono_class_init (klass);
11055 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11057 result |= mono_declsec_get_class_demands_params (klass, demands,
11058 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11065 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11067 * Note: Don't use the content of actions if the function return FALSE.
11070 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11072 /* quick exit if no declarative security is present in the metadata */
11073 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11076 /* we want the original as the wrapper is "free" of the security informations */
11077 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11078 method = mono_marshal_method_from_wrapper (method);
11083 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11084 mono_class_init (method->klass);
11085 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11087 return mono_declsec_get_method_demands_params (method, demands,
11088 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11095 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11097 guint32 cols [MONO_DECL_SECURITY_SIZE];
11101 int index = mono_metadata_declsec_from_index (image, token);
11105 t = &image->tables [MONO_TABLE_DECLSECURITY];
11106 for (i = index; i < t->rows; i++) {
11107 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11109 /* shortcut - index are ordered */
11110 if (token != cols [MONO_DECL_SECURITY_PARENT])
11113 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11114 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11115 entry->blob = (char*) (metadata + 2);
11116 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11125 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11127 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11128 guint32 idx = mono_method_get_index (method);
11129 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11130 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11131 return get_declsec_action (method->klass->image, idx, action, entry);
11137 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11140 guint32 flags = mono_declsec_flags_from_class (klass);
11141 if (declsec_flags_map [action] & flags) {
11142 guint32 idx = mono_metadata_token_index (klass->type_token);
11143 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11144 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11145 return get_declsec_action (klass->image, idx, action, entry);
11151 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11153 guint32 idx = 1; /* there is only one assembly */
11154 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11155 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11157 return get_declsec_action (assembly->image, idx, action, entry);
11161 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11163 MonoObject *res, *exc;
11165 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11166 static MonoMethod *method = NULL;
11168 if (!System_Reflection_Emit_TypeBuilder) {
11169 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11170 g_assert (System_Reflection_Emit_TypeBuilder);
11172 if (method == NULL) {
11173 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11178 * The result of mono_type_get_object () might be a System.MonoType but we
11179 * need a TypeBuilder so use klass->reflection_info.
11181 g_assert (klass->reflection_info);
11182 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11184 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11186 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11190 return *(MonoBoolean*)mono_object_unbox (res);