2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
42 static void* reflection_info_desc = NULL;
43 #define MOVING_GC_REGISTER(addr) do { \
44 if (!reflection_info_desc) { \
46 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
48 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
51 #define MOVING_GC_REGISTER(addr)
55 check_array_for_usertypes (MonoArray *arr)
62 for (i = 0; i < mono_array_length (arr); ++i)
63 CHECK_MONOTYPE (mono_array_get (arr, gpointer, i));
72 #define TEXT_OFFSET 512
73 #define CLI_H_SIZE 136
74 #define FILE_ALIGN 512
75 #define VIRT_ALIGN 8192
76 #define START_TEXT_RVA 0x00002000
79 MonoReflectionILGen *ilgen;
80 MonoReflectionType *rtype;
81 MonoArray *parameters;
82 MonoArray *generic_params;
83 MonoGenericContainer *generic_container;
89 guint32 *table_idx; /* note: it's a pointer */
93 MonoBoolean init_locals;
94 MonoBoolean skip_visibility;
95 MonoArray *return_modreq;
96 MonoArray *return_modopt;
97 MonoArray *param_modreq;
98 MonoArray *param_modopt;
99 MonoArray *permissions;
104 int charset, extra_flags, native_cc;
105 MonoString *dll, *dllentry;
106 } ReflectionMethodBuilder;
110 MonoReflectionGenericParam *gparam;
111 } GenericParamTableEntry;
113 const unsigned char table_sizes [MONO_TABLE_NUM] = {
123 MONO_INTERFACEIMPL_SIZE,
124 MONO_MEMBERREF_SIZE, /* 0x0A */
126 MONO_CUSTOM_ATTR_SIZE,
127 MONO_FIELD_MARSHAL_SIZE,
128 MONO_DECL_SECURITY_SIZE,
129 MONO_CLASS_LAYOUT_SIZE,
130 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
131 MONO_STAND_ALONE_SIGNATURE_SIZE,
135 MONO_PROPERTY_MAP_SIZE,
138 MONO_METHOD_SEMA_SIZE,
139 MONO_METHODIMPL_SIZE,
140 MONO_MODULEREF_SIZE, /* 0x1A */
146 MONO_ASSEMBLY_SIZE, /* 0x20 */
147 MONO_ASSEMBLY_PROCESSOR_SIZE,
148 MONO_ASSEMBLYOS_SIZE,
149 MONO_ASSEMBLYREF_SIZE,
150 MONO_ASSEMBLYREFPROC_SIZE,
151 MONO_ASSEMBLYREFOS_SIZE,
155 MONO_NESTED_CLASS_SIZE,
157 MONO_GENERICPARAM_SIZE, /* 0x2A */
158 MONO_METHODSPEC_SIZE,
159 MONO_GENPARCONSTRAINT_SIZE
163 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
164 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
165 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
166 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
167 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
168 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
169 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
170 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
171 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
172 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
173 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
174 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
175 static void ensure_runtime_vtable (MonoClass *klass);
176 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
177 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
178 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
179 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
180 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
181 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
182 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
183 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
186 mono_reflection_init (void)
191 sigbuffer_init (SigBuffer *buf, int size)
193 buf->buf = g_malloc (size);
195 buf->end = buf->buf + size;
199 sigbuffer_make_room (SigBuffer *buf, int size)
201 if (buf->end - buf->p < size) {
202 int new_size = buf->end - buf->buf + size + 32;
203 char *p = g_realloc (buf->buf, new_size);
204 size = buf->p - buf->buf;
207 buf->end = buf->buf + new_size;
212 sigbuffer_add_value (SigBuffer *buf, guint32 val)
214 sigbuffer_make_room (buf, 6);
215 mono_metadata_encode_value (val, buf->p, &buf->p);
219 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
221 sigbuffer_make_room (buf, 1);
227 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
229 sigbuffer_make_room (buf, size);
230 memcpy (buf->p, p, size);
235 sigbuffer_free (SigBuffer *buf)
243 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
247 image_g_malloc (MonoImage *image, guint size)
250 return mono_image_alloc (image, size);
252 return g_malloc (size);
258 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
262 image_g_malloc0 (MonoImage *image, guint size)
265 return mono_image_alloc0 (image, size);
267 return g_malloc0 (size);
271 image_strdup (MonoImage *image, const char *s)
274 return mono_image_strdup (image, s);
279 #define image_g_new(image,struct_type, n_structs) \
280 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
282 #define image_g_new0(image,struct_type, n_structs) \
283 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
287 alloc_table (MonoDynamicTable *table, guint nrows)
290 g_assert (table->columns);
291 if (nrows + 1 >= table->alloc_rows) {
292 while (nrows + 1 >= table->alloc_rows) {
293 if (table->alloc_rows == 0)
294 table->alloc_rows = 16;
296 table->alloc_rows *= 2;
299 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
304 make_room_in_stream (MonoDynamicStream *stream, int size)
306 if (size <= stream->alloc_size)
309 while (stream->alloc_size <= size) {
310 if (stream->alloc_size < 4096)
311 stream->alloc_size = 4096;
313 stream->alloc_size *= 2;
316 stream->data = g_realloc (stream->data, stream->alloc_size);
320 string_heap_insert (MonoDynamicStream *sh, const char *str)
324 gpointer oldkey, oldval;
326 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
327 return GPOINTER_TO_UINT (oldval);
329 len = strlen (str) + 1;
332 make_room_in_stream (sh, idx + len);
335 * We strdup the string even if we already copy them in sh->data
336 * so that the string pointers in the hash remain valid even if
337 * we need to realloc sh->data. We may want to avoid that later.
339 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
340 memcpy (sh->data + idx, str, len);
346 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
348 char *name = mono_string_to_utf8 (str);
350 idx = string_heap_insert (sh, name);
356 string_heap_init (MonoDynamicStream *sh)
359 sh->alloc_size = 4096;
360 sh->data = g_malloc (4096);
361 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
362 string_heap_insert (sh, "");
366 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
370 make_room_in_stream (stream, stream->index + len);
371 memcpy (stream->data + stream->index, data, len);
373 stream->index += len;
375 * align index? Not without adding an additional param that controls it since
376 * we may store a blob value in pieces.
382 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
386 make_room_in_stream (stream, stream->index + len);
387 memset (stream->data + stream->index, 0, len);
389 stream->index += len;
394 stream_data_align (MonoDynamicStream *stream)
397 guint32 count = stream->index % 4;
399 /* we assume the stream data will be aligned */
401 mono_image_add_stream_data (stream, buf, 4 - count);
405 mono_blob_entry_hash (const char* str)
409 len = mono_metadata_decode_blob_size (str, &str);
413 for (str += 1; str < end; str++)
414 h = (h << 5) - h + *str;
422 mono_blob_entry_equal (const char *str1, const char *str2) {
426 len = mono_metadata_decode_blob_size (str1, &end1);
427 len2 = mono_metadata_decode_blob_size (str2, &end2);
430 return memcmp (end1, end2, len) == 0;
434 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
438 gpointer oldkey, oldval;
440 copy = g_malloc (s1+s2);
441 memcpy (copy, b1, s1);
442 memcpy (copy + s1, b2, s2);
443 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
445 idx = GPOINTER_TO_UINT (oldval);
447 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
448 mono_image_add_stream_data (&assembly->blob, b2, s2);
449 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
455 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
459 guint32 size = buf->p - buf->buf;
461 g_assert (size <= (buf->end - buf->buf));
462 mono_metadata_encode_value (size, b, &b);
463 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
467 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
468 * dest may be misaligned.
471 swap_with_size (char *dest, const char* val, int len, int nelem) {
472 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
475 for (elem = 0; elem < nelem; ++elem) {
501 g_assert_not_reached ();
507 memcpy (dest, val, len * nelem);
512 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
516 guint32 idx = 0, len;
518 len = str->length * 2;
519 mono_metadata_encode_value (len, b, &b);
520 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
522 char *swapped = g_malloc (2 * mono_string_length (str));
523 const char *p = (const char*)mono_string_chars (str);
525 swap_with_size (swapped, p, 2, mono_string_length (str));
526 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
530 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
536 default_class_from_mono_type (MonoType *type)
538 switch (type->type) {
539 case MONO_TYPE_OBJECT:
540 return mono_defaults.object_class;
542 return mono_defaults.void_class;
543 case MONO_TYPE_BOOLEAN:
544 return mono_defaults.boolean_class;
546 return mono_defaults.char_class;
548 return mono_defaults.sbyte_class;
550 return mono_defaults.byte_class;
552 return mono_defaults.int16_class;
554 return mono_defaults.uint16_class;
556 return mono_defaults.int32_class;
558 return mono_defaults.uint32_class;
560 return mono_defaults.int_class;
562 return mono_defaults.uint_class;
564 return mono_defaults.int64_class;
566 return mono_defaults.uint64_class;
568 return mono_defaults.single_class;
570 return mono_defaults.double_class;
571 case MONO_TYPE_STRING:
572 return mono_defaults.string_class;
574 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
575 g_assert_not_reached ();
582 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
585 MonoGenericInst *class_inst;
590 class_inst = gclass->context.class_inst;
592 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
593 klass = gclass->container_class;
594 sigbuffer_add_value (buf, klass->byval_arg.type);
595 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
597 sigbuffer_add_value (buf, class_inst->type_argc);
598 for (i = 0; i < class_inst->type_argc; ++i)
599 encode_type (assembly, class_inst->type_argv [i], buf);
604 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
607 g_assert_not_reached ();
612 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
616 case MONO_TYPE_BOOLEAN:
630 case MONO_TYPE_STRING:
631 case MONO_TYPE_OBJECT:
632 case MONO_TYPE_TYPEDBYREF:
633 sigbuffer_add_value (buf, type->type);
636 sigbuffer_add_value (buf, type->type);
637 encode_type (assembly, type->data.type, buf);
639 case MONO_TYPE_SZARRAY:
640 sigbuffer_add_value (buf, type->type);
641 encode_type (assembly, &type->data.klass->byval_arg, buf);
643 case MONO_TYPE_VALUETYPE:
644 case MONO_TYPE_CLASS: {
645 MonoClass *k = mono_class_from_mono_type (type);
647 if (k->generic_container) {
648 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
649 encode_generic_class (assembly, gclass, buf);
652 * Make sure we use the correct type.
654 sigbuffer_add_value (buf, k->byval_arg.type);
656 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
657 * otherwise two typerefs could point to the same type, leading to
658 * verification errors.
660 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
664 case MONO_TYPE_ARRAY:
665 sigbuffer_add_value (buf, type->type);
666 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
667 sigbuffer_add_value (buf, type->data.array->rank);
668 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
669 sigbuffer_add_value (buf, 0);
671 case MONO_TYPE_GENERICINST:
672 encode_generic_class (assembly, type->data.generic_class, buf);
676 sigbuffer_add_value (buf, type->type);
677 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
680 g_error ("need to encode type %x", type->type);
685 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
688 sigbuffer_add_value (buf, MONO_TYPE_VOID);
693 ((type = mono_reflection_type_get_underlying_system_type (type)) && type->type)) {
694 encode_type (assembly, type->type, buf);
698 g_assert_not_reached ();
703 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
708 for (i = 0; i < mono_array_length (modreq); ++i) {
709 MonoReflectionType *mod = mono_type_array_get (modreq, i);
710 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
711 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
715 for (i = 0; i < mono_array_length (modopt); ++i) {
716 MonoReflectionType *mod = mono_type_array_get (modopt, i);
717 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
718 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod->type));
724 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
728 guint32 nparams = sig->param_count;
734 sigbuffer_init (&buf, 32);
736 * FIXME: vararg, explicit_this, differenc call_conv values...
738 idx = sig->call_convention;
740 idx |= 0x20; /* hasthis */
741 if (sig->generic_param_count)
742 idx |= 0x10; /* generic */
743 sigbuffer_add_byte (&buf, idx);
744 if (sig->generic_param_count)
745 sigbuffer_add_value (&buf, sig->generic_param_count);
746 sigbuffer_add_value (&buf, nparams);
747 encode_type (assembly, sig->ret, &buf);
748 for (i = 0; i < nparams; ++i) {
749 if (i == sig->sentinelpos)
750 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
751 encode_type (assembly, sig->params [i], &buf);
753 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
754 sigbuffer_free (&buf);
759 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
762 * FIXME: reuse code from method_encode_signature().
766 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
767 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
768 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
771 sigbuffer_init (&buf, 32);
772 /* LAMESPEC: all the call conv spec is foobared */
773 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
774 if (mb->call_conv & 2)
775 idx |= 0x5; /* vararg */
776 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
777 idx |= 0x20; /* hasthis */
779 idx |= 0x10; /* generic */
780 sigbuffer_add_byte (&buf, idx);
782 sigbuffer_add_value (&buf, ngparams);
783 sigbuffer_add_value (&buf, nparams + notypes);
784 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
785 encode_reflection_type (assembly, mb->rtype, &buf);
786 for (i = 0; i < nparams; ++i) {
787 MonoArray *modreq = NULL;
788 MonoArray *modopt = NULL;
789 MonoReflectionType *pt;
791 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
792 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
793 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
794 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
795 encode_custom_modifiers (assembly, modreq, modopt, &buf);
796 pt = mono_type_array_get (mb->parameters, i);
797 encode_reflection_type (assembly, pt, &buf);
800 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
801 for (i = 0; i < notypes; ++i) {
802 MonoReflectionType *pt;
804 pt = mono_type_array_get (mb->opt_types, i);
805 encode_reflection_type (assembly, pt, &buf);
808 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
809 sigbuffer_free (&buf);
814 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
816 MonoDynamicTable *table;
818 guint32 idx, sig_idx;
819 guint nl = mono_array_length (ilgen->locals);
823 sigbuffer_init (&buf, 32);
824 sigbuffer_add_value (&buf, 0x07);
825 sigbuffer_add_value (&buf, nl);
826 for (i = 0; i < nl; ++i) {
827 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
830 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
832 encode_reflection_type (assembly, monotype_cast (lb->type), &buf);
834 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
835 sigbuffer_free (&buf);
837 if (assembly->standalonesig_cache == NULL)
838 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
839 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
843 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
844 idx = table->next_idx ++;
846 alloc_table (table, table->rows);
847 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
849 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
851 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
857 method_count_clauses (MonoReflectionILGen *ilgen)
859 guint32 num_clauses = 0;
862 MonoILExceptionInfo *ex_info;
863 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
864 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
865 if (ex_info->handlers)
866 num_clauses += mono_array_length (ex_info->handlers);
874 static MonoExceptionClause*
875 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
877 MonoExceptionClause *clauses;
878 MonoExceptionClause *clause;
879 MonoILExceptionInfo *ex_info;
880 MonoILExceptionBlock *ex_block;
881 guint32 finally_start;
882 int i, j, clause_index;;
884 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
887 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
888 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
889 finally_start = ex_info->start + ex_info->len;
890 if (!ex_info->handlers)
892 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
893 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
894 clause = &(clauses [clause_index]);
896 clause->flags = ex_block->type;
897 clause->try_offset = ex_info->start;
899 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
900 clause->try_len = finally_start - ex_info->start;
902 clause->try_len = ex_info->len;
903 clause->handler_offset = ex_block->start;
904 clause->handler_len = ex_block->len;
905 if (ex_block->extype) {
906 clause->data.catch_class = mono_class_from_mono_type (monotype_cast (ex_block->extype)->type);
908 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
909 clause->data.filter_offset = ex_block->filter_offset;
911 clause->data.filter_offset = 0;
913 finally_start = ex_block->start + ex_block->len;
923 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
929 gint32 num_locals = 0;
930 gint32 num_exception = 0;
933 char fat_header [12];
936 guint32 local_sig = 0;
937 guint32 header_size = 12;
940 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
941 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
945 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
947 code = mb->ilgen->code;
948 code_size = mb->ilgen->code_len;
949 max_stack = mb->ilgen->max_stack;
950 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
951 if (mb->ilgen->ex_handlers)
952 num_exception = method_count_clauses (mb->ilgen);
956 char *name = mono_string_to_utf8 (mb->name);
957 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
958 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
961 mono_raise_exception (exception);
964 code_size = mono_array_length (code);
965 max_stack = 8; /* we probably need to run a verifier on the code... */
968 stream_data_align (&assembly->code);
970 /* check for exceptions, maxstack, locals */
971 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
973 if (code_size < 64 && !(code_size & 1)) {
974 flags = (code_size << 2) | 0x2;
975 } else if (code_size < 32 && (code_size & 1)) {
976 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
980 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
981 /* add to the fixup todo list */
982 if (mb->ilgen && mb->ilgen->num_token_fixups)
983 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
984 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
985 return assembly->text_rva + idx;
989 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
991 * FIXME: need to set also the header size in fat_flags.
992 * (and more sects and init locals flags)
996 fat_flags |= METHOD_HEADER_MORE_SECTS;
998 fat_flags |= METHOD_HEADER_INIT_LOCALS;
999 fat_header [0] = fat_flags;
1000 fat_header [1] = (header_size / 4 ) << 4;
1001 short_value = GUINT16_TO_LE (max_stack);
1002 memcpy (fat_header + 2, &short_value, 2);
1003 int_value = GUINT32_TO_LE (code_size);
1004 memcpy (fat_header + 4, &int_value, 4);
1005 int_value = GUINT32_TO_LE (local_sig);
1006 memcpy (fat_header + 8, &int_value, 4);
1007 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1008 /* add to the fixup todo list */
1009 if (mb->ilgen && mb->ilgen->num_token_fixups)
1010 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1012 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1013 if (num_exception) {
1014 unsigned char sheader [4];
1015 MonoILExceptionInfo * ex_info;
1016 MonoILExceptionBlock * ex_block;
1019 stream_data_align (&assembly->code);
1020 /* always use fat format for now */
1021 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1022 num_exception *= 6 * sizeof (guint32);
1023 num_exception += 4; /* include the size of the header */
1024 sheader [1] = num_exception & 0xff;
1025 sheader [2] = (num_exception >> 8) & 0xff;
1026 sheader [3] = (num_exception >> 16) & 0xff;
1027 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1028 /* fat header, so we are already aligned */
1030 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1031 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1032 if (ex_info->handlers) {
1033 int finally_start = ex_info->start + ex_info->len;
1034 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1036 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1038 val = GUINT32_TO_LE (ex_block->type);
1039 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1041 val = GUINT32_TO_LE (ex_info->start);
1042 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1043 /* need fault, too, probably */
1044 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1045 val = GUINT32_TO_LE (finally_start - ex_info->start);
1047 val = GUINT32_TO_LE (ex_info->len);
1048 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1049 /* handler offset */
1050 val = GUINT32_TO_LE (ex_block->start);
1051 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1053 val = GUINT32_TO_LE (ex_block->len);
1054 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1055 finally_start = ex_block->start + ex_block->len;
1056 if (ex_block->extype) {
1057 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, monotype_cast (ex_block->extype)->type));
1059 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1060 val = ex_block->filter_offset;
1064 val = GUINT32_TO_LE (val);
1065 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1066 /*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",
1067 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);*/
1070 g_error ("No clauses for ex info block %d", i);
1074 return assembly->text_rva + idx;
1078 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1081 MonoDynamicTable *table;
1084 table = &assembly->tables [table_idx];
1086 g_assert (col < table->columns);
1088 values = table->values + table->columns;
1089 for (i = 1; i <= table->rows; ++i) {
1090 if (values [col] == token)
1092 values += table->columns;
1098 * LOCKING: Acquires the loader lock.
1100 static MonoCustomAttrInfo*
1101 lookup_custom_attr (MonoImage *image, gpointer member)
1103 MonoCustomAttrInfo* res;
1105 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1110 return g_memdup (res, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (res->num_attrs - MONO_ZERO_LEN_ARRAY));
1114 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1116 /* FIXME: Need to do more checks */
1117 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1118 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1120 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1127 static MonoCustomAttrInfo*
1128 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1130 int i, index, count, not_visible;
1131 MonoCustomAttrInfo *ainfo;
1132 MonoReflectionCustomAttr *cattr;
1136 /* FIXME: check in assembly the Run flag is set */
1138 count = mono_array_length (cattrs);
1140 /* Skip nonpublic attributes since MS.NET seems to do the same */
1141 /* FIXME: This needs to be done more globally */
1143 for (i = 0; i < count; ++i) {
1144 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1145 if (!custom_attr_visible (image, cattr))
1148 count -= not_visible;
1150 ainfo = image_g_malloc0 (alloc_img, sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1152 ainfo->image = image;
1153 ainfo->num_attrs = count;
1154 ainfo->cached = alloc_img != NULL;
1156 for (i = 0; i < count; ++i) {
1157 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1158 if (custom_attr_visible (image, cattr)) {
1159 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1160 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1161 ainfo->attrs [index].ctor = cattr->ctor->method;
1162 ainfo->attrs [index].data = saved;
1163 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1172 * LOCKING: Acquires the loader lock.
1175 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1177 MonoCustomAttrInfo *ainfo, *tmp;
1179 if (!cattrs || !mono_array_length (cattrs))
1182 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1184 mono_loader_lock ();
1185 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1187 mono_custom_attrs_free (tmp);
1188 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1189 mono_loader_unlock ();
1194 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1201 * idx is the table index of the object
1202 * type is one of MONO_CUSTOM_ATTR_*
1205 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1207 MonoDynamicTable *table;
1208 MonoReflectionCustomAttr *cattr;
1210 guint32 count, i, token;
1212 char *p = blob_size;
1214 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1217 count = mono_array_length (cattrs);
1218 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1219 table->rows += count;
1220 alloc_table (table, table->rows);
1221 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1222 idx <<= MONO_CUSTOM_ATTR_BITS;
1224 for (i = 0; i < count; ++i) {
1225 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1226 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1227 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1228 type = mono_metadata_token_index (token);
1229 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1230 switch (mono_metadata_token_table (token)) {
1231 case MONO_TABLE_METHOD:
1232 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1234 case MONO_TABLE_MEMBERREF:
1235 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1238 g_warning ("got wrong token in custom attr");
1241 values [MONO_CUSTOM_ATTR_TYPE] = type;
1243 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1244 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1245 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1246 values += MONO_CUSTOM_ATTR_SIZE;
1252 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1254 MonoDynamicTable *table;
1256 guint32 count, i, idx;
1257 MonoReflectionPermissionSet *perm;
1262 count = mono_array_length (permissions);
1263 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1264 table->rows += count;
1265 alloc_table (table, table->rows);
1267 for (i = 0; i < mono_array_length (permissions); ++i) {
1268 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1270 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1272 idx = mono_metadata_token_index (parent_token);
1273 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1274 switch (mono_metadata_token_table (parent_token)) {
1275 case MONO_TABLE_TYPEDEF:
1276 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1278 case MONO_TABLE_METHOD:
1279 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1281 case MONO_TABLE_ASSEMBLY:
1282 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1285 g_assert_not_reached ();
1288 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1289 values [MONO_DECL_SECURITY_PARENT] = idx;
1290 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1297 * Fill in the MethodDef and ParamDef tables for a method.
1298 * This is used for both normal methods and constructors.
1301 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1303 MonoDynamicTable *table;
1307 /* room in this table is already allocated */
1308 table = &assembly->tables [MONO_TABLE_METHOD];
1309 *mb->table_idx = table->next_idx ++;
1310 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1311 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1312 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1313 values [MONO_METHOD_FLAGS] = mb->attrs;
1314 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1315 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1316 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1318 table = &assembly->tables [MONO_TABLE_PARAM];
1319 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1321 mono_image_add_decl_security (assembly,
1322 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1325 MonoDynamicTable *mtable;
1328 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1329 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1332 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1333 if (mono_array_get (mb->pinfo, gpointer, i))
1336 table->rows += count;
1337 alloc_table (table, table->rows);
1338 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1339 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1340 MonoReflectionParamBuilder *pb;
1341 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1342 values [MONO_PARAM_FLAGS] = pb->attrs;
1343 values [MONO_PARAM_SEQUENCE] = i;
1344 if (pb->name != NULL) {
1345 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1347 values [MONO_PARAM_NAME] = 0;
1349 values += MONO_PARAM_SIZE;
1350 if (pb->marshal_info) {
1352 alloc_table (mtable, mtable->rows);
1353 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1354 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1355 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1357 pb->table_idx = table->next_idx++;
1358 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1359 guint32 field_type = 0;
1360 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1362 alloc_table (mtable, mtable->rows);
1363 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1364 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1365 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1366 mvalues [MONO_CONSTANT_TYPE] = field_type;
1367 mvalues [MONO_CONSTANT_PADDING] = 0;
1375 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1377 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1379 rmb->ilgen = mb->ilgen;
1380 rmb->rtype = monotype_cast (mb->rtype);
1381 rmb->parameters = mb->parameters;
1382 rmb->generic_params = mb->generic_params;
1383 rmb->generic_container = mb->generic_container;
1384 rmb->opt_types = NULL;
1385 rmb->pinfo = mb->pinfo;
1386 rmb->attrs = mb->attrs;
1387 rmb->iattrs = mb->iattrs;
1388 rmb->call_conv = mb->call_conv;
1389 rmb->code = mb->code;
1390 rmb->type = mb->type;
1391 rmb->name = mb->name;
1392 rmb->table_idx = &mb->table_idx;
1393 rmb->init_locals = mb->init_locals;
1394 rmb->skip_visibility = FALSE;
1395 rmb->return_modreq = mb->return_modreq;
1396 rmb->return_modopt = mb->return_modopt;
1397 rmb->param_modreq = mb->param_modreq;
1398 rmb->param_modopt = mb->param_modopt;
1399 rmb->permissions = mb->permissions;
1400 rmb->mhandle = mb->mhandle;
1405 rmb->charset = mb->charset;
1406 rmb->extra_flags = mb->extra_flags;
1407 rmb->native_cc = mb->native_cc;
1408 rmb->dllentry = mb->dllentry;
1414 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1416 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1418 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1420 rmb->ilgen = mb->ilgen;
1421 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1422 rmb->parameters = mb->parameters;
1423 rmb->generic_params = NULL;
1424 rmb->generic_container = NULL;
1425 rmb->opt_types = NULL;
1426 rmb->pinfo = mb->pinfo;
1427 rmb->attrs = mb->attrs;
1428 rmb->iattrs = mb->iattrs;
1429 rmb->call_conv = mb->call_conv;
1431 rmb->type = mb->type;
1432 rmb->name = mono_string_new (mono_domain_get (), name);
1433 rmb->table_idx = &mb->table_idx;
1434 rmb->init_locals = mb->init_locals;
1435 rmb->skip_visibility = FALSE;
1436 rmb->return_modreq = NULL;
1437 rmb->return_modopt = NULL;
1438 rmb->param_modreq = mb->param_modreq;
1439 rmb->param_modopt = mb->param_modopt;
1440 rmb->permissions = mb->permissions;
1441 rmb->mhandle = mb->mhandle;
1447 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1449 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1451 rmb->ilgen = mb->ilgen;
1452 rmb->rtype = mb->rtype;
1453 rmb->parameters = mb->parameters;
1454 rmb->generic_params = NULL;
1455 rmb->generic_container = NULL;
1456 rmb->opt_types = NULL;
1458 rmb->attrs = mb->attrs;
1460 rmb->call_conv = mb->call_conv;
1462 rmb->type = (MonoObject *) mb->owner;
1463 rmb->name = mb->name;
1464 rmb->table_idx = NULL;
1465 rmb->init_locals = mb->init_locals;
1466 rmb->skip_visibility = mb->skip_visibility;
1467 rmb->return_modreq = NULL;
1468 rmb->return_modopt = NULL;
1469 rmb->param_modreq = NULL;
1470 rmb->param_modopt = NULL;
1471 rmb->permissions = NULL;
1472 rmb->mhandle = mb->mhandle;
1478 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1480 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1481 MonoDynamicTable *table;
1485 if (!mb->override_method)
1488 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1490 alloc_table (table, table->rows);
1491 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1492 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1493 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1495 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1496 switch (mono_metadata_token_table (tok)) {
1497 case MONO_TABLE_MEMBERREF:
1498 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1500 case MONO_TABLE_METHOD:
1501 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1504 g_assert_not_reached ();
1506 values [MONO_METHODIMPL_DECLARATION] = tok;
1510 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1512 MonoDynamicTable *table;
1514 ReflectionMethodBuilder rmb;
1517 reflection_methodbuilder_from_method_builder (&rmb, mb);
1519 mono_image_basic_method (&rmb, assembly);
1520 mb->table_idx = *rmb.table_idx;
1522 if (mb->dll) { /* It's a P/Invoke method */
1524 /* map CharSet values to on-disk values */
1525 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1526 int extra_flags = mb->extra_flags;
1527 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1529 alloc_table (table, table->rows);
1530 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1532 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1533 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1535 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1537 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1538 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1539 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1540 table = &assembly->tables [MONO_TABLE_MODULEREF];
1542 alloc_table (table, table->rows);
1543 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1544 values [MONO_IMPLMAP_SCOPE] = table->rows;
1548 if (mb->generic_params) {
1549 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1550 table->rows += mono_array_length (mb->generic_params);
1551 alloc_table (table, table->rows);
1552 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1553 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1555 mono_image_get_generic_param_info (
1556 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1563 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1565 ReflectionMethodBuilder rmb;
1567 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1569 mono_image_basic_method (&rmb, assembly);
1570 mb->table_idx = *rmb.table_idx;
1574 type_get_fully_qualified_name (MonoType *type)
1576 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1580 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1584 klass = mono_class_from_mono_type (type);
1586 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1587 ta = klass->image->assembly;
1588 if (ta->dynamic || (ta == ass)) {
1589 if (klass->generic_class || klass->generic_container)
1590 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1591 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1593 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1596 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1600 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1605 if (!assembly->save)
1608 sigbuffer_init (&buf, 32);
1610 sigbuffer_add_value (&buf, 0x06);
1611 /* encode custom attributes before the type */
1612 /* FIXME: This should probably go in encode_type () */
1613 if (type->num_mods) {
1614 for (i = 0; i < type->num_mods; ++i) {
1615 if (type->modifiers [i].required)
1616 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1618 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1619 sigbuffer_add_value (&buf, type->modifiers [i].token);
1622 encode_type (assembly, type, &buf);
1623 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1624 sigbuffer_free (&buf);
1629 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1634 sigbuffer_init (&buf, 32);
1636 sigbuffer_add_value (&buf, 0x06);
1637 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1638 /* encode custom attributes before the type */
1639 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1640 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1641 sigbuffer_free (&buf);
1646 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1647 char blob_size [64];
1648 char *b = blob_size;
1651 guint32 idx = 0, len = 0, dummy = 0;
1653 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1654 guint32 fpa_double [2];
1659 p = buf = g_malloc (64);
1661 *ret_type = MONO_TYPE_CLASS;
1663 box_val = (char*)&dummy;
1665 box_val = ((char*)val) + sizeof (MonoObject);
1666 *ret_type = val->vtable->klass->byval_arg.type;
1669 switch (*ret_type) {
1670 case MONO_TYPE_BOOLEAN:
1675 case MONO_TYPE_CHAR:
1692 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1693 fpa_p = (guint32*)box_val;
1694 fpa_double [0] = fpa_p [1];
1695 fpa_double [1] = fpa_p [0];
1696 box_val = (char*)fpa_double;
1700 case MONO_TYPE_VALUETYPE:
1701 if (val->vtable->klass->enumtype) {
1702 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1705 g_error ("we can't encode valuetypes");
1706 case MONO_TYPE_CLASS:
1708 case MONO_TYPE_STRING: {
1709 MonoString *str = (MonoString*)val;
1710 /* there is no signature */
1711 len = str->length * 2;
1712 mono_metadata_encode_value (len, b, &b);
1713 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1715 char *swapped = g_malloc (2 * mono_string_length (str));
1716 const char *p = (const char*)mono_string_chars (str);
1718 swap_with_size (swapped, p, 2, mono_string_length (str));
1719 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1723 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1729 case MONO_TYPE_GENERICINST:
1730 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1733 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1736 /* there is no signature */
1737 mono_metadata_encode_value (len, b, &b);
1738 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1739 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1740 swap_with_size (blob_size, box_val, len, 1);
1741 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1743 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1751 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1756 sigbuffer_init (&buf, 32);
1758 sigbuffer_add_value (&buf, minfo->type);
1760 switch (minfo->type) {
1761 case MONO_NATIVE_BYVALTSTR:
1762 case MONO_NATIVE_BYVALARRAY:
1763 sigbuffer_add_value (&buf, minfo->count);
1765 case MONO_NATIVE_LPARRAY:
1766 if (minfo->eltype || minfo->has_size) {
1767 sigbuffer_add_value (&buf, minfo->eltype);
1768 if (minfo->has_size) {
1769 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1770 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1772 /* LAMESPEC: ElemMult is undocumented */
1773 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1777 case MONO_NATIVE_CUSTOM:
1779 str = mono_string_to_utf8 (minfo->guid);
1781 sigbuffer_add_value (&buf, len);
1782 sigbuffer_add_mem (&buf, str, len);
1785 sigbuffer_add_value (&buf, 0);
1787 /* native type name */
1788 sigbuffer_add_value (&buf, 0);
1789 /* custom marshaler type name */
1790 if (minfo->marshaltype || minfo->marshaltyperef) {
1791 if (minfo->marshaltyperef)
1792 str = type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
1794 str = mono_string_to_utf8 (minfo->marshaltype);
1796 sigbuffer_add_value (&buf, len);
1797 sigbuffer_add_mem (&buf, str, len);
1800 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1801 sigbuffer_add_value (&buf, 0);
1803 if (minfo->mcookie) {
1804 str = mono_string_to_utf8 (minfo->mcookie);
1806 sigbuffer_add_value (&buf, len);
1807 sigbuffer_add_mem (&buf, str, len);
1810 sigbuffer_add_value (&buf, 0);
1816 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1817 sigbuffer_free (&buf);
1822 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1824 MonoDynamicTable *table;
1827 /* maybe this fixup should be done in the C# code */
1828 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1829 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1830 table = &assembly->tables [MONO_TABLE_FIELD];
1831 fb->table_idx = table->next_idx ++;
1832 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1833 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1834 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1835 values [MONO_FIELD_FLAGS] = fb->attrs;
1836 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1838 if (fb->offset != -1) {
1839 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1841 alloc_table (table, table->rows);
1842 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1843 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1844 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1846 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1847 guint32 field_type = 0;
1848 table = &assembly->tables [MONO_TABLE_CONSTANT];
1850 alloc_table (table, table->rows);
1851 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1852 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1853 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1854 values [MONO_CONSTANT_TYPE] = field_type;
1855 values [MONO_CONSTANT_PADDING] = 0;
1857 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1859 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1861 alloc_table (table, table->rows);
1862 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1863 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1865 * We store it in the code section because it's simpler for now.
1868 if (mono_array_length (fb->rva_data) >= 10)
1869 stream_data_align (&assembly->code);
1870 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1872 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1873 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1875 if (fb->marshal_info) {
1876 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1878 alloc_table (table, table->rows);
1879 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1880 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1881 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1886 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1889 guint32 nparams = 0;
1890 MonoReflectionMethodBuilder *mb = fb->get_method;
1891 MonoReflectionMethodBuilder *smb = fb->set_method;
1894 if (mb && mb->parameters)
1895 nparams = mono_array_length (mb->parameters);
1896 if (!mb && smb && smb->parameters)
1897 nparams = mono_array_length (smb->parameters) - 1;
1898 sigbuffer_init (&buf, 32);
1899 sigbuffer_add_byte (&buf, 0x08);
1900 sigbuffer_add_value (&buf, nparams);
1902 encode_reflection_type (assembly, monotype_cast (mb->rtype), &buf);
1903 for (i = 0; i < nparams; ++i) {
1904 MonoReflectionType *pt = mono_type_array_get (mb->parameters, i);
1905 encode_reflection_type (assembly, pt, &buf);
1907 } else if (smb && smb->parameters) {
1908 /* the property type is the last param */
1909 encode_reflection_type (assembly, mono_type_array_get (smb->parameters, nparams), &buf);
1910 for (i = 0; i < nparams; ++i) {
1911 MonoReflectionType *pt = mono_type_array_get (smb->parameters, i);
1912 encode_reflection_type (assembly, pt, &buf);
1915 encode_reflection_type (assembly, monotype_cast (fb->type), &buf);
1918 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1919 sigbuffer_free (&buf);
1924 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1926 MonoDynamicTable *table;
1928 guint num_methods = 0;
1932 * we need to set things in the following tables:
1933 * PROPERTYMAP (info already filled in _get_type_info ())
1934 * PROPERTY (rows already preallocated in _get_type_info ())
1935 * METHOD (method info already done with the generic method code)
1938 table = &assembly->tables [MONO_TABLE_PROPERTY];
1939 pb->table_idx = table->next_idx ++;
1940 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1941 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1942 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1943 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1945 /* FIXME: we still don't handle 'other' methods */
1946 if (pb->get_method) num_methods ++;
1947 if (pb->set_method) num_methods ++;
1949 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1950 table->rows += num_methods;
1951 alloc_table (table, table->rows);
1953 if (pb->get_method) {
1954 semaidx = table->next_idx ++;
1955 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1956 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1957 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1958 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1960 if (pb->set_method) {
1961 semaidx = table->next_idx ++;
1962 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1963 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1964 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1965 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1970 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1972 MonoDynamicTable *table;
1974 guint num_methods = 0;
1978 * we need to set things in the following tables:
1979 * EVENTMAP (info already filled in _get_type_info ())
1980 * EVENT (rows already preallocated in _get_type_info ())
1981 * METHOD (method info already done with the generic method code)
1984 table = &assembly->tables [MONO_TABLE_EVENT];
1985 eb->table_idx = table->next_idx ++;
1986 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1987 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
1988 values [MONO_EVENT_FLAGS] = eb->attrs;
1989 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1992 * FIXME: we still don't handle 'other' methods
1994 if (eb->add_method) num_methods ++;
1995 if (eb->remove_method) num_methods ++;
1996 if (eb->raise_method) num_methods ++;
1998 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1999 table->rows += num_methods;
2000 alloc_table (table, table->rows);
2002 if (eb->add_method) {
2003 semaidx = table->next_idx ++;
2004 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2005 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2006 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2007 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2009 if (eb->remove_method) {
2010 semaidx = table->next_idx ++;
2011 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2012 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2013 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2014 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2016 if (eb->raise_method) {
2017 semaidx = table->next_idx ++;
2018 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2019 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2020 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2021 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2026 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2028 MonoDynamicTable *table;
2029 guint32 num_constraints, i;
2033 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2034 num_constraints = gparam->iface_constraints ?
2035 mono_array_length (gparam->iface_constraints) : 0;
2036 table->rows += num_constraints;
2037 if (gparam->base_type)
2039 alloc_table (table, table->rows);
2041 if (gparam->base_type) {
2042 table_idx = table->next_idx ++;
2043 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2045 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2046 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2047 assembly, gparam->base_type->type);
2050 for (i = 0; i < num_constraints; i++) {
2051 MonoReflectionType *constraint = mono_array_get (
2052 gparam->iface_constraints, gpointer, i);
2054 table_idx = table->next_idx ++;
2055 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2057 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2058 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2059 assembly, constraint->type);
2064 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2066 GenericParamTableEntry *entry;
2069 * The GenericParam table must be sorted according to the `owner' field.
2070 * We need to do this sorting prior to writing the GenericParamConstraint
2071 * table, since we have to use the final GenericParam table indices there
2072 * and they must also be sorted.
2075 entry = g_new0 (GenericParamTableEntry, 1);
2076 entry->owner = owner;
2077 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2078 MOVING_GC_REGISTER (&entry->gparam);
2079 entry->gparam = gparam;
2081 g_ptr_array_add (assembly->gen_params, entry);
2085 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2087 MonoDynamicTable *table;
2088 MonoGenericParam *param;
2092 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2093 table_idx = table->next_idx ++;
2094 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2096 param = entry->gparam->type.type->data.generic_param;
2098 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2099 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2100 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2101 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2103 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2105 encode_constraints (entry->gparam, table_idx, assembly);
2109 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2111 MonoDynamicTable *table;
2114 guint32 cols [MONO_ASSEMBLY_SIZE];
2118 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2121 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2122 table = &assembly->tables [MONO_TABLE_MODULEREF];
2123 token = table->next_idx ++;
2125 alloc_table (table, table->rows);
2126 values = table->values + token * MONO_MODULEREF_SIZE;
2127 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2129 token <<= MONO_RESOLTION_SCOPE_BITS;
2130 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2131 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2136 if (image->assembly->dynamic)
2138 memset (cols, 0, sizeof (cols));
2140 /* image->assembly->image is the manifest module */
2141 image = image->assembly->image;
2142 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2145 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2146 token = table->next_idx ++;
2148 alloc_table (table, table->rows);
2149 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2150 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2151 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2152 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2153 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2154 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2155 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2156 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2157 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2159 if (strcmp ("", image->assembly->aname.culture)) {
2160 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2161 image->assembly->aname.culture);
2164 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2165 guchar pubtoken [9];
2167 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2168 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2170 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2172 token <<= MONO_RESOLTION_SCOPE_BITS;
2173 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2174 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2179 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2181 MonoDynamicTable *table;
2186 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2189 sigbuffer_init (&buf, 32);
2190 switch (type->type) {
2191 case MONO_TYPE_FNPTR:
2193 case MONO_TYPE_SZARRAY:
2194 case MONO_TYPE_ARRAY:
2196 case MONO_TYPE_MVAR:
2197 case MONO_TYPE_GENERICINST:
2198 encode_type (assembly, type, &buf);
2200 case MONO_TYPE_CLASS:
2201 case MONO_TYPE_VALUETYPE: {
2202 MonoClass *k = mono_class_from_mono_type (type);
2203 if (!k || !k->generic_container) {
2204 sigbuffer_free (&buf);
2207 encode_type (assembly, type, &buf);
2211 sigbuffer_free (&buf);
2215 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2216 if (assembly->save) {
2217 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2218 alloc_table (table, table->rows + 1);
2219 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2220 values [MONO_TYPESPEC_SIGNATURE] = token;
2222 sigbuffer_free (&buf);
2224 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2225 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2231 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2233 MonoDynamicTable *table;
2235 guint32 token, scope, enclosing;
2238 /* if the type requires a typespec, we must try that first*/
2239 if (try_typespec && (token = create_typespec (assembly, type)))
2241 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2244 klass = mono_class_from_mono_type (type);
2246 klass = mono_class_from_mono_type (type);
2249 * If it's in the same module and not a generic type parameter:
2251 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2252 (type->type != MONO_TYPE_MVAR)) {
2253 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2254 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2255 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2259 if (klass->nested_in) {
2260 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2261 /* get the typeref idx of the enclosing type */
2262 enclosing >>= MONO_TYPEDEFORREF_BITS;
2263 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2265 scope = resolution_scope_from_image (assembly, klass->image);
2267 table = &assembly->tables [MONO_TABLE_TYPEREF];
2268 if (assembly->save) {
2269 alloc_table (table, table->rows + 1);
2270 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2271 values [MONO_TYPEREF_SCOPE] = scope;
2272 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2273 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2275 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2276 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2278 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2283 * Despite the name, we handle also TypeSpec (with the above helper).
2286 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2288 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2292 * Insert a memberef row into the metadata: the token that point to the memberref
2293 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2294 * mono_image_get_fieldref_token()).
2295 * The sig param is an index to an already built signature.
2298 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2300 MonoDynamicTable *table;
2302 guint32 token, pclass;
2305 parent = mono_image_typedef_or_ref (assembly, type);
2306 switch (parent & MONO_TYPEDEFORREF_MASK) {
2307 case MONO_TYPEDEFORREF_TYPEREF:
2308 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2310 case MONO_TYPEDEFORREF_TYPESPEC:
2311 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2313 case MONO_TYPEDEFORREF_TYPEDEF:
2314 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2317 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2320 /* extract the index */
2321 parent >>= MONO_TYPEDEFORREF_BITS;
2323 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2325 if (assembly->save) {
2326 alloc_table (table, table->rows + 1);
2327 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2328 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2329 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2330 values [MONO_MEMBERREF_SIGNATURE] = sig;
2333 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2340 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2343 MonoMethodSignature *sig;
2345 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2347 if (create_typespec) {
2348 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2353 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2354 if (token && !create_typespec)
2357 g_assert (!method->is_inflated);
2360 * A methodref signature can't contain an unmanaged calling convention.
2362 sig = mono_metadata_signature_dup (mono_method_signature (method));
2363 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2364 sig->call_convention = MONO_CALL_DEFAULT;
2365 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2366 method->name, method_encode_signature (assembly, sig));
2368 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2371 if (create_typespec) {
2372 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2373 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2374 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2376 if (assembly->save) {
2379 alloc_table (table, table->rows + 1);
2380 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2381 values [MONO_METHODSPEC_METHOD] = token;
2382 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2385 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2387 /*methodspec and memberef tokens are diferent, */
2388 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2395 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2398 ReflectionMethodBuilder rmb;
2401 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2405 name = mono_string_to_utf8 (method->name);
2406 reflection_methodbuilder_from_method_builder (&rmb, method);
2409 * A methodref signature can't contain an unmanaged calling convention.
2410 * Since some flags are encoded as part of call_conv, we need to check against it.
2412 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2413 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2414 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2415 name, method_builder_encode_signature (assembly, &rmb));
2418 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2423 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2424 const gchar *name, guint32 sig)
2426 MonoDynamicTable *table;
2430 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2432 if (assembly->save) {
2433 alloc_table (table, table->rows + 1);
2434 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2435 values [MONO_MEMBERREF_CLASS] = original;
2436 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2437 values [MONO_MEMBERREF_SIGNATURE] = sig;
2440 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2447 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2451 guint32 nparams = mono_array_length (mb->generic_params);
2454 if (!assembly->save)
2457 sigbuffer_init (&buf, 32);
2459 sigbuffer_add_value (&buf, 0xa);
2460 sigbuffer_add_value (&buf, nparams);
2462 for (i = 0; i < nparams; i++) {
2463 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2464 sigbuffer_add_value (&buf, i);
2467 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2468 sigbuffer_free (&buf);
2473 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2475 MonoDynamicTable *table;
2477 guint32 token, mtoken = 0;
2479 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2483 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2485 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2486 switch (mono_metadata_token_table (mtoken)) {
2487 case MONO_TABLE_MEMBERREF:
2488 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2490 case MONO_TABLE_METHOD:
2491 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2494 g_assert_not_reached ();
2497 if (assembly->save) {
2498 alloc_table (table, table->rows + 1);
2499 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2500 values [MONO_METHODSPEC_METHOD] = mtoken;
2501 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2504 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2507 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2512 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2516 if (mb->generic_params && create_methodspec)
2517 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2519 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2523 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2524 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2529 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2532 ReflectionMethodBuilder rmb;
2535 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2539 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2541 name = mono_string_to_utf8 (rmb.name);
2542 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2543 name, method_builder_encode_signature (assembly, &rmb));
2546 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2551 is_field_on_inst (MonoClassField *field)
2553 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2557 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2560 get_field_on_inst_generic_type (MonoClassField *field)
2562 MonoDynamicGenericClass *dgclass;
2565 g_assert (is_field_on_inst (field));
2567 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2568 field_index = field - dgclass->fields;
2570 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
2571 return dgclass->field_generic_types [field_index];
2575 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2579 MonoClassField *field;
2581 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2584 g_assert (f->field->parent);
2587 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2588 int index = field - field->parent->fields;
2589 type = field->parent->generic_class->container_class->fields [index].type;
2591 if (is_field_on_inst (f->field))
2592 type = get_field_on_inst_generic_type (f->field);
2594 type = f->field->type;
2596 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2597 mono_field_get_name (f->field),
2598 fieldref_encode_signature (assembly, type));
2599 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2604 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2608 MonoGenericClass *gclass;
2609 MonoDynamicGenericClass *dgclass;
2610 MonoReflectionFieldBuilder *fb = f->fb;
2613 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2616 klass = mono_class_from_mono_type (f->inst->type.type);
2617 gclass = f->inst->type.type->data.generic_class;
2618 g_assert (gclass->is_dynamic);
2619 dgclass = (MonoDynamicGenericClass *) gclass;
2621 name = mono_string_to_utf8 (fb->name);
2622 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2623 field_encode_signature (assembly, fb));
2625 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER (token));
2630 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2634 MonoGenericClass *gclass;
2635 MonoDynamicGenericClass *dgclass;
2636 MonoReflectionCtorBuilder *cb = c->cb;
2637 ReflectionMethodBuilder rmb;
2640 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2642 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, c));
2645 klass = mono_class_from_mono_type (c->inst->type.type);
2646 gclass = c->inst->type.type->data.generic_class;
2647 g_assert (gclass->is_dynamic);
2648 dgclass = (MonoDynamicGenericClass *) gclass;
2650 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2652 name = mono_string_to_utf8 (rmb.name);
2654 sig = method_builder_encode_signature (assembly, &rmb);
2656 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2659 g_hash_table_insert (assembly->handleref, c, GUINT_TO_POINTER (token));
2664 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2668 MonoGenericClass *gclass;
2669 MonoReflectionMethodBuilder *mb = m->mb;
2670 ReflectionMethodBuilder rmb;
2673 if (create_methodspec && mb->generic_params)
2675 g_assert_not_reached ();
2677 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2680 klass = mono_class_from_mono_type (m->inst->type.type);
2681 gclass = m->inst->type.type->data.generic_class;
2682 g_assert (gclass->is_dynamic);
2684 reflection_methodbuilder_from_method_builder (&rmb, mb);
2686 name = mono_string_to_utf8 (rmb.name);
2688 sig = method_builder_encode_signature (assembly, &rmb);
2690 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2693 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER (token));
2698 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2702 guint32 nparams = context->method_inst->type_argc;
2705 if (!assembly->save)
2708 sigbuffer_init (&buf, 32);
2710 * FIXME: vararg, explicit_this, differenc call_conv values...
2712 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2713 sigbuffer_add_value (&buf, nparams);
2715 for (i = 0; i < nparams; i++)
2716 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2718 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2719 sigbuffer_free (&buf);
2724 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2726 MonoDynamicTable *table;
2728 guint32 token, mtoken = 0, sig;
2729 MonoMethodInflated *imethod;
2730 MonoMethod *declaring;
2732 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2734 g_assert (method->is_inflated);
2735 imethod = (MonoMethodInflated *) method;
2736 declaring = imethod->declaring;
2738 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2739 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2741 if (!mono_method_signature (declaring)->generic_param_count)
2744 switch (mono_metadata_token_table (mtoken)) {
2745 case MONO_TABLE_MEMBERREF:
2746 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2748 case MONO_TABLE_METHOD:
2749 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2752 g_assert_not_reached ();
2755 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2757 if (assembly->save) {
2758 alloc_table (table, table->rows + 1);
2759 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2760 values [MONO_METHODSPEC_METHOD] = mtoken;
2761 values [MONO_METHODSPEC_SIGNATURE] = sig;
2764 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2771 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2773 MonoMethodInflated *imethod;
2776 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2780 g_assert (method->is_inflated);
2781 imethod = (MonoMethodInflated *) method;
2783 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2784 token = method_encode_methodspec (assembly, method);
2786 guint32 sig = method_encode_signature (
2787 assembly, mono_method_signature (imethod->declaring));
2788 token = mono_image_get_memberref_token (
2789 assembly, &method->klass->byval_arg, method->name, sig);
2792 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2797 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2799 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2802 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2803 token = mono_image_get_memberref_token (
2804 assembly, &m->klass->byval_arg, m->name, sig);
2810 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2812 MonoDynamicTable *table;
2820 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2821 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2822 * Because of this, we must not insert it into the `typeref' hash table.
2825 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2829 sigbuffer_init (&buf, 32);
2831 g_assert (tb->generic_params);
2832 klass = mono_class_from_mono_type (tb->type.type);
2834 if (tb->generic_container)
2835 mono_reflection_create_generic_class (tb);
2837 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
2838 g_assert (klass->generic_container);
2839 sigbuffer_add_value (&buf, klass->byval_arg.type);
2840 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
2842 count = mono_array_length (tb->generic_params);
2843 sigbuffer_add_value (&buf, count);
2844 for (i = 0; i < count; i++) {
2845 MonoReflectionGenericParam *gparam;
2847 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2849 encode_type (assembly, gparam->type.type, &buf);
2852 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2854 if (assembly->save) {
2855 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2856 alloc_table (table, table->rows + 1);
2857 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2858 values [MONO_TYPESPEC_SIGNATURE] = token;
2860 sigbuffer_free (&buf);
2862 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2863 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2869 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2872 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
2874 int i, count, len, pos;
2879 count += mono_array_length (modreq);
2881 count += mono_array_length (modopt);
2884 return mono_metadata_type_dup (NULL, type);
2886 len = sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod);
2888 memcpy (t, type, len);
2890 t->num_mods = count;
2893 for (i = 0; i < mono_array_length (modreq); ++i) {
2894 MonoReflectionType *mod = mono_type_array_get (modreq, i);
2895 t->modifiers [pos].required = 1;
2896 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2901 for (i = 0; i < mono_array_length (modopt); ++i) {
2902 MonoReflectionType *mod = mono_type_array_get (modopt, i);
2903 t->modifiers [pos].required = 0;
2904 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod->type);
2913 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2915 MonoDynamicTable *table;
2917 MonoType *custom = NULL;
2919 guint32 token, pclass, parent, sig;
2922 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2926 klass = mono_class_from_mono_type (fb->typeb->type);
2927 name = mono_string_to_utf8 (fb->name);
2929 /* fb->type does not include the custom modifiers */
2930 /* FIXME: We should do this in one place when a fieldbuilder is created */
2931 if (fb->modreq || fb->modopt) {
2932 custom = add_custom_modifiers (assembly, monotype_cast (fb->type)->type, fb->modreq, fb->modopt);
2933 sig = fieldref_encode_signature (assembly, custom);
2936 sig = fieldref_encode_signature (assembly, monotype_cast (fb->type)->type);
2939 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2940 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2942 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2943 parent >>= MONO_TYPEDEFORREF_BITS;
2945 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2947 if (assembly->save) {
2948 alloc_table (table, table->rows + 1);
2949 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2950 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2951 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2952 values [MONO_MEMBERREF_SIGNATURE] = sig;
2955 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2957 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2963 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2970 if (!assembly->save)
2973 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2974 g_assert (helper->type == 2);
2976 if (helper->arguments)
2977 nargs = mono_array_length (helper->arguments);
2981 size = 10 + (nargs * 10);
2983 sigbuffer_init (&buf, 32);
2985 /* Encode calling convention */
2986 /* Change Any to Standard */
2987 if ((helper->call_conv & 0x03) == 0x03)
2988 helper->call_conv = 0x01;
2989 /* explicit_this implies has_this */
2990 if (helper->call_conv & 0x40)
2991 helper->call_conv &= 0x20;
2993 if (helper->call_conv == 0) { /* Unmanaged */
2994 idx = helper->unmanaged_call_conv - 1;
2997 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
2998 if (helper->call_conv & 0x02) /* varargs */
3002 sigbuffer_add_byte (&buf, idx);
3003 sigbuffer_add_value (&buf, nargs);
3004 encode_reflection_type (assembly, helper->return_type, &buf);
3005 for (i = 0; i < nargs; ++i) {
3006 MonoArray *modreqs = NULL;
3007 MonoArray *modopts = NULL;
3008 MonoReflectionType *pt;
3010 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3011 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3012 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3013 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3015 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3016 pt = mono_type_array_get (helper->arguments, i);
3017 encode_reflection_type (assembly, pt, &buf);
3019 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3020 sigbuffer_free (&buf);
3026 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3029 MonoDynamicTable *table;
3032 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3033 idx = table->next_idx ++;
3035 alloc_table (table, table->rows);
3036 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3038 values [MONO_STAND_ALONE_SIGNATURE] =
3039 mono_reflection_encode_sighelper (assembly, helper);
3045 reflection_cc_to_file (int call_conv) {
3046 switch (call_conv & 0x3) {
3048 case 1: return MONO_CALL_DEFAULT;
3049 case 2: return MONO_CALL_VARARG;
3051 g_assert_not_reached ();
3058 MonoMethodSignature *sig;
3064 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3069 MonoMethodSignature *sig;
3072 name = mono_string_to_utf8 (m->name);
3073 nparams = mono_array_length (m->parameters);
3074 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
3076 sig->sentinelpos = -1;
3077 sig->call_convention = reflection_cc_to_file (m->call_conv);
3078 sig->param_count = nparams;
3079 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
3080 for (i = 0; i < nparams; ++i) {
3081 MonoReflectionType *t = mono_type_array_get (m->parameters, i);
3082 sig->params [i] = t->type;
3085 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3087 if (strcmp (name, am->name) == 0 &&
3088 mono_metadata_type_equal (am->parent, m->parent->type) &&
3089 mono_metadata_signature_equal (am->sig, sig)) {
3092 m->table_idx = am->token & 0xffffff;
3096 am = g_new0 (ArrayMethod, 1);
3099 am->parent = m->parent->type;
3100 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3101 method_encode_signature (assembly, sig));
3102 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3103 m->table_idx = am->token & 0xffffff;
3108 * Insert into the metadata tables all the info about the TypeBuilder tb.
3109 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3112 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3114 MonoDynamicTable *table;
3116 int i, is_object = 0, is_system = 0;
3119 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3120 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3121 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3122 n = mono_string_to_utf8 (tb->name);
3123 if (strcmp (n, "Object") == 0)
3125 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3127 n = mono_string_to_utf8 (tb->nspace);
3128 if (strcmp (n, "System") == 0)
3130 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3132 if (tb->parent && !(is_system && is_object) &&
3133 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3134 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, monotype_cast (tb->parent)->type);
3136 values [MONO_TYPEDEF_EXTENDS] = 0;
3138 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3139 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3142 * if we have explicitlayout or sequentiallayouts, output data in the
3143 * ClassLayout table.
3145 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3146 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3147 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3149 alloc_table (table, table->rows);
3150 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3151 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3152 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3153 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3156 /* handle interfaces */
3157 if (tb->interfaces) {
3158 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3160 table->rows += mono_array_length (tb->interfaces);
3161 alloc_table (table, table->rows);
3162 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3163 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3164 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3165 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3166 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
3167 values += MONO_INTERFACEIMPL_SIZE;
3173 table = &assembly->tables [MONO_TABLE_FIELD];
3174 table->rows += tb->num_fields;
3175 alloc_table (table, table->rows);
3176 for (i = 0; i < tb->num_fields; ++i)
3177 mono_image_get_field_info (
3178 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3181 /* handle constructors */
3183 table = &assembly->tables [MONO_TABLE_METHOD];
3184 table->rows += mono_array_length (tb->ctors);
3185 alloc_table (table, table->rows);
3186 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3187 mono_image_get_ctor_info (domain,
3188 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3191 /* handle methods */
3193 table = &assembly->tables [MONO_TABLE_METHOD];
3194 table->rows += tb->num_methods;
3195 alloc_table (table, table->rows);
3196 for (i = 0; i < tb->num_methods; ++i)
3197 mono_image_get_method_info (
3198 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3201 /* Do the same with properties etc.. */
3202 if (tb->events && mono_array_length (tb->events)) {
3203 table = &assembly->tables [MONO_TABLE_EVENT];
3204 table->rows += mono_array_length (tb->events);
3205 alloc_table (table, table->rows);
3206 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3208 alloc_table (table, table->rows);
3209 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3210 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3211 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3212 for (i = 0; i < mono_array_length (tb->events); ++i)
3213 mono_image_get_event_info (
3214 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3216 if (tb->properties && mono_array_length (tb->properties)) {
3217 table = &assembly->tables [MONO_TABLE_PROPERTY];
3218 table->rows += mono_array_length (tb->properties);
3219 alloc_table (table, table->rows);
3220 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3222 alloc_table (table, table->rows);
3223 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3224 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3225 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3226 for (i = 0; i < mono_array_length (tb->properties); ++i)
3227 mono_image_get_property_info (
3228 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3231 /* handle generic parameters */
3232 if (tb->generic_params) {
3233 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3234 table->rows += mono_array_length (tb->generic_params);
3235 alloc_table (table, table->rows);
3236 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3237 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3239 mono_image_get_generic_param_info (
3240 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3244 mono_image_add_decl_security (assembly,
3245 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3248 MonoDynamicTable *ntable;
3250 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3251 ntable->rows += mono_array_length (tb->subtypes);
3252 alloc_table (ntable, ntable->rows);
3253 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3255 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3256 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3258 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3259 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3260 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3261 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3262 mono_string_to_utf8 (tb->name), tb->table_idx,
3263 ntable->next_idx, ntable->rows);*/
3264 values += MONO_NESTED_CLASS_SIZE;
3271 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3275 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3277 if (!type->subtypes)
3280 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3281 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3282 collect_types (types, subtype);
3287 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3289 if ((*type1)->table_idx < (*type2)->table_idx)
3292 if ((*type1)->table_idx > (*type2)->table_idx)
3299 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3304 for (i = 0; i < mono_array_length (pinfo); ++i) {
3305 MonoReflectionParamBuilder *pb;
3306 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3309 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3314 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3317 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3319 for (i = 0; i < tb->num_fields; ++i) {
3320 MonoReflectionFieldBuilder* fb;
3321 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3322 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3326 for (i = 0; i < mono_array_length (tb->events); ++i) {
3327 MonoReflectionEventBuilder* eb;
3328 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3329 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3332 if (tb->properties) {
3333 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3334 MonoReflectionPropertyBuilder* pb;
3335 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3336 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3340 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3341 MonoReflectionCtorBuilder* cb;
3342 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3343 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3344 params_add_cattrs (assembly, cb->pinfo);
3349 for (i = 0; i < tb->num_methods; ++i) {
3350 MonoReflectionMethodBuilder* mb;
3351 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3352 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3353 params_add_cattrs (assembly, mb->pinfo);
3358 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3359 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3364 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3368 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3370 if (moduleb->global_methods) {
3371 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3372 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3373 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3374 params_add_cattrs (assembly, mb->pinfo);
3378 if (moduleb->global_fields) {
3379 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3380 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3381 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3385 if (moduleb->types) {
3386 for (i = 0; i < moduleb->num_types; ++i)
3387 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3392 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3394 MonoDynamicTable *table;
3398 char *b = blob_size;
3401 table = &assembly->tables [MONO_TABLE_FILE];
3403 alloc_table (table, table->rows);
3404 values = table->values + table->next_idx * MONO_FILE_SIZE;
3405 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3406 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3407 if (module->image->dynamic) {
3408 /* This depends on the fact that the main module is emitted last */
3409 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3410 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3413 path = g_strdup (module->image->name);
3415 mono_sha1_get_digest_from_file (path, hash);
3418 mono_metadata_encode_value (20, b, &b);
3419 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3420 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3425 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3427 MonoDynamicTable *table;
3430 table = &assembly->tables [MONO_TABLE_MODULE];
3431 mb->table_idx = table->next_idx ++;
3432 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3433 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3436 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3437 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3438 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3439 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3443 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3444 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3446 MonoDynamicTable *table;
3450 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3451 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3454 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3456 alloc_table (table, table->rows);
3457 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3459 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3460 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3461 if (klass->nested_in)
3462 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3464 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3465 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3466 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3468 res = table->next_idx;
3472 /* Emit nested types */
3473 if (klass->ext && klass->ext->nested_classes) {
3476 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3477 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3484 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3485 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3490 klass = mono_class_from_mono_type (tb->type.type);
3492 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3494 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3495 parent_index, assembly);
3499 * We need to do this ourselves since klass->nested_classes is not set up.
3502 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3503 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3508 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3509 guint32 module_index, MonoDynamicImage *assembly)
3511 MonoImage *image = module->image;
3515 t = &image->tables [MONO_TABLE_TYPEDEF];
3517 for (i = 0; i < t->rows; ++i) {
3518 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3520 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3521 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3526 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3528 MonoDynamicTable *table;
3534 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3536 if (assemblyb->type_forwarders) {
3537 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3538 MonoReflectionType *t = mono_type_array_get (assemblyb->type_forwarders, i);
3544 klass = mono_class_from_mono_type (t->type);
3546 scope = resolution_scope_from_image (assembly, klass->image);
3547 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3548 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3551 alloc_table (table, table->rows);
3552 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3554 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3555 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3556 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3557 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3558 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3565 #define align_pointer(base,p)\
3567 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3569 (p) += 4 - (__diff & 3);\
3573 compare_constants (const void *a, const void *b)
3575 const guint32 *a_values = a;
3576 const guint32 *b_values = b;
3577 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3581 compare_semantics (const void *a, const void *b)
3583 const guint32 *a_values = a;
3584 const guint32 *b_values = b;
3585 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3588 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3592 compare_custom_attrs (const void *a, const void *b)
3594 const guint32 *a_values = a;
3595 const guint32 *b_values = b;
3597 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3601 compare_field_marshal (const void *a, const void *b)
3603 const guint32 *a_values = a;
3604 const guint32 *b_values = b;
3606 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3610 compare_nested (const void *a, const void *b)
3612 const guint32 *a_values = a;
3613 const guint32 *b_values = b;
3615 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3619 compare_genericparam (const void *a, const void *b)
3621 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3622 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3624 if ((*b_entry)->owner == (*a_entry)->owner)
3626 mono_type_get_generic_param_num ((*a_entry)->gparam->type.type) -
3627 mono_type_get_generic_param_num ((*b_entry)->gparam->type.type);
3629 return (*a_entry)->owner - (*b_entry)->owner;
3633 compare_declsecurity_attrs (const void *a, const void *b)
3635 const guint32 *a_values = a;
3636 const guint32 *b_values = b;
3638 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3642 compare_interface_impl (const void *a, const void *b)
3644 const guint32 *a_values = a;
3645 const guint32 *b_values = b;
3647 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3651 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3655 pad_heap (MonoDynamicStream *sh)
3657 if (sh->index & 3) {
3658 int sz = 4 - (sh->index & 3);
3659 memset (sh->data + sh->index, 0, sz);
3666 MonoDynamicStream *stream;
3670 * build_compressed_metadata() fills in the blob of data that represents the
3671 * raw metadata as it will be saved in the PE file. The five streams are output
3672 * and the metadata tables are comnpressed from the guint32 array representation,
3673 * to the compressed on-disk format.
3676 build_compressed_metadata (MonoDynamicImage *assembly)
3678 MonoDynamicTable *table;
3680 guint64 valid_mask = 0;
3681 guint64 sorted_mask;
3682 guint32 heapt_size = 0;
3683 guint32 meta_size = 256; /* allow for header and other stuff */
3684 guint32 table_offset;
3685 guint32 ntables = 0;
3691 struct StreamDesc stream_desc [5];
3693 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3694 for (i = 0; i < assembly->gen_params->len; i++){
3695 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3696 write_generic_param_entry (assembly, entry);
3699 stream_desc [0].name = "#~";
3700 stream_desc [0].stream = &assembly->tstream;
3701 stream_desc [1].name = "#Strings";
3702 stream_desc [1].stream = &assembly->sheap;
3703 stream_desc [2].name = "#US";
3704 stream_desc [2].stream = &assembly->us;
3705 stream_desc [3].name = "#Blob";
3706 stream_desc [3].stream = &assembly->blob;
3707 stream_desc [4].name = "#GUID";
3708 stream_desc [4].stream = &assembly->guid;
3710 /* tables that are sorted */
3711 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3712 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3713 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3714 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3715 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3716 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3717 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3719 /* Compute table sizes */
3720 /* the MonoImage has already been created in mono_image_basic_init() */
3721 meta = &assembly->image;
3723 /* sizes should be multiple of 4 */
3724 pad_heap (&assembly->blob);
3725 pad_heap (&assembly->guid);
3726 pad_heap (&assembly->sheap);
3727 pad_heap (&assembly->us);
3729 /* Setup the info used by compute_sizes () */
3730 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3731 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3732 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3734 meta_size += assembly->blob.index;
3735 meta_size += assembly->guid.index;
3736 meta_size += assembly->sheap.index;
3737 meta_size += assembly->us.index;
3739 for (i=0; i < MONO_TABLE_NUM; ++i)
3740 meta->tables [i].rows = assembly->tables [i].rows;
3742 for (i = 0; i < MONO_TABLE_NUM; i++){
3743 if (meta->tables [i].rows == 0)
3745 valid_mask |= (guint64)1 << i;
3747 meta->tables [i].row_size = mono_metadata_compute_size (
3748 meta, i, &meta->tables [i].size_bitfield);
3749 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3751 heapt_size += 24; /* #~ header size */
3752 heapt_size += ntables * 4;
3753 /* make multiple of 4 */
3756 meta_size += heapt_size;
3757 meta->raw_metadata = g_malloc0 (meta_size);
3758 p = (unsigned char*)meta->raw_metadata;
3759 /* the metadata signature */
3760 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3761 /* version numbers and 4 bytes reserved */
3762 int16val = (guint16*)p;
3763 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3764 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3766 /* version string */
3767 int32val = (guint32*)p;
3768 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3770 memcpy (p, meta->version, strlen (meta->version));
3771 p += GUINT32_FROM_LE (*int32val);
3772 align_pointer (meta->raw_metadata, p);
3773 int16val = (guint16*)p;
3774 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3775 *int16val = GUINT16_TO_LE (5); /* number of streams */
3779 * write the stream info.
3781 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3782 table_offset += 3; table_offset &= ~3;
3784 assembly->tstream.index = heapt_size;
3785 for (i = 0; i < 5; ++i) {
3786 int32val = (guint32*)p;
3787 stream_desc [i].stream->offset = table_offset;
3788 *int32val++ = GUINT32_TO_LE (table_offset);
3789 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3790 table_offset += GUINT32_FROM_LE (*int32val);
3791 table_offset += 3; table_offset &= ~3;
3793 strcpy ((char*)p, stream_desc [i].name);
3794 p += strlen (stream_desc [i].name) + 1;
3795 align_pointer (meta->raw_metadata, p);
3798 * now copy the data, the table stream header and contents goes first.
3800 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3801 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
3802 int32val = (guint32*)p;
3803 *int32val = GUINT32_TO_LE (0); /* reserved */
3806 if (mono_framework_version () > 1) {
3807 *p++ = 2; /* version */
3810 *p++ = 1; /* version */
3814 if (meta->idx_string_wide)
3816 if (meta->idx_guid_wide)
3818 if (meta->idx_blob_wide)
3821 *p++ = 1; /* reserved */
3822 int64val = (guint64*)p;
3823 *int64val++ = GUINT64_TO_LE (valid_mask);
3824 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3826 int32val = (guint32*)p;
3827 for (i = 0; i < MONO_TABLE_NUM; i++){
3828 if (meta->tables [i].rows == 0)
3830 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3832 p = (unsigned char*)int32val;
3834 /* sort the tables that still need sorting */
3835 table = &assembly->tables [MONO_TABLE_CONSTANT];
3837 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3838 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3840 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3841 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3843 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3844 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3846 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3847 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3849 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3850 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3851 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3853 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3854 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3856 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
3858 /* compress the tables */
3859 for (i = 0; i < MONO_TABLE_NUM; i++){
3862 guint32 bitfield = meta->tables [i].size_bitfield;
3863 if (!meta->tables [i].rows)
3865 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3866 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3867 meta->tables [i].base = (char*)p;
3868 for (row = 1; row <= meta->tables [i].rows; ++row) {
3869 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3870 for (col = 0; col < assembly->tables [i].columns; ++col) {
3871 switch (mono_metadata_table_size (bitfield, col)) {
3873 *p++ = values [col];
3876 *p++ = values [col] & 0xff;
3877 *p++ = (values [col] >> 8) & 0xff;
3880 *p++ = values [col] & 0xff;
3881 *p++ = (values [col] >> 8) & 0xff;
3882 *p++ = (values [col] >> 16) & 0xff;
3883 *p++ = (values [col] >> 24) & 0xff;
3886 g_assert_not_reached ();
3890 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3893 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3894 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3895 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3896 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3897 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3899 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3903 * Some tables in metadata need to be sorted according to some criteria, but
3904 * when methods and fields are first created with reflection, they may be assigned a token
3905 * that doesn't correspond to the final token they will get assigned after the sorting.
3906 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3907 * with the reflection objects that represent them. Once all the tables are set up, the
3908 * reflection objects will contains the correct table index. fixup_method() will fixup the
3909 * tokens for the method with ILGenerator @ilgen.
3912 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
3914 guint32 code_idx = GPOINTER_TO_UINT (value);
3915 MonoReflectionILTokenInfo *iltoken;
3916 MonoReflectionFieldBuilder *field;
3917 MonoReflectionCtorBuilder *ctor;
3918 MonoReflectionMethodBuilder *method;
3919 MonoReflectionTypeBuilder *tb;
3920 MonoReflectionArrayMethod *am;
3922 unsigned char *target;
3924 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3925 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3926 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
3927 switch (target [3]) {
3928 case MONO_TABLE_FIELD:
3929 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3930 field = (MonoReflectionFieldBuilder *)iltoken->member;
3931 idx = field->table_idx;
3932 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3933 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3934 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3936 g_assert_not_reached ();
3939 case MONO_TABLE_METHOD:
3940 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3941 method = (MonoReflectionMethodBuilder *)iltoken->member;
3942 idx = method->table_idx;
3943 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3944 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3945 idx = ctor->table_idx;
3946 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3947 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3948 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3949 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3951 g_assert_not_reached ();
3954 case MONO_TABLE_TYPEDEF:
3955 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3956 g_assert_not_reached ();
3957 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3958 idx = tb->table_idx;
3960 case MONO_TABLE_MEMBERREF:
3961 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3962 am = (MonoReflectionArrayMethod*)iltoken->member;
3963 idx = am->table_idx;
3964 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3965 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3966 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3967 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3968 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3969 g_assert (m->klass->generic_class || m->klass->generic_container);
3971 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3973 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3974 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3975 g_assert (is_field_on_inst (f));
3977 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
3978 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3980 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
3982 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
3984 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
3987 g_assert_not_reached ();
3990 case MONO_TABLE_METHODSPEC:
3991 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3992 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3993 g_assert (mono_method_signature (m)->generic_param_count);
3995 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3998 g_assert_not_reached ();
4002 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4004 target [0] = idx & 0xff;
4005 target [1] = (idx >> 8) & 0xff;
4006 target [2] = (idx >> 16) & 0xff;
4013 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4014 * value is not known when the table is emitted.
4017 fixup_cattrs (MonoDynamicImage *assembly)
4019 MonoDynamicTable *table;
4021 guint32 type, i, idx, token;
4024 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4026 for (i = 0; i < table->rows; ++i) {
4027 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4029 type = values [MONO_CUSTOM_ATTR_TYPE];
4030 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4031 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4032 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4033 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4036 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4037 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4038 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4039 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4046 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4048 MonoDynamicTable *table;
4051 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4053 alloc_table (table, table->rows);
4054 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4055 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4056 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4057 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4058 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4063 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4065 MonoDynamicTable *table;
4069 char *b = blob_size;
4071 guint32 idx, offset;
4073 if (rsrc->filename) {
4074 name = mono_string_to_utf8 (rsrc->filename);
4075 sname = g_path_get_basename (name);
4077 table = &assembly->tables [MONO_TABLE_FILE];
4079 alloc_table (table, table->rows);
4080 values = table->values + table->next_idx * MONO_FILE_SIZE;
4081 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4082 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4085 mono_sha1_get_digest_from_file (name, hash);
4086 mono_metadata_encode_value (20, b, &b);
4087 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4088 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4090 idx = table->next_idx++;
4092 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4098 data = mono_array_addr (rsrc->data, char, 0);
4099 len = mono_array_length (rsrc->data);
4105 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4106 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4107 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4108 mono_image_add_stream_data (&assembly->resources, data, len);
4112 * The entry should be emitted into the MANIFESTRESOURCE table of
4113 * the main module, but that needs to reference the FILE table
4114 * which isn't emitted yet.
4121 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4125 set_version_from_string (MonoString *version, guint32 *values)
4127 gchar *ver, *p, *str;
4130 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4131 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4132 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4133 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4136 ver = str = mono_string_to_utf8 (version);
4137 for (i = 0; i < 4; ++i) {
4138 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4144 /* handle Revision and Build */
4154 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4158 char *b = blob_size;
4163 len = mono_array_length (pkey);
4164 mono_metadata_encode_value (len, b, &b);
4165 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4166 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4168 assembly->public_key = g_malloc (len);
4169 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4170 assembly->public_key_len = len;
4172 /* Special case: check for ECMA key (16 bytes) */
4173 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4174 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4175 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4176 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4177 /* minimum key size (in 2.0) is 384 bits */
4178 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4180 /* FIXME - verifier */
4181 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4182 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4184 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4190 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4192 MonoDynamicTable *table;
4193 MonoDynamicImage *assembly;
4194 MonoReflectionAssemblyBuilder *assemblyb;
4198 guint32 module_index;
4200 assemblyb = moduleb->assemblyb;
4201 assembly = moduleb->dynamic_image;
4202 domain = mono_object_domain (assemblyb);
4204 /* Emit ASSEMBLY table */
4205 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4206 alloc_table (table, 1);
4207 values = table->values + MONO_ASSEMBLY_SIZE;
4208 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4209 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4210 if (assemblyb->culture) {
4211 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4213 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4215 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4216 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4217 set_version_from_string (assemblyb->version, values);
4219 /* Emit FILE + EXPORTED_TYPE table */
4221 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4223 MonoReflectionModuleBuilder *file_module =
4224 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4225 if (file_module != moduleb) {
4226 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4228 if (file_module->types) {
4229 for (j = 0; j < file_module->num_types; ++j) {
4230 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4231 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4236 if (assemblyb->loaded_modules) {
4237 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4238 MonoReflectionModule *file_module =
4239 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4240 mono_image_fill_file_table (domain, file_module, assembly);
4242 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4245 if (assemblyb->type_forwarders)
4246 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4248 /* Emit MANIFESTRESOURCE table */
4250 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4252 MonoReflectionModuleBuilder *file_module =
4253 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4254 /* The table for the main module is emitted later */
4255 if (file_module != moduleb) {
4257 if (file_module->resources) {
4258 int len = mono_array_length (file_module->resources);
4259 for (j = 0; j < len; ++j) {
4260 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4261 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4268 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4271 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4272 * for the modulebuilder @moduleb.
4273 * At the end of the process, method and field tokens are fixed up and the
4274 * on-disk compressed metadata representation is created.
4277 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4279 MonoDynamicTable *table;
4280 MonoDynamicImage *assembly;
4281 MonoReflectionAssemblyBuilder *assemblyb;
4287 assemblyb = moduleb->assemblyb;
4288 assembly = moduleb->dynamic_image;
4289 domain = mono_object_domain (assemblyb);
4291 if (assembly->text_rva)
4294 assembly->text_rva = START_TEXT_RVA;
4296 if (moduleb->is_main) {
4297 mono_image_emit_manifest (moduleb);
4300 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4301 table->rows = 1; /* .<Module> */
4303 alloc_table (table, table->rows);
4305 * Set the first entry.
4307 values = table->values + table->columns;
4308 values [MONO_TYPEDEF_FLAGS] = 0;
4309 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4310 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4311 values [MONO_TYPEDEF_EXTENDS] = 0;
4312 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4313 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4316 * handle global methods
4317 * FIXME: test what to do when global methods are defined in multiple modules.
4319 if (moduleb->global_methods) {
4320 table = &assembly->tables [MONO_TABLE_METHOD];
4321 table->rows += mono_array_length (moduleb->global_methods);
4322 alloc_table (table, table->rows);
4323 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4324 mono_image_get_method_info (
4325 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4327 if (moduleb->global_fields) {
4328 table = &assembly->tables [MONO_TABLE_FIELD];
4329 table->rows += mono_array_length (moduleb->global_fields);
4330 alloc_table (table, table->rows);
4331 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4332 mono_image_get_field_info (
4333 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4336 table = &assembly->tables [MONO_TABLE_MODULE];
4337 alloc_table (table, 1);
4338 mono_image_fill_module_table (domain, moduleb, assembly);
4340 /* Collect all types into a list sorted by their table_idx */
4341 types = g_ptr_array_new ();
4344 for (i = 0; i < moduleb->num_types; ++i) {
4345 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4346 collect_types (types, type);
4349 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4350 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4351 table->rows += types->len;
4352 alloc_table (table, table->rows);
4355 * Emit type names + namespaces at one place inside the string heap,
4356 * so load_class_names () needs to touch fewer pages.
4358 for (i = 0; i < types->len; ++i) {
4359 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4360 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4362 for (i = 0; i < types->len; ++i) {
4363 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4364 string_heap_insert_mstring (&assembly->sheap, tb->name);
4367 for (i = 0; i < types->len; ++i) {
4368 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4369 mono_image_get_type_info (domain, type, assembly);
4373 * table->rows is already set above and in mono_image_fill_module_table.
4375 /* add all the custom attributes at the end, once all the indexes are stable */
4376 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4378 /* CAS assembly permissions */
4379 if (assemblyb->permissions_minimum)
4380 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4381 if (assemblyb->permissions_optional)
4382 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4383 if (assemblyb->permissions_refused)
4384 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4386 module_add_cattrs (assembly, moduleb);
4389 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4391 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4392 * the final tokens and don't need another fixup pass. */
4394 if (moduleb->global_methods) {
4395 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4396 MonoReflectionMethodBuilder *mb = mono_array_get (
4397 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4398 mono_image_add_methodimpl (assembly, mb);
4402 for (i = 0; i < types->len; ++i) {
4403 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4404 if (type->methods) {
4405 for (j = 0; j < type->num_methods; ++j) {
4406 MonoReflectionMethodBuilder *mb = mono_array_get (
4407 type->methods, MonoReflectionMethodBuilder*, j);
4409 mono_image_add_methodimpl (assembly, mb);
4414 g_ptr_array_free (types, TRUE);
4416 fixup_cattrs (assembly);
4419 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4422 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4424 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4427 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4429 #ifndef DISABLE_REFLECTION_EMIT
4432 * mono_image_insert_string:
4433 * @module: module builder object
4436 * Insert @str into the user string stream of @module.
4439 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4441 MonoDynamicImage *assembly;
4446 MONO_ARCH_SAVE_REGS;
4448 if (!module->dynamic_image)
4449 mono_image_module_basic_init (module);
4451 assembly = module->dynamic_image;
4453 if (assembly->save) {
4454 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4455 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4456 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4458 char *swapped = g_malloc (2 * mono_string_length (str));
4459 const char *p = (const char*)mono_string_chars (str);
4461 swap_with_size (swapped, p, 2, mono_string_length (str));
4462 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4466 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4468 mono_image_add_stream_data (&assembly->us, "", 1);
4470 idx = assembly->us.index ++;
4473 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4475 return MONO_TOKEN_STRING | idx;
4479 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4484 klass = obj->vtable->klass;
4485 if (strcmp (klass->name, "MonoMethod") == 0) {
4486 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4487 MonoMethodSignature *sig, *old;
4488 guint32 sig_token, parent;
4491 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4493 nargs = mono_array_length (opt_param_types);
4494 old = mono_method_signature (method);
4495 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4497 sig->hasthis = old->hasthis;
4498 sig->explicit_this = old->explicit_this;
4499 sig->call_convention = old->call_convention;
4500 sig->generic_param_count = old->generic_param_count;
4501 sig->param_count = old->param_count + nargs;
4502 sig->sentinelpos = old->param_count;
4503 sig->ret = old->ret;
4505 for (i = 0; i < old->param_count; i++)
4506 sig->params [i] = old->params [i];
4508 for (i = 0; i < nargs; i++) {
4509 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4510 sig->params [old->param_count + i] = rt->type;
4513 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4514 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4515 parent >>= MONO_TYPEDEFORREF_BITS;
4517 parent <<= MONO_MEMBERREF_PARENT_BITS;
4518 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4520 sig_token = method_encode_signature (assembly, sig);
4521 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4522 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4523 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4524 ReflectionMethodBuilder rmb;
4525 guint32 parent, sig;
4528 reflection_methodbuilder_from_method_builder (&rmb, mb);
4529 rmb.opt_types = opt_param_types;
4531 sig = method_builder_encode_signature (assembly, &rmb);
4533 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4534 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4536 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4537 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4539 name = mono_string_to_utf8 (rmb.name);
4540 token = mono_image_get_varargs_method_token (
4541 assembly, parent, name, sig);
4544 g_error ("requested method token for %s\n", klass->name);
4551 * mono_image_create_token:
4552 * @assembly: a dynamic assembly
4554 * @register_token: Whenever to register the token in the assembly->tokens hash.
4556 * Get a token to insert in the IL code stream for the given MemberInfo.
4557 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4558 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4562 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4563 gboolean create_methodspec, gboolean register_token)
4568 klass = obj->vtable->klass;
4570 /* Check for user defined reflection objects */
4571 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4572 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4573 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4575 if (strcmp (klass->name, "MethodBuilder") == 0) {
4576 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4577 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4579 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4580 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4582 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4583 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4584 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4585 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4586 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4588 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4589 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4591 token = mono_image_get_ctorbuilder_token (assembly, mb);
4592 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4593 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4594 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4595 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4596 if (tb->generic_params) {
4597 token = mono_image_get_generic_field_token (assembly, fb);
4599 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4601 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4602 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4603 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4604 } else if (strcmp (klass->name, "MonoType") == 0) {
4605 MonoReflectionType *tb = (MonoReflectionType *)obj;
4606 MonoClass *mc = mono_class_from_mono_type (tb->type);
4607 token = mono_metadata_token_from_dor (
4608 mono_image_typedef_or_ref_full (assembly, tb->type, mc->generic_container == NULL));
4609 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4610 MonoReflectionType *tb = (MonoReflectionType *)obj;
4611 token = mono_metadata_token_from_dor (
4612 mono_image_typedef_or_ref (assembly, tb->type));
4613 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4614 MonoReflectionType *tb = (MonoReflectionType *)obj;
4615 token = mono_metadata_token_from_dor (
4616 mono_image_typedef_or_ref (assembly, tb->type));
4617 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4618 strcmp (klass->name, "MonoMethod") == 0 ||
4619 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4620 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4621 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4622 if (m->method->is_inflated) {
4623 if (create_methodspec)
4624 token = mono_image_get_methodspec_token (assembly, m->method);
4626 token = mono_image_get_inflated_method_token (assembly, m->method);
4627 } else if ((m->method->klass->image == &assembly->image) &&
4628 !m->method->klass->generic_class) {
4629 static guint32 method_table_idx = 0xffffff;
4630 if (m->method->klass->wastypebuilder) {
4631 /* we use the same token as the one that was assigned
4632 * to the Methodbuilder.
4633 * FIXME: do the equivalent for Fields.
4635 token = m->method->token;
4638 * Each token should have a unique index, but the indexes are
4639 * assigned by managed code, so we don't know about them. An
4640 * easy solution is to count backwards...
4642 method_table_idx --;
4643 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4646 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4648 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4649 } else if (strcmp (klass->name, "MonoField") == 0) {
4650 MonoReflectionField *f = (MonoReflectionField *)obj;
4651 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4652 static guint32 field_table_idx = 0xffffff;
4654 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4656 token = mono_image_get_fieldref_token (assembly, f);
4658 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4659 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4660 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4661 token = mono_image_get_array_token (assembly, m);
4662 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4663 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4664 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4665 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4666 MonoReflectionType *tb = (MonoReflectionType *)obj;
4667 token = mono_metadata_token_from_dor (
4668 mono_image_typedef_or_ref (assembly, tb->type));
4669 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4670 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4671 token = mono_image_get_field_on_inst_token (assembly, f);
4672 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4673 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4674 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4675 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4676 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4677 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4679 g_error ("requested token for %s\n", klass->name);
4683 mono_image_register_token (assembly, token, obj);
4689 * mono_image_register_token:
4691 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4692 * the Module.ResolveXXXToken () methods to work.
4695 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4697 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4699 /* There could be multiple MethodInfo objects with the same token */
4700 //g_assert (prev == obj);
4702 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4706 #endif /* DISABLE_REFLECTION_EMIT */
4709 guint32 import_lookup_table;
4713 guint32 import_address_table_rva;
4721 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4723 static MonoDynamicImage*
4724 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4726 static const guchar entrycode [16] = {0xff, 0x25, 0};
4727 MonoDynamicImage *image;
4730 const char *version;
4732 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4733 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4735 version = mono_get_runtime_info ()->runtime_version;
4738 image = GC_MALLOC (sizeof (MonoDynamicImage));
4740 image = g_new0 (MonoDynamicImage, 1);
4743 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
4745 /*g_print ("created image %p\n", image);*/
4746 /* keep in sync with image.c */
4747 image->image.name = assembly_name;
4748 image->image.assembly_name = image->image.name; /* they may be different */
4749 image->image.module_name = module_name;
4750 image->image.version = g_strdup (version);
4751 image->image.md_version_major = 1;
4752 image->image.md_version_minor = 1;
4753 image->image.dynamic = TRUE;
4755 image->image.references = g_new0 (MonoAssembly*, 1);
4756 image->image.references [0] = NULL;
4758 mono_image_init (&image->image);
4760 image->token_fixups = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4761 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4762 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4763 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4764 image->handleref = g_hash_table_new (NULL, NULL);
4765 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4766 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
4767 image->methodspec = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
4768 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4769 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4770 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4771 image->gen_params = g_ptr_array_new ();
4773 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4774 string_heap_init (&image->sheap);
4775 mono_image_add_stream_data (&image->us, "", 1);
4776 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4777 /* import tables... */
4778 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
4779 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4780 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4781 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4782 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4783 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4784 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4785 stream_data_align (&image->code);
4787 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4789 for (i=0; i < MONO_TABLE_NUM; ++i) {
4790 image->tables [i].next_idx = 1;
4791 image->tables [i].columns = table_sizes [i];
4794 image->image.assembly = (MonoAssembly*)assembly;
4795 image->run = assembly->run;
4796 image->save = assembly->save;
4797 image->pe_kind = 0x1; /* ILOnly */
4798 image->machine = 0x14c; /* I386 */
4800 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
4806 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
4812 mono_dynamic_image_free (MonoDynamicImage *image)
4814 MonoDynamicImage *di = image;
4819 mono_g_hash_table_destroy (di->methodspec);
4821 g_hash_table_destroy (di->typespec);
4823 g_hash_table_destroy (di->typeref);
4825 g_hash_table_destroy (di->handleref);
4827 mono_g_hash_table_destroy (di->tokens);
4828 if (di->generic_def_objects)
4829 mono_g_hash_table_destroy (di->generic_def_objects);
4830 if (di->blob_cache) {
4831 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
4832 g_hash_table_destroy (di->blob_cache);
4834 if (di->standalonesig_cache)
4835 g_hash_table_destroy (di->standalonesig_cache);
4836 for (list = di->array_methods; list; list = list->next) {
4837 ArrayMethod *am = (ArrayMethod *)list->data;
4842 g_list_free (di->array_methods);
4843 if (di->gen_params) {
4844 for (i = 0; i < di->gen_params->len; i++) {
4845 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
4846 if (entry->gparam->type.type) {
4847 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
4848 g_free ((char*)mono_generic_param_info (param)->name);
4853 g_ptr_array_free (di->gen_params, TRUE);
4855 if (di->token_fixups)
4856 mono_g_hash_table_destroy (di->token_fixups);
4857 if (di->method_to_table_idx)
4858 g_hash_table_destroy (di->method_to_table_idx);
4859 if (di->field_to_table_idx)
4860 g_hash_table_destroy (di->field_to_table_idx);
4861 if (di->method_aux_hash)
4862 g_hash_table_destroy (di->method_aux_hash);
4863 g_free (di->strong_name);
4864 g_free (di->win32_res);
4866 g_free (di->public_key);
4868 /*g_print ("string heap destroy for image %p\n", di);*/
4869 mono_dynamic_stream_reset (&di->sheap);
4870 mono_dynamic_stream_reset (&di->code);
4871 mono_dynamic_stream_reset (&di->resources);
4872 mono_dynamic_stream_reset (&di->us);
4873 mono_dynamic_stream_reset (&di->blob);
4874 mono_dynamic_stream_reset (&di->tstream);
4875 mono_dynamic_stream_reset (&di->guid);
4876 for (i = 0; i < MONO_TABLE_NUM; ++i) {
4877 g_free (di->tables [i].values);
4881 #ifndef DISABLE_REFLECTION_EMIT
4884 * mono_image_basic_init:
4885 * @assembly: an assembly builder object
4887 * Create the MonoImage that represents the assembly builder and setup some
4888 * of the helper hash table and the basic metadata streams.
4891 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4893 MonoDynamicAssembly *assembly;
4894 MonoDynamicImage *image;
4895 MonoDomain *domain = mono_object_domain (assemblyb);
4897 MONO_ARCH_SAVE_REGS;
4899 if (assemblyb->dynamic_assembly)
4903 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4905 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4908 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
4910 assembly->assembly.ref_count = 1;
4911 assembly->assembly.dynamic = TRUE;
4912 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4913 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4914 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4915 if (assemblyb->culture)
4916 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4918 assembly->assembly.aname.culture = g_strdup ("");
4920 if (assemblyb->version) {
4921 char *vstr = mono_string_to_utf8 (assemblyb->version);
4922 char **version = g_strsplit (vstr, ".", 4);
4923 char **parts = version;
4924 assembly->assembly.aname.major = atoi (*parts++);
4925 assembly->assembly.aname.minor = atoi (*parts++);
4926 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4927 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4929 g_strfreev (version);
4932 assembly->assembly.aname.major = 0;
4933 assembly->assembly.aname.minor = 0;
4934 assembly->assembly.aname.build = 0;
4935 assembly->assembly.aname.revision = 0;
4938 assembly->run = assemblyb->access != 2;
4939 assembly->save = assemblyb->access != 1;
4941 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4942 image->initial_image = TRUE;
4943 assembly->assembly.aname.name = image->image.name;
4944 assembly->assembly.image = &image->image;
4946 mono_domain_assemblies_lock (domain);
4947 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4948 mono_domain_assemblies_unlock (domain);
4950 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4952 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
4954 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4957 #endif /* DISABLE_REFLECTION_EMIT */
4959 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4962 calc_section_size (MonoDynamicImage *assembly)
4966 /* alignment constraints */
4967 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
4968 g_assert ((assembly->code.index % 4) == 0);
4969 assembly->meta_size += 3;
4970 assembly->meta_size &= ~3;
4971 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
4972 g_assert ((assembly->resources.index % 4) == 0);
4974 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4975 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4978 if (assembly->win32_res) {
4979 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4981 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4982 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4986 assembly->sections [MONO_SECTION_RELOC].size = 12;
4987 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4997 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5001 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5003 ResTreeNode *t1 = (ResTreeNode*)a;
5004 ResTreeNode *t2 = (ResTreeNode*)b;
5006 return t1->id - t2->id;
5010 * resource_tree_create:
5012 * Organize the resources into a resource tree.
5014 static ResTreeNode *
5015 resource_tree_create (MonoArray *win32_resources)
5017 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5021 tree = g_new0 (ResTreeNode, 1);
5023 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5024 MonoReflectionWin32Resource *win32_res =
5025 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5029 /* FIXME: BUG: this stores managed references in unmanaged memory */
5030 lang_node = g_new0 (ResTreeNode, 1);
5031 lang_node->id = win32_res->lang_id;
5032 lang_node->win32_res = win32_res;
5034 /* Create type node if neccesary */
5036 for (l = tree->children; l; l = l->next)
5037 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5038 type_node = (ResTreeNode*)l->data;
5043 type_node = g_new0 (ResTreeNode, 1);
5044 type_node->id = win32_res->res_type;
5047 * The resource types have to be sorted otherwise
5048 * Windows Explorer can't display the version information.
5050 tree->children = g_slist_insert_sorted (tree->children,
5051 type_node, resource_tree_compare_by_id);
5054 /* Create res node if neccesary */
5056 for (l = type_node->children; l; l = l->next)
5057 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5058 res_node = (ResTreeNode*)l->data;
5063 res_node = g_new0 (ResTreeNode, 1);
5064 res_node->id = win32_res->res_id;
5065 type_node->children = g_slist_append (type_node->children, res_node);
5068 res_node->children = g_slist_append (res_node->children, lang_node);
5075 * resource_tree_encode:
5077 * Encode the resource tree into the format used in the PE file.
5080 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5083 MonoPEResourceDir dir;
5084 MonoPEResourceDirEntry dir_entry;
5085 MonoPEResourceDataEntry data_entry;
5087 guint32 res_id_entries;
5090 * For the format of the resource directory, see the article
5091 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5095 memset (&dir, 0, sizeof (dir));
5096 memset (&dir_entry, 0, sizeof (dir_entry));
5097 memset (&data_entry, 0, sizeof (data_entry));
5099 g_assert (sizeof (dir) == 16);
5100 g_assert (sizeof (dir_entry) == 8);
5101 g_assert (sizeof (data_entry) == 16);
5103 node->offset = p - begin;
5105 /* IMAGE_RESOURCE_DIRECTORY */
5106 res_id_entries = g_slist_length (node->children);
5107 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5109 memcpy (p, &dir, sizeof (dir));
5112 /* Reserve space for entries */
5114 p += sizeof (dir_entry) * res_id_entries;
5116 /* Write children */
5117 for (l = node->children; l; l = l->next) {
5118 ResTreeNode *child = (ResTreeNode*)l->data;
5120 if (child->win32_res) {
5123 child->offset = p - begin;
5125 /* IMAGE_RESOURCE_DATA_ENTRY */
5126 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5127 size = mono_array_length (child->win32_res->res_data);
5128 data_entry.rde_size = GUINT32_TO_LE (size);
5130 memcpy (p, &data_entry, sizeof (data_entry));
5131 p += sizeof (data_entry);
5133 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5136 resource_tree_encode (child, begin, p, &p);
5140 /* IMAGE_RESOURCE_ENTRY */
5141 for (l = node->children; l; l = l->next) {
5142 ResTreeNode *child = (ResTreeNode*)l->data;
5144 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5145 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5147 memcpy (entries, &dir_entry, sizeof (dir_entry));
5148 entries += sizeof (dir_entry);
5155 resource_tree_free (ResTreeNode * node)
5158 for (list = node->children; list; list = list->next)
5159 resource_tree_free ((ResTreeNode*)list->data);
5160 g_slist_free(node->children);
5165 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5170 MonoReflectionWin32Resource *win32_res;
5173 if (!assemblyb->win32_resources)
5177 * Resources are stored in a three level tree inside the PE file.
5178 * - level one contains a node for each type of resource
5179 * - level two contains a node for each resource
5180 * - level three contains a node for each instance of a resource for a
5181 * specific language.
5184 tree = resource_tree_create (assemblyb->win32_resources);
5186 /* Estimate the size of the encoded tree */
5188 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5189 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5190 size += mono_array_length (win32_res->res_data);
5192 /* Directory structure */
5193 size += mono_array_length (assemblyb->win32_resources) * 256;
5194 p = buf = g_malloc (size);
5196 resource_tree_encode (tree, p, p, &p);
5198 g_assert (p - buf <= size);
5200 assembly->win32_res = g_malloc (p - buf);
5201 assembly->win32_res_size = p - buf;
5202 memcpy (assembly->win32_res, buf, p - buf);
5205 resource_tree_free (tree);
5209 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5211 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5214 p += sizeof (MonoPEResourceDir);
5215 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5216 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5217 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5218 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5219 fixup_resource_directory (res_section, child, rva);
5221 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5222 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5225 p += sizeof (MonoPEResourceDirEntry);
5230 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5233 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5234 g_error ("WriteFile returned %d\n", GetLastError ());
5238 * mono_image_create_pefile:
5239 * @mb: a module builder object
5241 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5242 * assembly->pefile where it can be easily retrieved later in chunks.
5245 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5247 MonoMSDOSHeader *msdos;
5248 MonoDotNetHeader *header;
5249 MonoSectionTable *section;
5250 MonoCLIHeader *cli_header;
5251 guint32 size, image_size, virtual_base, text_offset;
5252 guint32 header_start, section_start, file_offset, virtual_offset;
5253 MonoDynamicImage *assembly;
5254 MonoReflectionAssemblyBuilder *assemblyb;
5255 MonoDynamicStream pefile_stream = {0};
5256 MonoDynamicStream *pefile = &pefile_stream;
5258 guint32 *rva, value;
5260 static const unsigned char msheader[] = {
5261 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5262 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5265 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5266 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5267 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5268 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5271 assemblyb = mb->assemblyb;
5273 mono_image_basic_init (assemblyb);
5274 assembly = mb->dynamic_image;
5276 assembly->pe_kind = assemblyb->pe_kind;
5277 assembly->machine = assemblyb->machine;
5278 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5279 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5281 mono_image_build_metadata (mb);
5283 if (mb->is_main && assemblyb->resources) {
5284 int len = mono_array_length (assemblyb->resources);
5285 for (i = 0; i < len; ++i)
5286 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5289 if (mb->resources) {
5290 int len = mono_array_length (mb->resources);
5291 for (i = 0; i < len; ++i)
5292 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5295 build_compressed_metadata (assembly);
5298 assembly_add_win32_resources (assembly, assemblyb);
5300 nsections = calc_section_size (assembly);
5302 /* The DOS header and stub */
5303 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5304 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5306 /* the dotnet header */
5307 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5309 /* the section tables */
5310 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5312 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5313 virtual_offset = VIRT_ALIGN;
5316 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5317 if (!assembly->sections [i].size)
5320 file_offset += FILE_ALIGN - 1;
5321 file_offset &= ~(FILE_ALIGN - 1);
5322 virtual_offset += VIRT_ALIGN - 1;
5323 virtual_offset &= ~(VIRT_ALIGN - 1);
5325 assembly->sections [i].offset = file_offset;
5326 assembly->sections [i].rva = virtual_offset;
5328 file_offset += assembly->sections [i].size;
5329 virtual_offset += assembly->sections [i].size;
5330 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5333 file_offset += FILE_ALIGN - 1;
5334 file_offset &= ~(FILE_ALIGN - 1);
5336 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5338 /* back-patch info */
5339 msdos = (MonoMSDOSHeader*)pefile->data;
5340 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5342 header = (MonoDotNetHeader*)(pefile->data + header_start);
5343 header->pesig [0] = 'P';
5344 header->pesig [1] = 'E';
5346 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5347 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5348 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5349 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5350 if (assemblyb->pekind == 1) {
5352 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5355 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5358 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5360 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5361 header->pe.pe_major = 6;
5362 header->pe.pe_minor = 0;
5363 size = assembly->sections [MONO_SECTION_TEXT].size;
5364 size += FILE_ALIGN - 1;
5365 size &= ~(FILE_ALIGN - 1);
5366 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5367 size = assembly->sections [MONO_SECTION_RSRC].size;
5368 size += FILE_ALIGN - 1;
5369 size &= ~(FILE_ALIGN - 1);
5370 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5371 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5372 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5373 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5374 /* pe_rva_entry_point always at the beginning of the text section */
5375 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5377 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5378 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5379 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5380 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5381 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5382 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5383 size = section_start;
5384 size += FILE_ALIGN - 1;
5385 size &= ~(FILE_ALIGN - 1);
5386 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5388 size += VIRT_ALIGN - 1;
5389 size &= ~(VIRT_ALIGN - 1);
5390 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5393 // Translate the PEFileKind value to the value expected by the Windows loader
5399 // PEFileKinds.Dll == 1
5400 // PEFileKinds.ConsoleApplication == 2
5401 // PEFileKinds.WindowApplication == 3
5404 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5405 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5407 if (assemblyb->pekind == 3)
5412 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5414 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5415 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5416 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5417 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5418 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5419 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5421 /* fill data directory entries */
5423 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5424 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5426 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5427 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5429 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5430 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5431 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5432 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5433 /* patch entrypoint name */
5434 if (assemblyb->pekind == 1)
5435 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5437 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5438 /* patch imported function RVA name */
5439 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5440 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5442 /* the import table */
5443 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5444 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5445 /* patch imported dll RVA name and other entries in the dir */
5446 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5447 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5448 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5449 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5450 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5451 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5453 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5454 value = (assembly->text_rva + assembly->imp_names_offset);
5455 *p++ = (value) & 0xff;
5456 *p++ = (value >> 8) & (0xff);
5457 *p++ = (value >> 16) & (0xff);
5458 *p++ = (value >> 24) & (0xff);
5460 /* the CLI header info */
5461 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5462 cli_header->ch_size = GUINT32_FROM_LE (72);
5463 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5464 if (mono_framework_version () > 1)
5465 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5467 cli_header->ch_runtime_minor = GUINT16_FROM_LE (0);
5468 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5469 if (assemblyb->entry_point) {
5470 guint32 table_idx = 0;
5471 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5472 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5473 table_idx = methodb->table_idx;
5475 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5477 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5479 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5481 /* The embedded managed resources */
5482 text_offset = assembly->text_rva + assembly->code.index;
5483 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5484 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5485 text_offset += assembly->resources.index;
5486 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5487 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5488 text_offset += assembly->meta_size;
5489 if (assembly->strong_name_size) {
5490 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5491 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5492 text_offset += assembly->strong_name_size;
5495 /* write the section tables and section content */
5496 section = (MonoSectionTable*)(pefile->data + section_start);
5497 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5498 static const char section_names [][7] = {
5499 ".text", ".rsrc", ".reloc"
5501 if (!assembly->sections [i].size)
5503 strcpy (section->st_name, section_names [i]);
5504 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5505 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5506 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5507 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5508 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5509 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5510 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5514 checked_write_file (file, pefile->data, pefile->index);
5516 mono_dynamic_stream_reset (pefile);
5518 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5519 if (!assembly->sections [i].size)
5522 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5523 g_error ("SetFilePointer returned %d\n", GetLastError ());
5526 case MONO_SECTION_TEXT:
5527 /* patch entry point */
5528 p = (guchar*)(assembly->code.data + 2);
5529 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5530 *p++ = (value) & 0xff;
5531 *p++ = (value >> 8) & 0xff;
5532 *p++ = (value >> 16) & 0xff;
5533 *p++ = (value >> 24) & 0xff;
5535 checked_write_file (file, assembly->code.data, assembly->code.index);
5536 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5537 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5538 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5541 g_free (assembly->image.raw_metadata);
5543 case MONO_SECTION_RELOC: {
5547 guint16 type_and_offset;
5551 g_assert (sizeof (reloc) == 12);
5553 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5554 reloc.block_size = GUINT32_FROM_LE (12);
5557 * the entrypoint is always at the start of the text section
5558 * 3 is IMAGE_REL_BASED_HIGHLOW
5559 * 2 is patch_size_rva - text_rva
5561 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5564 checked_write_file (file, &reloc, sizeof (reloc));
5568 case MONO_SECTION_RSRC:
5569 if (assembly->win32_res) {
5571 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5572 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5573 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5577 g_assert_not_reached ();
5581 /* check that the file is properly padded */
5582 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5583 g_error ("SetFilePointer returned %d\n", GetLastError ());
5584 if (! SetEndOfFile (file))
5585 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5587 mono_dynamic_stream_reset (&assembly->code);
5588 mono_dynamic_stream_reset (&assembly->us);
5589 mono_dynamic_stream_reset (&assembly->blob);
5590 mono_dynamic_stream_reset (&assembly->guid);
5591 mono_dynamic_stream_reset (&assembly->sheap);
5593 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5594 g_hash_table_destroy (assembly->blob_cache);
5595 assembly->blob_cache = NULL;
5598 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5601 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5603 g_assert_not_reached ();
5606 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5608 #ifndef DISABLE_REFLECTION_EMIT
5610 MonoReflectionModule *
5611 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5615 MonoImageOpenStatus status;
5616 MonoDynamicAssembly *assembly;
5617 guint32 module_count;
5618 MonoImage **new_modules;
5619 gboolean *new_modules_loaded;
5621 name = mono_string_to_utf8 (fileName);
5623 image = mono_image_open (name, &status);
5626 if (status == MONO_IMAGE_ERROR_ERRNO)
5627 exc = mono_get_exception_file_not_found (fileName);
5629 exc = mono_get_exception_bad_image_format (name);
5631 mono_raise_exception (exc);
5636 assembly = ab->dynamic_assembly;
5637 image->assembly = (MonoAssembly*)assembly;
5639 module_count = image->assembly->image->module_count;
5640 new_modules = g_new0 (MonoImage *, module_count + 1);
5641 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5643 if (image->assembly->image->modules)
5644 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5645 if (image->assembly->image->modules_loaded)
5646 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5647 new_modules [module_count] = image;
5648 new_modules_loaded [module_count] = TRUE;
5649 mono_image_addref (image);
5651 g_free (image->assembly->image->modules);
5652 image->assembly->image->modules = new_modules;
5653 image->assembly->image->modules_loaded = new_modules_loaded;
5654 image->assembly->image->module_count ++;
5656 mono_assembly_load_references (image, &status);
5658 mono_image_close (image);
5659 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5662 return mono_module_get_object (mono_domain_get (), image);
5665 #endif /* DISABLE_REFLECTION_EMIT */
5668 * We need to return always the same object for MethodInfo, FieldInfo etc..
5669 * but we need to consider the reflected type.
5670 * type uses a different hash, since it uses custom hash/equal functions.
5675 MonoClass *refclass;
5679 reflected_equal (gconstpointer a, gconstpointer b) {
5680 const ReflectedEntry *ea = a;
5681 const ReflectedEntry *eb = b;
5683 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5687 reflected_hash (gconstpointer a) {
5688 const ReflectedEntry *ea = a;
5689 return mono_aligned_addr_hash (ea->item);
5692 #define CHECK_OBJECT(t,p,k) \
5698 mono_domain_lock (domain); \
5699 if (!domain->refobject_hash) \
5700 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5701 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5702 mono_domain_unlock (domain); \
5705 mono_domain_unlock (domain); \
5708 #ifdef HAVE_BOEHM_GC
5709 /* ReflectedEntry doesn't need to be GC tracked */
5710 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5711 #define FREE_REFENTRY(entry) g_free ((entry))
5713 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5715 #define FREE_REFENTRY(entry)
5718 #define CACHE_OBJECT(t,p,o,k) \
5721 ReflectedEntry pe; \
5723 pe.refclass = (k); \
5724 mono_domain_lock (domain); \
5725 if (!domain->refobject_hash) \
5726 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5727 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5729 ReflectedEntry *e = ALLOC_REFENTRY; \
5731 e->refclass = (k); \
5732 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5735 mono_domain_unlock (domain); \
5740 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
5742 mono_domain_lock (domain);
5743 if (domain->refobject_hash) {
5745 gpointer orig_pe, orig_value;
5748 pe.refclass = klass;
5749 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
5750 mono_g_hash_table_remove (domain->refobject_hash, &pe);
5751 FREE_REFENTRY (orig_pe);
5754 mono_domain_unlock (domain);
5758 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5760 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5764 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5766 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5769 #ifndef DISABLE_REFLECTION_EMIT
5772 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5774 MonoDynamicImage *image = moduleb->dynamic_image;
5775 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5778 MonoImage **new_modules;
5781 * FIXME: we already created an image in mono_image_basic_init (), but
5782 * we don't know which module it belongs to, since that is only
5783 * determined at assembly save time.
5785 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5786 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5788 moduleb->module.image = &image->image;
5789 moduleb->dynamic_image = image;
5790 register_module (mono_object_domain (moduleb), moduleb, image);
5792 /* register the module with the assembly */
5793 ass = ab->dynamic_assembly->assembly.image;
5794 module_count = ass->module_count;
5795 new_modules = g_new0 (MonoImage *, module_count + 1);
5798 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5799 new_modules [module_count] = &image->image;
5800 mono_image_addref (&image->image);
5802 g_free (ass->modules);
5803 ass->modules = new_modules;
5804 ass->module_count ++;
5811 * mono_assembly_get_object:
5812 * @domain: an app domain
5813 * @assembly: an assembly
5815 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5817 MonoReflectionAssembly*
5818 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5820 static MonoClass *System_Reflection_Assembly;
5821 MonoReflectionAssembly *res;
5823 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5824 if (!System_Reflection_Assembly)
5825 System_Reflection_Assembly = mono_class_from_name (
5826 mono_defaults.corlib, "System.Reflection", "Assembly");
5827 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5828 res->assembly = assembly;
5830 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5835 MonoReflectionModule*
5836 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5838 static MonoClass *System_Reflection_Module;
5839 MonoReflectionModule *res;
5842 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5843 if (!System_Reflection_Module)
5844 System_Reflection_Module = mono_class_from_name (
5845 mono_defaults.corlib, "System.Reflection", "Module");
5846 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5849 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5851 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5852 basename = g_path_get_basename (image->name);
5853 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5854 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5858 if (image->assembly->image == image) {
5859 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5863 if (image->assembly->image->modules) {
5864 for (i = 0; i < image->assembly->image->module_count; i++) {
5865 if (image->assembly->image->modules [i] == image)
5866 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5868 g_assert (res->token);
5872 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5875 MonoReflectionModule*
5876 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5878 static MonoClass *System_Reflection_Module;
5879 MonoReflectionModule *res;
5880 MonoTableInfo *table;
5881 guint32 cols [MONO_FILE_SIZE];
5883 guint32 i, name_idx;
5886 if (!System_Reflection_Module)
5887 System_Reflection_Module = mono_class_from_name (
5888 mono_defaults.corlib, "System.Reflection", "Module");
5889 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5891 table = &image->tables [MONO_TABLE_FILE];
5892 g_assert (table_index < table->rows);
5893 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5896 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5897 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5899 /* Check whenever the row has a corresponding row in the moduleref table */
5900 table = &image->tables [MONO_TABLE_MODULEREF];
5901 for (i = 0; i < table->rows; ++i) {
5902 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5903 val = mono_metadata_string_heap (image, name_idx);
5904 if (strcmp (val, name) == 0)
5905 res->image = image->modules [i];
5908 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5909 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5910 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5911 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5912 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5918 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5920 if ((t1->type != t2->type) ||
5921 (t1->byref != t2->byref))
5925 case MONO_TYPE_VOID:
5926 case MONO_TYPE_BOOLEAN:
5927 case MONO_TYPE_CHAR:
5938 case MONO_TYPE_STRING:
5941 case MONO_TYPE_OBJECT:
5942 case MONO_TYPE_TYPEDBYREF:
5944 case MONO_TYPE_VALUETYPE:
5945 case MONO_TYPE_CLASS:
5946 case MONO_TYPE_SZARRAY:
5947 return t1->data.klass == t2->data.klass;
5949 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5950 case MONO_TYPE_ARRAY:
5951 if (t1->data.array->rank != t2->data.array->rank)
5953 return t1->data.array->eklass == t2->data.array->eklass;
5954 case MONO_TYPE_GENERICINST: {
5956 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
5957 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
5958 if (i1->type_argc != i2->type_argc)
5960 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5961 &t2->data.generic_class->container_class->byval_arg))
5963 /* FIXME: we should probably just compare the instance pointers directly. */
5964 for (i = 0; i < i1->type_argc; ++i) {
5965 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
5971 case MONO_TYPE_MVAR:
5972 return t1->data.generic_param == t2->data.generic_param;
5974 g_error ("implement type compare for %0x!", t1->type);
5982 mymono_metadata_type_hash (MonoType *t1)
5988 hash |= t1->byref << 6; /* do not collide with t1->type values */
5990 case MONO_TYPE_VALUETYPE:
5991 case MONO_TYPE_CLASS:
5992 case MONO_TYPE_SZARRAY:
5993 /* check if the distribution is good enough */
5994 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5996 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5997 case MONO_TYPE_GENERICINST: {
5999 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6000 hash += g_str_hash (t1->data.generic_class->container_class->name);
6002 for (i = 0; i < inst->type_argc; ++i) {
6003 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6012 static MonoReflectionGenericClass*
6013 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6015 static MonoClass *System_Reflection_MonoGenericClass;
6016 MonoReflectionGenericClass *res;
6017 MonoClass *klass, *gklass;
6019 if (!System_Reflection_MonoGenericClass) {
6020 System_Reflection_MonoGenericClass = mono_class_from_name (
6021 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6022 g_assert (System_Reflection_MonoGenericClass);
6025 klass = mono_class_from_mono_type (geninst);
6026 gklass = klass->generic_class->container_class;
6028 mono_class_init (klass);
6031 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6033 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6036 res->type.type = geninst;
6037 g_assert (gklass->reflection_info);
6038 g_assert (!strcmp (((MonoObject*)gklass->reflection_info)->vtable->klass->name, "TypeBuilder"));
6039 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
6045 verify_safe_for_managed_space (MonoType *type)
6047 switch (type->type) {
6049 case MONO_TYPE_ARRAY:
6050 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6052 return verify_safe_for_managed_space (type->data.type);
6053 case MONO_TYPE_SZARRAY:
6054 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6055 case MONO_TYPE_GENERICINST: {
6056 MonoGenericInst *inst = type->data.generic_class->inst;
6060 for (i = 0; i < inst->type_argc; ++i)
6061 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6067 case MONO_TYPE_MVAR:
6074 * mono_type_get_object:
6075 * @domain: an app domain
6078 * Return an System.MonoType object representing the type @type.
6081 mono_type_get_object (MonoDomain *domain, MonoType *type)
6083 MonoReflectionType *res;
6084 MonoClass *klass = mono_class_from_mono_type (type);
6086 /*we must avoid using @type as it might have come
6087 * from a mono_metadata_type_dup and the caller
6088 * expects that is can be freed.
6089 * Using the right type from
6091 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6093 /* void is very common */
6094 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6095 return (MonoReflectionType*)domain->typeof_void;
6098 * If the vtable of the given class was already created, we can use
6099 * the MonoType from there and avoid all locking and hash table lookups.
6101 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6102 * that the resulting object is diferent.
6104 if (type == &klass->byval_arg && !klass->image->dynamic) {
6105 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6106 if (vtable && vtable->type)
6107 return vtable->type;
6110 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6111 mono_domain_lock (domain);
6112 if (!domain->type_hash)
6113 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6114 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6115 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6116 mono_domain_unlock (domain);
6117 mono_loader_unlock ();
6120 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6121 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6122 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6123 mono_g_hash_table_insert (domain->type_hash, type, res);
6124 mono_domain_unlock (domain);
6125 mono_loader_unlock ();
6129 if (!verify_safe_for_managed_space (type)) {
6130 mono_domain_unlock (domain);
6131 mono_loader_unlock ();
6132 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6135 if (klass->reflection_info && !klass->wastypebuilder) {
6136 /* g_assert_not_reached (); */
6137 /* should this be considered an error condition? */
6139 mono_domain_unlock (domain);
6140 mono_loader_unlock ();
6141 return klass->reflection_info;
6144 // FIXME: Get rid of this, do it in the icalls for Type
6145 mono_class_init (klass);
6147 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6149 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6152 mono_g_hash_table_insert (domain->type_hash, type, res);
6154 if (type->type == MONO_TYPE_VOID)
6155 MONO_OBJECT_SETREF (domain, typeof_void, res);
6157 mono_domain_unlock (domain);
6158 mono_loader_unlock ();
6163 * mono_method_get_object:
6164 * @domain: an app domain
6166 * @refclass: the reflected type (can be NULL)
6168 * Return an System.Reflection.MonoMethod object representing the method @method.
6170 MonoReflectionMethod*
6171 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6174 * We use the same C representation for methods and constructors, but the type
6175 * name in C# is different.
6177 static MonoClass *System_Reflection_MonoMethod = NULL;
6178 static MonoClass *System_Reflection_MonoCMethod = NULL;
6179 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6180 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6182 MonoReflectionMethod *ret;
6185 * Don't let static RGCTX invoke wrappers get into
6186 * MonoReflectionMethods.
6188 if (method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE)
6189 method = mono_marshal_method_from_wrapper (method);
6191 if (method->is_inflated) {
6192 MonoReflectionGenericMethod *gret;
6194 refclass = method->klass;
6195 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6196 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6197 if (!System_Reflection_MonoGenericCMethod)
6198 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6199 klass = System_Reflection_MonoGenericCMethod;
6201 if (!System_Reflection_MonoGenericMethod)
6202 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6203 klass = System_Reflection_MonoGenericMethod;
6205 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6206 gret->method.method = method;
6207 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6208 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6209 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6213 refclass = method->klass;
6215 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6216 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6217 if (!System_Reflection_MonoCMethod)
6218 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6219 klass = System_Reflection_MonoCMethod;
6222 if (!System_Reflection_MonoMethod)
6223 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6224 klass = System_Reflection_MonoMethod;
6226 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6227 ret->method = method;
6228 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6229 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6233 * mono_method_clear_object:
6235 * Clear the cached reflection objects for the dynamic method METHOD.
6238 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6240 g_assert (method->dynamic);
6242 clear_cached_object (domain, method, method->klass);
6243 /* Added by mono_param_get_objects () */
6244 clear_cached_object (domain, &(method->signature), NULL);
6248 * mono_field_get_object:
6249 * @domain: an app domain
6253 * Return an System.Reflection.MonoField object representing the field @field
6256 MonoReflectionField*
6257 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6259 MonoReflectionField *res;
6260 static MonoClass *monofield_klass;
6262 CHECK_OBJECT (MonoReflectionField *, field, klass);
6263 if (!monofield_klass)
6264 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6265 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6268 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6269 if (is_field_on_inst (field))
6270 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6272 res->attrs = field->type->attrs;
6273 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6274 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6278 * mono_property_get_object:
6279 * @domain: an app domain
6281 * @property: a property
6283 * Return an System.Reflection.MonoProperty object representing the property @property
6286 MonoReflectionProperty*
6287 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6289 MonoReflectionProperty *res;
6290 static MonoClass *monoproperty_klass;
6292 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6293 if (!monoproperty_klass)
6294 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6295 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6297 res->property = property;
6298 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6302 * mono_event_get_object:
6303 * @domain: an app domain
6307 * Return an System.Reflection.MonoEvent object representing the event @event
6310 MonoReflectionEvent*
6311 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6313 MonoReflectionEvent *res;
6314 MonoReflectionMonoEvent *mono_event;
6315 static MonoClass *monoevent_klass;
6317 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6318 if (!monoevent_klass)
6319 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6320 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6321 mono_event->klass = klass;
6322 mono_event->event = event;
6323 res = (MonoReflectionEvent*)mono_event;
6324 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6328 * mono_get_reflection_missing_object:
6329 * @domain: Domain where the object lives
6331 * Returns the System.Reflection.Missing.Value singleton object
6332 * (of type System.Reflection.Missing).
6334 * Used as the value for ParameterInfo.DefaultValue when Optional
6338 mono_get_reflection_missing_object (MonoDomain *domain)
6341 static MonoClassField *missing_value_field = NULL;
6343 if (!missing_value_field) {
6344 MonoClass *missing_klass;
6345 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6346 mono_class_init (missing_klass);
6347 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6348 g_assert (missing_value_field);
6350 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6356 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6359 *dbnull = mono_get_dbnull_object (domain);
6364 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6366 if (!*reflection_missing)
6367 *reflection_missing = mono_get_reflection_missing_object (domain);
6368 return *reflection_missing;
6372 * mono_param_get_objects:
6373 * @domain: an app domain
6376 * Return an System.Reflection.ParameterInfo array object representing the parameters
6377 * in the method @method.
6380 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6382 static MonoClass *System_Reflection_ParameterInfo;
6383 static MonoClass *System_Reflection_ParameterInfo_array;
6384 MonoArray *res = NULL;
6385 MonoReflectionMethod *member = NULL;
6386 MonoReflectionParameter *param = NULL;
6387 char **names, **blobs = NULL;
6388 guint32 *types = NULL;
6389 MonoType *type = NULL;
6390 MonoObject *dbnull = NULL;
6391 MonoObject *missing = NULL;
6392 MonoMarshalSpec **mspecs;
6393 MonoMethodSignature *sig;
6394 MonoVTable *pinfo_vtable;
6397 if (!System_Reflection_ParameterInfo_array) {
6400 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6401 mono_memory_barrier ();
6402 System_Reflection_ParameterInfo = klass;
6404 klass = mono_array_class_get (klass, 1);
6405 mono_memory_barrier ();
6406 System_Reflection_ParameterInfo_array = klass;
6409 if (!mono_method_signature (method)->param_count)
6410 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6412 /* Note: the cache is based on the address of the signature into the method
6413 * since we already cache MethodInfos with the method as keys.
6415 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6417 sig = mono_method_signature (method);
6418 member = mono_method_get_object (domain, method, refclass);
6419 names = g_new (char *, sig->param_count);
6420 mono_method_get_param_names (method, (const char **) names);
6422 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6423 mono_method_get_marshal_info (method, mspecs);
6425 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6426 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6427 for (i = 0; i < sig->param_count; ++i) {
6428 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6429 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6430 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6431 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6432 param->PositionImpl = i;
6433 param->AttrsImpl = sig->params [i]->attrs;
6435 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6436 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6437 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6439 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6443 blobs = g_new0 (char *, sig->param_count);
6444 types = g_new0 (guint32, sig->param_count);
6445 get_default_param_value_blobs (method, blobs, types);
6448 /* Build MonoType for the type from the Constant Table */
6450 type = g_new0 (MonoType, 1);
6451 type->type = types [i];
6452 type->data.klass = NULL;
6453 if (types [i] == MONO_TYPE_CLASS)
6454 type->data.klass = mono_defaults.object_class;
6455 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6456 /* For enums, types [i] contains the base type */
6458 type->type = MONO_TYPE_VALUETYPE;
6459 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6461 type->data.klass = mono_class_from_mono_type (type);
6463 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6465 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6466 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6467 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6468 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6470 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6476 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6478 mono_array_setref (res, i, param);
6485 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6487 mono_metadata_free_marshal_spec (mspecs [i]);
6490 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6494 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6496 return mono_param_get_objects_internal (domain, method, NULL);
6500 * mono_method_body_get_object:
6501 * @domain: an app domain
6504 * Return an System.Reflection.MethodBody object representing the method @method.
6506 MonoReflectionMethodBody*
6507 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6509 static MonoClass *System_Reflection_MethodBody = NULL;
6510 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6511 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6512 MonoReflectionMethodBody *ret;
6513 MonoMethodNormal *mn;
6514 MonoMethodHeader *header;
6515 guint32 method_rva, local_var_sig_token;
6517 unsigned char format, flags;
6520 if (!System_Reflection_MethodBody)
6521 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6522 if (!System_Reflection_LocalVariableInfo)
6523 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6524 if (!System_Reflection_ExceptionHandlingClause)
6525 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6527 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6529 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6530 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6531 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6532 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6534 mn = (MonoMethodNormal *)method;
6535 header = mono_method_get_header (method);
6537 /* Obtain local vars signature token */
6538 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6539 ptr = mono_image_rva_map (method->klass->image, method_rva);
6540 flags = *(const unsigned char *) ptr;
6541 format = flags & METHOD_HEADER_FORMAT_MASK;
6543 case METHOD_HEADER_TINY_FORMAT:
6544 case METHOD_HEADER_TINY_FORMAT1:
6545 local_var_sig_token = 0;
6547 case METHOD_HEADER_FAT_FORMAT:
6551 local_var_sig_token = read32 (ptr);
6554 g_assert_not_reached ();
6557 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6559 ret->init_locals = header->init_locals;
6560 ret->max_stack = header->max_stack;
6561 ret->local_var_sig_token = local_var_sig_token;
6562 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6563 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6566 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6567 for (i = 0; i < header->num_locals; ++i) {
6568 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6569 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6570 info->is_pinned = header->locals [i]->pinned;
6571 info->local_index = i;
6572 mono_array_setref (ret->locals, i, info);
6576 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6577 for (i = 0; i < header->num_clauses; ++i) {
6578 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6579 MonoExceptionClause *clause = &header->clauses [i];
6581 info->flags = clause->flags;
6582 info->try_offset = clause->try_offset;
6583 info->try_length = clause->try_len;
6584 info->handler_offset = clause->handler_offset;
6585 info->handler_length = clause->handler_len;
6586 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6587 info->filter_offset = clause->data.filter_offset;
6588 else if (clause->data.catch_class)
6589 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6591 mono_array_setref (ret->clauses, i, info);
6594 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6599 * mono_get_dbnull_object:
6600 * @domain: Domain where the object lives
6602 * Returns the System.DBNull.Value singleton object
6604 * Used as the value for ParameterInfo.DefaultValue
6607 mono_get_dbnull_object (MonoDomain *domain)
6610 static MonoClassField *dbnull_value_field = NULL;
6612 if (!dbnull_value_field) {
6613 MonoClass *dbnull_klass;
6614 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6615 mono_class_init (dbnull_klass);
6616 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6617 g_assert (dbnull_value_field);
6619 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6625 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6627 guint32 param_index, i, lastp, crow = 0;
6628 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6631 MonoClass *klass = method->klass;
6632 MonoImage *image = klass->image;
6633 MonoMethodSignature *methodsig = mono_method_signature (method);
6635 MonoTableInfo *constt;
6636 MonoTableInfo *methodt;
6637 MonoTableInfo *paramt;
6639 if (!methodsig->param_count)
6642 mono_class_init (klass);
6644 if (klass->image->dynamic) {
6645 MonoReflectionMethodAux *aux;
6646 if (method->is_inflated)
6647 method = ((MonoMethodInflated*)method)->declaring;
6648 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6649 if (aux && aux->param_defaults) {
6650 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
6651 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
6656 methodt = &klass->image->tables [MONO_TABLE_METHOD];
6657 paramt = &klass->image->tables [MONO_TABLE_PARAM];
6658 constt = &image->tables [MONO_TABLE_CONSTANT];
6660 idx = mono_method_get_index (method) - 1;
6661 g_assert (idx != -1);
6663 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
6664 if (idx + 1 < methodt->rows)
6665 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
6667 lastp = paramt->rows + 1;
6669 for (i = param_index; i < lastp; ++i) {
6672 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
6673 paramseq = param_cols [MONO_PARAM_SEQUENCE];
6675 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
6678 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
6683 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
6684 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
6685 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
6692 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
6697 MonoType *basetype = type;
6702 klass = mono_class_from_mono_type (type);
6703 if (klass->valuetype) {
6704 object = mono_object_new (domain, klass);
6705 retval = ((gchar *) object + sizeof (MonoObject));
6706 if (klass->enumtype)
6707 basetype = mono_class_enum_basetype (klass);
6712 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
6719 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
6723 memset (assembly, 0, sizeof (MonoAssemblyName));
6725 assembly->culture = "";
6726 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
6728 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
6731 while (g_ascii_isspace (*p) || *p == ',') {
6740 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
6742 assembly->major = strtoul (p, &s, 10);
6743 if (s == p || *s != '.')
6746 assembly->minor = strtoul (p, &s, 10);
6747 if (s == p || *s != '.')
6750 assembly->build = strtoul (p, &s, 10);
6751 if (s == p || *s != '.')
6754 assembly->revision = strtoul (p, &s, 10);
6758 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6760 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6761 assembly->culture = "";
6764 assembly->culture = p;
6765 while (*p && *p != ',') {
6769 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6771 if (strncmp (p, "null", 4) == 0) {
6776 while (*p && *p != ',') {
6779 len = (p - start + 1);
6780 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6781 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6782 g_strlcpy ((char*)assembly->public_key_token, start, len);
6785 while (*p && *p != ',')
6789 while (g_ascii_isspace (*p) || *p == ',') {
6803 * mono_reflection_parse_type:
6806 * Parse a type name as accepted by the GetType () method and output the info
6807 * extracted in the info structure.
6808 * the name param will be mangled, so, make a copy before passing it to this function.
6809 * The fields in info will be valid until the memory pointed to by name is valid.
6811 * See also mono_type_get_name () below.
6813 * Returns: 0 on parse error.
6816 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6817 MonoTypeNameParse *info)
6819 char *start, *p, *w, *temp, *last_point, *startn;
6820 int in_modifiers = 0;
6821 int isbyref = 0, rank, arity = 0, i;
6823 start = p = w = name;
6825 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6826 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6827 info->name = info->name_space = NULL;
6828 info->nested = NULL;
6829 info->modifiers = NULL;
6830 info->type_arguments = NULL;
6832 /* last_point separates the namespace from the name */
6835 while (*p == ' ') p++, start++, w++, name++;
6840 *p = 0; /* NULL terminate the name */
6842 info->nested = g_list_append (info->nested, startn);
6843 /* we have parsed the nesting namespace + name */
6847 info->name_space = start;
6849 info->name = last_point + 1;
6851 info->name_space = (char *)"";
6870 i = strtol (p, &temp, 10);
6887 info->name_space = start;
6889 info->name = last_point + 1;
6891 info->name_space = (char *)"";
6898 if (isbyref) /* only one level allowed by the spec */
6901 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6905 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6911 info->type_arguments = g_ptr_array_new ();
6912 for (i = 0; i < arity; i++) {
6913 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6914 gboolean fqname = FALSE;
6916 g_ptr_array_add (info->type_arguments, subinfo);
6923 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6934 while (*p && (*p != ']'))
6942 if (g_ascii_isspace (*aname)) {
6949 !assembly_name_to_aname (&subinfo->assembly, aname))
6953 if (i + 1 < arity) {
6973 else if (*p == '*') /* '*' means unknown lower bound */
6974 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
6981 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6992 if (g_ascii_isspace (*p)) {
6999 return 0; /* missing assembly name */
7000 if (!assembly_name_to_aname (&info->assembly, p))
7006 if (info->assembly.name)
7009 // *w = 0; /* terminate class name */
7011 if (!info->name || !*info->name)
7015 /* add other consistency checks */
7020 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7022 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7026 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7028 gboolean type_resolve = FALSE;
7030 MonoImage *rootimage = image;
7032 if (info->assembly.name) {
7033 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7034 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7036 * This could happen in the AOT compiler case when the search hook is not
7039 assembly = image->assembly;
7041 /* then we must load the assembly ourselve - see #60439 */
7042 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7046 image = assembly->image;
7047 } else if (!image) {
7048 image = mono_defaults.corlib;
7051 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7052 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7053 image = mono_defaults.corlib;
7054 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7061 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7066 gboolean bounded = FALSE;
7069 image = mono_defaults.corlib;
7072 klass = mono_class_from_name_case (image, info->name_space, info->name);
7074 klass = mono_class_from_name (image, info->name_space, info->name);
7077 for (mod = info->nested; mod; mod = mod->next) {
7078 gpointer iter = NULL;
7082 mono_class_init (parent);
7084 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7086 if (g_strcasecmp (klass->name, mod->data) == 0)
7089 if (strcmp (klass->name, mod->data) == 0)
7098 mono_class_init (klass);
7100 if (info->type_arguments) {
7101 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7102 MonoReflectionType *the_type;
7106 for (i = 0; i < info->type_arguments->len; i++) {
7107 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7109 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7110 if (!type_args [i]) {
7116 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7118 instance = mono_reflection_bind_generic_parameters (
7119 the_type, info->type_arguments->len, type_args);
7125 klass = mono_class_from_mono_type (instance);
7128 for (mod = info->modifiers; mod; mod = mod->next) {
7129 modval = GPOINTER_TO_UINT (mod->data);
7130 if (!modval) { /* byref: must be last modifier */
7131 return &klass->this_arg;
7132 } else if (modval == -1) {
7133 klass = mono_ptr_class_get (&klass->byval_arg);
7134 } else if (modval == -2) {
7136 } else { /* array rank */
7137 klass = mono_bounded_array_class_get (klass, modval, bounded);
7139 mono_class_init (klass);
7142 return &klass->byval_arg;
7146 * mono_reflection_get_type:
7147 * @image: a metadata context
7148 * @info: type description structure
7149 * @ignorecase: flag for case-insensitive string compares
7150 * @type_resolve: whenever type resolve was already tried
7152 * Build a MonoType from the type description in @info.
7157 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7158 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7162 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7164 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (mono_domain_get (), assembly);
7168 g_assert (assembly->dynamic);
7170 /* Enumerate all modules */
7173 if (abuilder->modules) {
7174 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7175 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7176 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7182 if (!type && abuilder->loaded_modules) {
7183 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7184 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7185 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7195 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7198 MonoReflectionAssembly *assembly;
7202 if (image && image->dynamic)
7203 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7205 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7208 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7215 *type_resolve = TRUE;
7218 /* Reconstruct the type name */
7219 fullName = g_string_new ("");
7220 if (info->name_space && (info->name_space [0] != '\0'))
7221 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7223 g_string_printf (fullName, info->name);
7224 for (mod = info->nested; mod; mod = mod->next)
7225 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7227 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7229 if (assembly->assembly->dynamic)
7230 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7232 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7235 g_string_free (fullName, TRUE);
7240 mono_reflection_free_type_info (MonoTypeNameParse *info)
7242 g_list_free (info->modifiers);
7243 g_list_free (info->nested);
7245 if (info->type_arguments) {
7248 for (i = 0; i < info->type_arguments->len; i++) {
7249 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7251 mono_reflection_free_type_info (subinfo);
7252 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7256 g_ptr_array_free (info->type_arguments, TRUE);
7261 * mono_reflection_type_from_name:
7263 * @image: a metadata context (can be NULL).
7265 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7266 * it defaults to get the type from @image or, if @image is NULL or loading
7267 * from it fails, uses corlib.
7271 mono_reflection_type_from_name (char *name, MonoImage *image)
7273 MonoType *type = NULL;
7274 MonoTypeNameParse info;
7277 /* Make a copy since parse_type modifies its argument */
7278 tmp = g_strdup (name);
7280 /*g_print ("requested type %s\n", str);*/
7281 if (mono_reflection_parse_type (tmp, &info)) {
7282 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7286 mono_reflection_free_type_info (&info);
7291 * mono_reflection_get_token:
7293 * Return the metadata token of OBJ which should be an object
7294 * representing a metadata element.
7297 mono_reflection_get_token (MonoObject *obj)
7302 klass = obj->vtable->klass;
7304 if (strcmp (klass->name, "MethodBuilder") == 0) {
7305 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7307 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7308 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7309 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7311 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7312 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7313 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7315 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7316 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7317 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7318 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7319 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7320 } else if (strcmp (klass->name, "MonoType") == 0) {
7321 MonoReflectionType *tb = (MonoReflectionType *)obj;
7322 token = mono_class_from_mono_type (tb->type)->type_token;
7323 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7324 strcmp (klass->name, "MonoMethod") == 0 ||
7325 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7326 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7327 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7328 if (m->method->is_inflated) {
7329 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7330 return inflated->declaring->token;
7332 token = m->method->token;
7334 } else if (strcmp (klass->name, "MonoField") == 0) {
7335 MonoReflectionField *f = (MonoReflectionField*)obj;
7337 if (is_field_on_inst (f->field)) {
7338 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7339 int field_index = f->field - dgclass->fields;
7342 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7343 obj = dgclass->field_objects [field_index];
7344 return mono_reflection_get_token (obj);
7346 token = mono_class_get_field_token (f->field);
7347 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7348 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7350 token = mono_class_get_property_token (p->property);
7351 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7352 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7354 token = mono_class_get_event_token (p->event);
7355 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7356 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7358 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7359 } else if (strcmp (klass->name, "Module") == 0) {
7360 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7363 } else if (strcmp (klass->name, "Assembly") == 0) {
7364 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7366 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7367 MonoException *ex = mono_get_exception_not_implemented (msg);
7369 mono_raise_exception (ex);
7376 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7378 int slen, type = t->type;
7379 MonoClass *tklass = t->data.klass;
7385 case MONO_TYPE_BOOLEAN: {
7386 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7391 case MONO_TYPE_CHAR:
7393 case MONO_TYPE_I2: {
7394 guint16 *val = g_malloc (sizeof (guint16));
7399 #if SIZEOF_VOID_P == 4
7405 case MONO_TYPE_I4: {
7406 guint32 *val = g_malloc (sizeof (guint32));
7411 #if SIZEOF_VOID_P == 8
7412 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7416 case MONO_TYPE_I8: {
7417 guint64 *val = g_malloc (sizeof (guint64));
7422 case MONO_TYPE_R8: {
7423 double *val = g_malloc (sizeof (double));
7428 case MONO_TYPE_VALUETYPE:
7429 if (t->data.klass->enumtype) {
7430 type = mono_class_enum_basetype (t->data.klass)->type;
7433 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7436 case MONO_TYPE_STRING:
7437 if (*p == (char)0xFF) {
7441 slen = mono_metadata_decode_value (p, &p);
7443 return mono_string_new_len (mono_domain_get (), p, slen);
7444 case MONO_TYPE_CLASS: {
7447 if (*p == (char)0xFF) {
7452 slen = mono_metadata_decode_value (p, &p);
7453 n = g_memdup (p, slen + 1);
7455 t = mono_reflection_type_from_name (n, image);
7457 g_warning ("Cannot load type '%s'", n);
7461 return mono_type_get_object (mono_domain_get (), t);
7465 case MONO_TYPE_OBJECT: {
7468 MonoClass *subc = NULL;
7473 } else if (subt == 0x0E) {
7474 type = MONO_TYPE_STRING;
7476 } else if (subt == 0x1D) {
7477 MonoType simple_type = {{0}};
7482 /* See Partition II, Appendix B3 */
7483 etype = MONO_TYPE_OBJECT;
7484 type = MONO_TYPE_SZARRAY;
7485 simple_type.type = etype;
7486 tklass = mono_class_from_mono_type (&simple_type);
7488 } else if (subt == 0x55) {
7491 slen = mono_metadata_decode_value (p, &p);
7492 n = g_memdup (p, slen + 1);
7494 t = mono_reflection_type_from_name (n, image);
7496 g_error ("Cannot load type '%s'", n);
7499 subc = mono_class_from_mono_type (t);
7500 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7501 MonoType simple_type = {{0}};
7502 simple_type.type = subt;
7503 subc = mono_class_from_mono_type (&simple_type);
7505 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7507 val = load_cattr_value (image, &subc->byval_arg, p, end);
7508 obj = mono_object_new (mono_domain_get (), subc);
7509 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7513 case MONO_TYPE_SZARRAY: {
7515 guint32 i, alen, basetype;
7518 if (alen == 0xffffffff) {
7522 arr = mono_array_new (mono_domain_get(), tklass, alen);
7523 basetype = tklass->byval_arg.type;
7524 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7525 basetype = mono_class_enum_basetype (tklass)->type;
7530 case MONO_TYPE_BOOLEAN:
7531 for (i = 0; i < alen; i++) {
7532 MonoBoolean val = *p++;
7533 mono_array_set (arr, MonoBoolean, i, val);
7536 case MONO_TYPE_CHAR:
7539 for (i = 0; i < alen; i++) {
7540 guint16 val = read16 (p);
7541 mono_array_set (arr, guint16, i, val);
7548 for (i = 0; i < alen; i++) {
7549 guint32 val = read32 (p);
7550 mono_array_set (arr, guint32, i, val);
7555 for (i = 0; i < alen; i++) {
7558 mono_array_set (arr, double, i, val);
7564 for (i = 0; i < alen; i++) {
7565 guint64 val = read64 (p);
7566 mono_array_set (arr, guint64, i, val);
7570 case MONO_TYPE_CLASS:
7571 case MONO_TYPE_OBJECT:
7572 case MONO_TYPE_STRING:
7573 for (i = 0; i < alen; i++) {
7574 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7575 mono_array_setref (arr, i, item);
7579 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7585 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7591 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7593 static MonoClass *klass;
7594 static MonoMethod *ctor;
7596 void *params [2], *unboxed;
7599 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7601 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7603 params [0] = mono_type_get_object (mono_domain_get (), t);
7605 retval = mono_object_new (mono_domain_get (), klass);
7606 unboxed = mono_object_unbox (retval);
7607 mono_runtime_invoke (ctor, unboxed, params, NULL);
7613 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
7615 static MonoClass *klass;
7616 static MonoMethod *ctor;
7618 void *unboxed, *params [2];
7621 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
7623 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7626 params [1] = typedarg;
7627 retval = mono_object_new (mono_domain_get (), klass);
7628 unboxed = mono_object_unbox (retval);
7629 mono_runtime_invoke (ctor, unboxed, params, NULL);
7635 type_is_reference (MonoType *type)
7637 switch (type->type) {
7638 case MONO_TYPE_BOOLEAN:
7639 case MONO_TYPE_CHAR:
7652 case MONO_TYPE_VALUETYPE:
7660 free_param_data (MonoMethodSignature *sig, void **params) {
7662 for (i = 0; i < sig->param_count; ++i) {
7663 if (!type_is_reference (sig->params [i]))
7664 g_free (params [i]);
7669 * Find the field index in the metadata FieldDef table.
7672 find_field_index (MonoClass *klass, MonoClassField *field) {
7675 for (i = 0; i < klass->field.count; ++i) {
7676 if (field == &klass->fields [i])
7677 return klass->field.first + 1 + i;
7683 * Find the property index in the metadata Property table.
7686 find_property_index (MonoClass *klass, MonoProperty *property) {
7689 for (i = 0; i < klass->ext->property.count; ++i) {
7690 if (property == &klass->ext->properties [i])
7691 return klass->ext->property.first + 1 + i;
7697 * Find the event index in the metadata Event table.
7700 find_event_index (MonoClass *klass, MonoEvent *event) {
7703 for (i = 0; i < klass->ext->event.count; ++i) {
7704 if (event == &klass->ext->events [i])
7705 return klass->ext->event.first + 1 + i;
7711 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7713 const char *p = (const char*)data;
7715 guint32 i, j, num_named;
7717 void *params_buf [32];
7719 MonoMethodSignature *sig;
7721 mono_class_init (method->klass);
7724 attr = mono_object_new (mono_domain_get (), method->klass);
7725 mono_runtime_invoke (method, attr, NULL, NULL);
7729 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7732 /*g_print ("got attr %s\n", method->klass->name);*/
7734 sig = mono_method_signature (method);
7735 if (sig->param_count < 32)
7736 params = params_buf;
7738 /* Allocate using GC so it gets GC tracking */
7739 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
7743 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7744 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7748 attr = mono_object_new (mono_domain_get (), method->klass);
7749 mono_runtime_invoke (method, attr, params, NULL);
7750 free_param_data (method->signature, params);
7751 num_named = read16 (named);
7753 for (j = 0; j < num_named; j++) {
7755 char *name, named_type, data_type;
7756 named_type = *named++;
7757 data_type = *named++; /* type of data */
7758 if (data_type == MONO_TYPE_SZARRAY)
7759 data_type = *named++;
7760 if (data_type == MONO_TYPE_ENUM) {
7763 type_len = mono_metadata_decode_blob_size (named, &named);
7764 type_name = g_malloc (type_len + 1);
7765 memcpy (type_name, named, type_len);
7766 type_name [type_len] = 0;
7768 /* FIXME: lookup the type and check type consistency */
7771 name_len = mono_metadata_decode_blob_size (named, &named);
7772 name = g_malloc (name_len + 1);
7773 memcpy (name, named, name_len);
7774 name [name_len] = 0;
7776 if (named_type == 0x53) {
7777 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
7778 void *val = load_cattr_value (image, field->type, named, &named);
7779 mono_field_set_value (attr, field, val);
7780 if (!type_is_reference (field->type))
7782 } else if (named_type == 0x54) {
7785 MonoType *prop_type;
7787 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
7788 /* can we have more that 1 arg in a custom attr named property? */
7789 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7790 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7791 pparams [0] = load_cattr_value (image, prop_type, named, &named);
7792 mono_property_set_value (prop, attr, pparams, NULL);
7793 if (!type_is_reference (prop_type))
7794 g_free (pparams [0]);
7799 if (params != params_buf)
7800 mono_gc_free_fixed (params);
7806 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
7808 MonoArray *typedargs, *namedargs;
7809 MonoClass *attrklass;
7810 static MonoMethod *ctor;
7813 const char *p = (const char*)data;
7815 guint32 i, j, num_named;
7818 mono_class_init (method->klass);
7821 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
7823 domain = mono_domain_get ();
7825 /* This is for Attributes with no parameters */
7826 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7827 params [0] = mono_method_get_object (domain, method, NULL);
7828 params [1] = params [2] = NULL;
7829 mono_runtime_invoke (method, attr, params, NULL);
7833 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7836 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7840 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7841 MonoObject *obj, *typedarg;
7844 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7845 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7846 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7847 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7848 mono_array_setref (typedargs, i, typedarg);
7850 if (!type_is_reference (mono_method_signature (method)->params [i]))
7855 num_named = read16 (named);
7856 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7858 attrklass = method->klass;
7859 for (j = 0; j < num_named; j++) {
7861 char *name, named_type, data_type;
7862 named_type = *named++;
7863 data_type = *named++; /* type of data */
7864 if (data_type == MONO_TYPE_SZARRAY)
7865 data_type = *named++;
7866 if (data_type == MONO_TYPE_ENUM) {
7869 type_len = mono_metadata_decode_blob_size (named, &named);
7870 type_name = g_malloc (type_len + 1);
7871 memcpy (type_name, named, type_len);
7872 type_name [type_len] = 0;
7874 /* FIXME: lookup the type and check type consistency */
7877 name_len = mono_metadata_decode_blob_size (named, &named);
7878 name = g_malloc (name_len + 1);
7879 memcpy (name, named, name_len);
7880 name [name_len] = 0;
7882 if (named_type == 0x53) {
7883 MonoObject *obj, *typedarg, *namedarg;
7884 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7885 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7887 minfo = mono_field_get_object (domain, NULL, field);
7888 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7889 typedarg = create_cattr_typed_arg (field->type, obj);
7890 namedarg = create_cattr_named_arg (minfo, typedarg);
7891 mono_array_setref (namedargs, j, namedarg);
7892 if (!type_is_reference (field->type))
7894 } else if (named_type == 0x54) {
7895 MonoObject *obj, *typedarg, *namedarg;
7896 MonoType *prop_type;
7898 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7900 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7901 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7902 minfo = mono_property_get_object (domain, NULL, prop);
7903 val = load_cattr_value (image, prop_type, named, &named);
7904 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7905 typedarg = create_cattr_typed_arg (prop_type, obj);
7906 namedarg = create_cattr_named_arg (minfo, typedarg);
7907 mono_array_setref (namedargs, j, namedarg);
7908 if (!type_is_reference (prop_type))
7913 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
7914 params [0] = mono_method_get_object (domain, method, NULL);
7915 params [1] = typedargs;
7916 params [2] = namedargs;
7917 mono_runtime_invoke (ctor, attr, params, NULL);
7922 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7928 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
7929 for (i = 0; i < cinfo->num_attrs; ++i) {
7930 if (!cinfo->attrs [i].ctor)
7931 /* The cattr type is not finished yet */
7932 /* We should include the type name but cinfo doesn't contain it */
7933 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
7934 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7935 mono_array_setref (result, i, attr);
7941 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7948 for (i = 0; i < cinfo->num_attrs; ++i) {
7949 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7953 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
7955 for (i = 0; i < cinfo->num_attrs; ++i) {
7956 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7957 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7958 mono_array_setref (result, n, attr);
7966 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7972 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
7973 for (i = 0; i < cinfo->num_attrs; ++i) {
7974 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7975 mono_array_setref (result, i, attr);
7981 * mono_custom_attrs_from_index:
7983 * Returns: NULL if no attributes are found or if a loading error occurs.
7986 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7988 guint32 mtoken, i, len;
7989 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7991 MonoCustomAttrInfo *ainfo;
7992 GList *tmp, *list = NULL;
7995 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7997 i = mono_metadata_custom_attrs_from_index (image, idx);
8001 while (i < ca->rows) {
8002 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8004 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8007 len = g_list_length (list);
8010 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
8011 ainfo->num_attrs = len;
8012 ainfo->image = image;
8013 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8014 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8015 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8016 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8017 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8018 mtoken |= MONO_TOKEN_METHOD_DEF;
8020 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8021 mtoken |= MONO_TOKEN_MEMBER_REF;
8024 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8027 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8028 if (!ainfo->attrs [i].ctor) {
8029 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8034 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8035 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8036 ainfo->attrs [i].data = (guchar*)data;
8044 mono_custom_attrs_from_method (MonoMethod *method)
8049 * An instantiated method has the same cattrs as the generic method definition.
8051 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8052 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8054 if (method->is_inflated)
8055 method = ((MonoMethodInflated *) method)->declaring;
8057 if (method->dynamic || method->klass->image->dynamic)
8058 return lookup_custom_attr (method->klass->image, method);
8060 idx = mono_method_get_index (method);
8061 idx <<= MONO_CUSTOM_ATTR_BITS;
8062 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8063 return mono_custom_attrs_from_index (method->klass->image, idx);
8067 mono_custom_attrs_from_class (MonoClass *klass)
8071 if (klass->generic_class)
8072 klass = klass->generic_class->container_class;
8074 if (klass->image->dynamic)
8075 return lookup_custom_attr (klass->image, klass);
8077 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8078 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8079 idx <<= MONO_CUSTOM_ATTR_BITS;
8080 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8082 idx = mono_metadata_token_index (klass->type_token);
8083 idx <<= MONO_CUSTOM_ATTR_BITS;
8084 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8086 return mono_custom_attrs_from_index (klass->image, idx);
8090 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8094 if (assembly->image->dynamic)
8095 return lookup_custom_attr (assembly->image, assembly);
8096 idx = 1; /* there is only one assembly */
8097 idx <<= MONO_CUSTOM_ATTR_BITS;
8098 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8099 return mono_custom_attrs_from_index (assembly->image, idx);
8102 static MonoCustomAttrInfo*
8103 mono_custom_attrs_from_module (MonoImage *image)
8108 return lookup_custom_attr (image, image);
8109 idx = 1; /* there is only one module */
8110 idx <<= MONO_CUSTOM_ATTR_BITS;
8111 idx |= MONO_CUSTOM_ATTR_MODULE;
8112 return mono_custom_attrs_from_index (image, idx);
8116 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8120 if (klass->image->dynamic) {
8121 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8122 return lookup_custom_attr (klass->image, property);
8124 idx = find_property_index (klass, property);
8125 idx <<= MONO_CUSTOM_ATTR_BITS;
8126 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8127 return mono_custom_attrs_from_index (klass->image, idx);
8131 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8135 if (klass->image->dynamic) {
8136 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8137 return lookup_custom_attr (klass->image, event);
8139 idx = find_event_index (klass, event);
8140 idx <<= MONO_CUSTOM_ATTR_BITS;
8141 idx |= MONO_CUSTOM_ATTR_EVENT;
8142 return mono_custom_attrs_from_index (klass->image, idx);
8146 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8149 if (klass->image->dynamic) {
8150 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8151 return lookup_custom_attr (klass->image, field);
8153 idx = find_field_index (klass, field);
8154 idx <<= MONO_CUSTOM_ATTR_BITS;
8155 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8156 return mono_custom_attrs_from_index (klass->image, idx);
8160 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8163 guint32 i, idx, method_index;
8164 guint32 param_list, param_last, param_pos, found;
8166 MonoReflectionMethodAux *aux;
8169 * An instantiated method has the same cattrs as the generic method definition.
8171 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8172 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8174 if (method->is_inflated)
8175 method = ((MonoMethodInflated *) method)->declaring;
8177 if (method->klass->image->dynamic) {
8178 MonoCustomAttrInfo *res, *ainfo;
8181 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8182 if (!aux || !aux->param_cattr)
8185 /* Need to copy since it will be freed later */
8186 ainfo = aux->param_cattr [param];
8187 size = sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (ainfo->num_attrs - MONO_ZERO_LEN_ARRAY);
8188 res = g_malloc0 (size);
8189 memcpy (res, ainfo, size);
8193 image = method->klass->image;
8194 method_index = mono_method_get_index (method);
8195 ca = &image->tables [MONO_TABLE_METHOD];
8197 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8198 if (method_index == ca->rows) {
8199 ca = &image->tables [MONO_TABLE_PARAM];
8200 param_last = ca->rows + 1;
8202 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8203 ca = &image->tables [MONO_TABLE_PARAM];
8206 for (i = param_list; i < param_last; ++i) {
8207 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8208 if (param_pos == param) {
8216 idx <<= MONO_CUSTOM_ATTR_BITS;
8217 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8218 return mono_custom_attrs_from_index (image, idx);
8222 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8226 for (i = 0; i < ainfo->num_attrs; ++i) {
8227 klass = ainfo->attrs [i].ctor->klass;
8228 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8235 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8242 for (i = 0; i < ainfo->num_attrs; ++i) {
8243 klass = ainfo->attrs [i].ctor->klass;
8244 if (mono_class_has_parent (klass, attr_klass)) {
8249 if (attr_index == -1)
8252 attrs = mono_custom_attrs_construct (ainfo);
8254 return mono_array_get (attrs, MonoObject*, attr_index);
8260 * mono_reflection_get_custom_attrs_info:
8261 * @obj: a reflection object handle
8263 * Return the custom attribute info for attributes defined for the
8264 * reflection handle @obj. The objects.
8266 * FIXME this function leaks like a sieve for SRE objects.
8269 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8272 MonoCustomAttrInfo *cinfo = NULL;
8274 klass = obj->vtable->klass;
8275 if (klass == mono_defaults.monotype_class) {
8276 MonoReflectionType *rtype = (MonoReflectionType*)obj;
8277 klass = mono_class_from_mono_type (rtype->type);
8278 cinfo = mono_custom_attrs_from_class (klass);
8279 } else if (strcmp ("Assembly", klass->name) == 0) {
8280 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8281 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8282 } else if (strcmp ("Module", klass->name) == 0) {
8283 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8284 cinfo = mono_custom_attrs_from_module (module->image);
8285 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8286 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8287 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8288 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8289 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8290 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8291 } else if (strcmp ("MonoField", klass->name) == 0) {
8292 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8293 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8294 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8295 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8296 cinfo = mono_custom_attrs_from_method (rmethod->method);
8297 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8298 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8299 cinfo = mono_custom_attrs_from_method (rmethod->method);
8300 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8301 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8302 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8303 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8304 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8305 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8306 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8307 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8308 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8309 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8310 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8311 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8312 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8313 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8314 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8315 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8316 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8317 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8318 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8319 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8320 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8321 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8322 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8323 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8324 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8325 } else { /* handle other types here... */
8326 g_error ("get custom attrs not yet supported for %s", klass->name);
8333 * mono_reflection_get_custom_attrs_by_type:
8334 * @obj: a reflection object handle
8336 * Return an array with all the custom attributes defined of the
8337 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8338 * of that type are returned. The objects are fully build. Return NULL if a loading error
8342 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8345 MonoCustomAttrInfo *cinfo;
8347 cinfo = mono_reflection_get_custom_attrs_info (obj);
8350 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8352 result = mono_custom_attrs_construct (cinfo);
8354 mono_custom_attrs_free (cinfo);
8356 if (mono_loader_get_last_error ())
8358 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8365 * mono_reflection_get_custom_attrs:
8366 * @obj: a reflection object handle
8368 * Return an array with all the custom attributes defined of the
8369 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8373 mono_reflection_get_custom_attrs (MonoObject *obj)
8375 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8379 * mono_reflection_get_custom_attrs_data:
8380 * @obj: a reflection obj handle
8382 * Returns an array of System.Reflection.CustomAttributeData,
8383 * which include information about attributes reflected on
8384 * types loaded using the Reflection Only methods
8387 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8390 MonoCustomAttrInfo *cinfo;
8392 cinfo = mono_reflection_get_custom_attrs_info (obj);
8394 result = mono_custom_attrs_data_construct (cinfo);
8396 mono_custom_attrs_free (cinfo);
8398 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8403 static MonoReflectionType*
8404 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8406 MonoMethod *method_get_underlying_system_type;
8408 method_get_underlying_system_type = mono_object_get_virtual_method ((MonoObject *) t,
8409 mono_class_get_method_from_name (mono_object_class (t),
8410 "get_UnderlyingSystemType",
8412 return (MonoReflectionType *) mono_runtime_invoke (method_get_underlying_system_type, t, NULL, NULL);
8416 mono_reflection_type_get_handle (MonoReflectionType* t)
8421 t = mono_reflection_type_get_underlying_system_type (t);
8429 * LOCKING: Assumes the loader lock is held.
8431 static MonoMethodSignature*
8432 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
8433 MonoMethodSignature *sig;
8436 count = parameters? mono_array_length (parameters): 0;
8438 sig = image_g_malloc0 (image, sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
8439 sig->param_count = count;
8440 sig->sentinelpos = -1; /* FIXME */
8441 for (i = 0; i < count; ++i) {
8442 MonoReflectionType *pt = mono_type_array_get (parameters, i);
8443 sig->params [i] = mono_reflection_type_get_handle (pt);
8449 * LOCKING: Assumes the loader lock is held.
8451 static MonoMethodSignature*
8452 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
8453 MonoMethodSignature *sig;
8455 sig = parameters_to_signature (image, ctor->parameters);
8456 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8457 sig->ret = &mono_defaults.void_class->byval_arg;
8462 * LOCKING: Assumes the loader lock is held.
8464 static MonoMethodSignature*
8465 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
8466 MonoMethodSignature *sig;
8468 sig = parameters_to_signature (image, method->parameters);
8469 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8470 sig->ret = method->rtype? monotype_cast (method->rtype)->type: &mono_defaults.void_class->byval_arg;
8471 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
8475 static MonoMethodSignature*
8476 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
8477 MonoMethodSignature *sig;
8479 sig = parameters_to_signature (NULL, method->parameters);
8480 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
8481 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
8482 sig->generic_param_count = 0;
8487 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
8489 MonoClass *klass = mono_object_class (prop);
8490 if (strcmp (klass->name, "PropertyBuilder") == 0) {
8491 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
8492 *name = mono_string_to_utf8 (pb->name);
8493 *type = monotype_cast (pb->type)->type;
8495 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
8496 *name = g_strdup (p->property->name);
8497 if (p->property->get)
8498 *type = mono_method_signature (p->property->get)->ret;
8500 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
8505 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
8507 MonoClass *klass = mono_object_class (field);
8508 if (strcmp (klass->name, "FieldBuilder") == 0) {
8509 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
8510 *name = mono_string_to_utf8 (fb->name);
8511 *type = monotype_cast (fb->type)->type;
8513 MonoReflectionField *f = (MonoReflectionField *)field;
8514 *name = g_strdup (mono_field_get_name (f->field));
8515 *type = f->field->type;
8520 * Encode a value in a custom attribute stream of bytes.
8521 * The value to encode is either supplied as an object in argument val
8522 * (valuetypes are boxed), or as a pointer to the data in the
8524 * @type represents the type of the value
8525 * @buffer is the start of the buffer
8526 * @p the current position in the buffer
8527 * @buflen contains the size of the buffer and is used to return the new buffer size
8528 * if this needs to be realloced.
8529 * @retbuffer and @retp return the start and the position of the buffer
8532 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
8534 MonoTypeEnum simple_type;
8536 if ((p-buffer) + 10 >= *buflen) {
8539 newbuf = g_realloc (buffer, *buflen);
8540 p = newbuf + (p-buffer);
8544 argval = ((char*)arg + sizeof (MonoObject));
8545 simple_type = type->type;
8547 switch (simple_type) {
8548 case MONO_TYPE_BOOLEAN:
8553 case MONO_TYPE_CHAR:
8556 swap_with_size (p, argval, 2, 1);
8562 swap_with_size (p, argval, 4, 1);
8566 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8576 swap_with_size (p, argval, 8, 1);
8582 swap_with_size (p, argval, 8, 1);
8585 case MONO_TYPE_VALUETYPE:
8586 if (type->data.klass->enumtype) {
8587 simple_type = mono_class_enum_basetype (type->data.klass)->type;
8590 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
8593 case MONO_TYPE_STRING: {
8600 str = mono_string_to_utf8 ((MonoString*)arg);
8601 slen = strlen (str);
8602 if ((p-buffer) + 10 + slen >= *buflen) {
8606 newbuf = g_realloc (buffer, *buflen);
8607 p = newbuf + (p-buffer);
8610 mono_metadata_encode_value (slen, p, &p);
8611 memcpy (p, str, slen);
8616 case MONO_TYPE_CLASS: {
8624 k = mono_object_class (arg);
8625 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
8626 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit"))) {
8627 MonoReflectionType* rt = mono_reflection_type_get_underlying_system_type ((MonoReflectionType*) arg);
8630 if (rt && (rtc = mono_object_class (rt)) &&
8631 (mono_object_isinst ((MonoObject *) rt, mono_defaults.monotype_class) ||
8632 !strcmp (rtc->name, "TypeBuilder") || !strcmp (rtc->name_space, "System.Reflection.Emit"))) {
8633 arg = (MonoObject *) rt;
8636 g_error ("Only System.Type allowed, not %s.%s", k->name_space, k->name);
8639 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
8640 slen = strlen (str);
8641 if ((p-buffer) + 10 + slen >= *buflen) {
8645 newbuf = g_realloc (buffer, *buflen);
8646 p = newbuf + (p-buffer);
8649 mono_metadata_encode_value (slen, p, &p);
8650 memcpy (p, str, slen);
8655 case MONO_TYPE_SZARRAY: {
8657 MonoClass *eclass, *arg_eclass;
8660 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
8663 len = mono_array_length ((MonoArray*)arg);
8665 *p++ = (len >> 8) & 0xff;
8666 *p++ = (len >> 16) & 0xff;
8667 *p++ = (len >> 24) & 0xff;
8669 *retbuffer = buffer;
8670 eclass = type->data.klass;
8671 arg_eclass = mono_object_class (arg)->element_class;
8674 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8675 eclass = mono_defaults.object_class;
8677 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
8678 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8679 int elsize = mono_class_array_element_size (arg_eclass);
8680 for (i = 0; i < len; ++i) {
8681 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
8684 } else if (eclass->valuetype && arg_eclass->valuetype) {
8685 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
8686 int elsize = mono_class_array_element_size (eclass);
8687 for (i = 0; i < len; ++i) {
8688 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
8692 for (i = 0; i < len; ++i) {
8693 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
8698 case MONO_TYPE_OBJECT: {
8704 * The parameter type is 'object' but the type of the actual
8705 * argument is not. So we have to add type information to the blob
8706 * too. This is completely undocumented in the spec.
8710 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
8715 klass = mono_object_class (arg);
8717 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
8720 } else if (klass->enumtype) {
8722 } else if (klass == mono_defaults.string_class) {
8723 simple_type = MONO_TYPE_STRING;
8726 } else if (klass->rank == 1) {
8728 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
8729 /* See Partition II, Appendix B3 */
8732 *p++ = klass->element_class->byval_arg.type;
8733 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
8735 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
8736 *p++ = simple_type = klass->byval_arg.type;
8739 g_error ("unhandled type in custom attr");
8741 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
8742 slen = strlen (str);
8743 if ((p-buffer) + 10 + slen >= *buflen) {
8747 newbuf = g_realloc (buffer, *buflen);
8748 p = newbuf + (p-buffer);
8751 mono_metadata_encode_value (slen, p, &p);
8752 memcpy (p, str, slen);
8755 simple_type = mono_class_enum_basetype (klass)->type;
8759 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
8762 *retbuffer = buffer;
8766 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
8768 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8769 char *str = type_get_qualified_name (type, NULL);
8770 int slen = strlen (str);
8774 * This seems to be optional...
8777 mono_metadata_encode_value (slen, p, &p);
8778 memcpy (p, str, slen);
8781 } else if (type->type == MONO_TYPE_OBJECT) {
8783 } else if (type->type == MONO_TYPE_CLASS) {
8784 /* it should be a type: encode_cattr_value () has the check */
8787 mono_metadata_encode_value (type->type, p, &p);
8788 if (type->type == MONO_TYPE_SZARRAY)
8789 /* See the examples in Partition VI, Annex B */
8790 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
8797 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
8800 /* Preallocate a large enough buffer */
8801 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
8802 char *str = type_get_qualified_name (type, NULL);
8805 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
8806 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
8812 len += strlen (name);
8814 if ((p-buffer) + 20 + len >= *buflen) {
8818 newbuf = g_realloc (buffer, *buflen);
8819 p = newbuf + (p-buffer);
8823 encode_field_or_prop_type (type, p, &p);
8825 len = strlen (name);
8826 mono_metadata_encode_value (len, p, &p);
8827 memcpy (p, name, len);
8829 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
8831 *retbuffer = buffer;
8834 #ifndef DISABLE_REFLECTION_EMIT
8837 * mono_reflection_get_custom_attrs_blob:
8838 * @ctor: custom attribute constructor
8839 * @ctorArgs: arguments o the constructor
8845 * Creates the blob of data that needs to be saved in the metadata and that represents
8846 * the custom attributed described by @ctor, @ctorArgs etc.
8847 * Returns: a Byte array representing the blob of data.
8850 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
8853 MonoMethodSignature *sig;
8858 MONO_ARCH_SAVE_REGS;
8860 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
8861 /* sig is freed later so allocate it in the heap */
8862 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
8864 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
8867 g_assert (mono_array_length (ctorArgs) == sig->param_count);
8869 p = buffer = g_malloc (buflen);
8870 /* write the prolog */
8873 for (i = 0; i < sig->param_count; ++i) {
8874 arg = mono_array_get (ctorArgs, MonoObject*, i);
8875 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
8879 i += mono_array_length (properties);
8881 i += mono_array_length (fields);
8883 *p++ = (i >> 8) & 0xff;
8886 for (i = 0; i < mono_array_length (properties); ++i) {
8890 prop = mono_array_get (properties, gpointer, i);
8891 get_prop_name_and_type (prop, &pname, &ptype);
8892 *p++ = 0x54; /* PROPERTY signature */
8893 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
8900 for (i = 0; i < mono_array_length (fields); ++i) {
8904 field = mono_array_get (fields, gpointer, i);
8905 get_field_name_and_type (field, &fname, &ftype);
8906 *p++ = 0x53; /* FIELD signature */
8907 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
8912 g_assert (p - buffer <= buflen);
8913 buflen = p - buffer;
8914 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8915 p = mono_array_addr (result, char, 0);
8916 memcpy (p, buffer, buflen);
8918 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
8924 * mono_reflection_setup_internal_class:
8925 * @tb: a TypeBuilder object
8927 * Creates a MonoClass that represents the TypeBuilder.
8928 * This is a trick that lets us simplify a lot of reflection code
8929 * (and will allow us to support Build and Run assemblies easier).
8932 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
8934 MonoClass *klass, *parent;
8936 MONO_ARCH_SAVE_REGS;
8938 CHECK_MONOTYPE (tb->parent);
8940 mono_loader_lock ();
8943 /* check so we can compile corlib correctly */
8944 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8945 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8946 parent = monotype_cast (tb->parent)->type->data.klass;
8948 parent = mono_class_from_mono_type (monotype_cast (tb->parent)->type);
8954 /* the type has already being created: it means we just have to change the parent */
8955 if (tb->type.type) {
8956 klass = mono_class_from_mono_type (tb->type.type);
8957 klass->parent = NULL;
8958 /* fool mono_class_setup_parent */
8959 klass->supertypes = NULL;
8960 mono_class_setup_parent (klass, parent);
8961 mono_class_setup_mono_type (klass);
8962 mono_loader_unlock ();
8966 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
8968 klass->image = &tb->module->dynamic_image->image;
8970 klass->inited = 1; /* we lie to the runtime */
8971 klass->name = mono_string_to_utf8_image (klass->image, tb->name);
8972 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace);
8973 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8974 klass->flags = tb->attrs;
8976 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
8978 klass->element_class = klass;
8980 MOVING_GC_REGISTER (&klass->reflection_info);
8981 klass->reflection_info = tb;
8983 /* Put into cache so mono_class_get () will find it */
8984 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8986 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8987 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8989 if (parent != NULL) {
8990 mono_class_setup_parent (klass, parent);
8991 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8992 const char *old_n = klass->name;
8993 /* trick to get relative numbering right when compiling corlib */
8994 klass->name = "BuildingObject";
8995 mono_class_setup_parent (klass, mono_defaults.object_class);
8996 klass->name = old_n;
8999 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9000 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9001 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9002 klass->instance_size = sizeof (MonoObject);
9003 klass->size_inited = 1;
9004 mono_class_setup_vtable_general (klass, NULL, 0);
9007 mono_class_setup_mono_type (klass);
9009 mono_class_setup_supertypes (klass);
9012 * FIXME: handle interfaces.
9015 tb->type.type = &klass->byval_arg;
9017 if (tb->nesting_type) {
9018 g_assert (tb->nesting_type->type);
9019 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
9022 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9024 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9026 mono_loader_unlock ();
9030 * mono_reflection_setup_generic_class:
9031 * @tb: a TypeBuilder object
9033 * Setup the generic class before adding the first generic parameter.
9036 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9041 * mono_reflection_create_generic_class:
9042 * @tb: a TypeBuilder object
9044 * Creates the generic class after all generic parameters have been added.
9047 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9052 MONO_ARCH_SAVE_REGS;
9054 klass = mono_class_from_mono_type (tb->type.type);
9056 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9058 if (klass->generic_container || (count == 0))
9061 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9063 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9065 klass->generic_container->owner.klass = klass;
9066 klass->generic_container->type_argc = count;
9067 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParam) * count);
9069 klass->is_generic = 1;
9071 for (i = 0; i < count; i++) {
9072 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9073 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
9074 /*Make sure we are a diferent type instance */
9075 klass->generic_container->type_params [i].owner = klass->generic_container;
9076 klass->generic_container->type_params [i].info.pklass = NULL;
9078 g_assert (klass->generic_container->type_params [i].owner);
9081 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9085 * mono_reflection_create_internal_class:
9086 * @tb: a TypeBuilder object
9088 * Actually create the MonoClass that is associated with the TypeBuilder.
9091 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9095 MONO_ARCH_SAVE_REGS;
9097 klass = mono_class_from_mono_type (tb->type.type);
9099 mono_loader_lock ();
9100 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9101 MonoReflectionFieldBuilder *fb;
9103 MonoType *enum_basetype;
9105 g_assert (tb->fields != NULL);
9106 g_assert (mono_array_length (tb->fields) >= 1);
9108 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9110 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb->type)->type)) {
9111 mono_loader_unlock ();
9115 enum_basetype = monotype_cast (fb->type)->type;
9116 klass->element_class = mono_class_from_mono_type (enum_basetype);
9117 if (!klass->element_class)
9118 klass->element_class = mono_class_from_mono_type (enum_basetype);
9121 * get the element_class from the current corlib.
9123 ec = default_class_from_mono_type (enum_basetype);
9124 klass->instance_size = ec->instance_size;
9125 klass->size_inited = 1;
9127 * this is almost safe to do with enums and it's needed to be able
9128 * to create objects of the enum type (for use in SetConstant).
9130 /* FIXME: Does this mean enums can't have method overrides ? */
9131 mono_class_setup_vtable_general (klass, NULL, 0);
9133 mono_loader_unlock ();
9136 #endif /* DISABLE_REFLECTION_EMIT */
9138 static MonoMarshalSpec*
9139 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9140 MonoReflectionMarshal *minfo)
9142 MonoMarshalSpec *res;
9144 res = image_g_new0 (image, MonoMarshalSpec, 1);
9145 res->native = minfo->type;
9147 switch (minfo->type) {
9148 case MONO_NATIVE_LPARRAY:
9149 res->data.array_data.elem_type = minfo->eltype;
9150 if (minfo->has_size) {
9151 res->data.array_data.param_num = minfo->param_num;
9152 res->data.array_data.num_elem = minfo->count;
9153 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9156 res->data.array_data.param_num = -1;
9157 res->data.array_data.num_elem = -1;
9158 res->data.array_data.elem_mult = -1;
9162 case MONO_NATIVE_BYVALTSTR:
9163 case MONO_NATIVE_BYVALARRAY:
9164 res->data.array_data.num_elem = minfo->count;
9167 case MONO_NATIVE_CUSTOM:
9168 if (minfo->marshaltyperef)
9169 res->data.custom_data.custom_name =
9170 type_get_fully_qualified_name (monotype_cast (minfo->marshaltyperef)->type);
9172 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9182 MonoReflectionMarshal*
9183 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9184 MonoMarshalSpec *spec)
9186 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9187 MonoReflectionMarshal *minfo;
9190 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9191 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9192 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9193 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9196 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9197 minfo->type = spec->native;
9199 switch (minfo->type) {
9200 case MONO_NATIVE_LPARRAY:
9201 minfo->eltype = spec->data.array_data.elem_type;
9202 minfo->count = spec->data.array_data.num_elem;
9203 minfo->param_num = spec->data.array_data.param_num;
9206 case MONO_NATIVE_BYVALTSTR:
9207 case MONO_NATIVE_BYVALARRAY:
9208 minfo->count = spec->data.array_data.num_elem;
9211 case MONO_NATIVE_CUSTOM:
9212 if (spec->data.custom_data.custom_name) {
9213 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
9215 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
9217 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
9219 if (spec->data.custom_data.cookie)
9220 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
9231 reflection_methodbuilder_to_mono_method (MonoClass *klass,
9232 ReflectionMethodBuilder *rmb,
9233 MonoMethodSignature *sig)
9236 MonoMethodNormal *pm;
9237 MonoMarshalSpec **specs;
9238 MonoReflectionMethodAux *method_aux;
9244 * Methods created using a MethodBuilder should have their memory allocated
9245 * inside the image mempool, while dynamic methods should have their memory
9248 dynamic = rmb->refs != NULL;
9249 image = dynamic ? NULL : klass->image;
9252 g_assert (!klass->generic_class);
9254 mono_loader_lock ();
9256 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
9257 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
9258 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
9260 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
9262 m = (MonoMethod *)image_g_new0 (image, MonoMethodNormal, 1);
9264 pm = (MonoMethodNormal*)m;
9266 m->dynamic = dynamic;
9268 m->flags = rmb->attrs;
9269 m->iflags = rmb->iattrs;
9270 m->name = mono_string_to_utf8_image (image, rmb->name);
9273 m->skip_visibility = rmb->skip_visibility;
9275 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
9277 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
9278 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
9281 m->signature->pinvoke = 1;
9282 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
9283 m->signature->pinvoke = 1;
9285 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9287 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry) : image_strdup (image, m->name);
9288 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll);
9290 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
9292 if (klass->image->dynamic)
9293 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9295 mono_loader_unlock ();
9298 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
9299 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
9300 MonoMethodHeader *header;
9302 gint32 max_stack, i;
9303 gint32 num_locals = 0;
9304 gint32 num_clauses = 0;
9308 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
9309 code_size = rmb->ilgen->code_len;
9310 max_stack = rmb->ilgen->max_stack;
9311 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
9312 if (rmb->ilgen->ex_handlers)
9313 num_clauses = method_count_clauses (rmb->ilgen);
9316 code = mono_array_addr (rmb->code, guint8, 0);
9317 code_size = mono_array_length (rmb->code);
9318 /* we probably need to run a verifier on the code... */
9328 header = image_g_malloc0 (image, sizeof (MonoMethodHeader) +
9329 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
9330 header->code_size = code_size;
9331 header->code = image_g_malloc (image, code_size);
9332 memcpy ((char*)header->code, code, code_size);
9333 header->max_stack = max_stack;
9334 header->init_locals = rmb->init_locals;
9335 header->num_locals = num_locals;
9337 for (i = 0; i < num_locals; ++i) {
9338 MonoReflectionLocalBuilder *lb =
9339 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
9341 header->locals [i] = image_g_new0 (image, MonoType, 1);
9342 memcpy (header->locals [i], monotype_cast (lb->type)->type, sizeof (MonoType));
9345 header->num_clauses = num_clauses;
9347 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
9348 rmb->ilgen, num_clauses);
9351 pm->header = header;
9354 if (rmb->generic_params) {
9355 int count = mono_array_length (rmb->generic_params);
9356 MonoGenericContainer *container;
9358 container = rmb->generic_container;
9360 m->is_generic = TRUE;
9361 mono_method_set_generic_container (m, container);
9363 container->type_argc = count;
9364 container->type_params = image_g_new0 (image, MonoGenericParam, count);
9365 container->owner.method = m;
9367 for (i = 0; i < count; i++) {
9368 MonoReflectionGenericParam *gp =
9369 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
9371 container->type_params [i] = *gp->type.type->data.generic_param;
9374 if (klass->generic_container) {
9375 container->parent = klass->generic_container;
9376 container->context.class_inst = klass->generic_container->context.class_inst;
9378 container->context.method_inst = mono_get_shared_generic_inst (container);
9382 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
9386 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
9388 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
9389 data [0] = GUINT_TO_POINTER (rmb->nrefs);
9390 for (i = 0; i < rmb->nrefs; ++i)
9391 data [i + 1] = rmb->refs [i];
9396 /* Parameter info */
9399 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9400 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
9401 for (i = 0; i <= m->signature->param_count; ++i) {
9402 MonoReflectionParamBuilder *pb;
9403 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9404 if ((i > 0) && (pb->attrs)) {
9405 /* Make a copy since it might point to a shared type structure */
9406 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
9407 m->signature->params [i - 1]->attrs = pb->attrs;
9410 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
9411 MonoDynamicImage *assembly;
9412 guint32 idx, def_type, len;
9416 if (!method_aux->param_defaults) {
9417 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
9418 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
9420 assembly = (MonoDynamicImage*)klass->image;
9421 idx = encode_constant (assembly, pb->def_value, &def_type);
9422 /* Copy the data from the blob since it might get realloc-ed */
9423 p = assembly->blob.data + idx;
9424 len = mono_metadata_decode_blob_size (p, &p2);
9426 method_aux->param_defaults [i] = image_g_malloc (image, len);
9427 method_aux->param_default_types [i] = def_type;
9428 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
9432 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name);
9434 if (!method_aux->param_cattr)
9435 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
9436 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
9442 /* Parameter marshalling */
9445 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
9446 MonoReflectionParamBuilder *pb;
9447 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
9448 if (pb->marshal_info) {
9450 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
9451 specs [pb->position] =
9452 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
9456 if (specs != NULL) {
9458 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
9459 method_aux->param_marshall = specs;
9462 if (klass->image->dynamic && method_aux)
9463 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
9465 mono_loader_unlock ();
9471 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
9473 ReflectionMethodBuilder rmb;
9474 MonoMethodSignature *sig;
9476 mono_loader_lock ();
9477 sig = ctor_builder_to_signature (klass->image, mb);
9478 mono_loader_unlock ();
9480 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
9482 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9483 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9485 /* If we are in a generic class, we might be called multiple times from inflate_method */
9486 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9487 /* ilgen is no longer needed */
9495 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
9497 ReflectionMethodBuilder rmb;
9498 MonoMethodSignature *sig;
9500 mono_loader_lock ();
9501 sig = method_builder_to_signature (klass->image, mb);
9502 mono_loader_unlock ();
9504 reflection_methodbuilder_from_method_builder (&rmb, mb);
9506 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
9507 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
9509 /* If we are in a generic class, we might be called multiple times from inflate_method */
9510 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
9511 /* ilgen is no longer needed */
9517 static MonoClassField*
9518 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
9520 MonoClassField *field;
9523 field = g_new0 (MonoClassField, 1);
9525 field->name = mono_string_to_utf8 (fb->name);
9526 if (fb->attrs || fb->modreq || fb->modopt) {
9527 field->type = mono_metadata_type_dup (NULL, monotype_cast (fb->type)->type);
9528 field->type->attrs = fb->attrs;
9530 g_assert (klass->image->dynamic);
9531 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
9532 g_free (field->type);
9533 field->type = custom;
9535 field->type = monotype_cast (fb->type)->type;
9537 if (fb->offset != -1)
9538 field->offset = fb->offset;
9539 field->parent = klass;
9540 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9542 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9548 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
9551 MonoReflectionTypeBuilder *tb = NULL;
9552 gboolean is_dynamic = FALSE;
9556 mono_loader_lock ();
9558 domain = mono_object_domain (type);
9560 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
9561 tb = (MonoReflectionTypeBuilder *) type;
9564 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
9565 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
9567 tb = rgi->generic_type;
9571 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9572 if (tb && tb->generic_container)
9573 mono_reflection_create_generic_class (tb);
9575 klass = mono_class_from_mono_type (type->type);
9576 if (!klass->generic_container) {
9577 mono_loader_unlock ();
9581 if (klass->wastypebuilder) {
9582 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
9587 mono_loader_unlock ();
9589 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
9591 return &geninst->byval_arg;
9595 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
9597 MonoGenericClass *gclass;
9598 MonoGenericInst *inst;
9600 g_assert (klass->generic_container);
9602 inst = mono_metadata_get_generic_inst (type_argc, types);
9603 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
9605 return mono_generic_class_get_class (gclass);
9608 MonoReflectionMethod*
9609 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
9612 MonoMethod *method, *inflated;
9613 MonoMethodInflated *imethod;
9614 MonoReflectionMethodBuilder *mb = NULL;
9615 MonoGenericContext tmp_context;
9616 MonoGenericInst *ginst;
9617 MonoType **type_argv;
9620 MONO_ARCH_SAVE_REGS;
9622 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
9623 #ifndef DISABLE_REFLECTION_EMIT
9624 MonoReflectionTypeBuilder *tb;
9627 mb = (MonoReflectionMethodBuilder *) rmethod;
9628 tb = (MonoReflectionTypeBuilder *) mb->type;
9629 klass = mono_class_from_mono_type (tb->type.type);
9631 method = methodbuilder_to_mono_method (klass, mb);
9633 g_assert_not_reached ();
9637 method = rmethod->method;
9640 klass = method->klass;
9642 if (method->is_inflated)
9643 method = ((MonoMethodInflated *) method)->declaring;
9645 count = mono_method_signature (method)->generic_param_count;
9646 if (count != mono_array_length (types))
9649 type_argv = g_new0 (MonoType *, count);
9650 for (i = 0; i < count; i++) {
9651 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
9652 type_argv [i] = garg->type;
9654 ginst = mono_metadata_get_generic_inst (count, type_argv);
9657 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
9658 tmp_context.method_inst = ginst;
9660 inflated = mono_class_inflate_generic_method (method, &tmp_context);
9661 imethod = (MonoMethodInflated *) inflated;
9663 if (method->klass->image->dynamic) {
9664 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9666 * This table maps metadata structures representing inflated methods/fields
9667 * to the reflection objects representing their generic definitions.
9669 mono_loader_lock ();
9670 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
9671 mono_loader_unlock ();
9674 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
9677 #ifndef DISABLE_REFLECTION_EMIT
9680 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
9682 MonoMethodInflated *imethod;
9683 MonoGenericContext *context;
9687 * With generic code sharing the klass might not be inflated.
9688 * This can happen because classes inflated with their own
9689 * type arguments are "normalized" to the uninflated class.
9691 if (!klass->generic_class)
9694 context = mono_class_get_context (klass);
9696 if (klass->method.count) {
9697 /* Find the already created inflated method */
9698 for (i = 0; i < klass->method.count; ++i) {
9699 g_assert (klass->methods [i]->is_inflated);
9700 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
9703 g_assert (i < klass->method.count);
9704 imethod = (MonoMethodInflated*)klass->methods [i];
9706 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
9709 if (method->is_generic && method->klass->image->dynamic) {
9710 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
9712 mono_loader_lock ();
9713 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
9714 mono_loader_unlock ();
9716 return (MonoMethod *) imethod;
9720 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
9725 gklass = mono_class_from_mono_type (type->generic_type->type.type);
9727 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
9728 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
9729 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
9731 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
9732 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
9733 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
9734 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
9735 method = ((MonoReflectionMethod *) obj)->method;
9737 method = NULL; /* prevent compiler warning */
9738 g_assert_not_reached ();
9741 return inflate_mono_method (mono_class_from_mono_type (type->type.type), method, obj);
9744 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9746 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
9747 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
9750 MonoGenericClass *gclass;
9751 MonoDynamicGenericClass *dgclass;
9752 MonoClass *klass, *gklass;
9755 MONO_ARCH_SAVE_REGS;
9757 klass = mono_class_from_mono_type (type->type.type);
9758 g_assert (type->type.type->type == MONO_TYPE_GENERICINST);
9759 gclass = type->type.type->data.generic_class;
9761 g_assert (gclass->is_dynamic);
9762 dgclass = (MonoDynamicGenericClass *) gclass;
9764 if (dgclass->initialized)
9767 gklass = gclass->container_class;
9768 mono_class_init (gklass);
9770 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9771 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9772 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9773 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9774 dgclass->count_events = events ? mono_array_length (events) : 0;
9776 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9777 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9778 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9779 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9780 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9781 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
9782 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
9784 for (i = 0; i < dgclass->count_methods; i++) {
9785 MonoObject *obj = mono_array_get (methods, gpointer, i);
9787 dgclass->methods [i] = inflate_method (type, obj);
9790 for (i = 0; i < dgclass->count_ctors; i++) {
9791 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9793 dgclass->ctors [i] = inflate_method (type, obj);
9796 for (i = 0; i < dgclass->count_fields; i++) {
9797 MonoObject *obj = mono_array_get (fields, gpointer, i);
9798 MonoClassField *field, *inflated_field = NULL;
9800 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9801 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9802 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9803 field = ((MonoReflectionField *) obj)->field;
9805 field = NULL; /* prevent compiler warning */
9806 g_assert_not_reached ();
9809 dgclass->fields [i] = *field;
9810 dgclass->fields [i].parent = klass;
9811 dgclass->fields [i].type = mono_class_inflate_generic_type (
9812 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
9813 dgclass->field_generic_types [i] = field->type;
9814 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
9815 dgclass->field_objects [i] = obj;
9817 if (inflated_field) {
9818 g_free (inflated_field);
9820 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
9824 for (i = 0; i < dgclass->count_properties; i++) {
9825 MonoObject *obj = mono_array_get (properties, gpointer, i);
9826 MonoProperty *property = &dgclass->properties [i];
9828 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9829 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9831 property->parent = klass;
9832 property->attrs = pb->attrs;
9833 property->name = mono_string_to_utf8 (pb->name);
9835 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9837 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9838 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9839 *property = *((MonoReflectionProperty *) obj)->property;
9840 property->name = g_strdup (property->name);
9843 property->get = inflate_mono_method (klass, property->get, NULL);
9845 property->set = inflate_mono_method (klass, property->set, NULL);
9847 g_assert_not_reached ();
9850 for (i = 0; i < dgclass->count_events; i++) {
9851 MonoObject *obj = mono_array_get (events, gpointer, i);
9852 MonoEvent *event = &dgclass->events [i];
9854 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9855 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9857 event->parent = klass;
9858 event->attrs = eb->attrs;
9859 event->name = mono_string_to_utf8 (eb->name);
9861 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9862 if (eb->remove_method)
9863 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9864 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9865 *event = *((MonoReflectionMonoEvent *) obj)->event;
9866 event->name = g_strdup (event->name);
9869 event->add = inflate_mono_method (klass, event->add, NULL);
9871 event->remove = inflate_mono_method (klass, event->remove, NULL);
9873 g_assert_not_reached ();
9876 dgclass->initialized = TRUE;
9880 ensure_generic_class_runtime_vtable (MonoClass *klass)
9882 MonoClass *gklass = klass->generic_class->container_class;
9885 if (klass->wastypebuilder)
9888 ensure_runtime_vtable (gklass);
9890 klass->method.count = gklass->method.count;
9891 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
9893 for (i = 0; i < klass->method.count; i++) {
9894 klass->methods [i] = mono_class_inflate_generic_method_full (
9895 gklass->methods [i], klass, mono_class_get_context (klass));
9898 klass->interface_count = gklass->interface_count;
9899 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9900 for (i = 0; i < klass->interface_count; ++i) {
9901 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
9902 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
9903 mono_metadata_free_type (iface_type);
9905 ensure_runtime_vtable (klass->interfaces [i]);
9907 klass->interfaces_inited = 1;
9909 /*We can only finish with this klass once it's parent has as well*/
9910 if (gklass->wastypebuilder)
9911 klass->wastypebuilder = TRUE;
9916 ensure_runtime_vtable (MonoClass *klass)
9918 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9921 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
9924 ensure_runtime_vtable (klass->parent);
9927 num = tb->ctors? mono_array_length (tb->ctors): 0;
9928 num += tb->num_methods;
9929 klass->method.count = num;
9930 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
9931 num = tb->ctors? mono_array_length (tb->ctors): 0;
9932 for (i = 0; i < num; ++i)
9933 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9934 num = tb->num_methods;
9936 for (i = 0; i < num; ++i)
9937 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9939 if (tb->interfaces) {
9940 klass->interface_count = mono_array_length (tb->interfaces);
9941 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
9942 for (i = 0; i < klass->interface_count; ++i) {
9943 MonoReflectionType *iface = mono_type_array_get (tb->interfaces, i);
9944 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9945 ensure_runtime_vtable (klass->interfaces [i]);
9947 klass->interfaces_inited = 1;
9949 } else if (klass->generic_class){
9950 ensure_generic_class_runtime_vtable (klass);
9953 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9954 for (i = 0; i < klass->method.count; ++i)
9955 klass->methods [i]->slot = i;
9957 mono_class_setup_interface_offsets (klass);
9958 mono_class_setup_interface_id (klass);
9962 * The generic vtable is needed even if image->run is not set since some
9963 * runtime code like ves_icall_Type_GetMethodsByName depends on
9964 * method->slot being defined.
9968 * tb->methods could not be freed since it is used for determining
9969 * overrides during dynamic vtable construction.
9974 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9976 MonoReflectionTypeBuilder *tb;
9982 g_assert (klass->image->dynamic);
9984 if (!klass->reflection_info)
9987 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9989 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9993 for (i = 0; i < tb->num_methods; ++i) {
9994 MonoReflectionMethodBuilder *mb =
9995 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9996 if (mb->override_method)
10002 *overrides = g_new0 (MonoMethod*, onum * 2);
10005 for (i = 0; i < tb->num_methods; ++i) {
10006 MonoReflectionMethodBuilder *mb =
10007 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10008 if (mb->override_method) {
10009 (*overrides) [onum * 2] =
10010 mb->override_method->method;
10011 (*overrides) [onum * 2 + 1] =
10014 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10015 g_assert (mb->override_method->method);
10016 g_assert (mb->mhandle);
10023 *num_overrides = onum;
10027 typebuilder_setup_fields (MonoClass *klass)
10029 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10030 MonoReflectionFieldBuilder *fb;
10031 MonoClassField *field;
10032 MonoImage *image = klass->image;
10033 const char *p, *p2;
10035 guint32 len, idx, real_size = 0;
10037 klass->field.count = tb->num_fields;
10038 klass->field.first = 0;
10040 if (tb->class_size) {
10041 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10042 klass->packing_size = tb->packing_size;
10043 real_size = klass->instance_size + tb->class_size;
10046 if (!klass->field.count) {
10047 klass->instance_size = MAX (klass->instance_size, real_size);
10051 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10052 mono_class_alloc_ext (klass);
10053 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10055 for (i = 0; i < klass->field.count; ++i) {
10056 fb = mono_array_get (tb->fields, gpointer, i);
10057 field = &klass->fields [i];
10058 field->name = mono_string_to_utf8_image (image, fb->name);
10060 field->type = mono_metadata_type_dup (klass->image, monotype_cast (fb->type)->type);
10061 field->type->attrs = fb->attrs;
10063 field->type = monotype_cast (fb->type)->type;
10065 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10066 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10067 if (fb->offset != -1)
10068 field->offset = fb->offset;
10069 field->parent = klass;
10070 fb->handle = field;
10071 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10073 if (fb->def_value) {
10074 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10075 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10076 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10077 /* Copy the data from the blob since it might get realloc-ed */
10078 p = assembly->blob.data + idx;
10079 len = mono_metadata_decode_blob_size (p, &p2);
10081 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10082 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10086 klass->instance_size = MAX (klass->instance_size, real_size);
10087 mono_class_layout_fields (klass);
10091 typebuilder_setup_properties (MonoClass *klass)
10093 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10094 MonoReflectionPropertyBuilder *pb;
10095 MonoImage *image = klass->image;
10096 MonoProperty *properties;
10100 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10102 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10103 klass->ext->property.first = 0;
10105 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10106 klass->ext->properties = properties;
10107 for (i = 0; i < klass->ext->property.count; ++i) {
10108 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10109 properties [i].parent = klass;
10110 properties [i].attrs = pb->attrs;
10111 properties [i].name = mono_string_to_utf8_image (image, pb->name);
10112 if (pb->get_method)
10113 properties [i].get = pb->get_method->mhandle;
10114 if (pb->set_method)
10115 properties [i].set = pb->set_method->mhandle;
10117 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10121 MonoReflectionEvent *
10122 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10124 MonoEvent *event = g_new0 (MonoEvent, 1);
10128 klass = mono_class_from_mono_type (tb->type.type);
10130 event->parent = klass;
10131 event->attrs = eb->attrs;
10132 event->name = mono_string_to_utf8 (eb->name);
10133 if (eb->add_method)
10134 event->add = eb->add_method->mhandle;
10135 if (eb->remove_method)
10136 event->remove = eb->remove_method->mhandle;
10137 if (eb->raise_method)
10138 event->raise = eb->raise_method->mhandle;
10140 if (eb->other_methods) {
10141 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10142 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10143 MonoReflectionMethodBuilder *mb =
10144 mono_array_get (eb->other_methods,
10145 MonoReflectionMethodBuilder*, j);
10146 event->other [j] = mb->mhandle;
10150 return mono_event_get_object (mono_object_domain (tb), klass, event);
10154 typebuilder_setup_events (MonoClass *klass)
10156 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10157 MonoReflectionEventBuilder *eb;
10158 MonoImage *image = klass->image;
10163 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10165 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
10166 klass->ext->event.first = 0;
10168 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
10169 klass->ext->events = events;
10170 for (i = 0; i < klass->ext->event.count; ++i) {
10171 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
10172 events [i].parent = klass;
10173 events [i].attrs = eb->attrs;
10174 events [i].name = mono_string_to_utf8_image (image, eb->name);
10175 if (eb->add_method)
10176 events [i].add = eb->add_method->mhandle;
10177 if (eb->remove_method)
10178 events [i].remove = eb->remove_method->mhandle;
10179 if (eb->raise_method)
10180 events [i].raise = eb->raise_method->mhandle;
10182 if (eb->other_methods) {
10183 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
10184 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10185 MonoReflectionMethodBuilder *mb =
10186 mono_array_get (eb->other_methods,
10187 MonoReflectionMethodBuilder*, j);
10188 events [i].other [j] = mb->mhandle;
10191 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
10196 remove_instantiations_of (gpointer key,
10198 gpointer user_data)
10200 MonoType *type = (MonoType*)key;
10201 MonoClass *klass = (MonoClass*)user_data;
10203 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass))
10209 MonoReflectionType*
10210 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10213 MonoDomain* domain;
10214 MonoReflectionType* res;
10217 MONO_ARCH_SAVE_REGS;
10219 domain = mono_object_domain (tb);
10220 klass = mono_class_from_mono_type (tb->type.type);
10223 * Check for user defined Type subclasses.
10225 CHECK_MONOTYPE (tb->parent);
10226 check_array_for_usertypes (tb->interfaces);
10228 for (i = 0; i < mono_array_length (tb->fields); ++i) {
10229 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
10231 CHECK_MONOTYPE (fb->type);
10232 check_array_for_usertypes (fb->modreq);
10233 check_array_for_usertypes (fb->modopt);
10234 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
10235 CHECK_MONOTYPE (fb->marshal_info->marshaltyperef);
10240 for (i = 0; i < mono_array_length (tb->methods); ++i) {
10241 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
10243 CHECK_MONOTYPE (mb->rtype);
10244 check_array_for_usertypes (mb->return_modreq);
10245 check_array_for_usertypes (mb->return_modopt);
10246 check_array_for_usertypes (mb->parameters);
10247 if (mb->param_modreq)
10248 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10249 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10250 if (mb->param_modopt)
10251 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10252 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10257 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
10258 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
10260 check_array_for_usertypes (mb->parameters);
10261 if (mb->param_modreq)
10262 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
10263 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
10264 if (mb->param_modopt)
10265 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
10266 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
10271 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
10274 * we need to lock the domain because the lock will be taken inside
10275 * So, we need to keep the locking order correct.
10277 mono_loader_lock ();
10278 mono_domain_lock (domain);
10279 if (klass->wastypebuilder) {
10280 mono_domain_unlock (domain);
10281 mono_loader_unlock ();
10282 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10285 * Fields to set in klass:
10286 * the various flags: delegate/unicode/contextbound etc.
10288 klass->flags = tb->attrs;
10289 klass->has_cctor = 1;
10290 klass->has_finalize = 1;
10293 if (!((MonoDynamicImage*)klass->image)->run) {
10294 if (klass->generic_container) {
10295 /* FIXME: The code below can't handle generic classes */
10296 klass->wastypebuilder = TRUE;
10297 mono_loader_unlock ();
10298 mono_domain_unlock (domain);
10299 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10304 /* enums are done right away */
10305 if (!klass->enumtype)
10306 ensure_runtime_vtable (klass);
10308 if (tb->subtypes) {
10309 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
10310 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
10311 mono_class_alloc_ext (klass);
10312 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtb->type.type));
10316 klass->nested_classes_inited = TRUE;
10318 /* fields and object layout */
10319 if (klass->parent) {
10320 if (!klass->parent->size_inited)
10321 mono_class_init (klass->parent);
10322 klass->instance_size = klass->parent->instance_size;
10323 klass->sizes.class_size = 0;
10324 klass->min_align = klass->parent->min_align;
10325 /* if the type has no fields we won't call the field_setup
10326 * routine which sets up klass->has_references.
10328 klass->has_references |= klass->parent->has_references;
10330 klass->instance_size = sizeof (MonoObject);
10331 klass->min_align = 1;
10334 /* FIXME: handle packing_size and instance_size */
10335 typebuilder_setup_fields (klass);
10337 typebuilder_setup_properties (klass);
10339 typebuilder_setup_events (klass);
10341 klass->wastypebuilder = TRUE;
10344 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10345 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10346 * we want to return normal System.MonoType objects, so clear these out from the cache.
10348 if (domain->type_hash && klass->generic_container)
10349 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of, klass);
10351 mono_domain_unlock (domain);
10352 mono_loader_unlock ();
10354 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
10355 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10356 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
10359 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
10360 g_assert (res != (MonoReflectionType*)tb);
10366 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10368 MonoGenericParam *param;
10372 MONO_ARCH_SAVE_REGS;
10374 param = g_new0 (MonoGenericParam, 1);
10376 if (gparam->mbuilder) {
10377 if (!gparam->mbuilder->generic_container) {
10378 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
10379 MonoClass *klass = mono_class_from_mono_type (tb->type.type);
10380 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10381 gparam->mbuilder->generic_container->is_method = TRUE;
10383 param->owner = gparam->mbuilder->generic_container;
10384 } else if (gparam->tbuilder) {
10385 if (!gparam->tbuilder->generic_container) {
10386 MonoClass *klass = mono_class_from_mono_type (gparam->tbuilder->type.type);
10387 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10388 gparam->tbuilder->generic_container->owner.klass = klass;
10390 param->owner = gparam->tbuilder->generic_container;
10393 param->info.name = mono_string_to_utf8 (gparam->name);
10394 param->num = gparam->index;
10396 image = &gparam->tbuilder->module->dynamic_image->image;
10397 pklass = mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
10399 gparam->type.type = &pklass->byval_arg;
10401 MOVING_GC_REGISTER (&pklass->reflection_info);
10402 pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
10406 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10408 MonoDynamicImage *assembly = sig->module->dynamic_image;
10409 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10414 check_array_for_usertypes (sig->arguments);
10416 sigbuffer_init (&buf, 32);
10418 sigbuffer_add_value (&buf, 0x07);
10419 sigbuffer_add_value (&buf, na);
10420 for (i = 0; i < na; ++i) {
10421 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10422 encode_reflection_type (assembly, type, &buf);
10425 buflen = buf.p - buf.buf;
10426 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10427 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10428 sigbuffer_free (&buf);
10434 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10436 MonoDynamicImage *assembly = sig->module->dynamic_image;
10437 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
10442 check_array_for_usertypes (sig->arguments);
10444 sigbuffer_init (&buf, 32);
10446 sigbuffer_add_value (&buf, 0x06);
10447 for (i = 0; i < na; ++i) {
10448 MonoReflectionType *type = mono_type_array_get (sig->arguments, i);
10449 encode_reflection_type (assembly, type, &buf);
10452 buflen = buf.p - buf.buf;
10453 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10454 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
10455 sigbuffer_free (&buf);
10461 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10463 ReflectionMethodBuilder rmb;
10464 MonoMethodSignature *sig;
10469 sig = dynamic_method_to_signature (mb);
10471 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
10474 * Resolve references.
10477 * Every second entry in the refs array is reserved for storing handle_class,
10478 * which is needed by the ldtoken implementation in the JIT.
10480 rmb.nrefs = mb->nrefs;
10481 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
10482 for (i = 0; i < mb->nrefs; i += 2) {
10483 MonoClass *handle_class;
10485 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
10487 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10488 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10490 * The referenced DynamicMethod should already be created by the managed
10491 * code, except in the case of circular references. In that case, we store
10492 * method in the refs array, and fix it up later when the referenced
10493 * DynamicMethod is created.
10495 if (method->mhandle) {
10496 ref = method->mhandle;
10498 /* FIXME: GC object stored in unmanaged memory */
10501 /* FIXME: GC object stored in unmanaged memory */
10502 method->referenced_by = g_slist_append (method->referenced_by, mb);
10504 handle_class = mono_defaults.methodhandle_class;
10506 MonoException *ex = NULL;
10507 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
10509 ex = mono_get_exception_type_load (NULL, NULL);
10510 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
10511 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
10515 mono_raise_exception (ex);
10520 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10521 rmb.refs [i + 1] = handle_class;
10524 klass = mb->owner ? mono_class_from_mono_type (mb->owner->type) : mono_defaults.object_class;
10526 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10528 /* Fix up refs entries pointing at us */
10529 for (l = mb->referenced_by; l; l = l->next) {
10530 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
10531 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
10534 g_assert (method->mhandle);
10536 data = (gpointer*)wrapper->method_data;
10537 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
10538 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
10539 data [i + 1] = mb->mhandle;
10542 g_slist_free (mb->referenced_by);
10546 /* ilgen is no longer needed */
10550 #endif /* DISABLE_REFLECTION_EMIT */
10553 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
10558 mono_runtime_free_method (
10559 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
10564 * mono_reflection_is_valid_dynamic_token:
10566 * Returns TRUE if token is valid.
10570 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
10572 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
10575 #ifndef DISABLE_REFLECTION_EMIT
10578 * mono_reflection_lookup_dynamic_token:
10580 * Finish the Builder object pointed to by TOKEN and return the corresponding
10581 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10582 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10585 * LOCKING: Take the loader lock
10588 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10590 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
10594 mono_loader_lock ();
10595 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
10596 mono_loader_unlock ();
10599 g_assert_not_reached ();
10605 handle_class = &klass;
10606 return resolve_object (image, obj, handle_class, context);
10610 * ensure_complete_type:
10612 * Ensure that KLASS is completed if it is a dynamic type, or references
10616 ensure_complete_type (MonoClass *klass)
10618 if (klass->image->dynamic && !klass->wastypebuilder) {
10619 MonoReflectionTypeBuilder *tb = klass->reflection_info;
10621 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10623 // Asserting here could break a lot of code
10624 //g_assert (klass->wastypebuilder);
10627 if (klass->generic_class) {
10628 MonoGenericInst *inst = klass->generic_class->context.class_inst;
10631 for (i = 0; i < inst->type_argc; ++i) {
10632 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
10638 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
10640 gpointer result = NULL;
10642 if (strcmp (obj->vtable->klass->name, "String") == 0) {
10643 result = mono_string_intern ((MonoString*)obj);
10644 *handle_class = NULL;
10646 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
10647 MonoReflectionType *tb = (MonoReflectionType*)obj;
10649 MonoType *inflated = mono_class_inflate_generic_type (tb->type, context);
10650 result = mono_class_from_mono_type (inflated);
10651 mono_metadata_free_type (inflated);
10653 result = mono_class_from_mono_type (tb->type);
10655 *handle_class = mono_defaults.typehandle_class;
10657 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
10658 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
10659 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
10660 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
10661 result = ((MonoReflectionMethod*)obj)->method;
10663 result = mono_class_inflate_generic_method (result, context);
10664 *handle_class = mono_defaults.methodhandle_class;
10666 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
10667 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10668 result = mb->mhandle;
10670 /* Type is not yet created */
10671 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
10673 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10676 * Hopefully this has been filled in by calling CreateType() on the
10680 * TODO: This won't work if the application finishes another
10681 * TypeBuilder instance instead of this one.
10683 result = mb->mhandle;
10686 result = mono_class_inflate_generic_method (result, context);
10687 *handle_class = mono_defaults.methodhandle_class;
10688 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
10689 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10691 result = cb->mhandle;
10693 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
10695 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10696 result = cb->mhandle;
10699 result = mono_class_inflate_generic_method (result, context);
10700 *handle_class = mono_defaults.methodhandle_class;
10701 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
10702 MonoClassField *field = ((MonoReflectionField*)obj)->field;
10704 ensure_complete_type (field->parent);
10706 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
10707 MonoClass *class = mono_class_from_mono_type (inflated);
10708 MonoClassField *inflated_field;
10709 gpointer iter = NULL;
10710 mono_metadata_free_type (inflated);
10711 while ((inflated_field = mono_class_get_fields (class, &iter))) {
10712 if (!strcmp (field->name, inflated_field->name))
10715 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
10716 result = inflated_field;
10720 *handle_class = mono_defaults.fieldhandle_class;
10722 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
10723 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10724 result = fb->handle;
10727 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
10729 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10730 result = fb->handle;
10733 if (fb->handle && fb->handle->parent->generic_container) {
10734 MonoClass *klass = fb->handle->parent;
10735 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
10736 MonoClass *inflated = mono_class_from_mono_type (type);
10738 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
10740 mono_metadata_free_type (type);
10742 *handle_class = mono_defaults.fieldhandle_class;
10743 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
10744 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10747 klass = tb->type.type->data.klass;
10748 if (klass->wastypebuilder) {
10749 /* Already created */
10753 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
10754 result = tb->type.type->data.klass;
10757 *handle_class = mono_defaults.typehandle_class;
10758 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
10759 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
10760 MonoMethodSignature *sig;
10763 if (helper->arguments)
10764 nargs = mono_array_length (helper->arguments);
10768 sig = mono_metadata_signature_alloc (image, nargs);
10769 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
10770 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
10772 if (helper->call_conv == 0) /* unmanaged */
10773 sig->call_convention = helper->unmanaged_call_conv - 1;
10775 if (helper->call_conv & 0x02)
10776 sig->call_convention = MONO_CALL_VARARG;
10778 sig->call_convention = MONO_CALL_DEFAULT;
10780 sig->param_count = nargs;
10781 /* TODO: Copy type ? */
10782 sig->ret = helper->return_type->type;
10783 for (i = 0; i < nargs; ++i) {
10784 MonoReflectionType *rt = mono_type_array_get (helper->arguments, i);
10785 sig->params [i] = rt->type;
10789 *handle_class = NULL;
10790 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
10791 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
10792 /* Already created by the managed code */
10793 g_assert (method->mhandle);
10794 result = method->mhandle;
10795 *handle_class = mono_defaults.methodhandle_class;
10796 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
10797 MonoReflectionType *tb = (MonoReflectionType*)obj;
10798 MonoType *type = mono_class_inflate_generic_type (tb->type, context);
10799 result = mono_class_from_mono_type (type);
10800 *handle_class = mono_defaults.typehandle_class;
10802 mono_metadata_free_type (type);
10803 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
10804 MonoReflectionGenericClass *ref = (MonoReflectionGenericClass*)obj;
10805 MonoType *type = mono_class_inflate_generic_type (ref->type.type, context);
10806 result = mono_class_from_mono_type (type);
10807 *handle_class = mono_defaults.typehandle_class;
10809 mono_metadata_free_type (type);
10810 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
10811 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
10812 MonoClass *inflated;
10815 type = mono_class_inflate_generic_type (f->inst->type.type, context);
10816 inflated = mono_class_from_mono_type (type);
10818 g_assert (f->fb->handle);
10819 result = mono_class_get_field_from_name (inflated, mono_field_get_name (f->fb->handle));
10821 mono_metadata_free_type (type);
10822 *handle_class = mono_defaults.fieldhandle_class;
10823 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
10824 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
10825 MonoType *type = mono_class_inflate_generic_type (c->inst->type.type, context);
10826 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10827 g_assert (c->cb->mhandle);
10828 result = inflate_mono_method (inflated_klass, c->cb->mhandle, (MonoObject*)c->cb);
10829 *handle_class = mono_defaults.methodhandle_class;
10830 mono_metadata_free_type (type);
10831 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
10832 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
10833 MonoType *type = mono_class_inflate_generic_type (m->inst->type.type, context);
10834 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10835 g_assert (m->mb->mhandle);
10836 result = inflate_mono_method (inflated_klass, m->mb->mhandle, (MonoObject*)m->mb);
10837 *handle_class = mono_defaults.methodhandle_class;
10838 mono_metadata_free_type (type);
10840 g_print (obj->vtable->klass->name);
10841 g_assert_not_reached ();
10846 #else /* DISABLE_REFLECTION_EMIT */
10849 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
10851 g_assert_not_reached ();
10856 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10858 g_assert_not_reached ();
10862 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10864 g_assert_not_reached ();
10868 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10870 g_assert_not_reached ();
10874 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10876 g_assert_not_reached ();
10880 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
10882 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10886 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
10888 g_assert_not_reached ();
10891 MonoReflectionModule *
10892 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
10894 g_assert_not_reached ();
10899 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
10901 g_assert_not_reached ();
10906 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
10908 g_assert_not_reached ();
10913 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
10914 gboolean create_methodspec, gboolean register_token)
10916 g_assert_not_reached ();
10921 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
10926 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10927 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10930 g_assert_not_reached ();
10934 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10937 *num_overrides = 0;
10940 MonoReflectionEvent *
10941 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10943 g_assert_not_reached ();
10947 MonoReflectionType*
10948 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
10950 g_assert_not_reached ();
10955 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
10957 g_assert_not_reached ();
10961 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
10963 g_assert_not_reached ();
10968 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
10970 g_assert_not_reached ();
10975 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
10980 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
10985 #endif /* DISABLE_REFLECTION_EMIT */
10987 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10988 const static guint32 declsec_flags_map[] = {
10989 0x00000000, /* empty */
10990 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
10991 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
10992 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
10993 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
10994 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
10995 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
10996 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10997 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10998 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10999 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11000 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11001 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11002 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11003 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11004 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11005 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11006 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11007 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11011 * Returns flags that includes all available security action associated to the handle.
11012 * @token: metadata token (either for a class or a method)
11013 * @image: image where resides the metadata.
11016 mono_declsec_get_flags (MonoImage *image, guint32 token)
11018 int index = mono_metadata_declsec_from_index (image, token);
11019 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
11020 guint32 result = 0;
11024 /* HasSecurity can be present for other, not specially encoded, attributes,
11025 e.g. SuppressUnmanagedCodeSecurityAttribute */
11029 for (i = index; i < t->rows; i++) {
11030 guint32 cols [MONO_DECL_SECURITY_SIZE];
11032 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11033 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11036 action = cols [MONO_DECL_SECURITY_ACTION];
11037 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
11038 result |= declsec_flags_map [action];
11040 g_assert_not_reached ();
11047 * Get the security actions (in the form of flags) associated with the specified method.
11049 * @method: The method for which we want the declarative security flags.
11050 * Return the declarative security flags for the method (only).
11052 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11053 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11056 mono_declsec_flags_from_method (MonoMethod *method)
11058 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11059 /* FIXME: No cache (for the moment) */
11060 guint32 idx = mono_method_get_index (method);
11061 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11062 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11063 return mono_declsec_get_flags (method->klass->image, idx);
11069 * Get the security actions (in the form of flags) associated with the specified class.
11071 * @klass: The class for which we want the declarative security flags.
11072 * Return the declarative security flags for the class.
11074 * Note: We cache the flags inside the MonoClass structure as this will get
11075 * called very often (at least for each method).
11078 mono_declsec_flags_from_class (MonoClass *klass)
11080 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
11081 if (!klass->ext || !klass->ext->declsec_flags) {
11084 idx = mono_metadata_token_index (klass->type_token);
11085 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11086 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11087 mono_loader_lock ();
11088 mono_class_alloc_ext (klass);
11089 mono_loader_unlock ();
11090 /* we cache the flags on classes */
11091 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
11093 return klass->ext->declsec_flags;
11099 * Get the security actions (in the form of flags) associated with the specified assembly.
11101 * @assembly: The assembly for which we want the declarative security flags.
11102 * Return the declarative security flags for the assembly.
11105 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
11107 guint32 idx = 1; /* there is only one assembly */
11108 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11109 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11110 return mono_declsec_get_flags (assembly->image, idx);
11115 * Fill actions for the specific index (which may either be an encoded class token or
11116 * an encoded method token) from the metadata image.
11117 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11120 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
11121 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11123 MonoBoolean result = FALSE;
11125 guint32 cols [MONO_DECL_SECURITY_SIZE];
11126 int index = mono_metadata_declsec_from_index (image, token);
11129 t = &image->tables [MONO_TABLE_DECLSECURITY];
11130 for (i = index; i < t->rows; i++) {
11131 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11133 if (cols [MONO_DECL_SECURITY_PARENT] != token)
11136 /* if present only replace (class) permissions with method permissions */
11137 /* if empty accept either class or method permissions */
11138 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
11139 if (!actions->demand.blob) {
11140 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11141 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11142 actions->demand.blob = (char*) (blob + 2);
11143 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
11146 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
11147 if (!actions->noncasdemand.blob) {
11148 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11149 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11150 actions->noncasdemand.blob = (char*) (blob + 2);
11151 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
11154 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
11155 if (!actions->demandchoice.blob) {
11156 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11157 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
11158 actions->demandchoice.blob = (char*) (blob + 2);
11159 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
11169 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
11170 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11172 guint32 idx = mono_metadata_token_index (klass->type_token);
11173 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11174 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11175 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
11179 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
11180 guint32 id_std, guint32 id_noncas, guint32 id_choice)
11182 guint32 idx = mono_method_get_index (method);
11183 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11185 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
11189 * Collect all actions (that requires to generate code in mini) assigned for
11190 * the specified method.
11191 * Note: Don't use the content of actions if the function return FALSE.
11194 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
11196 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
11197 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
11198 MonoBoolean result = FALSE;
11201 /* quick exit if no declarative security is present in the metadata */
11202 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11205 /* we want the original as the wrapper is "free" of the security informations */
11206 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11207 method = mono_marshal_method_from_wrapper (method);
11212 /* First we look for method-level attributes */
11213 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11214 mono_class_init (method->klass);
11215 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11217 result = mono_declsec_get_method_demands_params (method, demands,
11218 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11221 /* Here we use (or create) the class declarative cache to look for demands */
11222 flags = mono_declsec_flags_from_class (method->klass);
11223 if (flags & mask) {
11225 mono_class_init (method->klass);
11226 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11228 result |= mono_declsec_get_class_demands_params (method->klass, demands,
11229 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
11232 /* The boolean return value is used as a shortcut in case nothing needs to
11233 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11239 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11241 * Note: Don't use the content of actions if the function return FALSE.
11244 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
11246 MonoBoolean result = FALSE;
11249 /* quick exit if no declarative security is present in the metadata */
11250 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11253 /* we want the original as the wrapper is "free" of the security informations */
11254 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11255 method = mono_marshal_method_from_wrapper (method);
11260 /* results are independant - zeroize both */
11261 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
11262 memset (klass, 0, sizeof (MonoDeclSecurityActions));
11264 /* First we look for method-level attributes */
11265 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11266 mono_class_init (method->klass);
11268 result = mono_declsec_get_method_demands_params (method, cmethod,
11269 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11272 /* Here we use (or create) the class declarative cache to look for demands */
11273 flags = mono_declsec_flags_from_class (method->klass);
11274 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
11275 mono_class_init (method->klass);
11277 result |= mono_declsec_get_class_demands_params (method->klass, klass,
11278 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
11285 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11287 * @klass The inherited class - this is the class that provides the security check (attributes)
11289 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11291 * Note: Don't use the content of actions if the function return FALSE.
11294 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
11296 MonoBoolean result = FALSE;
11299 /* quick exit if no declarative security is present in the metadata */
11300 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11303 /* Here we use (or create) the class declarative cache to look for demands */
11304 flags = mono_declsec_flags_from_class (klass);
11305 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
11306 mono_class_init (klass);
11307 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11309 result |= mono_declsec_get_class_demands_params (klass, demands,
11310 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11317 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11319 * Note: Don't use the content of actions if the function return FALSE.
11322 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
11324 /* quick exit if no declarative security is present in the metadata */
11325 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
11328 /* we want the original as the wrapper is "free" of the security informations */
11329 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
11330 method = mono_marshal_method_from_wrapper (method);
11335 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11336 mono_class_init (method->klass);
11337 memset (demands, 0, sizeof (MonoDeclSecurityActions));
11339 return mono_declsec_get_method_demands_params (method, demands,
11340 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
11347 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
11349 guint32 cols [MONO_DECL_SECURITY_SIZE];
11353 int index = mono_metadata_declsec_from_index (image, token);
11357 t = &image->tables [MONO_TABLE_DECLSECURITY];
11358 for (i = index; i < t->rows; i++) {
11359 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
11361 /* shortcut - index are ordered */
11362 if (token != cols [MONO_DECL_SECURITY_PARENT])
11365 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
11366 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
11367 entry->blob = (char*) (metadata + 2);
11368 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
11377 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
11379 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
11380 guint32 idx = mono_method_get_index (method);
11381 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11382 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
11383 return get_declsec_action (method->klass->image, idx, action, entry);
11389 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
11392 guint32 flags = mono_declsec_flags_from_class (klass);
11393 if (declsec_flags_map [action] & flags) {
11394 guint32 idx = mono_metadata_token_index (klass->type_token);
11395 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11396 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
11397 return get_declsec_action (klass->image, idx, action, entry);
11403 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
11405 guint32 idx = 1; /* there is only one assembly */
11406 idx <<= MONO_HAS_DECL_SECURITY_BITS;
11407 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
11409 return get_declsec_action (assembly->image, idx, action, entry);
11413 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
11415 MonoObject *res, *exc;
11417 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
11418 static MonoMethod *method = NULL;
11420 if (!System_Reflection_Emit_TypeBuilder) {
11421 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
11422 g_assert (System_Reflection_Emit_TypeBuilder);
11424 if (method == NULL) {
11425 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
11430 * The result of mono_type_get_object () might be a System.MonoType but we
11431 * need a TypeBuilder so use klass->reflection_info.
11433 g_assert (klass->reflection_info);
11434 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
11436 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
11438 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
11442 return *(MonoBoolean*)mono_object_unbox (res);