2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/marshal.h>
23 #include <mono/metadata/security-manager.h>
32 #include "rawbuffer.h"
33 #include "mono-endian.h"
34 #include <mono/os/gc_wrapper.h>
36 #define TEXT_OFFSET 512
37 #define CLI_H_SIZE 136
38 #define FILE_ALIGN 512
39 #define VIRT_ALIGN 8192
40 #define START_TEXT_RVA 0x00002000
43 MonoReflectionILGen *ilgen;
44 MonoReflectionType *rtype;
45 MonoArray *parameters;
46 MonoArray *generic_params;
47 MonoGenericContainer *generic_container;
53 guint32 *table_idx; /* note: it's a pointer */
57 MonoBoolean init_locals;
58 MonoArray *return_modreq;
59 MonoArray *return_modopt;
60 MonoArray *param_modreq;
61 MonoArray *param_modopt;
62 MonoArray *permissions;
67 int charset, extra_flags, native_cc;
68 MonoString *dll, *dllentry;
69 } ReflectionMethodBuilder;
73 MonoReflectionGenericParam *gparam;
74 } GenericParamTableEntry;
76 const unsigned char table_sizes [MONO_TABLE_NUM] = {
86 MONO_INTERFACEIMPL_SIZE,
87 MONO_MEMBERREF_SIZE, /* 0x0A */
89 MONO_CUSTOM_ATTR_SIZE,
90 MONO_FIELD_MARSHAL_SIZE,
91 MONO_DECL_SECURITY_SIZE,
92 MONO_CLASS_LAYOUT_SIZE,
93 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
94 MONO_STAND_ALONE_SIGNATURE_SIZE,
98 MONO_PROPERTY_MAP_SIZE,
101 MONO_METHOD_SEMA_SIZE,
102 MONO_METHODIMPL_SIZE,
103 MONO_MODULEREF_SIZE, /* 0x1A */
109 MONO_ASSEMBLY_SIZE, /* 0x20 */
110 MONO_ASSEMBLY_PROCESSOR_SIZE,
111 MONO_ASSEMBLYOS_SIZE,
112 MONO_ASSEMBLYREF_SIZE,
113 MONO_ASSEMBLYREFPROC_SIZE,
114 MONO_ASSEMBLYREFOS_SIZE,
118 MONO_NESTED_CLASS_SIZE,
120 MONO_GENERICPARAM_SIZE, /* 0x2A */
121 MONO_METHODSPEC_SIZE,
122 MONO_GENPARCONSTRAINT_SIZE
126 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
127 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
128 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
129 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
130 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
131 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
132 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
133 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
134 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
135 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
136 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
137 static void ensure_runtime_vtable (MonoClass *klass);
138 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
139 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
140 static guint32 type_get_signature_size (MonoType *type);
141 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
142 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
143 static inline MonoType *dup_type (const MonoType *original);
146 alloc_table (MonoDynamicTable *table, guint nrows)
149 g_assert (table->columns);
150 if (nrows + 1 >= table->alloc_rows) {
151 while (nrows + 1 >= table->alloc_rows) {
152 if (table->alloc_rows == 0)
153 table->alloc_rows = 16;
155 table->alloc_rows *= 2;
158 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
163 make_room_in_stream (MonoDynamicStream *stream, int size)
165 if (size <= stream->alloc_size)
168 while (stream->alloc_size <= size) {
169 if (stream->alloc_size < 4096)
170 stream->alloc_size = 4096;
172 stream->alloc_size *= 2;
175 stream->data = g_realloc (stream->data, stream->alloc_size);
179 string_heap_insert (MonoDynamicStream *sh, const char *str)
183 gpointer oldkey, oldval;
185 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
186 return GPOINTER_TO_UINT (oldval);
188 len = strlen (str) + 1;
191 make_room_in_stream (sh, idx + len);
194 * We strdup the string even if we already copy them in sh->data
195 * so that the string pointers in the hash remain valid even if
196 * we need to realloc sh->data. We may want to avoid that later.
198 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
199 memcpy (sh->data + idx, str, len);
205 string_heap_init (MonoDynamicStream *sh)
208 sh->alloc_size = 4096;
209 sh->data = g_malloc (4096);
210 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
211 string_heap_insert (sh, "");
215 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
219 make_room_in_stream (stream, stream->index + len);
220 memcpy (stream->data + stream->index, data, len);
222 stream->index += len;
224 * align index? Not without adding an additional param that controls it since
225 * we may store a blob value in pieces.
231 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
235 make_room_in_stream (stream, stream->index + len);
236 memset (stream->data + stream->index, 0, len);
238 stream->index += len;
243 stream_data_align (MonoDynamicStream *stream)
246 guint32 count = stream->index % 4;
248 /* we assume the stream data will be aligned */
250 mono_image_add_stream_data (stream, buf, 4 - count);
254 mono_blob_entry_hash (const char* str)
258 len = mono_metadata_decode_blob_size (str, &str);
262 for (str += 1; str < end; str++)
263 h = (h << 5) - h + *str;
271 mono_blob_entry_equal (const char *str1, const char *str2) {
275 len = mono_metadata_decode_blob_size (str1, &end1);
276 len2 = mono_metadata_decode_blob_size (str2, &end2);
279 return memcmp (end1, end2, len) == 0;
283 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
287 gpointer oldkey, oldval;
289 copy = g_malloc (s1+s2);
290 memcpy (copy, b1, s1);
291 memcpy (copy + s1, b2, s2);
292 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
294 idx = GPOINTER_TO_UINT (oldval);
296 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
297 mono_image_add_stream_data (&assembly->blob, b2, s2);
298 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
304 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
305 * dest may be misaligned.
308 swap_with_size (char *dest, const char* val, int len, int nelem) {
309 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
312 for (elem = 0; elem < nelem; ++elem) {
338 g_assert_not_reached ();
344 memcpy (dest, val, len * nelem);
349 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
353 guint32 idx = 0, len;
355 len = str->length * 2;
356 mono_metadata_encode_value (len, b, &b);
357 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
359 char *swapped = g_malloc (2 * mono_string_length (str));
360 const char *p = (const char*)mono_string_chars (str);
362 swap_with_size (swapped, p, 2, mono_string_length (str));
363 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
367 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
372 /* modified version needed to handle building corlib */
374 my_mono_class_from_mono_type (MonoType *type) {
375 switch (type->type) {
376 case MONO_TYPE_ARRAY:
378 case MONO_TYPE_SZARRAY:
379 case MONO_TYPE_GENERICINST:
380 return mono_class_from_mono_type (type);
383 g_assert (type->data.generic_param->pklass);
384 return type->data.generic_param->pklass;
386 /* should be always valid when we reach this case... */
387 return type->data.klass;
392 default_class_from_mono_type (MonoType *type)
394 switch (type->type) {
395 case MONO_TYPE_OBJECT:
396 return mono_defaults.object_class;
398 return mono_defaults.void_class;
399 case MONO_TYPE_BOOLEAN:
400 return mono_defaults.boolean_class;
402 return mono_defaults.char_class;
404 return mono_defaults.sbyte_class;
406 return mono_defaults.byte_class;
408 return mono_defaults.int16_class;
410 return mono_defaults.uint16_class;
412 return mono_defaults.int32_class;
414 return mono_defaults.uint32_class;
416 return mono_defaults.int_class;
418 return mono_defaults.uint_class;
420 return mono_defaults.int64_class;
422 return mono_defaults.uint64_class;
424 return mono_defaults.single_class;
426 return mono_defaults.double_class;
427 case MONO_TYPE_STRING:
428 return mono_defaults.string_class;
430 g_warning ("implement me 0x%02x\n", type->type);
431 g_assert_not_reached ();
438 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
443 g_assert_not_reached ();
447 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
448 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
449 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
450 for (i = 0; i < gclass->inst->type_argc; ++i)
451 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
457 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
460 g_assert_not_reached ();
465 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
469 case MONO_TYPE_BOOLEAN:
483 case MONO_TYPE_STRING:
484 case MONO_TYPE_OBJECT:
485 case MONO_TYPE_TYPEDBYREF:
486 mono_metadata_encode_value (type->type, p, &p);
489 mono_metadata_encode_value (type->type, p, &p);
490 encode_type (assembly, type->data.type, p, &p);
492 case MONO_TYPE_SZARRAY:
493 mono_metadata_encode_value (type->type, p, &p);
494 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
496 case MONO_TYPE_VALUETYPE:
497 case MONO_TYPE_CLASS: {
498 MonoClass *k = mono_class_from_mono_type (type);
500 * Make sure we use the correct type.
502 mono_metadata_encode_value (k->byval_arg.type, p, &p);
504 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
505 * otherwise two typerefs could point to the same type, leading to
506 * verification errors.
508 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
511 case MONO_TYPE_ARRAY:
512 mono_metadata_encode_value (type->type, p, &p);
513 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
514 mono_metadata_encode_value (type->data.array->rank, p, &p);
515 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
516 mono_metadata_encode_value (0, p, &p);
518 case MONO_TYPE_GENERICINST:
519 encode_generic_class (assembly, type->data.generic_class, p, &p);
523 mono_metadata_encode_value (type->type, p, &p);
524 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
527 g_error ("need to encode type %x", type->type);
533 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
536 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
540 encode_type (assembly, type->type, p, endbuf);
544 g_assert_not_reached ();
549 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
554 for (i = 0; i < mono_array_length (modreq); ++i) {
555 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
556 *p = MONO_TYPE_CMOD_REQD;
558 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
562 for (i = 0; i < mono_array_length (modopt); ++i) {
563 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
564 *p = MONO_TYPE_CMOD_OPT;
566 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
573 generic_class_get_signature_size (MonoGenericClass *gclass)
579 g_assert_not_reached ();
582 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
584 for (i = 0; i < gclass->inst->type_argc; ++i)
585 size += type_get_signature_size (gclass->inst->type_argv [i]);
591 type_get_signature_size (MonoType *type)
596 g_assert_not_reached ();
604 case MONO_TYPE_BOOLEAN:
618 case MONO_TYPE_STRING:
619 case MONO_TYPE_OBJECT:
620 case MONO_TYPE_TYPEDBYREF:
623 return size + 1 + type_get_signature_size (type->data.type);
624 case MONO_TYPE_SZARRAY:
625 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
626 case MONO_TYPE_VALUETYPE:
627 case MONO_TYPE_CLASS:
629 case MONO_TYPE_ARRAY:
630 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
631 case MONO_TYPE_GENERICINST:
632 return size + generic_class_get_signature_size (type->data.generic_class);
637 g_error ("need to encode type %x", type->type);
643 method_get_signature_size (MonoMethodSignature *sig)
648 size = type_get_signature_size (sig->ret);
649 for (i = 0; i < sig->param_count; i++)
650 size += type_get_signature_size (sig->params [i]);
652 if (sig->generic_param_count)
654 if (sig->sentinelpos >= 0)
661 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
666 guint32 nparams = sig->param_count;
667 guint32 size = 11 + method_get_signature_size (sig);
675 p = buf = g_malloc (size);
677 * FIXME: vararg, explicit_this, differenc call_conv values...
679 *p = sig->call_convention;
681 *p |= 0x20; /* hasthis */
682 if (sig->generic_param_count)
683 *p |= 0x10; /* generic */
685 if (sig->generic_param_count)
686 mono_metadata_encode_value (sig->generic_param_count, p, &p);
687 mono_metadata_encode_value (nparams, p, &p);
688 encode_type (assembly, sig->ret, p, &p);
689 for (i = 0; i < nparams; ++i) {
690 if (i == sig->sentinelpos)
691 *p++ = MONO_TYPE_SENTINEL;
692 encode_type (assembly, sig->params [i], p, &p);
695 g_assert (p - buf < size);
696 mono_metadata_encode_value (p-buf, b, &b);
697 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
703 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
706 * FIXME: reuse code from method_encode_signature().
711 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
712 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
713 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
714 guint32 size = 41 + nparams * 40 + notypes * 40;
719 p = buf = g_malloc (size);
720 /* LAMESPEC: all the call conv spec is foobared */
721 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
722 if (mb->call_conv & 2)
723 *p |= 0x5; /* vararg */
724 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
725 *p |= 0x20; /* hasthis */
727 *p |= 0x10; /* generic */
730 mono_metadata_encode_value (ngparams, p, &p);
731 mono_metadata_encode_value (nparams + notypes, p, &p);
732 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
733 encode_reflection_type (assembly, mb->rtype, p, &p);
734 for (i = 0; i < nparams; ++i) {
735 MonoArray *modreq = NULL;
736 MonoArray *modopt = NULL;
737 MonoReflectionType *pt;
739 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
740 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
741 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
742 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
743 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
744 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
745 encode_reflection_type (assembly, pt, p, &p);
748 *p++ = MONO_TYPE_SENTINEL;
749 for (i = 0; i < notypes; ++i) {
750 MonoReflectionType *pt;
752 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
753 encode_reflection_type (assembly, pt, p, &p);
757 g_assert (p - buf < size);
758 mono_metadata_encode_value (p-buf, b, &b);
759 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
765 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
767 MonoDynamicTable *table;
770 guint32 idx, sig_idx, size;
771 guint nl = mono_array_length (ilgen->locals);
778 p = buf = g_malloc (size);
779 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
780 idx = table->next_idx ++;
782 alloc_table (table, table->rows);
783 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
785 mono_metadata_encode_value (0x07, p, &p);
786 mono_metadata_encode_value (nl, p, &p);
787 for (i = 0; i < nl; ++i) {
788 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
791 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
793 encode_reflection_type (assembly, lb->type, p, &p);
795 g_assert (p - buf < size);
796 mono_metadata_encode_value (p-buf, b, &b);
797 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
800 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
806 method_count_clauses (MonoReflectionILGen *ilgen)
808 guint32 num_clauses = 0;
811 MonoILExceptionInfo *ex_info;
812 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
813 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
814 if (ex_info->handlers)
815 num_clauses += mono_array_length (ex_info->handlers);
823 static MonoExceptionClause*
824 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
826 MonoExceptionClause *clauses;
827 MonoExceptionClause *clause;
828 MonoILExceptionInfo *ex_info;
829 MonoILExceptionBlock *ex_block;
830 guint32 finally_start;
831 int i, j, clause_index;;
833 clauses = g_new0 (MonoExceptionClause, num_clauses);
836 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
837 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
838 finally_start = ex_info->start + ex_info->len;
839 g_assert (ex_info->handlers);
840 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
841 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
842 clause = &(clauses [clause_index]);
844 clause->flags = ex_block->type;
845 clause->try_offset = ex_info->start;
847 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
848 clause->try_len = finally_start - ex_info->start;
850 clause->try_len = ex_info->len;
851 clause->handler_offset = ex_block->start;
852 clause->handler_len = ex_block->len;
853 if (ex_block->extype) {
854 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
856 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
857 clause->data.filter_offset = ex_block->filter_offset;
859 clause->data.filter_offset = 0;
861 finally_start = ex_block->start + ex_block->len;
871 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
877 gint32 num_locals = 0;
878 gint32 num_exception = 0;
881 char fat_header [12];
884 guint32 local_sig = 0;
885 guint32 header_size = 12;
888 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
889 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
893 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
895 code = mb->ilgen->code;
896 code_size = mb->ilgen->code_len;
897 max_stack = mb->ilgen->max_stack;
898 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
899 if (mb->ilgen->ex_handlers)
900 num_exception = method_count_clauses (mb->ilgen);
904 char *name = mono_string_to_utf8 (mb->name);
905 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
906 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
909 mono_raise_exception (exception);
912 code_size = mono_array_length (code);
913 max_stack = 8; /* we probably need to run a verifier on the code... */
916 stream_data_align (&assembly->code);
918 /* check for exceptions, maxstack, locals */
919 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
921 if (code_size < 64 && !(code_size & 1)) {
922 flags = (code_size << 2) | 0x2;
923 } else if (code_size < 32 && (code_size & 1)) {
924 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
928 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
929 /* add to the fixup todo list */
930 if (mb->ilgen && mb->ilgen->num_token_fixups)
931 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
932 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
933 return assembly->text_rva + idx;
937 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
939 * FIXME: need to set also the header size in fat_flags.
940 * (and more sects and init locals flags)
944 fat_flags |= METHOD_HEADER_MORE_SECTS;
946 fat_flags |= METHOD_HEADER_INIT_LOCALS;
947 fat_header [0] = fat_flags;
948 fat_header [1] = (header_size / 4 ) << 4;
949 short_value = GUINT16_TO_LE (max_stack);
950 memcpy (fat_header + 2, &short_value, 2);
951 int_value = GUINT32_TO_LE (code_size);
952 memcpy (fat_header + 4, &int_value, 4);
953 int_value = GUINT32_TO_LE (local_sig);
954 memcpy (fat_header + 8, &int_value, 4);
955 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
956 /* add to the fixup todo list */
957 if (mb->ilgen && mb->ilgen->num_token_fixups)
958 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
960 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
962 unsigned char sheader [4];
963 MonoILExceptionInfo * ex_info;
964 MonoILExceptionBlock * ex_block;
967 stream_data_align (&assembly->code);
968 /* always use fat format for now */
969 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
970 num_exception *= 6 * sizeof (guint32);
971 num_exception += 4; /* include the size of the header */
972 sheader [1] = num_exception & 0xff;
973 sheader [2] = (num_exception >> 8) & 0xff;
974 sheader [3] = (num_exception >> 16) & 0xff;
975 mono_image_add_stream_data (&assembly->code, sheader, 4);
976 /* fat header, so we are already aligned */
978 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
979 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
980 if (ex_info->handlers) {
981 int finally_start = ex_info->start + ex_info->len;
982 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
984 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
986 val = GUINT32_TO_LE (ex_block->type);
987 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
989 val = GUINT32_TO_LE (ex_info->start);
990 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
991 /* need fault, too, probably */
992 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
993 val = GUINT32_TO_LE (finally_start - ex_info->start);
995 val = GUINT32_TO_LE (ex_info->len);
996 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
998 val = GUINT32_TO_LE (ex_block->start);
999 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1001 val = GUINT32_TO_LE (ex_block->len);
1002 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1003 finally_start = ex_block->start + ex_block->len;
1004 if (ex_block->extype) {
1005 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1007 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1008 val = ex_block->filter_offset;
1012 val = GUINT32_TO_LE (val);
1013 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1014 /*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",
1015 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);*/
1018 g_error ("No clauses for ex info block %d", i);
1022 return assembly->text_rva + idx;
1026 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1029 MonoDynamicTable *table;
1032 table = &assembly->tables [table_idx];
1034 g_assert (col < table->columns);
1036 values = table->values + table->columns;
1037 for (i = 1; i <= table->rows; ++i) {
1038 if (values [col] == token)
1040 values += table->columns;
1045 static GHashTable *dynamic_custom_attrs = NULL;
1048 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1050 /* FIXME: Need to do more checks */
1051 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1052 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1054 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1061 static MonoCustomAttrInfo*
1062 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1064 int i, index, count, not_visible;
1065 MonoCustomAttrInfo *ainfo;
1066 MonoReflectionCustomAttr *cattr;
1070 /* FIXME: check in assembly the Run flag is set */
1072 count = mono_array_length (cattrs);
1074 /* Skip nonpublic attributes since MS.NET seems to do the same */
1075 /* FIXME: This needs to be done more globally */
1077 for (i = 0; i < count; ++i) {
1078 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1079 if (!custom_attr_visible (image, cattr))
1082 count -= not_visible;
1084 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1086 ainfo->image = image;
1087 ainfo->num_attrs = count;
1089 for (i = 0; i < count; ++i) {
1090 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1091 if (custom_attr_visible (image, cattr)) {
1092 ainfo->attrs [index].ctor = cattr->ctor->method;
1093 /* FIXME: might want to memdup the data here */
1094 ainfo->attrs [index].data = mono_array_addr (cattr->data, char, 0);
1095 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1104 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1106 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1111 if (!dynamic_custom_attrs)
1112 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1114 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1115 ainfo->cached = TRUE;
1119 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1121 /* they are cached, so we don't free them */
1122 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1128 * idx is the table index of the object
1129 * type is one of MONO_CUSTOM_ATTR_*
1132 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1134 MonoDynamicTable *table;
1135 MonoReflectionCustomAttr *cattr;
1137 guint32 count, i, token;
1139 char *p = blob_size;
1141 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1144 count = mono_array_length (cattrs);
1145 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1146 table->rows += count;
1147 alloc_table (table, table->rows);
1148 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1149 idx <<= MONO_CUSTOM_ATTR_BITS;
1151 for (i = 0; i < count; ++i) {
1152 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1153 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1154 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1155 type = mono_metadata_token_index (token);
1156 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1157 switch (mono_metadata_token_table (token)) {
1158 case MONO_TABLE_METHOD:
1159 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1161 case MONO_TABLE_MEMBERREF:
1162 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1165 g_warning ("got wrong token in custom attr");
1168 values [MONO_CUSTOM_ATTR_TYPE] = type;
1170 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1171 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1172 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1173 values += MONO_CUSTOM_ATTR_SIZE;
1179 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1181 MonoDynamicTable *table;
1183 guint32 count, i, idx;
1184 MonoReflectionPermissionSet *perm;
1189 count = mono_array_length (permissions);
1190 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1191 table->rows += count;
1192 alloc_table (table, table->rows);
1194 for (i = 0; i < mono_array_length (permissions); ++i) {
1195 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1197 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1199 idx = mono_metadata_token_index (parent_token);
1200 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1201 switch (mono_metadata_token_table (parent_token)) {
1202 case MONO_TABLE_TYPEDEF:
1203 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1205 case MONO_TABLE_METHOD:
1206 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1208 case MONO_TABLE_ASSEMBLY:
1209 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1212 g_assert_not_reached ();
1215 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1216 values [MONO_DECL_SECURITY_PARENT] = idx;
1217 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1224 * Fill in the MethodDef and ParamDef tables for a method.
1225 * This is used for both normal methods and constructors.
1228 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1230 MonoDynamicTable *table;
1235 /* room in this table is already allocated */
1236 table = &assembly->tables [MONO_TABLE_METHOD];
1237 *mb->table_idx = table->next_idx ++;
1238 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1239 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1240 name = mono_string_to_utf8 (mb->name);
1241 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1243 values [MONO_METHOD_FLAGS] = mb->attrs;
1244 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1245 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1246 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1248 table = &assembly->tables [MONO_TABLE_PARAM];
1249 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1251 mono_image_add_decl_security (assembly,
1252 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1255 MonoDynamicTable *mtable;
1258 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1259 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1262 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1263 if (mono_array_get (mb->pinfo, gpointer, i))
1266 table->rows += count;
1267 alloc_table (table, table->rows);
1268 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1269 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1270 MonoReflectionParamBuilder *pb;
1271 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1272 values [MONO_PARAM_FLAGS] = pb->attrs;
1273 values [MONO_PARAM_SEQUENCE] = i;
1274 if (pb->name != NULL) {
1275 name = mono_string_to_utf8 (pb->name);
1276 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1279 values [MONO_PARAM_NAME] = 0;
1281 values += MONO_PARAM_SIZE;
1282 if (pb->marshal_info) {
1284 alloc_table (mtable, mtable->rows);
1285 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1286 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1287 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1289 pb->table_idx = table->next_idx++;
1290 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1291 guint32 field_type = 0;
1292 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1294 alloc_table (mtable, mtable->rows);
1295 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1296 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1297 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1298 mvalues [MONO_CONSTANT_TYPE] = field_type;
1299 mvalues [MONO_CONSTANT_PADDING] = 0;
1307 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1309 rmb->ilgen = mb->ilgen;
1310 rmb->rtype = mb->rtype;
1311 rmb->parameters = mb->parameters;
1312 rmb->generic_params = mb->generic_params;
1313 rmb->generic_container = mb->generic_container;
1314 rmb->opt_types = NULL;
1315 rmb->pinfo = mb->pinfo;
1316 rmb->attrs = mb->attrs;
1317 rmb->iattrs = mb->iattrs;
1318 rmb->call_conv = mb->call_conv;
1319 rmb->code = mb->code;
1320 rmb->type = mb->type;
1321 rmb->name = mb->name;
1322 rmb->table_idx = &mb->table_idx;
1323 rmb->init_locals = mb->init_locals;
1324 rmb->return_modreq = mb->return_modreq;
1325 rmb->return_modopt = mb->return_modopt;
1326 rmb->param_modreq = mb->param_modreq;
1327 rmb->param_modopt = mb->param_modopt;
1328 rmb->permissions = mb->permissions;
1329 rmb->mhandle = mb->mhandle;
1334 rmb->charset = mb->charset;
1335 rmb->extra_flags = mb->extra_flags;
1336 rmb->native_cc = mb->native_cc;
1337 rmb->dllentry = mb->dllentry;
1343 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1345 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1347 rmb->ilgen = mb->ilgen;
1348 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1349 rmb->parameters = mb->parameters;
1350 rmb->generic_params = NULL;
1351 rmb->generic_container = NULL;
1352 rmb->opt_types = NULL;
1353 rmb->pinfo = mb->pinfo;
1354 rmb->attrs = mb->attrs;
1355 rmb->iattrs = mb->iattrs;
1356 rmb->call_conv = mb->call_conv;
1358 rmb->type = mb->type;
1359 rmb->name = mono_string_new (mono_domain_get (), name);
1360 rmb->table_idx = &mb->table_idx;
1361 rmb->init_locals = mb->init_locals;
1362 rmb->return_modreq = NULL;
1363 rmb->return_modopt = NULL;
1364 rmb->param_modreq = mb->param_modreq;
1365 rmb->param_modopt = mb->param_modopt;
1366 rmb->permissions = mb->permissions;
1367 rmb->mhandle = mb->mhandle;
1373 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1375 rmb->ilgen = mb->ilgen;
1376 rmb->rtype = mb->rtype;
1377 rmb->parameters = mb->parameters;
1378 rmb->generic_params = NULL;
1379 rmb->generic_container = NULL;
1380 rmb->opt_types = NULL;
1382 rmb->attrs = mb->attrs;
1384 rmb->call_conv = mb->call_conv;
1387 rmb->name = mb->name;
1388 rmb->table_idx = NULL;
1389 rmb->init_locals = mb->init_locals;
1390 rmb->return_modreq = NULL;
1391 rmb->return_modopt = NULL;
1392 rmb->param_modreq = NULL;
1393 rmb->param_modopt = NULL;
1394 rmb->permissions = NULL;
1395 rmb->mhandle = mb->mhandle;
1401 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1403 MonoDynamicTable *table;
1406 ReflectionMethodBuilder rmb;
1409 reflection_methodbuilder_from_method_builder (&rmb, mb);
1411 mono_image_basic_method (&rmb, assembly);
1412 mb->table_idx = *rmb.table_idx;
1414 if (mb->dll) { /* It's a P/Invoke method */
1416 /* map CharSet values to on-disk values */
1417 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1418 int extra_flags = mb->extra_flags;
1419 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1421 alloc_table (table, table->rows);
1422 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1424 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1425 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1427 name = mono_string_to_utf8 (mb->dllentry);
1429 name = mono_string_to_utf8 (mb->name);
1430 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1432 name = mono_string_to_utf8 (mb->dll);
1433 moduleref = string_heap_insert (&assembly->sheap, name);
1435 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1436 table = &assembly->tables [MONO_TABLE_MODULEREF];
1438 alloc_table (table, table->rows);
1439 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1440 values [MONO_IMPLMAP_SCOPE] = table->rows;
1444 if (mb->override_method) {
1445 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1447 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1449 alloc_table (table, table->rows);
1450 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1451 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1452 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1454 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1455 switch (mono_metadata_token_table (tok)) {
1456 case MONO_TABLE_MEMBERREF:
1457 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1459 case MONO_TABLE_METHOD:
1460 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1463 g_assert_not_reached ();
1465 values [MONO_METHODIMPL_DECLARATION] = tok;
1468 if (mb->generic_params) {
1469 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1470 table->rows += mono_array_length (mb->generic_params);
1471 alloc_table (table, table->rows);
1472 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1473 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1475 mono_image_get_generic_param_info (
1476 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1483 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1485 ReflectionMethodBuilder rmb;
1487 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1489 mono_image_basic_method (&rmb, assembly);
1490 mb->table_idx = *rmb.table_idx;
1494 type_get_fully_qualified_name (MonoType *type)
1496 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1500 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1504 klass = my_mono_class_from_mono_type (type);
1506 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1507 ta = klass->image->assembly;
1508 if (ta->dynamic || (ta == ass))
1509 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1511 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1515 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1517 char blob_size [64];
1518 char *b = blob_size;
1523 if (!assembly->save)
1526 p = buf = g_malloc (256);
1528 mono_metadata_encode_value (0x06, p, &p);
1529 /* encode custom attributes before the type */
1530 encode_type (assembly, type, p, &p);
1531 g_assert (p-buf < 256);
1532 mono_metadata_encode_value (p-buf, b, &b);
1533 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1539 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1541 char blob_size [64];
1542 char *b = blob_size;
1547 p = buf = g_malloc (256);
1549 mono_metadata_encode_value (0x06, p, &p);
1550 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1551 /* encode custom attributes before the type */
1552 encode_reflection_type (assembly, fb->type, p, &p);
1553 g_assert (p-buf < 256);
1554 mono_metadata_encode_value (p-buf, b, &b);
1555 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1561 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1562 char blob_size [64];
1563 char *b = blob_size;
1566 guint32 idx = 0, len = 0, dummy = 0;
1568 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1569 guint32 fpa_double [2];
1574 p = buf = g_malloc (64);
1576 *ret_type = MONO_TYPE_CLASS;
1578 box_val = (char*)&dummy;
1580 box_val = ((char*)val) + sizeof (MonoObject);
1581 *ret_type = val->vtable->klass->byval_arg.type;
1584 switch (*ret_type) {
1585 case MONO_TYPE_BOOLEAN:
1590 case MONO_TYPE_CHAR:
1607 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1608 fpa_p = (guint32*)box_val;
1609 fpa_double [0] = fpa_p [1];
1610 fpa_double [1] = fpa_p [0];
1611 box_val = (char*)fpa_double;
1615 case MONO_TYPE_VALUETYPE:
1616 if (val->vtable->klass->enumtype) {
1617 *ret_type = val->vtable->klass->enum_basetype->type;
1620 g_error ("we can't encode valuetypes");
1621 case MONO_TYPE_CLASS:
1623 case MONO_TYPE_STRING: {
1624 MonoString *str = (MonoString*)val;
1625 /* there is no signature */
1626 len = str->length * 2;
1627 mono_metadata_encode_value (len, b, &b);
1628 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1630 char *swapped = g_malloc (2 * mono_string_length (str));
1631 const char *p = (const char*)mono_string_chars (str);
1633 swap_with_size (swapped, p, 2, mono_string_length (str));
1634 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1638 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1645 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1648 /* there is no signature */
1649 mono_metadata_encode_value (len, b, &b);
1650 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1651 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1652 swap_with_size (blob_size, box_val, len, 1);
1653 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1655 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1663 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1664 char blob_size [64];
1665 char *b = blob_size;
1666 char *p, *buf, *str;
1667 guint32 idx, len, bufsize = 256;
1669 p = buf = g_malloc (bufsize);
1671 mono_metadata_encode_value (minfo->type, p, &p);
1673 switch (minfo->type) {
1674 case MONO_NATIVE_BYVALTSTR:
1675 case MONO_NATIVE_BYVALARRAY:
1676 mono_metadata_encode_value (minfo->count, p, &p);
1678 case MONO_NATIVE_LPARRAY:
1679 if (minfo->eltype || minfo->has_size) {
1680 mono_metadata_encode_value (minfo->eltype, p, &p);
1681 if (minfo->has_size) {
1682 if (minfo->param_num != -1)
1683 mono_metadata_encode_value (minfo->param_num, p, &p);
1685 mono_metadata_encode_value (0, p, &p);
1686 if (minfo->count != -1)
1687 mono_metadata_encode_value (minfo->count, p, &p);
1689 mono_metadata_encode_value (0, p, &p);
1691 /* LAMESPEC: ElemMult is undocumented */
1692 if (minfo->param_num != -1)
1693 mono_metadata_encode_value (1, p, &p);
1695 mono_metadata_encode_value (0, p, &p);
1699 case MONO_NATIVE_CUSTOM:
1701 str = mono_string_to_utf8 (minfo->guid);
1703 mono_metadata_encode_value (len, p, &p);
1704 memcpy (p, str, len);
1708 mono_metadata_encode_value (0, p, &p);
1710 /* native type name */
1711 mono_metadata_encode_value (0, p, &p);
1712 /* custom marshaler type name */
1713 if (minfo->marshaltype || minfo->marshaltyperef) {
1714 if (minfo->marshaltyperef)
1715 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1717 str = mono_string_to_utf8 (minfo->marshaltype);
1719 mono_metadata_encode_value (len, p, &p);
1720 if (p + len >= buf + bufsize) {
1723 buf = g_realloc (buf, bufsize);
1726 memcpy (p, str, len);
1730 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1731 mono_metadata_encode_value (0, p, &p);
1733 if (minfo->mcookie) {
1734 str = mono_string_to_utf8 (minfo->mcookie);
1736 mono_metadata_encode_value (len, p, &p);
1737 if (p + len >= buf + bufsize) {
1740 buf = g_realloc (buf, bufsize);
1743 memcpy (p, str, len);
1747 mono_metadata_encode_value (0, p, &p);
1754 mono_metadata_encode_value (len, b, &b);
1755 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1761 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1763 MonoDynamicTable *table;
1767 /* maybe this fixup should be done in the C# code */
1768 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1769 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1770 table = &assembly->tables [MONO_TABLE_FIELD];
1771 fb->table_idx = table->next_idx ++;
1772 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1773 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1774 name = mono_string_to_utf8 (fb->name);
1775 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1777 values [MONO_FIELD_FLAGS] = fb->attrs;
1778 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1780 if (fb->offset != -1) {
1781 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1783 alloc_table (table, table->rows);
1784 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1785 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1786 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1788 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1789 guint32 field_type = 0;
1790 table = &assembly->tables [MONO_TABLE_CONSTANT];
1792 alloc_table (table, table->rows);
1793 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1794 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1795 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1796 values [MONO_CONSTANT_TYPE] = field_type;
1797 values [MONO_CONSTANT_PADDING] = 0;
1799 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1801 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1803 alloc_table (table, table->rows);
1804 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1805 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1807 * We store it in the code section because it's simpler for now.
1810 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1812 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1813 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1815 if (fb->marshal_info) {
1816 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1818 alloc_table (table, table->rows);
1819 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1820 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1821 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1826 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1830 char *b = blob_size;
1831 guint32 nparams = 0;
1832 MonoReflectionMethodBuilder *mb = fb->get_method;
1833 MonoReflectionMethodBuilder *smb = fb->set_method;
1834 guint32 idx, i, size;
1836 if (mb && mb->parameters)
1837 nparams = mono_array_length (mb->parameters);
1838 if (!mb && smb && smb->parameters)
1839 nparams = mono_array_length (smb->parameters) - 1;
1840 size = 24 + nparams * 10;
1841 buf = p = g_malloc (size);
1844 mono_metadata_encode_value (nparams, p, &p);
1846 encode_reflection_type (assembly, mb->rtype, p, &p);
1847 for (i = 0; i < nparams; ++i) {
1848 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1849 encode_reflection_type (assembly, pt, p, &p);
1852 /* the property type is the last param */
1853 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1854 for (i = 0; i < nparams; ++i) {
1855 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1856 encode_reflection_type (assembly, pt, p, &p);
1860 encode_reflection_type (assembly, fb->type, p, &p);
1864 g_assert (p - buf < size);
1865 mono_metadata_encode_value (p-buf, b, &b);
1866 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1872 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1874 MonoDynamicTable *table;
1877 guint num_methods = 0;
1881 * we need to set things in the following tables:
1882 * PROPERTYMAP (info already filled in _get_type_info ())
1883 * PROPERTY (rows already preallocated in _get_type_info ())
1884 * METHOD (method info already done with the generic method code)
1887 table = &assembly->tables [MONO_TABLE_PROPERTY];
1888 pb->table_idx = table->next_idx ++;
1889 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1890 name = mono_string_to_utf8 (pb->name);
1891 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1893 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1894 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1896 /* FIXME: we still don't handle 'other' methods */
1897 if (pb->get_method) num_methods ++;
1898 if (pb->set_method) num_methods ++;
1900 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1901 table->rows += num_methods;
1902 alloc_table (table, table->rows);
1904 if (pb->get_method) {
1905 semaidx = table->next_idx ++;
1906 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1907 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1908 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1909 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1911 if (pb->set_method) {
1912 semaidx = table->next_idx ++;
1913 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1914 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1915 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1916 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1921 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1923 MonoDynamicTable *table;
1926 guint num_methods = 0;
1930 * we need to set things in the following tables:
1931 * EVENTMAP (info already filled in _get_type_info ())
1932 * EVENT (rows already preallocated in _get_type_info ())
1933 * METHOD (method info already done with the generic method code)
1936 table = &assembly->tables [MONO_TABLE_EVENT];
1937 eb->table_idx = table->next_idx ++;
1938 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1939 name = mono_string_to_utf8 (eb->name);
1940 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1942 values [MONO_EVENT_FLAGS] = eb->attrs;
1943 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1946 * FIXME: we still don't handle 'other' methods
1948 if (eb->add_method) num_methods ++;
1949 if (eb->remove_method) num_methods ++;
1950 if (eb->raise_method) num_methods ++;
1952 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1953 table->rows += num_methods;
1954 alloc_table (table, table->rows);
1956 if (eb->add_method) {
1957 semaidx = table->next_idx ++;
1958 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1959 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1960 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1961 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1963 if (eb->remove_method) {
1964 semaidx = table->next_idx ++;
1965 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1966 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1967 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1968 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1970 if (eb->raise_method) {
1971 semaidx = table->next_idx ++;
1972 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1973 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1974 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1975 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1980 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1982 MonoDynamicTable *table;
1983 guint32 num_constraints, i;
1987 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1988 num_constraints = gparam->iface_constraints ?
1989 mono_array_length (gparam->iface_constraints) : 0;
1990 table->rows += num_constraints;
1991 if (gparam->base_type)
1993 alloc_table (table, table->rows);
1995 if (gparam->base_type) {
1996 table_idx = table->next_idx ++;
1997 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1999 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2000 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2001 assembly, gparam->base_type->type);
2004 for (i = 0; i < num_constraints; i++) {
2005 MonoReflectionType *constraint = mono_array_get (
2006 gparam->iface_constraints, gpointer, i);
2008 table_idx = table->next_idx ++;
2009 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2011 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2012 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2013 assembly, constraint->type);
2018 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2020 GenericParamTableEntry *entry;
2023 * The GenericParam table must be sorted according to the `owner' field.
2024 * We need to do this sorting prior to writing the GenericParamConstraint
2025 * table, since we have to use the final GenericParam table indices there
2026 * and they must also be sorted.
2029 entry = g_new0 (GenericParamTableEntry, 1);
2030 entry->owner = owner;
2031 entry->gparam = gparam; /* FIXME: GC object stored in unmanaged mem */
2033 g_ptr_array_add (assembly->gen_params, entry);
2037 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2039 MonoDynamicTable *table;
2040 MonoGenericParam *param;
2044 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2045 table_idx = table->next_idx ++;
2046 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2048 param = entry->gparam->type.type->data.generic_param;
2050 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2051 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2052 values [MONO_GENERICPARAM_NUMBER] = param->num;
2053 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2055 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2057 encode_constraints (entry->gparam, table_idx, assembly);
2061 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2063 MonoDynamicTable *table;
2066 guint32 cols [MONO_ASSEMBLY_SIZE];
2070 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2073 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2074 table = &assembly->tables [MONO_TABLE_MODULEREF];
2075 token = table->next_idx ++;
2077 alloc_table (table, table->rows);
2078 values = table->values + token * MONO_MODULEREF_SIZE;
2079 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2081 token <<= MONO_RESOLTION_SCOPE_BITS;
2082 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2083 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2088 if (image->assembly->dynamic)
2090 memset (cols, 0, sizeof (cols));
2092 /* image->assembly->image is the manifest module */
2093 image = image->assembly->image;
2094 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2097 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2098 token = table->next_idx ++;
2100 alloc_table (table, table->rows);
2101 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2102 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2103 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2104 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2105 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2106 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2107 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2108 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2109 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2111 if (strcmp ("", image->assembly->aname.culture)) {
2112 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2113 image->assembly->aname.culture);
2116 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2117 guchar pubtoken [9];
2119 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2120 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2122 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2124 token <<= MONO_RESOLTION_SCOPE_BITS;
2125 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2126 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2131 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2133 MonoDynamicTable *table;
2139 char *b = blob_size;
2141 switch (type->type) {
2142 case MONO_TYPE_FNPTR:
2144 case MONO_TYPE_SZARRAY:
2145 case MONO_TYPE_ARRAY:
2147 case MONO_TYPE_MVAR:
2148 case MONO_TYPE_GENERICINST:
2149 encode_type (assembly, type, p, &p);
2151 case MONO_TYPE_CLASS:
2152 case MONO_TYPE_VALUETYPE: {
2153 MonoClass *k = mono_class_from_mono_type (type);
2154 if (!k || !k->generic_class)
2156 encode_generic_class (assembly, k->generic_class, p, &p);
2163 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2164 if (assembly->save) {
2165 g_assert (p-sig < 128);
2166 mono_metadata_encode_value (p-sig, b, &b);
2167 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2168 alloc_table (table, table->rows + 1);
2169 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2170 values [MONO_TYPESPEC_SIGNATURE] = token;
2173 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2174 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2180 * Despite the name, we handle also TypeSpec (with the above helper).
2183 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2185 MonoDynamicTable *table;
2187 guint32 token, scope, enclosing;
2190 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2193 token = create_typespec (assembly, type);
2196 klass = my_mono_class_from_mono_type (type);
2198 klass = mono_class_from_mono_type (type);
2201 * If it's in the same module and not a generic type parameter:
2203 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2204 (type->type != MONO_TYPE_MVAR)) {
2205 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2206 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2207 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2211 if (klass->nested_in) {
2212 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2213 /* get the typeref idx of the enclosing type */
2214 enclosing >>= MONO_TYPEDEFORREF_BITS;
2215 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2217 scope = resolution_scope_from_image (assembly, klass->image);
2219 table = &assembly->tables [MONO_TABLE_TYPEREF];
2220 if (assembly->save) {
2221 alloc_table (table, table->rows + 1);
2222 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2223 values [MONO_TYPEREF_SCOPE] = scope;
2224 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2225 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2227 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2228 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2230 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2235 * Insert a memberef row into the metadata: the token that point to the memberref
2236 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2237 * mono_image_get_fieldref_token()).
2238 * The sig param is an index to an already built signature.
2241 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2243 MonoDynamicTable *table;
2245 guint32 token, pclass;
2248 parent = mono_image_typedef_or_ref (assembly, type);
2249 switch (parent & MONO_TYPEDEFORREF_MASK) {
2250 case MONO_TYPEDEFORREF_TYPEREF:
2251 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2253 case MONO_TYPEDEFORREF_TYPESPEC:
2254 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2256 case MONO_TYPEDEFORREF_TYPEDEF:
2257 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2260 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2263 /* extract the index */
2264 parent >>= MONO_TYPEDEFORREF_BITS;
2266 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2268 if (assembly->save) {
2269 alloc_table (table, table->rows + 1);
2270 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2271 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2272 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2273 values [MONO_MEMBERREF_SIGNATURE] = sig;
2276 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2283 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2286 MonoMethodSignature *sig;
2288 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2293 * A methodref signature can't contain an unmanaged calling convention.
2295 sig = mono_metadata_signature_dup (mono_method_signature (method));
2296 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2297 sig->call_convention = MONO_CALL_DEFAULT;
2298 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2299 method->name, method_encode_signature (assembly, sig));
2301 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2306 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2307 const gchar *name, guint32 sig)
2309 MonoDynamicTable *table;
2313 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2315 if (assembly->save) {
2316 alloc_table (table, table->rows + 1);
2317 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2318 values [MONO_MEMBERREF_CLASS] = original;
2319 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2320 values [MONO_MEMBERREF_SIGNATURE] = sig;
2323 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2330 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2333 ReflectionMethodBuilder rmb;
2335 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2339 reflection_methodbuilder_from_method_builder (&rmb, mb);
2341 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2342 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2343 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2348 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2351 ReflectionMethodBuilder rmb;
2353 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2357 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2359 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2360 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2361 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2366 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2371 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2374 g_assert (f->field->parent);
2375 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2376 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2377 f->field->name, fieldref_encode_signature (assembly, type));
2378 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2383 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2388 guint32 nparams = gmethod->inst->type_argc;
2389 guint32 size = 10 + nparams * 30;
2392 char *b = blob_size;
2394 if (!assembly->save)
2397 p = buf = g_malloc (size);
2399 * FIXME: vararg, explicit_this, differenc call_conv values...
2401 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2402 mono_metadata_encode_value (nparams, p, &p);
2404 for (i = 0; i < nparams; i++)
2405 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2408 g_assert (p - buf < size);
2409 mono_metadata_encode_value (p-buf, b, &b);
2410 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2416 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2418 MonoDynamicTable *table;
2420 guint32 token, mtoken = 0, sig;
2421 MonoMethodInflated *imethod;
2422 MonoMethod *declaring;
2424 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2426 g_assert (method->is_inflated);
2427 method = mono_get_inflated_method (method);
2428 imethod = (MonoMethodInflated *) method;
2429 declaring = imethod->declaring;
2431 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2432 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2434 if (!mono_method_signature (declaring)->generic_param_count)
2437 switch (mono_metadata_token_table (mtoken)) {
2438 case MONO_TABLE_MEMBERREF:
2439 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2441 case MONO_TABLE_METHOD:
2442 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2445 g_assert_not_reached ();
2448 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2450 if (assembly->save) {
2451 alloc_table (table, table->rows + 1);
2452 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2453 values [MONO_METHODSPEC_METHOD] = mtoken;
2454 values [MONO_METHODSPEC_SIGNATURE] = sig;
2457 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2464 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2466 MonoMethodInflated *imethod;
2467 MonoMethod *inflated;
2470 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2474 g_assert (method->is_inflated);
2475 inflated = mono_get_inflated_method (method);
2476 imethod = (MonoMethodInflated *) inflated;
2478 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2479 token = method_encode_methodspec (assembly, inflated);
2481 guint32 sig = method_encode_signature (
2482 assembly, mono_method_signature (imethod->declaring));
2483 token = mono_image_get_memberref_token (
2484 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2487 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2492 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2494 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2497 m = mono_get_inflated_method (m);
2499 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2500 token = mono_image_get_memberref_token (
2501 assembly, &m->klass->byval_arg, m->name, sig);
2507 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2509 MonoDynamicTable *table;
2516 char *b = blob_size;
2520 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2521 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2522 * Because of this, we must not insert it into the `typeref' hash table.
2525 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2529 g_assert (tb->generic_params);
2530 klass = mono_class_from_mono_type (tb->type.type);
2532 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2533 encode_type (assembly, &klass->byval_arg, p, &p);
2535 count = mono_array_length (tb->generic_params);
2536 mono_metadata_encode_value (count, p, &p);
2537 for (i = 0; i < count; i++) {
2538 MonoReflectionGenericParam *gparam;
2540 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2542 encode_type (assembly, gparam->type.type, p, &p);
2545 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2546 g_assert (p-sig < 128);
2548 if (assembly->save) {
2549 mono_metadata_encode_value (p-sig, b, &b);
2550 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2551 alloc_table (table, table->rows + 1);
2552 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2553 values [MONO_TYPESPEC_SIGNATURE] = token;
2556 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2557 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2563 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2565 MonoDynamicTable *table;
2568 guint32 token, pclass, parent, sig;
2571 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2575 klass = mono_class_from_mono_type (fb->typeb->type);
2576 name = mono_string_to_utf8 (fb->name);
2578 sig = fieldref_encode_signature (assembly, fb->type->type);
2580 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2581 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2583 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2584 parent >>= MONO_TYPEDEFORREF_BITS;
2586 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2588 if (assembly->save) {
2589 alloc_table (table, table->rows + 1);
2590 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2591 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2592 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2593 values [MONO_MEMBERREF_SIGNATURE] = sig;
2596 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2598 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2603 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2611 char *b = blob_size;
2613 if (!assembly->save)
2617 g_assert (helper->type == 2);
2619 if (helper->arguments)
2620 nargs = mono_array_length (helper->arguments);
2624 size = 10 + (nargs * 10);
2626 p = buf = g_malloc (size);
2628 /* Encode calling convention */
2629 /* Change Any to Standard */
2630 if ((helper->call_conv & 0x03) == 0x03)
2631 helper->call_conv = 0x01;
2632 /* explicit_this implies has_this */
2633 if (helper->call_conv & 0x40)
2634 helper->call_conv &= 0x20;
2636 if (helper->call_conv == 0) { /* Unmanaged */
2637 *p = helper->unmanaged_call_conv - 1;
2640 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2641 if (helper->call_conv & 0x02) /* varargs */
2646 mono_metadata_encode_value (nargs, p, &p);
2647 encode_reflection_type (assembly, helper->return_type, p, &p);
2648 for (i = 0; i < nargs; ++i) {
2649 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2650 encode_reflection_type (assembly, pt, p, &p);
2653 g_assert (p - buf < size);
2654 mono_metadata_encode_value (p-buf, b, &b);
2655 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2662 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2665 MonoDynamicTable *table;
2668 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2669 idx = table->next_idx ++;
2671 alloc_table (table, table->rows);
2672 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2674 values [MONO_STAND_ALONE_SIGNATURE] =
2675 mono_reflection_encode_sighelper (assembly, helper);
2681 reflection_cc_to_file (int call_conv) {
2682 switch (call_conv & 0x3) {
2684 case 1: return MONO_CALL_DEFAULT;
2685 case 2: return MONO_CALL_VARARG;
2687 g_assert_not_reached ();
2694 MonoMethodSignature *sig;
2700 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2705 MonoMethodSignature *sig;
2708 name = mono_string_to_utf8 (m->name);
2709 nparams = mono_array_length (m->parameters);
2710 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2712 sig->sentinelpos = -1;
2713 sig->call_convention = reflection_cc_to_file (m->call_conv);
2714 sig->param_count = nparams;
2715 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2716 for (i = 0; i < nparams; ++i) {
2717 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2718 sig->params [i] = t->type;
2721 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2723 if (strcmp (name, am->name) == 0 &&
2724 mono_metadata_type_equal (am->parent, m->parent->type) &&
2725 mono_metadata_signature_equal (am->sig, sig)) {
2728 m->table_idx = am->token & 0xffffff;
2732 am = g_new0 (ArrayMethod, 1);
2735 am->parent = m->parent->type;
2736 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2737 method_encode_signature (assembly, sig));
2738 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2739 m->table_idx = am->token & 0xffffff;
2744 * Insert into the metadata tables all the info about the TypeBuilder tb.
2745 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2748 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2750 MonoDynamicTable *table;
2752 int i, is_object = 0, is_system = 0;
2755 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2756 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2757 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2758 n = mono_string_to_utf8 (tb->name);
2759 if (strcmp (n, "Object") == 0)
2761 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2763 n = mono_string_to_utf8 (tb->nspace);
2764 if (strcmp (n, "System") == 0)
2766 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2768 if (tb->parent && !(is_system && is_object) &&
2769 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2770 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2772 values [MONO_TYPEDEF_EXTENDS] = 0;
2774 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2775 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2778 * if we have explicitlayout or sequentiallayouts, output data in the
2779 * ClassLayout table.
2781 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2782 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2783 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2785 alloc_table (table, table->rows);
2786 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2787 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2788 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2789 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2792 /* handle interfaces */
2793 if (tb->interfaces) {
2794 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2796 table->rows += mono_array_length (tb->interfaces);
2797 alloc_table (table, table->rows);
2798 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2799 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2800 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2801 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2802 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2803 values += MONO_INTERFACEIMPL_SIZE;
2809 table = &assembly->tables [MONO_TABLE_FIELD];
2810 table->rows += tb->num_fields;
2811 alloc_table (table, table->rows);
2812 for (i = 0; i < tb->num_fields; ++i)
2813 mono_image_get_field_info (
2814 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2817 /* handle constructors */
2819 table = &assembly->tables [MONO_TABLE_METHOD];
2820 table->rows += mono_array_length (tb->ctors);
2821 alloc_table (table, table->rows);
2822 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2823 mono_image_get_ctor_info (domain,
2824 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2827 /* handle methods */
2829 table = &assembly->tables [MONO_TABLE_METHOD];
2830 table->rows += tb->num_methods;
2831 alloc_table (table, table->rows);
2832 for (i = 0; i < tb->num_methods; ++i)
2833 mono_image_get_method_info (
2834 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2837 /* Do the same with properties etc.. */
2838 if (tb->events && mono_array_length (tb->events)) {
2839 table = &assembly->tables [MONO_TABLE_EVENT];
2840 table->rows += mono_array_length (tb->events);
2841 alloc_table (table, table->rows);
2842 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2844 alloc_table (table, table->rows);
2845 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2846 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2847 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2848 for (i = 0; i < mono_array_length (tb->events); ++i)
2849 mono_image_get_event_info (
2850 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2852 if (tb->properties && mono_array_length (tb->properties)) {
2853 table = &assembly->tables [MONO_TABLE_PROPERTY];
2854 table->rows += mono_array_length (tb->properties);
2855 alloc_table (table, table->rows);
2856 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2858 alloc_table (table, table->rows);
2859 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2860 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2861 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2862 for (i = 0; i < mono_array_length (tb->properties); ++i)
2863 mono_image_get_property_info (
2864 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2867 /* handle generic parameters */
2868 if (tb->generic_params) {
2869 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2870 table->rows += mono_array_length (tb->generic_params);
2871 alloc_table (table, table->rows);
2872 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2873 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2875 mono_image_get_generic_param_info (
2876 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2880 mono_image_add_decl_security (assembly,
2881 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2884 MonoDynamicTable *ntable;
2886 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2887 ntable->rows += mono_array_length (tb->subtypes);
2888 alloc_table (ntable, ntable->rows);
2889 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2891 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2892 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2894 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2895 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2896 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2897 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2898 mono_string_to_utf8 (tb->name), tb->table_idx,
2899 ntable->next_idx, ntable->rows);*/
2900 values += MONO_NESTED_CLASS_SIZE;
2907 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2911 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
2913 if (!type->subtypes)
2916 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2917 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2918 collect_types (types, subtype);
2923 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2925 if ((*type1)->table_idx < (*type2)->table_idx)
2928 if ((*type1)->table_idx > (*type2)->table_idx)
2935 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2940 for (i = 0; i < mono_array_length (pinfo); ++i) {
2941 MonoReflectionParamBuilder *pb;
2942 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2945 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2950 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2953 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2955 for (i = 0; i < tb->num_fields; ++i) {
2956 MonoReflectionFieldBuilder* fb;
2957 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2958 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2962 for (i = 0; i < mono_array_length (tb->events); ++i) {
2963 MonoReflectionEventBuilder* eb;
2964 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2965 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2968 if (tb->properties) {
2969 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2970 MonoReflectionPropertyBuilder* pb;
2971 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2972 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2976 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2977 MonoReflectionCtorBuilder* cb;
2978 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2979 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2980 params_add_cattrs (assembly, cb->pinfo);
2985 for (i = 0; i < tb->num_methods; ++i) {
2986 MonoReflectionMethodBuilder* mb;
2987 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2988 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2989 params_add_cattrs (assembly, mb->pinfo);
2994 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2995 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3000 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3004 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3006 if (moduleb->global_methods) {
3007 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3008 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3009 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3010 params_add_cattrs (assembly, mb->pinfo);
3014 if (moduleb->global_fields) {
3015 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3016 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3017 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3021 if (moduleb->types) {
3022 for (i = 0; i < moduleb->num_types; ++i)
3023 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3028 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3030 MonoDynamicTable *table;
3034 char *b = blob_size;
3037 table = &assembly->tables [MONO_TABLE_FILE];
3039 alloc_table (table, table->rows);
3040 values = table->values + table->next_idx * MONO_FILE_SIZE;
3041 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3042 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3043 if (module->image->dynamic) {
3044 /* This depends on the fact that the main module is emitted last */
3045 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3046 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3049 path = g_strdup (module->image->name);
3051 mono_sha1_get_digest_from_file (path, hash);
3054 mono_metadata_encode_value (20, b, &b);
3055 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3056 mono_image_add_stream_data (&assembly->blob, hash, 20);
3061 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3063 MonoDynamicTable *table;
3067 table = &assembly->tables [MONO_TABLE_MODULE];
3068 mb->table_idx = table->next_idx ++;
3069 name = mono_string_to_utf8 (mb->module.name);
3070 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3072 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3075 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3076 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3077 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3082 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3083 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3085 MonoDynamicTable *table;
3089 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3090 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3093 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3095 alloc_table (table, table->rows);
3096 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3098 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3099 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3100 if (klass->nested_in)
3101 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3103 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3104 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3105 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3107 res = table->next_idx;
3111 /* Emit nested types */
3112 if (klass->nested_classes) {
3115 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3116 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3123 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3124 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3129 klass = mono_class_from_mono_type (tb->type.type);
3131 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3133 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3134 parent_index, assembly);
3138 * We need to do this ourselves since klass->nested_classes is not set up.
3141 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3142 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3147 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3148 guint32 module_index, MonoDynamicImage *assembly)
3150 MonoImage *image = module->image;
3154 t = &image->tables [MONO_TABLE_TYPEDEF];
3156 for (i = 0; i < t->rows; ++i) {
3157 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3159 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3160 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3165 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3167 MonoDynamicTable *table;
3173 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3175 if (assemblyb->type_forwarders) {
3176 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3177 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType*, i);
3183 klass = mono_class_from_mono_type (t->type);
3185 scope = resolution_scope_from_image (assembly, klass->image);
3186 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3187 idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3190 alloc_table (table, table->rows);
3191 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3193 values [MONO_EXP_TYPE_FLAGS] = TYPE_ATTRIBUTE_FORWARDER;
3194 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3195 values [MONO_EXP_TYPE_IMPLEMENTATION] = (idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3196 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3197 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3202 #define align_pointer(base,p)\
3204 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3206 (p) += 4 - (__diff & 3);\
3210 compare_constants (const void *a, const void *b)
3212 const guint32 *a_values = a;
3213 const guint32 *b_values = b;
3214 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3218 compare_semantics (const void *a, const void *b)
3220 const guint32 *a_values = a;
3221 const guint32 *b_values = b;
3222 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3225 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3229 compare_custom_attrs (const void *a, const void *b)
3231 const guint32 *a_values = a;
3232 const guint32 *b_values = b;
3234 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3238 compare_field_marshal (const void *a, const void *b)
3240 const guint32 *a_values = a;
3241 const guint32 *b_values = b;
3243 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3247 compare_nested (const void *a, const void *b)
3249 const guint32 *a_values = a;
3250 const guint32 *b_values = b;
3252 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3256 compare_genericparam (const void *a, const void *b)
3258 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3259 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3261 if ((*b_entry)->owner == (*a_entry)->owner)
3263 (*a_entry)->gparam->type.type->data.generic_param->num -
3264 (*b_entry)->gparam->type.type->data.generic_param->num;
3266 return (*a_entry)->owner - (*b_entry)->owner;
3270 compare_declsecurity_attrs (const void *a, const void *b)
3272 const guint32 *a_values = a;
3273 const guint32 *b_values = b;
3275 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3279 pad_heap (MonoDynamicStream *sh)
3281 if (sh->index & 3) {
3282 int sz = 4 - (sh->index & 3);
3283 memset (sh->data + sh->index, 0, sz);
3290 MonoDynamicStream *stream;
3294 * build_compressed_metadata() fills in the blob of data that represents the
3295 * raw metadata as it will be saved in the PE file. The five streams are output
3296 * and the metadata tables are comnpressed from the guint32 array representation,
3297 * to the compressed on-disk format.
3300 build_compressed_metadata (MonoDynamicImage *assembly)
3302 MonoDynamicTable *table;
3304 guint64 valid_mask = 0;
3305 guint64 sorted_mask;
3306 guint32 heapt_size = 0;
3307 guint32 meta_size = 256; /* allow for header and other stuff */
3308 guint32 table_offset;
3309 guint32 ntables = 0;
3315 struct StreamDesc stream_desc [5];
3317 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3318 for (i = 0; i < assembly->gen_params->len; i++){
3319 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3320 write_generic_param_entry (assembly, entry);
3323 stream_desc [0].name = "#~";
3324 stream_desc [0].stream = &assembly->tstream;
3325 stream_desc [1].name = "#Strings";
3326 stream_desc [1].stream = &assembly->sheap;
3327 stream_desc [2].name = "#US";
3328 stream_desc [2].stream = &assembly->us;
3329 stream_desc [3].name = "#Blob";
3330 stream_desc [3].stream = &assembly->blob;
3331 stream_desc [4].name = "#GUID";
3332 stream_desc [4].stream = &assembly->guid;
3334 /* tables that are sorted */
3335 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3336 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3337 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3338 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3339 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3340 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3342 /* Compute table sizes */
3343 /* the MonoImage has already been created in mono_image_basic_init() */
3344 meta = &assembly->image;
3346 /* sizes should be multiple of 4 */
3347 pad_heap (&assembly->blob);
3348 pad_heap (&assembly->guid);
3349 pad_heap (&assembly->sheap);
3350 pad_heap (&assembly->us);
3352 /* Setup the info used by compute_sizes () */
3353 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3354 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3355 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3357 meta_size += assembly->blob.index;
3358 meta_size += assembly->guid.index;
3359 meta_size += assembly->sheap.index;
3360 meta_size += assembly->us.index;
3362 for (i=0; i < MONO_TABLE_NUM; ++i)
3363 meta->tables [i].rows = assembly->tables [i].rows;
3365 for (i = 0; i < MONO_TABLE_NUM; i++){
3366 if (meta->tables [i].rows == 0)
3368 valid_mask |= (guint64)1 << i;
3370 meta->tables [i].row_size = mono_metadata_compute_size (
3371 meta, i, &meta->tables [i].size_bitfield);
3372 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3374 heapt_size += 24; /* #~ header size */
3375 heapt_size += ntables * 4;
3376 /* make multiple of 4 */
3379 meta_size += heapt_size;
3380 meta->raw_metadata = g_malloc0 (meta_size);
3381 p = meta->raw_metadata;
3382 /* the metadata signature */
3383 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3384 /* version numbers and 4 bytes reserved */
3385 int16val = (guint16*)p;
3386 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3387 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3389 /* version string */
3390 int32val = (guint32*)p;
3391 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3393 memcpy (p, meta->version, strlen (meta->version));
3394 p += GUINT32_FROM_LE (*int32val);
3395 align_pointer (meta->raw_metadata, p);
3396 int16val = (guint16*)p;
3397 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3398 *int16val = GUINT16_TO_LE (5); /* number of streams */
3402 * write the stream info.
3404 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3405 table_offset += 3; table_offset &= ~3;
3407 assembly->tstream.index = heapt_size;
3408 for (i = 0; i < 5; ++i) {
3409 int32val = (guint32*)p;
3410 stream_desc [i].stream->offset = table_offset;
3411 *int32val++ = GUINT32_TO_LE (table_offset);
3412 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3413 table_offset += GUINT32_FROM_LE (*int32val);
3414 table_offset += 3; table_offset &= ~3;
3416 strcpy (p, stream_desc [i].name);
3417 p += strlen (stream_desc [i].name) + 1;
3418 align_pointer (meta->raw_metadata, p);
3421 * now copy the data, the table stream header and contents goes first.
3423 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3424 p = meta->raw_metadata + assembly->tstream.offset;
3425 int32val = (guint32*)p;
3426 *int32val = GUINT32_TO_LE (0); /* reserved */
3429 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3430 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3431 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3432 *p++ = 2; /* version */
3435 *p++ = 1; /* version */
3439 if (meta->idx_string_wide)
3441 if (meta->idx_guid_wide)
3443 if (meta->idx_blob_wide)
3446 *p++ = 1; /* reserved */
3447 int64val = (guint64*)p;
3448 *int64val++ = GUINT64_TO_LE (valid_mask);
3449 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3451 int32val = (guint32*)p;
3452 for (i = 0; i < MONO_TABLE_NUM; i++){
3453 if (meta->tables [i].rows == 0)
3455 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3457 p = (unsigned char*)int32val;
3459 /* sort the tables that still need sorting */
3460 table = &assembly->tables [MONO_TABLE_CONSTANT];
3462 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3463 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3465 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3466 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3468 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3469 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3471 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3472 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3474 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3475 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3476 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3478 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3480 /* compress the tables */
3481 for (i = 0; i < MONO_TABLE_NUM; i++){
3484 guint32 bitfield = meta->tables [i].size_bitfield;
3485 if (!meta->tables [i].rows)
3487 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3488 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3489 meta->tables [i].base = p;
3490 for (row = 1; row <= meta->tables [i].rows; ++row) {
3491 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3492 for (col = 0; col < assembly->tables [i].columns; ++col) {
3493 switch (mono_metadata_table_size (bitfield, col)) {
3495 *p++ = values [col];
3498 *p++ = values [col] & 0xff;
3499 *p++ = (values [col] >> 8) & 0xff;
3502 *p++ = values [col] & 0xff;
3503 *p++ = (values [col] >> 8) & 0xff;
3504 *p++ = (values [col] >> 16) & 0xff;
3505 *p++ = (values [col] >> 24) & 0xff;
3508 g_assert_not_reached ();
3512 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3515 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3516 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3517 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3518 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3519 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3521 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3525 * Some tables in metadata need to be sorted according to some criteria, but
3526 * when methods and fields are first created with reflection, they may be assigned a token
3527 * that doesn't correspond to the final token they will get assigned after the sorting.
3528 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3529 * with the reflection objects that represent them. Once all the tables are set up, the
3530 * reflection objects will contains the correct table index. fixup_method() will fixup the
3531 * tokens for the method with ILGenerator @ilgen.
3534 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3535 guint32 code_idx = GPOINTER_TO_UINT (value);
3536 MonoReflectionILTokenInfo *iltoken;
3537 MonoReflectionFieldBuilder *field;
3538 MonoReflectionCtorBuilder *ctor;
3539 MonoReflectionMethodBuilder *method;
3540 MonoReflectionTypeBuilder *tb;
3541 MonoReflectionArrayMethod *am;
3543 unsigned char *target;
3545 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3546 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3547 target = assembly->code.data + code_idx + iltoken->code_pos;
3548 switch (target [3]) {
3549 case MONO_TABLE_FIELD:
3550 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3551 field = (MonoReflectionFieldBuilder *)iltoken->member;
3552 idx = field->table_idx;
3553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3554 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3555 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3557 g_assert_not_reached ();
3560 case MONO_TABLE_METHOD:
3561 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3562 method = (MonoReflectionMethodBuilder *)iltoken->member;
3563 idx = method->table_idx;
3564 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3565 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3566 idx = ctor->table_idx;
3567 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3568 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3569 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3570 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3572 g_assert_not_reached ();
3575 case MONO_TABLE_TYPEDEF:
3576 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3577 g_assert_not_reached ();
3578 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3579 idx = tb->table_idx;
3581 case MONO_TABLE_MEMBERREF:
3582 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3583 am = (MonoReflectionArrayMethod*)iltoken->member;
3584 idx = am->table_idx;
3585 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3586 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3587 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3588 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3589 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3590 g_assert (m->klass->generic_class || m->klass->generic_container);
3592 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3594 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3595 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3596 g_assert (f->generic_info);
3598 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3601 g_assert_not_reached ();
3604 case MONO_TABLE_METHODSPEC:
3605 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3606 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3607 g_assert (mono_method_signature (m)->generic_param_count);
3610 g_assert_not_reached ();
3614 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3616 target [0] = idx & 0xff;
3617 target [1] = (idx >> 8) & 0xff;
3618 target [2] = (idx >> 16) & 0xff;
3625 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3626 * value is not known when the table is emitted.
3629 fixup_cattrs (MonoDynamicImage *assembly)
3631 MonoDynamicTable *table;
3633 guint32 type, i, idx, token;
3636 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3638 for (i = 0; i < table->rows; ++i) {
3639 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3641 type = values [MONO_CUSTOM_ATTR_TYPE];
3642 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3643 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3644 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3645 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3648 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3649 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3650 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3651 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3660 * The METHODIMPL table might contain METHODDEF tokens whose final
3661 * value is not known when the table is emitted.
3664 fixup_methodimpl (MonoDynamicImage *assembly)
3666 MonoDynamicTable *table;
3668 guint32 decl, i, idx, token;
3671 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3673 for (i = 0; i < table->rows; ++i) {
3674 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3675 decl = values [MONO_METHODIMPL_DECLARATION];
3677 idx = decl >> MONO_METHODDEFORREF_BITS;
3678 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3681 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3682 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3685 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3686 token = mono_image_create_token (assembly, method, FALSE);
3687 idx = mono_metadata_token_index (token);
3688 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3694 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3696 MonoDynamicTable *table;
3700 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3702 alloc_table (table, table->rows);
3703 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3704 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3705 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3706 name = mono_string_to_utf8 (rsrc->name);
3707 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3709 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3714 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3716 MonoDynamicTable *table;
3720 char *b = blob_size;
3722 guint32 idx, offset;
3724 if (rsrc->filename) {
3725 name = mono_string_to_utf8 (rsrc->filename);
3726 sname = g_path_get_basename (name);
3728 table = &assembly->tables [MONO_TABLE_FILE];
3730 alloc_table (table, table->rows);
3731 values = table->values + table->next_idx * MONO_FILE_SIZE;
3732 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3733 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3736 mono_sha1_get_digest_from_file (name, hash);
3737 mono_metadata_encode_value (20, b, &b);
3738 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3739 mono_image_add_stream_data (&assembly->blob, hash, 20);
3741 idx = table->next_idx++;
3743 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3746 offset = mono_array_length (rsrc->data);
3747 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3748 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3749 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3750 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3754 * The entry should be emitted into the MANIFESTRESOURCE table of
3755 * the main module, but that needs to reference the FILE table
3756 * which isn't emitted yet.
3763 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3767 set_version_from_string (MonoString *version, guint32 *values)
3769 gchar *ver, *p, *str;
3772 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3773 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3774 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3775 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3778 ver = str = mono_string_to_utf8 (version);
3779 for (i = 0; i < 4; ++i) {
3780 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3786 /* handle Revision and Build */
3796 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3800 char *b = blob_size;
3805 len = mono_array_length (pkey);
3806 mono_metadata_encode_value (len, b, &b);
3807 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3808 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3810 /* Special case: check for ECMA key (16 bytes) */
3811 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3812 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3813 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3814 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3815 /* minimum key size (in 2.0) is 384 bits */
3816 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3818 /* FIXME - verifier */
3819 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
3820 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3822 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3828 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3830 MonoDynamicTable *table;
3831 MonoDynamicImage *assembly;
3832 MonoReflectionAssemblyBuilder *assemblyb;
3837 guint32 module_index;
3839 assemblyb = moduleb->assemblyb;
3840 assembly = moduleb->dynamic_image;
3841 domain = mono_object_domain (assemblyb);
3843 /* Emit ASSEMBLY table */
3844 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3845 alloc_table (table, 1);
3846 values = table->values + MONO_ASSEMBLY_SIZE;
3847 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3848 name = mono_string_to_utf8 (assemblyb->name);
3849 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3851 if (assemblyb->culture) {
3852 name = mono_string_to_utf8 (assemblyb->culture);
3853 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3856 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3858 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3859 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3860 set_version_from_string (assemblyb->version, values);
3862 /* Emit FILE + EXPORTED_TYPE table */
3864 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3866 MonoReflectionModuleBuilder *file_module =
3867 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3868 if (file_module != moduleb) {
3869 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3871 if (file_module->types) {
3872 for (j = 0; j < file_module->num_types; ++j) {
3873 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3874 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3879 if (assemblyb->loaded_modules) {
3880 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3881 MonoReflectionModule *file_module =
3882 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3883 mono_image_fill_file_table (domain, file_module, assembly);
3885 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3888 if (assemblyb->type_forwarders)
3889 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
3891 /* Emit MANIFESTRESOURCE table */
3893 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3895 MonoReflectionModuleBuilder *file_module =
3896 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3897 /* The table for the main module is emitted later */
3898 if (file_module != moduleb) {
3900 if (file_module->resources) {
3901 int len = mono_array_length (file_module->resources);
3902 for (j = 0; j < len; ++j) {
3903 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3904 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3912 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3913 * for the modulebuilder @moduleb.
3914 * At the end of the process, method and field tokens are fixed up and the
3915 * on-disk compressed metadata representation is created.
3918 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3920 MonoDynamicTable *table;
3921 MonoDynamicImage *assembly;
3922 MonoReflectionAssemblyBuilder *assemblyb;
3927 assemblyb = moduleb->assemblyb;
3928 assembly = moduleb->dynamic_image;
3929 domain = mono_object_domain (assemblyb);
3931 if (assembly->text_rva)
3934 assembly->text_rva = START_TEXT_RVA;
3936 if (moduleb->is_main) {
3937 mono_image_emit_manifest (moduleb);
3940 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3941 table->rows = 1; /* .<Module> */
3943 alloc_table (table, table->rows);
3945 * Set the first entry.
3947 values = table->values + table->columns;
3948 values [MONO_TYPEDEF_FLAGS] = 0;
3949 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3950 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3951 values [MONO_TYPEDEF_EXTENDS] = 0;
3952 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3953 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3956 * handle global methods
3957 * FIXME: test what to do when global methods are defined in multiple modules.
3959 if (moduleb->global_methods) {
3960 table = &assembly->tables [MONO_TABLE_METHOD];
3961 table->rows += mono_array_length (moduleb->global_methods);
3962 alloc_table (table, table->rows);
3963 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3964 mono_image_get_method_info (
3965 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3967 if (moduleb->global_fields) {
3968 table = &assembly->tables [MONO_TABLE_FIELD];
3969 table->rows += mono_array_length (moduleb->global_fields);
3970 alloc_table (table, table->rows);
3971 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3972 mono_image_get_field_info (
3973 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3976 table = &assembly->tables [MONO_TABLE_MODULE];
3977 alloc_table (table, 1);
3978 mono_image_fill_module_table (domain, moduleb, assembly);
3982 /* Collect all types into a list sorted by their table_idx */
3983 GPtrArray *types = g_ptr_array_new ();
3986 for (i = 0; i < moduleb->num_types; ++i) {
3987 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3988 collect_types (types, type);
3991 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3992 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3993 table->rows += types->len;
3994 alloc_table (table, table->rows);
3997 * Emit type names + namespaces at one place inside the string heap,
3998 * so load_class_names () needs to touch fewer pages.
4000 for (i = 0; i < types->len; ++i) {
4001 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4004 n = mono_string_to_utf8 (tb->nspace);
4005 string_heap_insert (&assembly->sheap, n);
4008 for (i = 0; i < types->len; ++i) {
4009 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4012 n = mono_string_to_utf8 (tb->name);
4013 string_heap_insert (&assembly->sheap, n);
4017 for (i = 0; i < types->len; ++i) {
4018 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4019 mono_image_get_type_info (domain, type, assembly);
4021 g_ptr_array_free (types, TRUE);
4025 * table->rows is already set above and in mono_image_fill_module_table.
4027 /* add all the custom attributes at the end, once all the indexes are stable */
4028 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4030 /* CAS assembly permissions */
4031 if (assemblyb->permissions_minimum)
4032 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4033 if (assemblyb->permissions_optional)
4034 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4035 if (assemblyb->permissions_refused)
4036 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4038 module_add_cattrs (assembly, moduleb);
4041 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4042 fixup_cattrs (assembly);
4043 fixup_methodimpl (assembly);
4047 * mono_image_insert_string:
4048 * @module: module builder object
4051 * Insert @str into the user string stream of @module.
4054 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4056 MonoDynamicImage *assembly;
4061 MONO_ARCH_SAVE_REGS;
4063 if (!module->dynamic_image)
4064 mono_image_module_basic_init (module);
4066 assembly = module->dynamic_image;
4068 if (assembly->save) {
4069 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4070 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4071 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4073 char *swapped = g_malloc (2 * mono_string_length (str));
4074 const char *p = (const char*)mono_string_chars (str);
4076 swap_with_size (swapped, p, 2, mono_string_length (str));
4077 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4081 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4083 mono_image_add_stream_data (&assembly->us, "", 1);
4085 idx = assembly->us.index ++;
4088 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4090 return MONO_TOKEN_STRING | idx;
4094 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4099 klass = obj->vtable->klass;
4100 if (strcmp (klass->name, "MonoMethod") == 0) {
4101 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4102 MonoMethodSignature *sig, *old;
4103 guint32 sig_token, parent;
4106 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4108 nargs = mono_array_length (opt_param_types);
4109 old = mono_method_signature (method);
4110 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4112 sig->hasthis = old->hasthis;
4113 sig->explicit_this = old->explicit_this;
4114 sig->call_convention = old->call_convention;
4115 sig->generic_param_count = old->generic_param_count;
4116 sig->param_count = old->param_count + nargs;
4117 sig->sentinelpos = old->param_count;
4118 sig->ret = old->ret;
4120 for (i = 0; i < old->param_count; i++)
4121 sig->params [i] = old->params [i];
4123 for (i = 0; i < nargs; i++) {
4124 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4125 sig->params [old->param_count + i] = rt->type;
4128 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4129 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4130 parent >>= MONO_TYPEDEFORREF_BITS;
4132 parent <<= MONO_MEMBERREF_PARENT_BITS;
4133 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4135 sig_token = method_encode_signature (assembly, sig);
4136 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4137 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4138 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4139 ReflectionMethodBuilder rmb;
4140 guint32 parent, sig;
4142 reflection_methodbuilder_from_method_builder (&rmb, mb);
4143 rmb.opt_types = opt_param_types;
4145 sig = method_builder_encode_signature (assembly, &rmb);
4147 parent = mono_image_create_token (assembly, obj, TRUE);
4148 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4150 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4151 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4153 token = mono_image_get_varargs_method_token (
4154 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4156 g_error ("requested method token for %s\n", klass->name);
4163 * mono_image_create_token:
4164 * @assembly: a dynamic assembly
4167 * Get a token to insert in the IL code stream for the given MemberInfo.
4168 * @obj can be one of:
4169 * ConstructorBuilder
4179 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4184 klass = obj->vtable->klass;
4185 if (strcmp (klass->name, "MethodBuilder") == 0) {
4186 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4188 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4189 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4191 token = mono_image_get_methodbuilder_token (assembly, mb);
4192 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4193 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4194 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4196 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4197 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4199 token = mono_image_get_ctorbuilder_token (assembly, mb);
4200 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4201 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4202 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4203 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4204 if (tb->generic_params) {
4205 token = mono_image_get_generic_field_token (assembly, fb);
4207 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4209 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4210 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4211 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4212 } else if (strcmp (klass->name, "MonoType") == 0 ||
4213 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4214 MonoReflectionType *tb = (MonoReflectionType *)obj;
4215 token = mono_metadata_token_from_dor (
4216 mono_image_typedef_or_ref (assembly, tb->type));
4217 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4218 MonoReflectionType *tb = (MonoReflectionType *)obj;
4219 token = mono_metadata_token_from_dor (
4220 mono_image_typedef_or_ref (assembly, tb->type));
4221 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4222 strcmp (klass->name, "MonoMethod") == 0 ||
4223 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4224 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4225 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4226 if (m->method->is_inflated) {
4227 if (create_methodspec)
4228 token = mono_image_get_methodspec_token (assembly, m->method);
4230 token = mono_image_get_inflated_method_token (assembly, m->method);
4231 } else if ((m->method->klass->image == &assembly->image) &&
4232 !m->method->klass->generic_class) {
4233 static guint32 method_table_idx = 0xffffff;
4234 if (m->method->klass->wastypebuilder) {
4235 /* we use the same token as the one that was assigned
4236 * to the Methodbuilder.
4237 * FIXME: do the equivalent for Fields.
4239 token = m->method->token;
4242 * Each token should have a unique index, but the indexes are
4243 * assigned by managed code, so we don't know about them. An
4244 * easy solution is to count backwards...
4246 method_table_idx --;
4247 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4250 token = mono_image_get_methodref_token (assembly, m->method);
4252 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4253 } else if (strcmp (klass->name, "MonoField") == 0) {
4254 MonoReflectionField *f = (MonoReflectionField *)obj;
4255 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4256 static guint32 field_table_idx = 0xffffff;
4258 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4260 token = mono_image_get_fieldref_token (assembly, f);
4262 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4263 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4264 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4265 token = mono_image_get_array_token (assembly, m);
4266 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4267 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4268 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4270 g_error ("requested token for %s\n", klass->name);
4273 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4279 guint32 import_lookup_table;
4283 guint32 import_address_table_rva;
4291 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4293 static MonoDynamicImage*
4294 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4296 static const guchar entrycode [16] = {0xff, 0x25, 0};
4297 MonoDynamicImage *image;
4300 const char *version = mono_get_runtime_info ()->runtime_version;
4303 image = GC_MALLOC (sizeof (MonoDynamicImage));
4305 image = g_new0 (MonoDynamicImage, 1);
4308 /*g_print ("created image %p\n", image);*/
4309 /* keep in sync with image.c */
4310 image->image.name = assembly_name;
4311 image->image.assembly_name = image->image.name; /* they may be different */
4312 image->image.module_name = module_name;
4313 image->image.version = g_strdup (version);
4314 image->image.md_version_major = 1;
4315 image->image.md_version_minor = 1;
4316 image->image.dynamic = TRUE;
4318 image->image.references = g_new0 (MonoAssembly*, 1);
4319 image->image.references [0] = NULL;
4321 mono_image_init (&image->image);
4323 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4324 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4325 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4326 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4327 image->handleref = g_hash_table_new (NULL, NULL);
4328 image->tokens = mono_g_hash_table_new (NULL, NULL);
4329 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4330 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4331 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4332 image->gen_params = g_ptr_array_new ();
4334 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4335 string_heap_init (&image->sheap);
4336 mono_image_add_stream_data (&image->us, "", 1);
4337 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4338 /* import tables... */
4339 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4340 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4341 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4342 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4343 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4344 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4345 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4346 stream_data_align (&image->code);
4348 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4350 for (i=0; i < MONO_TABLE_NUM; ++i) {
4351 image->tables [i].next_idx = 1;
4352 image->tables [i].columns = table_sizes [i];
4355 image->image.assembly = (MonoAssembly*)assembly;
4356 image->run = assembly->run;
4357 image->save = assembly->save;
4358 image->pe_kind = 0x1; /* ILOnly */
4359 image->machine = 0x14c; /* I386 */
4365 * mono_image_basic_init:
4366 * @assembly: an assembly builder object
4368 * Create the MonoImage that represents the assembly builder and setup some
4369 * of the helper hash table and the basic metadata streams.
4372 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4374 MonoDynamicAssembly *assembly;
4375 MonoDynamicImage *image;
4376 MonoDomain *domain = mono_object_domain (assemblyb);
4378 MONO_ARCH_SAVE_REGS;
4380 if (assemblyb->dynamic_assembly)
4384 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4386 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4389 assembly->assembly.ref_count = 1;
4390 assembly->assembly.dynamic = TRUE;
4391 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4392 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4393 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4394 if (assemblyb->culture)
4395 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4397 assembly->assembly.aname.culture = g_strdup ("");
4399 if (assemblyb->version) {
4400 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4401 char **parts = version;
4402 assembly->assembly.aname.major = atoi (*parts++);
4403 assembly->assembly.aname.minor = atoi (*parts++);
4404 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4405 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4407 g_strfreev (version);
4409 assembly->assembly.aname.major = 0;
4410 assembly->assembly.aname.minor = 0;
4411 assembly->assembly.aname.build = 0;
4412 assembly->assembly.aname.revision = 0;
4415 assembly->run = assemblyb->access != 2;
4416 assembly->save = assemblyb->access != 1;
4418 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4419 image->initial_image = TRUE;
4420 assembly->assembly.aname.name = image->image.name;
4421 assembly->assembly.image = &image->image;
4423 mono_domain_assemblies_lock (domain);
4424 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4425 mono_domain_assemblies_unlock (domain);
4427 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4428 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4432 calc_section_size (MonoDynamicImage *assembly)
4436 /* alignment constraints */
4437 assembly->code.index += 3;
4438 assembly->code.index &= ~3;
4439 assembly->meta_size += 3;
4440 assembly->meta_size &= ~3;
4441 assembly->resources.index += 3;
4442 assembly->resources.index &= ~3;
4444 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4445 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4448 if (assembly->win32_res) {
4449 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4451 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4452 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4456 assembly->sections [MONO_SECTION_RELOC].size = 12;
4457 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4467 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4471 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4473 ResTreeNode *t1 = (ResTreeNode*)a;
4474 ResTreeNode *t2 = (ResTreeNode*)b;
4476 return t1->id - t2->id;
4480 * resource_tree_create:
4482 * Organize the resources into a resource tree.
4484 static ResTreeNode *
4485 resource_tree_create (MonoArray *win32_resources)
4487 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4491 tree = g_new0 (ResTreeNode, 1);
4493 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4494 MonoReflectionWin32Resource *win32_res =
4495 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4499 /* FIXME: BUG: this stores managed references in unmanaged memory */
4500 lang_node = g_new0 (ResTreeNode, 1);
4501 lang_node->id = win32_res->lang_id;
4502 lang_node->win32_res = win32_res;
4504 /* Create type node if neccesary */
4506 for (l = tree->children; l; l = l->next)
4507 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4508 type_node = (ResTreeNode*)l->data;
4513 type_node = g_new0 (ResTreeNode, 1);
4514 type_node->id = win32_res->res_type;
4517 * The resource types have to be sorted otherwise
4518 * Windows Explorer can't display the version information.
4520 tree->children = g_slist_insert_sorted (tree->children,
4521 type_node, resource_tree_compare_by_id);
4524 /* Create res node if neccesary */
4526 for (l = type_node->children; l; l = l->next)
4527 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4528 res_node = (ResTreeNode*)l->data;
4533 res_node = g_new0 (ResTreeNode, 1);
4534 res_node->id = win32_res->res_id;
4535 type_node->children = g_slist_append (type_node->children, res_node);
4538 res_node->children = g_slist_append (res_node->children, lang_node);
4545 * resource_tree_encode:
4547 * Encode the resource tree into the format used in the PE file.
4550 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4553 MonoPEResourceDir dir;
4554 MonoPEResourceDirEntry dir_entry;
4555 MonoPEResourceDataEntry data_entry;
4559 * For the format of the resource directory, see the article
4560 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4564 memset (&dir, 0, sizeof (dir));
4565 memset (&dir_entry, 0, sizeof (dir_entry));
4566 memset (&data_entry, 0, sizeof (data_entry));
4568 g_assert (sizeof (dir) == 16);
4569 g_assert (sizeof (dir_entry) == 8);
4570 g_assert (sizeof (data_entry) == 16);
4572 node->offset = p - begin;
4574 /* IMAGE_RESOURCE_DIRECTORY */
4575 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4577 memcpy (p, &dir, sizeof (dir));
4580 /* Reserve space for entries */
4582 p += sizeof (dir_entry) * dir.res_id_entries;
4584 /* Write children */
4585 for (l = node->children; l; l = l->next) {
4586 ResTreeNode *child = (ResTreeNode*)l->data;
4588 if (child->win32_res) {
4590 child->offset = p - begin;
4592 /* IMAGE_RESOURCE_DATA_ENTRY */
4593 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4594 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4596 memcpy (p, &data_entry, sizeof (data_entry));
4597 p += sizeof (data_entry);
4599 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4600 p += data_entry.rde_size;
4602 resource_tree_encode (child, begin, p, &p);
4606 /* IMAGE_RESOURCE_ENTRY */
4607 for (l = node->children; l; l = l->next) {
4608 ResTreeNode *child = (ResTreeNode*)l->data;
4609 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4611 dir_entry.is_dir = child->win32_res ? 0 : 1;
4612 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4614 memcpy (entries, &dir_entry, sizeof (dir_entry));
4615 entries += sizeof (dir_entry);
4622 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4627 MonoReflectionWin32Resource *win32_res;
4630 if (!assemblyb->win32_resources)
4634 * Resources are stored in a three level tree inside the PE file.
4635 * - level one contains a node for each type of resource
4636 * - level two contains a node for each resource
4637 * - level three contains a node for each instance of a resource for a
4638 * specific language.
4641 tree = resource_tree_create (assemblyb->win32_resources);
4643 /* Estimate the size of the encoded tree */
4645 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4646 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4647 size += mono_array_length (win32_res->res_data);
4649 /* Directory structure */
4650 size += mono_array_length (assemblyb->win32_resources) * 256;
4651 p = buf = g_malloc (size);
4653 resource_tree_encode (tree, p, p, &p);
4655 g_assert (p - buf < size);
4657 assembly->win32_res = g_malloc (p - buf);
4658 assembly->win32_res_size = p - buf;
4659 memcpy (assembly->win32_res, buf, p - buf);
4665 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4667 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4670 p += sizeof (MonoPEResourceDir);
4671 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4672 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4673 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4674 if (dir_entry->is_dir) {
4675 fixup_resource_directory (res_section, child, rva);
4677 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4678 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4681 p += sizeof (MonoPEResourceDirEntry);
4686 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4689 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4690 g_error ("WriteFile returned %d\n", GetLastError ());
4694 * mono_image_create_pefile:
4695 * @mb: a module builder object
4697 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4698 * assembly->pefile where it can be easily retrieved later in chunks.
4701 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4702 MonoMSDOSHeader *msdos;
4703 MonoDotNetHeader *header;
4704 MonoSectionTable *section;
4705 MonoCLIHeader *cli_header;
4706 guint32 size, image_size, virtual_base, text_offset;
4707 guint32 header_start, section_start, file_offset, virtual_offset;
4708 MonoDynamicImage *assembly;
4709 MonoReflectionAssemblyBuilder *assemblyb;
4710 MonoDynamicStream pefile_stream = {0};
4711 MonoDynamicStream *pefile = &pefile_stream;
4713 guint32 *rva, value;
4715 static const unsigned char msheader[] = {
4716 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4717 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4718 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4719 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4720 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4721 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4722 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4723 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4726 assemblyb = mb->assemblyb;
4728 mono_image_basic_init (assemblyb);
4729 assembly = mb->dynamic_image;
4731 assembly->pe_kind = assemblyb->pe_kind;
4732 assembly->machine = assemblyb->machine;
4733 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4734 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4736 mono_image_build_metadata (mb);
4738 if (mb->is_main && assemblyb->resources) {
4739 int len = mono_array_length (assemblyb->resources);
4740 for (i = 0; i < len; ++i)
4741 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4744 if (mb->resources) {
4745 int len = mono_array_length (mb->resources);
4746 for (i = 0; i < len; ++i)
4747 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4750 build_compressed_metadata (assembly);
4753 assembly_add_win32_resources (assembly, assemblyb);
4755 nsections = calc_section_size (assembly);
4757 /* The DOS header and stub */
4758 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4759 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4761 /* the dotnet header */
4762 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4764 /* the section tables */
4765 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4767 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4768 virtual_offset = VIRT_ALIGN;
4771 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4772 if (!assembly->sections [i].size)
4775 file_offset += FILE_ALIGN - 1;
4776 file_offset &= ~(FILE_ALIGN - 1);
4777 virtual_offset += VIRT_ALIGN - 1;
4778 virtual_offset &= ~(VIRT_ALIGN - 1);
4780 assembly->sections [i].offset = file_offset;
4781 assembly->sections [i].rva = virtual_offset;
4783 file_offset += assembly->sections [i].size;
4784 virtual_offset += assembly->sections [i].size;
4785 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4788 file_offset += FILE_ALIGN - 1;
4789 file_offset &= ~(FILE_ALIGN - 1);
4791 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4793 /* back-patch info */
4794 msdos = (MonoMSDOSHeader*)pefile->data;
4795 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4797 header = (MonoDotNetHeader*)(pefile->data + header_start);
4798 header->pesig [0] = 'P';
4799 header->pesig [1] = 'E';
4801 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4802 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4803 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4804 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4805 if (assemblyb->pekind == 1) {
4807 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4810 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4813 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4815 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4816 header->pe.pe_major = 6;
4817 header->pe.pe_minor = 0;
4818 size = assembly->sections [MONO_SECTION_TEXT].size;
4819 size += FILE_ALIGN - 1;
4820 size &= ~(FILE_ALIGN - 1);
4821 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4822 size = assembly->sections [MONO_SECTION_RSRC].size;
4823 size += FILE_ALIGN - 1;
4824 size &= ~(FILE_ALIGN - 1);
4825 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4826 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4827 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4828 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4829 /* pe_rva_entry_point always at the beginning of the text section */
4830 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4832 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4833 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4834 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4835 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4836 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4837 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4838 size = section_start;
4839 size += FILE_ALIGN - 1;
4840 size &= ~(FILE_ALIGN - 1);
4841 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4843 size += VIRT_ALIGN - 1;
4844 size &= ~(VIRT_ALIGN - 1);
4845 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4848 // Translate the PEFileKind value to the value expected by the Windows loader
4854 // PEFileKinds.Dll == 1
4855 // PEFileKinds.ConsoleApplication == 2
4856 // PEFileKinds.WindowApplication == 3
4859 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4860 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4862 if (assemblyb->pekind == 3)
4867 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4869 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4870 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4871 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4872 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4873 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4874 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4876 /* fill data directory entries */
4878 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4879 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4881 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4882 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4884 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4885 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4886 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4887 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4888 /* patch entrypoint name */
4889 if (assemblyb->pekind == 1)
4890 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4892 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4893 /* patch imported function RVA name */
4894 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4895 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4897 /* the import table */
4898 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4899 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4900 /* patch imported dll RVA name and other entries in the dir */
4901 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4902 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4903 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4904 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4905 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4906 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4908 p = (assembly->code.data + assembly->ilt_offset);
4909 value = (assembly->text_rva + assembly->imp_names_offset);
4910 *p++ = (value) & 0xff;
4911 *p++ = (value >> 8) & (0xff);
4912 *p++ = (value >> 16) & (0xff);
4913 *p++ = (value >> 24) & (0xff);
4915 /* the CLI header info */
4916 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4917 cli_header->ch_size = GUINT32_FROM_LE (72);
4918 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4919 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4920 if (assemblyb->entry_point) {
4921 guint32 table_idx = 0;
4922 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4923 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4924 table_idx = methodb->table_idx;
4926 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4928 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4930 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4932 /* The embedded managed resources */
4933 text_offset = assembly->text_rva + assembly->code.index;
4934 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4935 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4936 text_offset += assembly->resources.index;
4937 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4938 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4939 text_offset += assembly->meta_size;
4940 if (assembly->strong_name_size) {
4941 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4942 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4943 text_offset += assembly->strong_name_size;
4946 /* write the section tables and section content */
4947 section = (MonoSectionTable*)(pefile->data + section_start);
4948 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4949 static const char *section_names [] = {
4950 ".text", ".rsrc", ".reloc"
4952 if (!assembly->sections [i].size)
4954 strcpy (section->st_name, section_names [i]);
4955 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4956 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4957 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4958 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4959 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4960 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4961 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4965 checked_write_file (file, pefile->data, pefile->index);
4967 mono_dynamic_stream_reset (pefile);
4969 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4970 if (!assembly->sections [i].size)
4973 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4974 g_error ("SetFilePointer returned %d\n", GetLastError ());
4977 case MONO_SECTION_TEXT:
4978 /* patch entry point */
4979 p = (assembly->code.data + 2);
4980 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4981 *p++ = (value) & 0xff;
4982 *p++ = (value >> 8) & 0xff;
4983 *p++ = (value >> 16) & 0xff;
4984 *p++ = (value >> 24) & 0xff;
4986 checked_write_file (file, assembly->code.data, assembly->code.index);
4987 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4988 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4989 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4992 g_free (assembly->image.raw_metadata);
4994 case MONO_SECTION_RELOC: {
4998 guint16 type_and_offset;
5002 g_assert (sizeof (reloc) == 12);
5004 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5005 reloc.block_size = GUINT32_FROM_LE (12);
5008 * the entrypoint is always at the start of the text section
5009 * 3 is IMAGE_REL_BASED_HIGHLOW
5010 * 2 is patch_size_rva - text_rva
5012 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5015 checked_write_file (file, &reloc, sizeof (reloc));
5019 case MONO_SECTION_RSRC:
5020 if (assembly->win32_res) {
5022 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5023 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5024 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5028 g_assert_not_reached ();
5032 /* check that the file is properly padded */
5033 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5034 g_error ("SetFilePointer returned %d\n", GetLastError ());
5035 if (! SetEndOfFile (file))
5036 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5038 mono_dynamic_stream_reset (&assembly->code);
5039 mono_dynamic_stream_reset (&assembly->us);
5040 mono_dynamic_stream_reset (&assembly->blob);
5041 mono_dynamic_stream_reset (&assembly->guid);
5042 mono_dynamic_stream_reset (&assembly->sheap);
5044 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5045 g_hash_table_destroy (assembly->blob_cache);
5046 assembly->blob_cache = NULL;
5049 MonoReflectionModule *
5050 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5054 MonoImageOpenStatus status;
5055 MonoDynamicAssembly *assembly;
5056 guint32 module_count;
5057 MonoImage **new_modules;
5059 name = mono_string_to_utf8 (fileName);
5061 image = mono_image_open (name, &status);
5064 if (status == MONO_IMAGE_ERROR_ERRNO)
5065 exc = mono_get_exception_file_not_found (fileName);
5067 exc = mono_get_exception_bad_image_format (name);
5069 mono_raise_exception (exc);
5074 assembly = ab->dynamic_assembly;
5075 image->assembly = (MonoAssembly*)assembly;
5077 module_count = image->assembly->image->module_count;
5078 new_modules = g_new0 (MonoImage *, module_count + 1);
5080 if (image->assembly->image->modules)
5081 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5082 new_modules [module_count] = image;
5083 mono_image_addref (image);
5085 g_free (image->assembly->image->modules);
5086 image->assembly->image->modules = new_modules;
5087 image->assembly->image->module_count ++;
5089 mono_assembly_load_references (image, &status);
5091 mono_image_close (image);
5092 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5095 return mono_module_get_object (mono_domain_get (), image);
5099 * We need to return always the same object for MethodInfo, FieldInfo etc..
5100 * but we need to consider the reflected type.
5101 * type uses a different hash, since it uses custom hash/equal functions.
5106 MonoClass *refclass;
5110 reflected_equal (gconstpointer a, gconstpointer b) {
5111 const ReflectedEntry *ea = a;
5112 const ReflectedEntry *eb = b;
5114 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5118 reflected_hash (gconstpointer a) {
5119 const ReflectedEntry *ea = a;
5120 return GPOINTER_TO_UINT (ea->item);
5123 #define CHECK_OBJECT(t,p,k) \
5129 mono_domain_lock (domain); \
5130 if (!domain->refobject_hash) \
5131 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5132 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5133 mono_domain_unlock (domain); \
5136 mono_domain_unlock (domain); \
5140 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5142 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5145 #define CACHE_OBJECT(t,p,o,k) \
5148 ReflectedEntry pe; \
5150 pe.refclass = (k); \
5151 mono_domain_lock (domain); \
5152 if (!domain->refobject_hash) \
5153 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5154 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5156 ReflectedEntry *e = ALLOC_REFENTRY; \
5158 e->refclass = (k); \
5159 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5162 mono_domain_unlock (domain); \
5167 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5169 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5173 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5175 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5179 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5181 MonoDynamicImage *image = moduleb->dynamic_image;
5182 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5185 MonoImage **new_modules;
5188 * FIXME: we already created an image in mono_image_basic_init (), but
5189 * we don't know which module it belongs to, since that is only
5190 * determined at assembly save time.
5192 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5193 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5195 moduleb->module.image = &image->image;
5196 moduleb->dynamic_image = image;
5197 register_module (mono_object_domain (moduleb), moduleb, image);
5199 /* register the module with the assembly */
5200 ass = ab->dynamic_assembly->assembly.image;
5201 module_count = ass->module_count;
5202 new_modules = g_new0 (MonoImage *, module_count + 1);
5205 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5206 new_modules [module_count] = &image->image;
5207 mono_image_addref (&image->image);
5209 g_free (ass->modules);
5210 ass->modules = new_modules;
5211 ass->module_count ++;
5216 * mono_assembly_get_object:
5217 * @domain: an app domain
5218 * @assembly: an assembly
5220 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5222 MonoReflectionAssembly*
5223 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5225 static MonoClass *System_Reflection_Assembly;
5226 MonoReflectionAssembly *res;
5228 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5229 if (!System_Reflection_Assembly)
5230 System_Reflection_Assembly = mono_class_from_name (
5231 mono_defaults.corlib, "System.Reflection", "Assembly");
5232 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5233 res->assembly = assembly;
5235 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5240 MonoReflectionModule*
5241 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5243 static MonoClass *System_Reflection_Module;
5244 MonoReflectionModule *res;
5247 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5248 if (!System_Reflection_Module)
5249 System_Reflection_Module = mono_class_from_name (
5250 mono_defaults.corlib, "System.Reflection", "Module");
5251 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5254 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5256 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
5257 basename = g_path_get_basename (image->name);
5258 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
5259 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
5263 if (image->assembly->image == image) {
5264 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5267 g_assert (image->assembly->image->modules);
5269 for (i = 0; i < image->assembly->image->module_count; i++) {
5270 if (image->assembly->image->modules [i] == image)
5271 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5273 g_assert (res->token);
5276 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5279 MonoReflectionModule*
5280 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5282 static MonoClass *System_Reflection_Module;
5283 MonoReflectionModule *res;
5284 MonoTableInfo *table;
5285 guint32 cols [MONO_FILE_SIZE];
5287 guint32 i, name_idx;
5290 if (!System_Reflection_Module)
5291 System_Reflection_Module = mono_class_from_name (
5292 mono_defaults.corlib, "System.Reflection", "Module");
5293 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5295 table = &image->tables [MONO_TABLE_FILE];
5296 g_assert (table_index < table->rows);
5297 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5300 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
5301 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5303 /* Check whenever the row has a corresponding row in the moduleref table */
5304 table = &image->tables [MONO_TABLE_MODULEREF];
5305 for (i = 0; i < table->rows; ++i) {
5306 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5307 val = mono_metadata_string_heap (image, name_idx);
5308 if (strcmp (val, name) == 0)
5309 res->image = image->modules [i];
5312 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
5313 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
5314 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
5315 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5316 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5322 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5324 if ((t1->type != t2->type) ||
5325 (t1->byref != t2->byref))
5329 case MONO_TYPE_VOID:
5330 case MONO_TYPE_BOOLEAN:
5331 case MONO_TYPE_CHAR:
5342 case MONO_TYPE_STRING:
5345 case MONO_TYPE_OBJECT:
5346 case MONO_TYPE_TYPEDBYREF:
5348 case MONO_TYPE_VALUETYPE:
5349 case MONO_TYPE_CLASS:
5350 case MONO_TYPE_SZARRAY:
5351 return t1->data.klass == t2->data.klass;
5353 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5354 case MONO_TYPE_ARRAY:
5355 if (t1->data.array->rank != t2->data.array->rank)
5357 return t1->data.array->eklass == t2->data.array->eklass;
5358 case MONO_TYPE_GENERICINST: {
5360 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5362 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5363 &t2->data.generic_class->container_class->byval_arg))
5365 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5366 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5372 case MONO_TYPE_MVAR:
5373 return t1->data.generic_param == t2->data.generic_param;
5375 g_error ("implement type compare for %0x!", t1->type);
5383 mymono_metadata_type_hash (MonoType *t1)
5389 hash |= t1->byref << 6; /* do not collide with t1->type values */
5391 case MONO_TYPE_VALUETYPE:
5392 case MONO_TYPE_CLASS:
5393 case MONO_TYPE_SZARRAY:
5394 /* check if the distribution is good enough */
5395 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5397 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5398 case MONO_TYPE_GENERICINST: {
5400 MonoGenericInst *inst = t1->data.generic_class->inst;
5401 hash += g_str_hash (t1->data.generic_class->container_class->name);
5403 for (i = 0; i < inst->type_argc; ++i) {
5404 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5413 static MonoReflectionGenericClass*
5414 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5416 static MonoClass *System_Reflection_MonoGenericClass;
5417 MonoReflectionGenericClass *res;
5418 MonoInflatedGenericClass *gclass;
5421 if (!System_Reflection_MonoGenericClass) {
5422 System_Reflection_MonoGenericClass = mono_class_from_name (
5423 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5424 g_assert (System_Reflection_MonoGenericClass);
5427 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5428 gklass = gclass->generic_class.container_class;
5429 g_assert (gklass->generic_container);
5431 mono_class_init (gclass->klass);
5433 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5435 res->type.type = geninst;
5436 if (gklass->wastypebuilder && gklass->reflection_info)
5437 MONO_OBJECT_SETREF (res, generic_type, gklass->reflection_info);
5439 MONO_OBJECT_SETREF (res, generic_type, mono_type_get_object (domain, &gklass->byval_arg));
5445 verify_safe_for_managed_space (MonoType *type)
5447 switch (type->type) {
5449 case MONO_TYPE_ARRAY:
5450 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
5452 return verify_safe_for_managed_space (type->data.type);
5453 case MONO_TYPE_SZARRAY:
5454 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
5455 case MONO_TYPE_GENERICINST: {
5456 MonoGenericInst *inst = type->data.generic_class->inst;
5460 for (i = 0; i < inst->type_argc; ++i)
5461 if (!verify_safe_for_managed_space (inst->type_argv [i]))
5467 case MONO_TYPE_MVAR:
5468 return type->data.generic_param->owner != NULL;
5474 * mono_type_get_object:
5475 * @domain: an app domain
5478 * Return an System.MonoType object representing the type @type.
5481 mono_type_get_object (MonoDomain *domain, MonoType *type)
5483 MonoReflectionType *res;
5484 MonoClass *klass = mono_class_from_mono_type (type);
5486 mono_domain_lock (domain);
5487 if (!domain->type_hash)
5488 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5489 (GCompareFunc)mymono_metadata_type_equal);
5490 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5491 mono_domain_unlock (domain);
5494 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5495 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5496 mono_g_hash_table_insert (domain->type_hash, type, res);
5497 mono_domain_unlock (domain);
5501 if (!verify_safe_for_managed_space (type)) {
5502 mono_domain_unlock (domain);
5503 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
5506 if (klass->reflection_info && !klass->wastypebuilder) {
5507 /* g_assert_not_reached (); */
5508 /* should this be considered an error condition? */
5510 mono_domain_unlock (domain);
5511 return klass->reflection_info;
5514 mono_class_init (klass);
5515 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5517 mono_g_hash_table_insert (domain->type_hash, type, res);
5518 mono_domain_unlock (domain);
5523 * mono_method_get_object:
5524 * @domain: an app domain
5526 * @refclass: the reflected type (can be NULL)
5528 * Return an System.Reflection.MonoMethod object representing the method @method.
5530 MonoReflectionMethod*
5531 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5534 * We use the same C representation for methods and constructors, but the type
5535 * name in C# is different.
5539 MonoReflectionMethod *ret;
5541 if (method->is_inflated) {
5542 MonoReflectionGenericMethod *gret;
5544 method = mono_get_inflated_method (method);
5545 refclass = method->klass;
5546 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5547 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5548 cname = "MonoGenericCMethod";
5550 cname = "MonoGenericMethod";
5551 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5553 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5554 gret->method.method = method;
5555 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
5556 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
5557 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5561 refclass = method->klass;
5563 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5564 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5565 cname = "MonoCMethod";
5567 cname = "MonoMethod";
5568 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5570 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5571 ret->method = method;
5572 MONO_OBJECT_SETREF (ret, name, mono_string_new (domain, method->name));
5573 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
5574 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5578 * mono_field_get_object:
5579 * @domain: an app domain
5583 * Return an System.Reflection.MonoField object representing the field @field
5586 MonoReflectionField*
5587 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5589 MonoReflectionField *res;
5592 CHECK_OBJECT (MonoReflectionField *, field, klass);
5593 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5594 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5597 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, field->name));
5598 if (field->generic_info)
5599 res->attrs = field->generic_info->generic_type->attrs;
5601 res->attrs = field->type->attrs;
5602 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
5603 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5607 * mono_property_get_object:
5608 * @domain: an app domain
5610 * @property: a property
5612 * Return an System.Reflection.MonoProperty object representing the property @property
5615 MonoReflectionProperty*
5616 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5618 MonoReflectionProperty *res;
5621 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5622 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5623 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5625 res->property = property;
5626 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5630 * mono_event_get_object:
5631 * @domain: an app domain
5635 * Return an System.Reflection.MonoEvent object representing the event @event
5638 MonoReflectionEvent*
5639 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5641 MonoReflectionEvent *res;
5644 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5645 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5646 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5649 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5653 * mono_param_get_objects:
5654 * @domain: an app domain
5657 * Return an System.Reflection.ParameterInfo array object representing the parameters
5658 * in the method @method.
5661 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5663 static MonoClass *System_Reflection_ParameterInfo;
5664 MonoArray *res = NULL;
5665 MonoReflectionMethod *member = NULL;
5666 MonoReflectionParameter *param = NULL;
5667 char **names, **blobs = NULL;
5668 guint32 *types = NULL;
5669 MonoType *type = NULL;
5670 MonoObject *dbnull = mono_get_dbnull_object (domain);
5671 MonoMarshalSpec **mspecs;
5674 if (!System_Reflection_ParameterInfo)
5675 System_Reflection_ParameterInfo = mono_class_from_name (
5676 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5678 if (!mono_method_signature (method)->param_count)
5679 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5681 /* Note: the cache is based on the address of the signature into the method
5682 * since we already cache MethodInfos with the method as keys.
5684 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5686 member = mono_method_get_object (domain, method, NULL);
5687 names = g_new (char *, mono_method_signature (method)->param_count);
5688 mono_method_get_param_names (method, (const char **) names);
5690 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5691 mono_method_get_marshal_info (method, mspecs);
5693 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5694 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5695 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5696 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, mono_method_signature (method)->params [i]));
5697 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
5698 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
5699 param->PositionImpl = i;
5700 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5702 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5703 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5707 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5708 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5709 get_default_param_value_blobs (method, blobs, types);
5712 /* Build MonoType for the type from the Constant Table */
5714 type = g_new0 (MonoType, 1);
5715 type->type = types [i];
5716 type->data.klass = NULL;
5717 if (types [i] == MONO_TYPE_CLASS)
5718 type->data.klass = mono_defaults.object_class;
5720 type->data.klass = mono_class_from_mono_type (type);
5722 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
5724 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5725 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5726 MONO_OBJECT_SETREF (param, DefaultValueImpl, dbnull);
5731 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
5733 mono_array_setref (res, i, param);
5740 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5742 mono_metadata_free_marshal_spec (mspecs [i]);
5745 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5749 * mono_method_body_get_object:
5750 * @domain: an app domain
5753 * Return an System.Reflection.MethodBody object representing the method @method.
5755 MonoReflectionMethodBody*
5756 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5758 static MonoClass *System_Reflection_MethodBody = NULL;
5759 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5760 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5761 MonoReflectionMethodBody *ret;
5762 MonoMethodNormal *mn;
5763 MonoMethodHeader *header;
5764 guint32 method_rva, local_var_sig_token;
5766 unsigned char format, flags;
5769 if (!System_Reflection_MethodBody)
5770 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5771 if (!System_Reflection_LocalVariableInfo)
5772 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5773 if (!System_Reflection_ExceptionHandlingClause)
5774 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5776 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5778 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5779 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5780 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5781 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5783 mn = (MonoMethodNormal *)method;
5784 header = mono_method_get_header (method);
5786 /* Obtain local vars signature token */
5787 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5788 ptr = mono_image_rva_map (method->klass->image, method_rva);
5789 flags = *(const unsigned char *) ptr;
5790 format = flags & METHOD_HEADER_FORMAT_MASK;
5792 case METHOD_HEADER_TINY_FORMAT:
5793 case METHOD_HEADER_TINY_FORMAT1:
5794 local_var_sig_token = 0;
5796 case METHOD_HEADER_FAT_FORMAT:
5800 local_var_sig_token = read32 (ptr);
5803 g_assert_not_reached ();
5806 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5808 ret->init_locals = header->init_locals;
5809 ret->max_stack = header->max_stack;
5810 ret->local_var_sig_token = local_var_sig_token;
5811 MONO_OBJECT_SETREF (ret, il, mono_array_new (domain, mono_defaults.byte_class, header->code_size));
5812 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
5815 MONO_OBJECT_SETREF (ret, locals, mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals));
5816 for (i = 0; i < header->num_locals; ++i) {
5817 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5818 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
5819 info->is_pinned = header->locals [i]->pinned;
5820 info->local_index = i;
5821 mono_array_setref (ret->locals, i, info);
5825 MONO_OBJECT_SETREF (ret, clauses, mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
5826 for (i = 0; i < header->num_clauses; ++i) {
5827 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5828 MonoExceptionClause *clause = &header->clauses [i];
5830 info->flags = clause->flags;
5831 info->try_offset = clause->try_offset;
5832 info->try_length = clause->try_len;
5833 info->handler_offset = clause->handler_offset;
5834 info->handler_length = clause->handler_len;
5835 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5836 info->filter_offset = clause->data.filter_offset;
5837 else if (clause->data.catch_class)
5838 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
5840 mono_array_setref (ret->clauses, i, info);
5843 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5848 mono_get_dbnull_object (MonoDomain *domain)
5852 static MonoClassField *dbnull_value_field = NULL;
5854 if (!dbnull_value_field) {
5855 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5856 mono_class_init (klass);
5857 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5858 g_assert (dbnull_value_field);
5860 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5867 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5869 guint32 param_index, i, lastp, crow = 0;
5870 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5873 MonoClass *klass = method->klass;
5874 MonoImage *image = klass->image;
5875 MonoMethodSignature *methodsig = mono_method_signature (method);
5877 MonoTableInfo *constt;
5878 MonoTableInfo *methodt;
5879 MonoTableInfo *paramt;
5881 if (!methodsig->param_count)
5884 mono_class_init (klass);
5886 if (klass->image->dynamic) {
5887 MonoReflectionMethodAux *aux;
5888 if (method->is_inflated)
5889 method = ((MonoMethodInflated*)method)->declaring;
5890 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5891 if (aux && aux->param_defaults) {
5892 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5893 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5898 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5899 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5900 constt = &image->tables [MONO_TABLE_CONSTANT];
5902 idx = mono_method_get_index (method) - 1;
5903 g_assert (idx != -1);
5905 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5906 if (idx + 1 < methodt->rows)
5907 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5909 lastp = paramt->rows + 1;
5911 for (i = param_index; i < lastp; ++i) {
5914 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5915 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5917 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5920 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5925 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5926 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5927 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5934 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5939 MonoType *basetype = type;
5944 klass = mono_class_from_mono_type (type);
5945 if (klass->valuetype) {
5946 object = mono_object_new (domain, klass);
5947 retval = ((gchar *) object + sizeof (MonoObject));
5948 if (klass->enumtype)
5949 basetype = klass->enum_basetype;
5954 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5961 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5965 memset (assembly, 0, sizeof (MonoAssemblyName));
5967 assembly->culture = "";
5968 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5970 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5973 while (g_ascii_isspace (*p) || *p == ',') {
5982 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5984 assembly->major = strtoul (p, &s, 10);
5985 if (s == p || *s != '.')
5988 assembly->minor = strtoul (p, &s, 10);
5989 if (s == p || *s != '.')
5992 assembly->build = strtoul (p, &s, 10);
5993 if (s == p || *s != '.')
5996 assembly->revision = strtoul (p, &s, 10);
6000 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
6002 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
6003 assembly->culture = "";
6006 assembly->culture = p;
6007 while (*p && *p != ',') {
6011 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
6013 if (strncmp (p, "null", 4) == 0) {
6018 while (*p && *p != ',') {
6021 len = (p - start + 1);
6022 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
6023 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
6024 g_strlcpy (assembly->public_key_token, start, len);
6027 while (*p && *p != ',')
6031 while (g_ascii_isspace (*p) || *p == ',') {
6045 * mono_reflection_parse_type:
6048 * Parse a type name as accepted by the GetType () method and output the info
6049 * extracted in the info structure.
6050 * the name param will be mangled, so, make a copy before passing it to this function.
6051 * The fields in info will be valid until the memory pointed to by name is valid.
6053 * See also mono_type_get_name () below.
6055 * Returns: 0 on parse error.
6058 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
6059 MonoTypeNameParse *info)
6061 char *start, *p, *w, *temp, *last_point, *startn;
6062 int in_modifiers = 0;
6063 int isbyref = 0, rank, arity = 0, i;
6065 start = p = w = name;
6067 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6068 info->name = info->name_space = NULL;
6069 info->nested = NULL;
6070 info->modifiers = NULL;
6071 info->type_arguments = NULL;
6073 /* last_point separates the namespace from the name */
6079 *p = 0; /* NULL terminate the name */
6081 info->nested = g_list_append (info->nested, startn);
6082 /* we have parsed the nesting namespace + name */
6086 info->name_space = start;
6088 info->name = last_point + 1;
6090 info->name_space = (char *)"";
6109 i = strtol (p, &temp, 10);
6126 info->name_space = start;
6128 info->name = last_point + 1;
6130 info->name_space = (char *)"";
6137 if (isbyref) /* only one level allowed by the spec */
6140 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6144 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6150 info->type_arguments = g_ptr_array_new ();
6151 for (i = 0; i < arity; i++) {
6152 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6153 gboolean fqname = FALSE;
6155 g_ptr_array_add (info->type_arguments, subinfo);
6162 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6173 while (*p && (*p != ']'))
6181 if (g_ascii_isspace (*aname)) {
6188 !assembly_name_to_aname (&subinfo->assembly, aname))
6192 if (i + 1 < arity) {
6212 else if (*p != '*') /* '*' means unknown lower bound */
6218 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6229 if (g_ascii_isspace (*p)) {
6236 return 0; /* missing assembly name */
6237 if (!assembly_name_to_aname (&info->assembly, p))
6243 if (info->assembly.name)
6246 // *w = 0; /* terminate class name */
6248 if (!info->name || !*info->name)
6252 /* add other consistency checks */
6257 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6259 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6263 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6265 gboolean type_resolve = FALSE;
6268 if (info->assembly.name) {
6269 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6271 /* then we must load the assembly ourselve - see #60439 */
6272 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6276 image = assembly->image;
6277 } else if (!image) {
6278 image = mono_defaults.corlib;
6281 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6282 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6283 image = mono_defaults.corlib;
6284 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6291 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6298 image = mono_defaults.corlib;
6301 klass = mono_class_from_name_case (image, info->name_space, info->name);
6303 klass = mono_class_from_name (image, info->name_space, info->name);
6306 for (mod = info->nested; mod; mod = mod->next) {
6309 mono_class_init (klass);
6310 nested = klass->nested_classes;
6313 klass = nested->data;
6315 if (g_strcasecmp (klass->name, mod->data) == 0)
6318 if (strcmp (klass->name, mod->data) == 0)
6322 nested = nested->next;
6329 mono_class_init (klass);
6331 if (info->type_arguments) {
6332 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6333 MonoReflectionType *the_type;
6337 for (i = 0; i < info->type_arguments->len; i++) {
6338 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6340 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6341 if (!type_args [i]) {
6347 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6349 instance = mono_reflection_bind_generic_parameters (
6350 the_type, info->type_arguments->len, type_args);
6357 klass = mono_class_from_mono_type (instance);
6360 for (mod = info->modifiers; mod; mod = mod->next) {
6361 modval = GPOINTER_TO_UINT (mod->data);
6362 if (!modval) { /* byref: must be last modifier */
6363 return &klass->this_arg;
6364 } else if (modval == -1) {
6365 klass = mono_ptr_class_get (&klass->byval_arg);
6366 } else { /* array rank */
6367 klass = mono_array_class_get (klass, modval);
6369 mono_class_init (klass);
6372 return &klass->byval_arg;
6376 * mono_reflection_get_type:
6377 * @image: a metadata context
6378 * @info: type description structure
6379 * @ignorecase: flag for case-insensitive string compares
6380 * @type_resolve: whenever type resolve was already tried
6382 * Build a MonoType from the type description in @info.
6387 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6390 MonoReflectionAssembly *assembly;
6394 type = mono_reflection_get_type_internal (image, info, ignorecase);
6397 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6404 *type_resolve = TRUE;
6407 /* Reconstruct the type name */
6408 fullName = g_string_new ("");
6409 if (info->name_space && (info->name_space [0] != '\0'))
6410 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6412 g_string_printf (fullName, info->name);
6413 for (mod = info->nested; mod; mod = mod->next)
6414 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6416 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6418 if (assembly->assembly->dynamic) {
6419 /* Enumerate all modules */
6420 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6424 if (abuilder->modules) {
6425 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6426 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6427 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6433 if (!type && abuilder->loaded_modules) {
6434 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6435 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6436 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6443 type = mono_reflection_get_type_internal (assembly->assembly->image,
6446 g_string_free (fullName, TRUE);
6451 free_type_info (MonoTypeNameParse *info)
6453 g_list_free (info->modifiers);
6454 g_list_free (info->nested);
6456 if (info->type_arguments) {
6459 for (i = 0; i < info->type_arguments->len; i++) {
6460 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6462 free_type_info (subinfo);
6465 g_ptr_array_free (info->type_arguments, TRUE);
6470 * mono_reflection_type_from_name:
6472 * @image: a metadata context (can be NULL).
6474 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6475 * it defaults to get the type from @image or, if @image is NULL or loading
6476 * from it fails, uses corlib.
6480 mono_reflection_type_from_name (char *name, MonoImage *image)
6482 MonoType *type = NULL;
6483 MonoTypeNameParse info;
6486 /* Make a copy since parse_type modifies its argument */
6487 tmp = g_strdup (name);
6489 /*g_print ("requested type %s\n", str);*/
6490 if (mono_reflection_parse_type (tmp, &info)) {
6491 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6495 free_type_info (&info);
6500 * mono_reflection_get_token:
6502 * Return the metadata token of OBJ which should be an object
6503 * representing a metadata element.
6506 mono_reflection_get_token (MonoObject *obj)
6511 klass = obj->vtable->klass;
6513 if (strcmp (klass->name, "MethodBuilder") == 0) {
6514 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6516 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6517 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6518 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6520 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6521 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6522 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6523 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6524 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6525 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6526 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6527 } else if (strcmp (klass->name, "MonoType") == 0) {
6528 MonoReflectionType *tb = (MonoReflectionType *)obj;
6529 token = mono_class_from_mono_type (tb->type)->type_token;
6530 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6531 strcmp (klass->name, "MonoMethod") == 0 ||
6532 strcmp (klass->name, "MonoGenericMethod") == 0 ||
6533 strcmp (klass->name, "MonoGenericCMethod") == 0) {
6534 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6535 if (m->method->is_inflated) {
6536 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
6537 return inflated->declaring->token;
6539 token = m->method->token;
6541 } else if (strcmp (klass->name, "MonoField") == 0) {
6542 MonoReflectionField *f = (MonoReflectionField*)obj;
6544 if (f->field->generic_info && f->field->generic_info->reflection_info)
6545 return mono_reflection_get_token (f->field->generic_info->reflection_info);
6547 token = mono_class_get_field_token (f->field);
6548 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6549 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6551 token = mono_class_get_property_token (p->property);
6552 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6553 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6555 token = mono_class_get_event_token (p->event);
6556 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6557 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6559 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6560 } else if (strcmp (klass->name, "Module") == 0) {
6561 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6564 } else if (strcmp (klass->name, "Assembly") == 0) {
6565 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6567 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6568 MonoException *ex = mono_get_exception_not_implemented (msg);
6570 mono_raise_exception (ex);
6577 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6579 int slen, type = t->type;
6580 MonoClass *tklass = t->data.klass;
6586 case MONO_TYPE_BOOLEAN: {
6587 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6592 case MONO_TYPE_CHAR:
6594 case MONO_TYPE_I2: {
6595 guint16 *val = g_malloc (sizeof (guint16));
6600 #if SIZEOF_VOID_P == 4
6606 case MONO_TYPE_I4: {
6607 guint32 *val = g_malloc (sizeof (guint32));
6612 #if SIZEOF_VOID_P == 8
6613 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6618 case MONO_TYPE_I8: {
6619 guint64 *val = g_malloc (sizeof (guint64));
6624 case MONO_TYPE_VALUETYPE:
6625 if (t->data.klass->enumtype) {
6626 type = t->data.klass->enum_basetype->type;
6629 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6632 case MONO_TYPE_STRING:
6633 if (*p == (char)0xFF) {
6637 slen = mono_metadata_decode_value (p, &p);
6639 return mono_string_new_len (mono_domain_get (), p, slen);
6640 case MONO_TYPE_CLASS: {
6643 if (*p == (char)0xFF) {
6648 slen = mono_metadata_decode_value (p, &p);
6649 n = g_memdup (p, slen + 1);
6651 t = mono_reflection_type_from_name (n, image);
6653 g_warning ("Cannot load type '%s'", n);
6657 return mono_type_get_object (mono_domain_get (), t);
6661 case MONO_TYPE_OBJECT: {
6664 MonoClass *subc = NULL;
6669 } else if (subt == 0x0E) {
6670 type = MONO_TYPE_STRING;
6672 } else if (subt == 0x1D) {
6673 MonoType simple_type = {{0}};
6677 type = MONO_TYPE_SZARRAY;
6678 simple_type.type = etype;
6679 tklass = mono_class_from_mono_type (&simple_type);
6681 } else if (subt == 0x55) {
6684 slen = mono_metadata_decode_value (p, &p);
6685 n = g_memdup (p, slen + 1);
6687 t = mono_reflection_type_from_name (n, image);
6689 g_warning ("Cannot load type '%s'", n);
6692 subc = mono_class_from_mono_type (t);
6693 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6694 MonoType simple_type = {{0}};
6695 simple_type.type = subt;
6696 subc = mono_class_from_mono_type (&simple_type);
6698 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6700 val = load_cattr_value (image, &subc->byval_arg, p, end);
6701 obj = mono_object_new (mono_domain_get (), subc);
6702 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6706 case MONO_TYPE_SZARRAY: {
6708 guint32 i, alen, basetype;
6711 if (alen == 0xffffffff) {
6715 arr = mono_array_new (mono_domain_get(), tklass, alen);
6716 basetype = tklass->byval_arg.type;
6721 case MONO_TYPE_BOOLEAN:
6722 for (i = 0; i < alen; i++) {
6723 MonoBoolean val = *p++;
6724 mono_array_set (arr, MonoBoolean, i, val);
6727 case MONO_TYPE_CHAR:
6730 for (i = 0; i < alen; i++) {
6731 guint16 val = read16 (p);
6732 mono_array_set (arr, guint16, i, val);
6739 for (i = 0; i < alen; i++) {
6740 guint32 val = read32 (p);
6741 mono_array_set (arr, guint32, i, val);
6748 for (i = 0; i < alen; i++) {
6749 guint64 val = read64 (p);
6750 mono_array_set (arr, guint64, i, val);
6754 case MONO_TYPE_CLASS:
6755 case MONO_TYPE_OBJECT:
6756 case MONO_TYPE_STRING:
6757 for (i = 0; i < alen; i++) {
6758 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
6759 mono_array_setref (arr, i, item);
6763 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6769 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6775 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6777 static MonoClass *klass;
6778 static MonoMethod *ctor;
6780 void *params [2], *unboxed;
6783 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6785 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6787 params [0] = mono_type_get_object (mono_domain_get (), t);
6789 retval = mono_object_new (mono_domain_get (), klass);
6790 unboxed = mono_object_unbox (retval);
6791 mono_runtime_invoke (ctor, unboxed, params, NULL);
6797 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6799 static MonoClass *klass;
6800 static MonoMethod *ctor;
6802 void *unboxed, *params [2];
6805 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6807 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6810 params [1] = typedarg;
6811 retval = mono_object_new (mono_domain_get (), klass);
6812 unboxed = mono_object_unbox (retval);
6813 mono_runtime_invoke (ctor, unboxed, params, NULL);
6819 type_is_reference (MonoType *type)
6821 switch (type->type) {
6822 case MONO_TYPE_BOOLEAN:
6823 case MONO_TYPE_CHAR:
6836 case MONO_TYPE_VALUETYPE:
6844 free_param_data (MonoMethodSignature *sig, void **params) {
6846 for (i = 0; i < sig->param_count; ++i) {
6847 if (!type_is_reference (sig->params [i]))
6848 g_free (params [i]);
6853 * Find the field index in the metadata FieldDef table.
6856 find_field_index (MonoClass *klass, MonoClassField *field) {
6859 for (i = 0; i < klass->field.count; ++i) {
6860 if (field == &klass->fields [i])
6861 return klass->field.first + 1 + i;
6867 * Find the property index in the metadata Property table.
6870 find_property_index (MonoClass *klass, MonoProperty *property) {
6873 for (i = 0; i < klass->property.count; ++i) {
6874 if (property == &klass->properties [i])
6875 return klass->property.first + 1 + i;
6881 * Find the event index in the metadata Event table.
6884 find_event_index (MonoClass *klass, MonoEvent *event) {
6887 for (i = 0; i < klass->event.count; ++i) {
6888 if (event == &klass->events [i])
6889 return klass->event.first + 1 + i;
6895 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6897 const char *p = data;
6899 guint32 i, j, num_named;
6903 mono_class_init (method->klass);
6906 attr = mono_object_new (mono_domain_get (), method->klass);
6907 mono_runtime_invoke (method, attr, NULL, NULL);
6911 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6914 /*g_print ("got attr %s\n", method->klass->name);*/
6916 /* Allocate using alloca so it gets GC tracking */
6917 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6921 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6922 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6926 attr = mono_object_new (mono_domain_get (), method->klass);
6927 mono_runtime_invoke (method, attr, params, NULL);
6928 free_param_data (method->signature, params);
6929 num_named = read16 (named);
6931 for (j = 0; j < num_named; j++) {
6933 gboolean is_boxed = FALSE;
6934 char *name, named_type, data_type;
6935 named_type = *named++;
6936 data_type = *named++; /* type of data */
6937 if (data_type == 0x51)
6940 if (data_type == 0x55) {
6943 type_len = mono_metadata_decode_blob_size (named, &named);
6944 type_name = g_malloc (type_len + 1);
6945 memcpy (type_name, named, type_len);
6946 type_name [type_len] = 0;
6948 /* FIXME: lookup the type and check type consistency */
6950 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6951 /* this seems to be the type of the element of the array */
6952 /* g_print ("skipping 0x%02x after prop\n", *named); */
6955 name_len = mono_metadata_decode_blob_size (named, &named);
6956 name = g_malloc (name_len + 1);
6957 memcpy (name, named, name_len);
6958 name [name_len] = 0;
6960 if (named_type == 0x53) {
6961 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6962 void *val = load_cattr_value (image, field->type, named, &named);
6963 mono_field_set_value (attr, field, val);
6964 if (!type_is_reference (field->type))
6966 } else if (named_type == 0x54) {
6969 MonoType *prop_type;
6971 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6972 /* can we have more that 1 arg in a custom attr named property? */
6973 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6974 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6975 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6976 mono_property_set_value (prop, attr, pparams, NULL);
6977 if (!type_is_reference (prop_type))
6978 g_free (pparams [0]);
6987 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6989 MonoArray *typedargs, *namedargs;
6990 MonoClass *attrklass;
6991 static MonoClass *klass;
6992 static MonoMethod *ctor;
6995 const char *p = data;
6997 guint32 i, j, num_named;
7000 mono_class_init (method->klass);
7003 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7005 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
7007 domain = mono_domain_get ();
7009 /* This is for Attributes with no parameters */
7010 attr = mono_object_new (domain, klass);
7011 params [0] = mono_method_get_object (domain, method, NULL);
7012 params [1] = params [2] = NULL;
7013 mono_runtime_invoke (method, attr, params, NULL);
7017 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
7020 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
7024 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
7025 MonoObject *obj, *typedarg;
7028 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
7029 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
7030 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
7031 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
7032 mono_array_setref (typedargs, i, typedarg);
7034 if (!type_is_reference (mono_method_signature (method)->params [i]))
7039 num_named = read16 (named);
7040 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
7042 attrklass = method->klass;
7043 for (j = 0; j < num_named; j++) {
7045 char *name, named_type, data_type;
7046 named_type = *named++;
7047 data_type = *named++; /* type of data */
7048 if (data_type == 0x55) {
7051 type_len = mono_metadata_decode_blob_size (named, &named);
7052 type_name = g_malloc (type_len + 1);
7053 memcpy (type_name, named, type_len);
7054 type_name [type_len] = 0;
7056 /* FIXME: lookup the type and check type consistency */
7058 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
7059 /* this seems to be the type of the element of the array */
7060 /* g_print ("skipping 0x%02x after prop\n", *named); */
7063 name_len = mono_metadata_decode_blob_size (named, &named);
7064 name = g_malloc (name_len + 1);
7065 memcpy (name, named, name_len);
7066 name [name_len] = 0;
7068 if (named_type == 0x53) {
7069 MonoObject *obj, *typedarg, *namedarg;
7070 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7071 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7073 minfo = mono_field_get_object (domain, NULL, field);
7074 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7075 typedarg = create_cattr_typed_arg (field->type, obj);
7076 namedarg = create_cattr_named_arg (minfo, typedarg);
7077 mono_array_setref (namedargs, j, namedarg);
7078 if (!type_is_reference (field->type))
7080 } else if (named_type == 0x54) {
7081 MonoObject *obj, *typedarg, *namedarg;
7082 MonoType *prop_type;
7084 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7086 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7087 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7088 minfo = mono_property_get_object (domain, NULL, prop);
7089 val = load_cattr_value (image, prop_type, named, &named);
7090 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7091 typedarg = create_cattr_typed_arg (prop_type, obj);
7092 namedarg = create_cattr_named_arg (minfo, typedarg);
7093 mono_array_setref (namedargs, j, namedarg);
7094 if (!type_is_reference (prop_type))
7099 attr = mono_object_new (domain, klass);
7100 params [0] = mono_method_get_object (domain, method, NULL);
7101 params [1] = typedargs;
7102 params [2] = namedargs;
7103 mono_runtime_invoke (ctor, attr, params, NULL);
7108 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7115 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7116 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7117 for (i = 0; i < cinfo->num_attrs; ++i) {
7118 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7119 mono_array_setref (result, i, attr);
7125 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7133 for (i = 0; i < cinfo->num_attrs; ++i) {
7134 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
7138 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7139 result = mono_array_new (mono_domain_get (), klass, n);
7141 for (i = 0; i < cinfo->num_attrs; ++i) {
7142 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
7143 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7144 mono_array_setref (result, n, attr);
7152 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7155 static MonoClass *klass;
7160 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7162 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7163 for (i = 0; i < cinfo->num_attrs; ++i) {
7164 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7165 mono_array_setref (result, i, attr);
7171 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7173 guint32 mtoken, i, len;
7174 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7176 MonoCustomAttrInfo *ainfo;
7177 GList *tmp, *list = NULL;
7180 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7182 i = mono_metadata_custom_attrs_from_index (image, idx);
7186 while (i < ca->rows) {
7187 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7189 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7192 len = g_list_length (list);
7195 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7196 ainfo->num_attrs = len;
7197 ainfo->image = image;
7198 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7199 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7200 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7201 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7202 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7203 mtoken |= MONO_TOKEN_METHOD_DEF;
7205 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7206 mtoken |= MONO_TOKEN_MEMBER_REF;
7209 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7212 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7213 if (!ainfo->attrs [i].ctor)
7214 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7215 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7216 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7217 ainfo->attrs [i].data = data;
7225 mono_custom_attrs_from_method (MonoMethod *method)
7227 MonoCustomAttrInfo *cinfo;
7230 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7232 idx = mono_method_get_index (method);
7233 idx <<= MONO_CUSTOM_ATTR_BITS;
7234 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7235 return mono_custom_attrs_from_index (method->klass->image, idx);
7239 mono_custom_attrs_from_class (MonoClass *klass)
7241 MonoCustomAttrInfo *cinfo;
7244 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7246 idx = mono_metadata_token_index (klass->type_token);
7247 idx <<= MONO_CUSTOM_ATTR_BITS;
7248 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7249 return mono_custom_attrs_from_index (klass->image, idx);
7253 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7255 MonoCustomAttrInfo *cinfo;
7258 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7260 idx = 1; /* there is only one assembly */
7261 idx <<= MONO_CUSTOM_ATTR_BITS;
7262 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7263 return mono_custom_attrs_from_index (assembly->image, idx);
7266 static MonoCustomAttrInfo*
7267 mono_custom_attrs_from_module (MonoImage *image)
7269 MonoCustomAttrInfo *cinfo;
7272 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7274 idx = 1; /* there is only one module */
7275 idx <<= MONO_CUSTOM_ATTR_BITS;
7276 idx |= MONO_CUSTOM_ATTR_MODULE;
7277 return mono_custom_attrs_from_index (image, idx);
7281 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7283 MonoCustomAttrInfo *cinfo;
7286 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7288 idx = find_property_index (klass, property);
7289 idx <<= MONO_CUSTOM_ATTR_BITS;
7290 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7291 return mono_custom_attrs_from_index (klass->image, idx);
7295 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7297 MonoCustomAttrInfo *cinfo;
7300 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7302 idx = find_event_index (klass, event);
7303 idx <<= MONO_CUSTOM_ATTR_BITS;
7304 idx |= MONO_CUSTOM_ATTR_EVENT;
7305 return mono_custom_attrs_from_index (klass->image, idx);
7309 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7311 MonoCustomAttrInfo *cinfo;
7314 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7316 idx = find_field_index (klass, field);
7317 idx <<= MONO_CUSTOM_ATTR_BITS;
7318 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7319 return mono_custom_attrs_from_index (klass->image, idx);
7323 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7326 guint32 i, idx, method_index;
7327 guint32 param_list, param_last, param_pos, found;
7329 MonoReflectionMethodAux *aux;
7331 if (method->klass->image->dynamic) {
7332 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7333 if (!aux || !aux->param_cattr)
7335 return aux->param_cattr [param];
7338 image = method->klass->image;
7339 method_index = mono_method_get_index (method);
7340 ca = &image->tables [MONO_TABLE_METHOD];
7342 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7343 /* FIXME FIXME FIXME */
7347 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7348 if (method_index == ca->rows) {
7349 ca = &image->tables [MONO_TABLE_PARAM];
7350 param_last = ca->rows + 1;
7352 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7353 ca = &image->tables [MONO_TABLE_PARAM];
7356 for (i = param_list; i < param_last; ++i) {
7357 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7358 if (param_pos == param) {
7366 idx <<= MONO_CUSTOM_ATTR_BITS;
7367 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7368 return mono_custom_attrs_from_index (image, idx);
7372 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7376 for (i = 0; i < ainfo->num_attrs; ++i) {
7377 klass = ainfo->attrs [i].ctor->klass;
7378 if (mono_class_has_parent (klass, attr_klass))
7385 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7392 for (i = 0; i < ainfo->num_attrs; ++i) {
7393 klass = ainfo->attrs [i].ctor->klass;
7394 if (mono_class_has_parent (klass, attr_klass)) {
7399 if (attr_index == -1)
7402 attrs = mono_custom_attrs_construct (ainfo);
7404 return mono_array_get (attrs, MonoObject*, attr_index);
7410 * mono_reflection_get_custom_attrs_info:
7411 * @obj: a reflection object handle
7413 * Return the custom attribute info for attributes defined for the
7414 * reflection handle @obj. The objects.
7417 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7420 MonoCustomAttrInfo *cinfo = NULL;
7422 klass = obj->vtable->klass;
7423 if (klass == mono_defaults.monotype_class) {
7424 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7425 klass = mono_class_from_mono_type (rtype->type);
7426 cinfo = mono_custom_attrs_from_class (klass);
7427 } else if (strcmp ("Assembly", klass->name) == 0) {
7428 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7429 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7430 } else if (strcmp ("Module", klass->name) == 0) {
7431 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7432 cinfo = mono_custom_attrs_from_module (module->image);
7433 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7434 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7435 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7436 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7437 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7438 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7439 } else if (strcmp ("MonoField", klass->name) == 0) {
7440 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7441 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7442 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7443 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7444 cinfo = mono_custom_attrs_from_method (rmethod->method);
7445 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7446 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7447 cinfo = mono_custom_attrs_from_method (method);
7448 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7449 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7450 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7451 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7452 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7453 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7454 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7455 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7456 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7457 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7458 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7459 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7460 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7461 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7462 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7463 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7464 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7465 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7466 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7467 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7468 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7469 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7470 } else { /* handle other types here... */
7471 g_error ("get custom attrs not yet supported for %s", klass->name);
7478 * mono_reflection_get_custom_attrs_by_type:
7479 * @obj: a reflection object handle
7481 * Return an array with all the custom attributes defined of the
7482 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7483 * of that type are returned. The objects are fully build.
7486 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7489 MonoCustomAttrInfo *cinfo;
7491 cinfo = mono_reflection_get_custom_attrs_info (obj);
7494 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7496 result = mono_custom_attrs_construct (cinfo);
7498 mono_custom_attrs_free (cinfo);
7501 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7502 result = mono_array_new (mono_domain_get (), klass, 0);
7509 * mono_reflection_get_custom_attrs:
7510 * @obj: a reflection object handle
7512 * Return an array with all the custom attributes defined of the
7513 * reflection handle @obj. The objects are fully build.
7516 mono_reflection_get_custom_attrs (MonoObject *obj)
7518 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7522 * mono_reflection_get_custom_attrs_data:
7523 * @obj: a reflection obj handle
7525 * Returns an array of System.Reflection.CustomAttributeData,
7526 * which include information about attributes reflected on
7527 * types loaded using the Reflection Only methods
7530 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7533 MonoCustomAttrInfo *cinfo;
7535 cinfo = mono_reflection_get_custom_attrs_info (obj);
7537 result = mono_custom_attrs_data_construct (cinfo);
7539 mono_custom_attrs_free (cinfo);
7542 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7543 result = mono_array_new (mono_domain_get (), klass, 0);
7549 static MonoMethodSignature*
7550 parameters_to_signature (MonoArray *parameters) {
7551 MonoMethodSignature *sig;
7554 count = parameters? mono_array_length (parameters): 0;
7556 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7557 sig->param_count = count;
7558 sig->sentinelpos = -1; /* FIXME */
7559 for (i = 0; i < count; ++i) {
7560 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7561 sig->params [i] = pt->type;
7566 static MonoMethodSignature*
7567 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7568 MonoMethodSignature *sig;
7570 sig = parameters_to_signature (ctor->parameters);
7571 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7572 sig->ret = &mono_defaults.void_class->byval_arg;
7576 static MonoMethodSignature*
7577 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7578 MonoMethodSignature *sig;
7580 sig = parameters_to_signature (method->parameters);
7581 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7582 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7583 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7587 static MonoMethodSignature*
7588 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7589 MonoMethodSignature *sig;
7591 sig = parameters_to_signature (method->parameters);
7592 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7593 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7594 sig->generic_param_count = 0;
7599 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7601 MonoClass *klass = mono_object_class (prop);
7602 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7603 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7604 *name = mono_string_to_utf8 (pb->name);
7605 *type = pb->type->type;
7607 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7608 *name = g_strdup (p->property->name);
7609 if (p->property->get)
7610 *type = mono_method_signature (p->property->get)->ret;
7612 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7617 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7619 MonoClass *klass = mono_object_class (field);
7620 if (strcmp (klass->name, "FieldBuilder") == 0) {
7621 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7622 *name = mono_string_to_utf8 (fb->name);
7623 *type = fb->type->type;
7625 MonoReflectionField *f = (MonoReflectionField *)field;
7626 *name = g_strdup (f->field->name);
7627 *type = f->field->type;
7632 * Encode a value in a custom attribute stream of bytes.
7633 * The value to encode is either supplied as an object in argument val
7634 * (valuetypes are boxed), or as a pointer to the data in the
7636 * @type represents the type of the value
7637 * @buffer is the start of the buffer
7638 * @p the current position in the buffer
7639 * @buflen contains the size of the buffer and is used to return the new buffer size
7640 * if this needs to be realloced.
7641 * @retbuffer and @retp return the start and the position of the buffer
7644 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7646 MonoTypeEnum simple_type;
7648 if ((p-buffer) + 10 >= *buflen) {
7651 newbuf = g_realloc (buffer, *buflen);
7652 p = newbuf + (p-buffer);
7656 argval = ((char*)arg + sizeof (MonoObject));
7657 simple_type = type->type;
7659 switch (simple_type) {
7660 case MONO_TYPE_BOOLEAN:
7665 case MONO_TYPE_CHAR:
7668 swap_with_size (p, argval, 2, 1);
7674 swap_with_size (p, argval, 4, 1);
7680 swap_with_size (p, argval, 8, 1);
7683 case MONO_TYPE_VALUETYPE:
7684 if (type->data.klass->enumtype) {
7685 simple_type = type->data.klass->enum_basetype->type;
7688 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7691 case MONO_TYPE_STRING: {
7698 str = mono_string_to_utf8 ((MonoString*)arg);
7699 slen = strlen (str);
7700 if ((p-buffer) + 10 + slen >= *buflen) {
7704 newbuf = g_realloc (buffer, *buflen);
7705 p = newbuf + (p-buffer);
7708 mono_metadata_encode_value (slen, p, &p);
7709 memcpy (p, str, slen);
7714 case MONO_TYPE_CLASS: {
7722 k = mono_object_class (arg);
7723 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7724 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7725 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7727 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7728 slen = strlen (str);
7729 if ((p-buffer) + 10 + slen >= *buflen) {
7733 newbuf = g_realloc (buffer, *buflen);
7734 p = newbuf + (p-buffer);
7737 mono_metadata_encode_value (slen, p, &p);
7738 memcpy (p, str, slen);
7743 case MONO_TYPE_SZARRAY: {
7745 MonoClass *eclass, *arg_eclass;
7748 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7751 len = mono_array_length ((MonoArray*)arg);
7753 *p++ = (len >> 8) & 0xff;
7754 *p++ = (len >> 16) & 0xff;
7755 *p++ = (len >> 24) & 0xff;
7757 *retbuffer = buffer;
7758 eclass = type->data.klass;
7759 arg_eclass = mono_object_class (arg)->element_class;
7760 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
7761 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
7762 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7763 int elsize = mono_class_array_element_size (arg_eclass);
7764 for (i = 0; i < len; ++i) {
7765 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
7768 } else if (eclass->valuetype && arg_eclass->valuetype) {
7769 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7770 int elsize = mono_class_array_element_size (eclass);
7771 for (i = 0; i < len; ++i) {
7772 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7776 for (i = 0; i < len; ++i) {
7777 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7782 case MONO_TYPE_OBJECT: {
7788 * The parameter type is 'object' but the type of the actual
7789 * argument is not. So we have to add type information to the blob
7790 * too. This is completely undocumented in the spec.
7794 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7799 klass = mono_object_class (arg);
7801 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
7804 } else if (klass->enumtype) {
7806 } else if (klass == mono_defaults.string_class) {
7807 simple_type = MONO_TYPE_STRING;
7810 } else if (klass->rank == 1) {
7811 simple_type = MONO_TYPE_SZARRAY;
7813 *p++ = klass->element_class->byval_arg.type;
7815 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7816 *p++ = simple_type = klass->byval_arg.type;
7819 g_error ("unhandled type in custom attr");
7821 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7822 slen = strlen (str);
7823 if ((p-buffer) + 10 + slen >= *buflen) {
7827 newbuf = g_realloc (buffer, *buflen);
7828 p = newbuf + (p-buffer);
7831 mono_metadata_encode_value (slen, p, &p);
7832 memcpy (p, str, slen);
7835 simple_type = klass->enum_basetype->type;
7839 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7842 *retbuffer = buffer;
7846 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7849 /* Preallocate a large enough buffer */
7850 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7851 char *str = type_get_qualified_name (type, NULL);
7857 len += strlen (name);
7859 if ((p-buffer) + 20 + len >= *buflen) {
7863 newbuf = g_realloc (buffer, *buflen);
7864 p = newbuf + (p-buffer);
7868 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7869 char *str = type_get_qualified_name (type, NULL);
7870 int slen = strlen (str);
7874 * This seems to be optional...
7877 mono_metadata_encode_value (slen, p, &p);
7878 memcpy (p, str, slen);
7881 } else if (type->type == MONO_TYPE_OBJECT) {
7883 } else if (type->type == MONO_TYPE_CLASS) {
7884 /* it should be a type: encode_cattr_value () has the check */
7887 mono_metadata_encode_value (type->type, p, &p);
7888 if (type->type == MONO_TYPE_SZARRAY)
7889 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7891 len = strlen (name);
7892 mono_metadata_encode_value (len, p, &p);
7893 memcpy (p, name, len);
7895 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7897 *retbuffer = buffer;
7901 * mono_reflection_get_custom_attrs_blob:
7902 * @ctor: custom attribute constructor
7903 * @ctorArgs: arguments o the constructor
7909 * Creates the blob of data that needs to be saved in the metadata and that represents
7910 * the custom attributed described by @ctor, @ctorArgs etc.
7911 * Returns: a Byte array representing the blob of data.
7914 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7917 MonoMethodSignature *sig;
7922 MONO_ARCH_SAVE_REGS;
7924 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7925 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7927 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7929 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7931 p = buffer = g_malloc (buflen);
7932 /* write the prolog */
7935 for (i = 0; i < sig->param_count; ++i) {
7936 arg = mono_array_get (ctorArgs, MonoObject*, i);
7937 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7941 i += mono_array_length (properties);
7943 i += mono_array_length (fields);
7945 *p++ = (i >> 8) & 0xff;
7948 for (i = 0; i < mono_array_length (properties); ++i) {
7952 prop = mono_array_get (properties, gpointer, i);
7953 get_prop_name_and_type (prop, &pname, &ptype);
7954 *p++ = 0x54; /* PROPERTY signature */
7955 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7962 for (i = 0; i < mono_array_length (fields); ++i) {
7966 field = mono_array_get (fields, gpointer, i);
7967 get_field_name_and_type (field, &fname, &ftype);
7968 *p++ = 0x53; /* FIELD signature */
7969 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7974 g_assert (p - buffer <= buflen);
7975 buflen = p - buffer;
7976 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7977 p = mono_array_addr (result, char, 0);
7978 memcpy (p, buffer, buflen);
7980 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7986 * mono_reflection_setup_internal_class:
7987 * @tb: a TypeBuilder object
7989 * Creates a MonoClass that represents the TypeBuilder.
7990 * This is a trick that lets us simplify a lot of reflection code
7991 * (and will allow us to support Build and Run assemblies easier).
7994 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7996 MonoClass *klass, *parent;
7998 MONO_ARCH_SAVE_REGS;
8000 mono_loader_lock ();
8003 /* check so we can compile corlib correctly */
8004 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
8005 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8006 parent = tb->parent->type->data.klass;
8008 parent = my_mono_class_from_mono_type (tb->parent->type);
8014 /* the type has already being created: it means we just have to change the parent */
8015 if (tb->type.type) {
8016 klass = mono_class_from_mono_type (tb->type.type);
8017 klass->parent = NULL;
8018 /* fool mono_class_setup_parent */
8019 klass->supertypes = NULL;
8020 mono_class_setup_parent (klass, parent);
8021 mono_class_setup_mono_type (klass);
8022 mono_loader_unlock ();
8026 klass = mono_mempool_alloc0 (tb->module->dynamic_image->image.mempool, sizeof (MonoClass));
8028 klass->image = &tb->module->dynamic_image->image;
8030 klass->inited = 1; /* we lie to the runtime */
8031 klass->name = mono_string_to_utf8_mp (klass->image->mempool, tb->name);
8032 klass->name_space = mono_string_to_utf8_mp (klass->image->mempool, tb->nspace);
8033 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
8034 klass->flags = tb->attrs;
8036 klass->element_class = klass;
8037 klass->reflection_info = tb; /* FIXME: GC need to pin. */
8039 /* Put into cache so mono_class_get () will find it */
8040 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
8042 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
8043 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
8045 if (parent != NULL) {
8046 mono_class_setup_parent (klass, parent);
8047 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
8048 const char *old_n = klass->name;
8049 /* trick to get relative numbering right when compiling corlib */
8050 klass->name = "BuildingObject";
8051 mono_class_setup_parent (klass, mono_defaults.object_class);
8052 klass->name = old_n;
8055 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
8056 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
8057 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
8058 klass->instance_size = sizeof (MonoObject);
8059 klass->size_inited = 1;
8060 mono_class_setup_vtable_general (klass, NULL, 0);
8063 mono_class_setup_mono_type (klass);
8065 mono_class_setup_supertypes (klass);
8068 * FIXME: handle interfaces.
8071 tb->type.type = &klass->byval_arg;
8073 if (tb->nesting_type) {
8074 g_assert (tb->nesting_type->type);
8075 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
8078 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8080 mono_loader_unlock ();
8084 * mono_reflection_setup_generic_class:
8085 * @tb: a TypeBuilder object
8087 * Setup the generic class before adding the first generic parameter.
8090 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8094 MONO_ARCH_SAVE_REGS;
8096 klass = my_mono_class_from_mono_type (tb->type.type);
8097 if (tb->generic_container)
8100 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8101 tb->generic_container->klass = klass;
8103 tb->generic_container->context.container = tb->generic_container;
8107 * mono_reflection_create_generic_class:
8108 * @tb: a TypeBuilder object
8110 * Creates the generic class after all generic parameters have been added.
8113 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8118 MONO_ARCH_SAVE_REGS;
8120 klass = my_mono_class_from_mono_type (tb->type.type);
8122 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8124 if (klass->generic_container || (count == 0))
8127 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8129 klass->generic_container = tb->generic_container;
8131 klass->generic_container->type_argc = count;
8132 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8134 for (i = 0; i < count; i++) {
8135 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8136 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8137 g_assert (klass->generic_container->type_params [i].owner);
8140 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8144 * mono_reflection_create_internal_class:
8145 * @tb: a TypeBuilder object
8147 * Actually create the MonoClass that is associated with the TypeBuilder.
8150 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8154 MONO_ARCH_SAVE_REGS;
8156 klass = my_mono_class_from_mono_type (tb->type.type);
8158 mono_loader_lock ();
8159 if (klass->enumtype && klass->enum_basetype == NULL) {
8160 MonoReflectionFieldBuilder *fb;
8163 g_assert (tb->fields != NULL);
8164 g_assert (mono_array_length (tb->fields) >= 1);
8166 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8168 klass->enum_basetype = fb->type->type;
8169 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8170 if (!klass->element_class)
8171 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8174 * get the element_class from the current corlib.
8176 ec = default_class_from_mono_type (klass->enum_basetype);
8177 klass->instance_size = ec->instance_size;
8178 klass->size_inited = 1;
8180 * this is almost safe to do with enums and it's needed to be able
8181 * to create objects of the enum type (for use in SetConstant).
8183 /* FIXME: Does this mean enums can't have method overrides ? */
8184 mono_class_setup_vtable_general (klass, NULL, 0);
8186 mono_loader_unlock ();
8189 static MonoMarshalSpec*
8190 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8191 MonoReflectionMarshal *minfo)
8193 MonoMarshalSpec *res;
8195 res = g_new0 (MonoMarshalSpec, 1);
8196 res->native = minfo->type;
8198 switch (minfo->type) {
8199 case MONO_NATIVE_LPARRAY:
8200 res->data.array_data.elem_type = minfo->eltype;
8201 if (minfo->has_size) {
8202 res->data.array_data.param_num = minfo->param_num;
8203 res->data.array_data.num_elem = minfo->count;
8204 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8207 res->data.array_data.param_num = -1;
8208 res->data.array_data.num_elem = -1;
8209 res->data.array_data.elem_mult = -1;
8213 case MONO_NATIVE_BYVALTSTR:
8214 case MONO_NATIVE_BYVALARRAY:
8215 res->data.array_data.num_elem = minfo->count;
8218 case MONO_NATIVE_CUSTOM:
8219 if (minfo->marshaltyperef)
8220 res->data.custom_data.custom_name =
8221 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8223 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8233 MonoReflectionMarshal*
8234 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8235 MonoMarshalSpec *spec)
8237 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8238 MonoReflectionMarshal *minfo;
8241 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8242 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8243 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8244 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8247 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8248 minfo->type = spec->native;
8250 switch (minfo->type) {
8251 case MONO_NATIVE_LPARRAY:
8252 minfo->eltype = spec->data.array_data.elem_type;
8253 minfo->count = spec->data.array_data.num_elem;
8254 minfo->param_num = spec->data.array_data.param_num;
8257 case MONO_NATIVE_BYVALTSTR:
8258 case MONO_NATIVE_BYVALARRAY:
8259 minfo->count = spec->data.array_data.num_elem;
8262 case MONO_NATIVE_CUSTOM:
8263 if (spec->data.custom_data.custom_name) {
8264 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8266 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
8268 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
8270 if (spec->data.custom_data.cookie)
8271 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
8282 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8283 ReflectionMethodBuilder *rmb,
8284 MonoMethodSignature *sig)
8287 MonoMethodNormal *pm;
8288 MonoMarshalSpec **specs;
8289 MonoReflectionMethodAux *method_aux;
8292 g_assert (!klass->generic_class);
8294 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8295 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8296 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8298 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8300 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8302 pm = (MonoMethodNormal*)m;
8305 m->flags = rmb->attrs;
8306 m->iflags = rmb->iattrs;
8307 m->name = mono_string_to_utf8 (rmb->name);
8311 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8313 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8314 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8317 m->signature->pinvoke = 1;
8318 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8319 m->signature->pinvoke = 1;
8321 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8323 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8324 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8326 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8328 if (klass->image->dynamic)
8329 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8332 } else if (!m->klass->dummy &&
8333 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8334 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8335 MonoMethodHeader *header;
8337 gint32 max_stack, i;
8338 gint32 num_locals = 0;
8339 gint32 num_clauses = 0;
8343 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8344 code_size = rmb->ilgen->code_len;
8345 max_stack = rmb->ilgen->max_stack;
8346 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8347 if (rmb->ilgen->ex_handlers)
8348 num_clauses = method_count_clauses (rmb->ilgen);
8351 code = mono_array_addr (rmb->code, guint8, 0);
8352 code_size = mono_array_length (rmb->code);
8353 /* we probably need to run a verifier on the code... */
8363 header = g_malloc0 (sizeof (MonoMethodHeader) +
8364 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8365 header->code_size = code_size;
8366 header->code = g_malloc (code_size);
8367 memcpy ((char*)header->code, code, code_size);
8368 header->max_stack = max_stack;
8369 header->init_locals = rmb->init_locals;
8370 header->num_locals = num_locals;
8372 for (i = 0; i < num_locals; ++i) {
8373 MonoReflectionLocalBuilder *lb =
8374 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8376 header->locals [i] = g_new0 (MonoType, 1);
8377 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8380 header->num_clauses = num_clauses;
8382 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8383 rmb->ilgen, num_clauses);
8386 pm->header = header;
8389 if (rmb->generic_params) {
8390 int count = mono_array_length (rmb->generic_params);
8391 MonoGenericContainer *container;
8392 MonoGenericContext *context;
8394 m->generic_container = container = rmb->generic_container;
8395 container->type_argc = count;
8396 container->type_params = g_new0 (MonoGenericParam, count);
8398 for (i = 0; i < count; i++) {
8399 MonoReflectionGenericParam *gp =
8400 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8402 container->type_params [i] = *gp->type.type->data.generic_param;
8403 container->type_params [i].method = m;
8406 context = &container->context;
8407 context->container = container;
8408 if (klass->generic_container) {
8409 container->parent = klass->generic_container;
8410 context->gclass = klass->generic_container->context.gclass;
8412 context->gmethod = mono_get_shared_generic_method (container);
8416 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8420 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8422 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8423 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8424 for (i = 0; i < rmb->nrefs; ++i)
8425 data [i + 1] = rmb->refs [i];
8430 /* Parameter info */
8433 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8434 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8435 for (i = 0; i <= m->signature->param_count; ++i) {
8436 MonoReflectionParamBuilder *pb;
8437 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8438 if ((i > 0) && (pb->attrs)) {
8439 /* Make a copy since it might point to a shared type structure */
8440 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8441 m->signature->params [i - 1]->attrs = pb->attrs;
8444 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
8445 MonoDynamicImage *assembly;
8446 guint32 idx, def_type, len;
8450 if (!method_aux->param_defaults) {
8451 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8452 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8454 assembly = (MonoDynamicImage*)klass->image;
8455 idx = encode_constant (assembly, pb->def_value, &def_type);
8456 /* Copy the data from the blob since it might get realloc-ed */
8457 p = assembly->blob.data + idx;
8458 len = mono_metadata_decode_blob_size (p, &p2);
8460 method_aux->param_defaults [i] = g_malloc (len);
8461 method_aux->param_default_types [i] = def_type;
8462 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8466 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8468 if (!method_aux->param_cattr)
8469 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8470 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8476 /* Parameter marshalling */
8479 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8480 MonoReflectionParamBuilder *pb;
8481 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8482 if (pb->marshal_info) {
8484 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8485 specs [pb->position] =
8486 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8490 if (specs != NULL) {
8492 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8493 method_aux->param_marshall = specs;
8496 if (klass->image->dynamic && method_aux)
8497 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8503 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8505 ReflectionMethodBuilder rmb;
8506 MonoMethodSignature *sig;
8508 sig = ctor_builder_to_signature (mb);
8510 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8512 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8513 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8515 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8516 /* ilgen is no longer needed */
8524 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8526 ReflectionMethodBuilder rmb;
8527 MonoMethodSignature *sig;
8529 sig = method_builder_to_signature (mb);
8531 reflection_methodbuilder_from_method_builder (&rmb, mb);
8533 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8534 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8536 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8537 /* ilgen is no longer needed */
8543 static MonoClassField*
8544 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8546 MonoClassField *field;
8550 field = g_new0 (MonoClassField, 1);
8552 field->name = mono_string_to_utf8 (fb->name);
8554 /* FIXME: handle type modifiers */
8555 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8556 field->type->attrs = fb->attrs;
8558 field->type = fb->type->type;
8560 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8561 field->data = mono_array_addr (fb->rva_data, char, 0); /* FIXME: GC pin array */
8562 if (fb->offset != -1)
8563 field->offset = fb->offset;
8564 field->parent = klass;
8565 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8567 if (fb->def_value) {
8568 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8569 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8570 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8571 /* Copy the data from the blob since it might get realloc-ed */
8572 p = assembly->blob.data + idx;
8573 len = mono_metadata_decode_blob_size (p, &p2);
8575 field->data = g_malloc (len);
8576 memcpy ((gpointer)field->data, p, len);
8583 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8586 MonoReflectionTypeBuilder *tb = NULL;
8587 MonoGenericClass *gclass, *cached;
8588 MonoInflatedGenericClass *igclass;
8589 MonoDynamicGenericClass *dgclass = NULL;
8590 gboolean is_dynamic = FALSE;
8595 klass = mono_class_from_mono_type (type->type);
8596 if (!klass->generic_container && !klass->generic_class &&
8597 !(klass->nested_in && klass->nested_in->generic_container))
8600 mono_loader_lock ();
8602 domain = mono_object_domain (type);
8604 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8605 tb = (MonoReflectionTypeBuilder *) type;
8608 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8609 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8610 MonoReflectionType *rgt = rgi->generic_type;
8612 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8613 tb = (MonoReflectionTypeBuilder *) rgt;
8616 } else if (klass->wastypebuilder) {
8617 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8623 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8624 igclass = &dgclass->generic_class;
8625 gclass = &igclass->generic_class;
8626 gclass->is_dynamic = TRUE;
8627 gclass->is_inflated = TRUE;
8629 igclass = g_new0 (MonoInflatedGenericClass, 1);
8630 gclass = &igclass->generic_class;
8631 gclass->is_inflated = TRUE;
8634 gclass->inst = g_new0 (MonoGenericInst, 1);
8636 gclass->inst->type_argc = type_argc;
8637 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8638 gclass->inst->is_reference = 1;
8640 for (i = 0; i < gclass->inst->type_argc; ++i) {
8641 MonoType *t = dup_type (types [i]);
8643 if (!gclass->inst->is_open)
8644 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8645 if (gclass->inst->is_reference)
8646 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8647 gclass->inst->type_argv [i] = t;
8650 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8652 gclass->container_class = klass;
8654 if (klass->generic_class) {
8655 MonoGenericClass *kgclass = klass->generic_class;
8656 MonoGenericClass *ogclass = gclass;
8658 ogclass->context = g_new0 (MonoGenericContext, 1);
8659 ogclass->context->container = gclass->container_class->generic_container;
8660 ogclass->context->gclass = gclass;
8663 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8664 igclass = &dgclass->generic_class;
8665 gclass = &igclass->generic_class;
8666 gclass->is_dynamic = TRUE;
8667 gclass->is_inflated = TRUE;
8669 igclass = g_new0 (MonoInflatedGenericClass, 1);
8670 gclass = &igclass->generic_class;
8671 gclass->is_inflated = TRUE;
8674 gclass->inst = g_new0 (MonoGenericInst, 1);
8676 gclass->inst->type_argc = kgclass->inst->type_argc;
8677 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8678 gclass->inst->is_reference = 1;
8680 for (i = 0; i < gclass->inst->type_argc; i++) {
8681 MonoType *t = kgclass->inst->type_argv [i];
8683 t = mono_class_inflate_generic_type (t, ogclass->context);
8685 if (!gclass->inst->is_open)
8686 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8687 if (gclass->inst->is_reference)
8688 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8690 gclass->inst->type_argv [i] = t;
8693 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8695 gclass->container_class = kgclass->container_class;
8698 geninst = g_new0 (MonoType, 1);
8699 geninst->type = MONO_TYPE_GENERICINST;
8701 cached = mono_metadata_lookup_generic_class (gclass);
8704 mono_loader_unlock ();
8705 geninst->data.generic_class = cached;
8709 geninst->data.generic_class = gclass;
8711 gclass->context = g_new0 (MonoGenericContext, 1);
8712 gclass->context->container = gclass->container_class->generic_container;
8713 gclass->context->gclass = gclass;
8715 mono_loader_unlock ();
8721 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8724 MonoGenericClass *gclass, *cached;
8725 MonoInflatedGenericClass *igclass;
8729 klass = mono_class_from_mono_type (type);
8730 if (!klass->generic_container && !klass->generic_class &&
8731 !(klass->nested_in && klass->nested_in->generic_container))
8734 mono_loader_lock ();
8736 igclass = g_new0 (MonoInflatedGenericClass, 1);
8737 gclass = &igclass->generic_class;
8738 gclass->is_inflated = TRUE;
8740 gclass->inst = g_new0 (MonoGenericInst, 1);
8741 gclass->inst->type_argc = type_argc;
8742 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8743 gclass->inst->is_reference = 1;
8745 for (i = 0; i < gclass->inst->type_argc; ++i) {
8746 MonoType *t = dup_type (types [i]);
8748 if (!gclass->inst->is_open)
8749 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8750 if (gclass->inst->is_reference)
8751 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8753 gclass->inst->type_argv [i] = t;
8756 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8758 gclass->container_class = klass;
8760 if (klass->generic_class) {
8761 MonoGenericClass *kgclass = klass->generic_class;
8762 MonoGenericClass *ogclass = gclass;
8764 gclass->context = g_new0 (MonoGenericContext, 1);
8765 gclass->context->container = gclass->container_class->generic_container;
8766 gclass->context->gclass = gclass;
8768 igclass = g_new0 (MonoInflatedGenericClass, 1);
8769 gclass = &igclass->generic_class;
8770 gclass->is_inflated = TRUE;
8772 gclass->inst = g_new0 (MonoGenericInst, 1);
8773 gclass->inst->type_argc = kgclass->inst->type_argc;
8774 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8775 gclass->inst->is_reference = 1;
8777 for (i = 0; i < gclass->inst->type_argc; i++) {
8778 MonoType *t = kgclass->inst->type_argv [i];
8780 t = mono_class_inflate_generic_type (t, ogclass->context);
8782 if (!gclass->inst->is_open)
8783 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8784 if (gclass->inst->is_reference)
8785 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8787 gclass->inst->type_argv [i] = t;
8790 gclass->inst = mono_metadata_lookup_generic_inst (gclass->inst);
8792 gclass->container_class = kgclass->container_class;
8795 geninst = g_new0 (MonoType, 1);
8796 geninst->type = MONO_TYPE_GENERICINST;
8798 cached = mono_metadata_lookup_generic_class (gclass);
8801 mono_loader_unlock ();
8802 geninst->data.generic_class = cached;
8806 geninst->data.generic_class = gclass;
8808 gclass->context = g_new0 (MonoGenericContext, 1);
8809 gclass->context->container = gclass->container_class->generic_container;
8810 gclass->context->gclass = gclass;
8812 mono_loader_unlock ();
8817 static inline MonoType*
8818 dup_type (const MonoType *original)
8820 MonoType *r = g_new0 (MonoType, 1);
8822 r->attrs = original->attrs;
8823 r->byref = original->byref;
8824 if (original->type == MONO_TYPE_PTR)
8825 r->data.type = dup_type (original->data.type);
8826 else if (original->type == MONO_TYPE_ARRAY)
8827 r->data.array = mono_dup_array_type (original->data.array);
8828 else if (original->type == MONO_TYPE_FNPTR)
8829 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8830 mono_stats.generics_metadata_size += sizeof (MonoType);
8834 MonoReflectionMethod*
8835 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8837 MonoMethod *method, *inflated;
8838 MonoReflectionMethodBuilder *mb = NULL;
8839 MonoGenericContainer *container;
8840 MonoGenericMethod *gmethod;
8841 MonoGenericContext *context;
8842 MonoGenericInst *ginst;
8845 MONO_ARCH_SAVE_REGS;
8846 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8847 MonoReflectionTypeBuilder *tb;
8850 mb = (MonoReflectionMethodBuilder *) rmethod;
8851 tb = (MonoReflectionTypeBuilder *) mb->type;
8852 klass = mono_class_from_mono_type (tb->type.type);
8854 method = methodbuilder_to_mono_method (klass, mb);
8856 method = rmethod->method;
8859 method = mono_get_inflated_method (method);
8861 count = mono_method_signature (method)->generic_param_count;
8862 if (count != mono_array_length (types))
8865 container = method->generic_container;
8866 g_assert (container);
8868 if (!container->method_hash)
8869 container->method_hash = g_hash_table_new (
8870 (GHashFunc) mono_metadata_generic_method_hash,
8871 (GCompareFunc) mono_metadata_generic_method_equal);
8873 ginst = g_new0 (MonoGenericInst,1 );
8874 ginst->type_argc = count;
8875 ginst->type_argv = g_new0 (MonoType *, count);
8876 ginst->is_reference = 1;
8877 for (i = 0; i < count; i++) {
8878 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8879 ginst->type_argv [i] = dup_type (garg->type);
8881 if (!ginst->is_open)
8882 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8883 if (ginst->is_reference)
8884 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8886 ginst = mono_metadata_lookup_generic_inst (ginst);
8888 gmethod = g_new0 (MonoGenericMethod, 1);
8889 gmethod->generic_class = method->klass->generic_class;
8890 gmethod->container = container;
8891 gmethod->inst = ginst;
8893 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8897 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8900 gmethod->reflection_info = rmethod;
8902 context = g_new0 (MonoGenericContext, 1);
8903 context->container = container;
8904 context->gclass = method->klass->generic_class;
8905 context->gmethod = gmethod;
8907 if (method->is_inflated)
8908 method = ((MonoMethodInflated *) method)->declaring;
8910 inflated = mono_class_inflate_generic_method (method, context);
8911 g_hash_table_insert (container->method_hash, gmethod, inflated);
8913 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8917 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8919 MonoGenericMethod *gmethod = NULL;
8920 MonoInflatedGenericClass *gclass;
8921 MonoGenericContext *context;
8925 klass = mono_class_from_mono_type (type->type.type);
8926 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8927 n = mono_method_signature (method)->generic_param_count;
8929 context = gclass->generic_class.context;
8930 g_assert (context && context->container);
8932 gmethod = g_new0 (MonoGenericMethod, 1);
8933 gmethod->generic_class = &gclass->generic_class;
8934 gmethod->container = method->generic_container;
8935 gmethod->reflection_info = obj;
8937 gmethod->inst = g_new0 (MonoGenericInst, 1);
8938 gmethod->inst->type_argc = n;
8939 gmethod->inst->type_argv = g_new0 (MonoType *, n);
8941 for (i = 0; i < n; i++) {
8942 MonoGenericParam *gparam = &method->generic_container->type_params [i];
8943 g_assert (gparam->pklass);
8944 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8947 g_assert (gmethod->container->parent == context->container);
8949 context = g_new0 (MonoGenericContext, 1);
8950 context->container = gmethod->container;
8951 context->gclass = &gclass->generic_class;
8952 context->gmethod = gmethod;
8955 return mono_class_inflate_generic_method (method, context);
8959 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8964 gklass = mono_class_from_mono_type (type->generic_type->type);
8966 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8967 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
8968 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8969 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
8970 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8971 method = ((MonoReflectionMethod *) obj)->method;
8973 method = NULL; /* prevent compiler warning */
8974 g_assert_not_reached ();
8977 return inflate_mono_method (type, method, obj);
8981 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8982 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8985 MonoGenericClass *gclass;
8986 MonoDynamicGenericClass *dgclass;
8987 MonoClass *klass, *gklass;
8990 MONO_ARCH_SAVE_REGS;
8992 klass = mono_class_from_mono_type (type->type.type);
8993 gclass = type->type.type->data.generic_class;
8995 g_assert (gclass->is_dynamic);
8996 dgclass = (MonoDynamicGenericClass *) gclass;
8998 if (dgclass->initialized)
9001 gklass = gclass->container_class;
9002 mono_class_init (gklass);
9004 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
9005 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
9006 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
9007 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
9008 dgclass->count_events = events ? mono_array_length (events) : 0;
9010 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
9011 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
9012 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
9013 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
9014 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
9016 for (i = 0; i < dgclass->count_methods; i++) {
9017 MonoObject *obj = mono_array_get (methods, gpointer, i);
9019 dgclass->methods [i] = inflate_method (type, obj);
9022 for (i = 0; i < dgclass->count_ctors; i++) {
9023 MonoObject *obj = mono_array_get (ctors, gpointer, i);
9025 dgclass->ctors [i] = inflate_method (type, obj);
9028 for (i = 0; i < dgclass->count_fields; i++) {
9029 MonoObject *obj = mono_array_get (fields, gpointer, i);
9030 MonoClassField *field;
9031 MonoInflatedField *ifield;
9033 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
9034 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9035 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9036 field = ((MonoReflectionField *) obj)->field;
9038 field = NULL; /* prevent compiler warning */
9039 g_assert_not_reached ();
9042 ifield = g_new0 (MonoInflatedField, 1);
9043 ifield->generic_type = field->type;
9044 ifield->reflection_info = obj;
9046 dgclass->fields [i] = *field;
9047 dgclass->fields [i].parent = klass;
9048 dgclass->fields [i].generic_info = ifield;
9049 dgclass->fields [i].type = mono_class_inflate_generic_type (
9050 field->type, dgclass->generic_class.generic_class.context);
9053 for (i = 0; i < dgclass->count_properties; i++) {
9054 MonoObject *obj = mono_array_get (properties, gpointer, i);
9055 MonoProperty *property = &dgclass->properties [i];
9057 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9058 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9060 property->parent = klass;
9061 property->attrs = pb->attrs;
9062 property->name = mono_string_to_utf8 (pb->name);
9064 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9066 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9067 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9068 *property = *((MonoReflectionProperty *) obj)->property;
9071 property->get = inflate_mono_method (type, property->get, NULL);
9073 property->set = inflate_mono_method (type, property->set, NULL);
9075 g_assert_not_reached ();
9078 for (i = 0; i < dgclass->count_events; i++) {
9079 MonoObject *obj = mono_array_get (events, gpointer, i);
9080 MonoEvent *event = &dgclass->events [i];
9082 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9083 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9085 event->parent = klass;
9086 event->attrs = eb->attrs;
9087 event->name = mono_string_to_utf8 (eb->name);
9089 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9090 if (eb->remove_method)
9091 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9092 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9093 *event = *((MonoReflectionEvent *) obj)->event;
9096 event->add = inflate_mono_method (type, event->add, NULL);
9098 event->remove = inflate_mono_method (type, event->remove, NULL);
9100 g_assert_not_reached ();
9103 dgclass->initialized = TRUE;
9107 ensure_runtime_vtable (MonoClass *klass)
9109 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9112 if (!tb || klass->wastypebuilder)
9115 ensure_runtime_vtable (klass->parent);
9117 num = tb->ctors? mono_array_length (tb->ctors): 0;
9118 num += tb->num_methods;
9119 klass->method.count = num;
9120 klass->methods = mono_mempool_alloc (klass->image->mempool, sizeof (MonoMethod*) * num);
9121 num = tb->ctors? mono_array_length (tb->ctors): 0;
9122 for (i = 0; i < num; ++i)
9123 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9124 num = tb->num_methods;
9126 for (i = 0; i < num; ++i)
9127 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9129 if (tb->interfaces) {
9130 klass->interface_count = mono_array_length (tb->interfaces);
9131 klass->interfaces = mono_mempool_alloc (klass->image->mempool, sizeof (MonoClass*) * klass->interface_count);
9132 for (i = 0; i < klass->interface_count; ++i) {
9133 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9134 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9138 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
9139 for (i = 0; i < klass->method.count; ++i)
9140 klass->methods [i]->slot = i;
9142 mono_class_setup_interface_offsets (klass);
9146 * The generic vtable is needed even if image->run is not set since some
9147 * runtime code like ves_icall_Type_GetMethodsByName depends on
9148 * method->slot being defined.
9152 * tb->methods could not be freed since it is used for determining
9153 * overrides during dynamic vtable construction.
9158 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
9160 MonoReflectionTypeBuilder *tb;
9166 g_assert (klass->image->dynamic);
9168 if (!klass->reflection_info)
9171 g_assert (strcmp (((MonoObject*)klass->reflection_info)->vtable->klass->name, "TypeBuilder") == 0);
9173 tb = (MonoReflectionTypeBuilder*)klass->reflection_info;
9177 for (i = 0; i < tb->num_methods; ++i) {
9178 MonoReflectionMethodBuilder *mb =
9179 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9180 if (mb->override_method)
9186 *overrides = g_new0 (MonoMethod*, onum * 2);
9189 for (i = 0; i < tb->num_methods; ++i) {
9190 MonoReflectionMethodBuilder *mb =
9191 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9192 if (mb->override_method) {
9193 (*overrides) [onum * 2] =
9194 mb->override_method->method;
9195 (*overrides) [onum * 2 + 1] =
9198 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9199 g_assert (mb->override_method->method);
9200 g_assert (mb->mhandle);
9207 *num_overrides = onum;
9211 typebuilder_setup_fields (MonoClass *klass)
9213 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9214 MonoReflectionFieldBuilder *fb;
9215 MonoClassField *field;
9220 klass->field.count = tb->num_fields;
9221 klass->field.first = 0;
9223 if (!klass->field.count)
9226 klass->fields = g_new0 (MonoClassField, klass->field.count);
9228 for (i = 0; i < klass->field.count; ++i) {
9229 fb = mono_array_get (tb->fields, gpointer, i);
9230 field = &klass->fields [i];
9231 field->name = mono_string_to_utf8 (fb->name);
9233 /* FIXME: handle type modifiers */
9234 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9235 field->type->attrs = fb->attrs;
9237 field->type = fb->type->type;
9239 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9240 field->data = mono_array_addr (fb->rva_data, char, 0);
9241 if (fb->offset != -1)
9242 field->offset = fb->offset;
9243 field->parent = klass;
9245 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9247 if (fb->def_value) {
9248 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9249 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9250 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9251 /* Copy the data from the blob since it might get realloc-ed */
9252 p = assembly->blob.data + idx;
9253 len = mono_metadata_decode_blob_size (p, &p2);
9255 field->data = g_malloc (len);
9256 memcpy ((gpointer)field->data, p, len);
9259 mono_class_layout_fields (klass);
9263 typebuilder_setup_properties (MonoClass *klass)
9265 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9266 MonoReflectionPropertyBuilder *pb;
9269 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9270 klass->property.first = 0;
9272 klass->properties = g_new0 (MonoProperty, klass->property.count);
9273 for (i = 0; i < klass->property.count; ++i) {
9274 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9275 klass->properties [i].parent = klass;
9276 klass->properties [i].attrs = pb->attrs;
9277 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9279 klass->properties [i].get = pb->get_method->mhandle;
9281 klass->properties [i].set = pb->set_method->mhandle;
9285 MonoReflectionEvent *
9286 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9288 MonoEvent *event = g_new0 (MonoEvent, 1);
9292 klass = my_mono_class_from_mono_type (tb->type.type);
9294 event->parent = klass;
9295 event->attrs = eb->attrs;
9296 event->name = mono_string_to_utf8 (eb->name);
9298 event->add = eb->add_method->mhandle;
9299 if (eb->remove_method)
9300 event->remove = eb->remove_method->mhandle;
9301 if (eb->raise_method)
9302 event->raise = eb->raise_method->mhandle;
9304 if (eb->other_methods) {
9305 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9306 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9307 MonoReflectionMethodBuilder *mb =
9308 mono_array_get (eb->other_methods,
9309 MonoReflectionMethodBuilder*, j);
9310 event->other [j] = mb->mhandle;
9314 return mono_event_get_object (mono_object_domain (tb), klass, event);
9318 typebuilder_setup_events (MonoClass *klass)
9320 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9321 MonoReflectionEventBuilder *eb;
9324 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9325 klass->event.first = 0;
9327 klass->events = g_new0 (MonoEvent, klass->event.count);
9328 for (i = 0; i < klass->event.count; ++i) {
9329 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9330 klass->events [i].parent = klass;
9331 klass->events [i].attrs = eb->attrs;
9332 klass->events [i].name = mono_string_to_utf8 (eb->name);
9334 klass->events [i].add = eb->add_method->mhandle;
9335 if (eb->remove_method)
9336 klass->events [i].remove = eb->remove_method->mhandle;
9337 if (eb->raise_method)
9338 klass->events [i].raise = eb->raise_method->mhandle;
9340 if (eb->other_methods) {
9341 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9342 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9343 MonoReflectionMethodBuilder *mb =
9344 mono_array_get (eb->other_methods,
9345 MonoReflectionMethodBuilder*, j);
9346 klass->events [i].other [j] = mb->mhandle;
9353 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9357 MonoReflectionType* res;
9360 MONO_ARCH_SAVE_REGS;
9362 domain = mono_object_domain (tb);
9363 klass = my_mono_class_from_mono_type (tb->type.type);
9365 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9368 * we need to lock the domain because the lock will be taken inside
9369 * So, we need to keep the locking order correct.
9371 mono_domain_lock (domain);
9372 mono_loader_lock ();
9373 if (klass->wastypebuilder) {
9374 mono_loader_unlock ();
9375 mono_domain_unlock (domain);
9376 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9379 * Fields to set in klass:
9380 * the various flags: delegate/unicode/contextbound etc.
9382 klass->flags = tb->attrs;
9383 klass->has_cctor = 1;
9384 klass->has_finalize = 1;
9387 if (!((MonoDynamicImage*)klass->image)->run) {
9388 if (klass->generic_container) {
9389 /* FIXME: The code below can't handle generic classes */
9390 klass->wastypebuilder = TRUE;
9391 mono_loader_unlock ();
9392 mono_domain_unlock (domain);
9393 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9398 /* enums are done right away */
9399 if (!klass->enumtype)
9400 ensure_runtime_vtable (klass);
9403 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9404 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9405 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9409 /* fields and object layout */
9410 if (klass->parent) {
9411 if (!klass->parent->size_inited)
9412 mono_class_init (klass->parent);
9413 klass->instance_size += klass->parent->instance_size;
9414 klass->class_size += klass->parent->class_size;
9415 klass->min_align = klass->parent->min_align;
9416 /* if the type has no fields we won't call the field_setup
9417 * routine which sets up klass->has_references.
9419 klass->has_references |= klass->parent->has_references;
9421 klass->instance_size = sizeof (MonoObject);
9422 klass->min_align = 1;
9425 /* FIXME: handle packing_size and instance_size */
9426 typebuilder_setup_fields (klass);
9428 typebuilder_setup_properties (klass);
9430 typebuilder_setup_events (klass);
9432 klass->wastypebuilder = TRUE;
9433 mono_loader_unlock ();
9434 mono_domain_unlock (domain);
9436 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9437 g_assert (res != (MonoReflectionType*)tb);
9443 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9445 MonoGenericParam *param;
9448 MONO_ARCH_SAVE_REGS;
9450 param = g_new0 (MonoGenericParam, 1);
9452 if (gparam->mbuilder) {
9453 if (!gparam->mbuilder->generic_container)
9454 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9455 param->owner = gparam->mbuilder->generic_container;
9456 } else if (gparam->tbuilder) {
9457 g_assert (gparam->tbuilder->generic_container);
9458 param->owner = gparam->tbuilder->generic_container;
9461 param->method = NULL;
9462 param->name = mono_string_to_utf8 (gparam->name);
9463 param->num = gparam->index;
9465 image = &gparam->tbuilder->module->dynamic_image->image;
9466 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9468 param->pklass->reflection_info = gparam; /* FIXME: GC pin gparam */
9470 gparam->type.type = g_new0 (MonoType, 1);
9471 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9472 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9473 gparam->type.type->data.generic_param = param;
9477 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9479 MonoDynamicImage *assembly = sig->module->dynamic_image;
9480 guint32 na = mono_array_length (sig->arguments);
9481 guint32 buflen, i, size;
9485 MONO_ARCH_SAVE_REGS;
9487 p = buf = g_malloc (size = 50 + na * 50);
9489 mono_metadata_encode_value (0x07, p, &p);
9490 mono_metadata_encode_value (na, p, &p);
9491 for (i = 0; i < na; ++i) {
9492 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9493 encode_reflection_type (assembly, type, p, &p);
9497 g_assert (buflen < size);
9498 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9499 p = mono_array_addr (result, char, 0);
9500 memcpy (p, buf, buflen);
9507 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9509 MonoDynamicImage *assembly = sig->module->dynamic_image;
9510 guint32 na = mono_array_length (sig->arguments);
9511 guint32 buflen, i, size;
9515 MONO_ARCH_SAVE_REGS;
9517 p = buf = g_malloc (size = 10 + na * 10);
9519 mono_metadata_encode_value (0x06, p, &p);
9520 for (i = 0; i < na; ++i) {
9521 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9522 encode_reflection_type (assembly, type, p, &p);
9526 g_assert (buflen < size);
9527 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9528 p = mono_array_addr (result, char, 0);
9529 memcpy (p, buf, buflen);
9536 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9538 ReflectionMethodBuilder rmb;
9539 MonoMethodSignature *sig;
9542 sig = dynamic_method_to_signature (mb);
9544 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9547 * Resolve references.
9550 * Every second entry in the refs array is reserved for storing handle_class,
9551 * which is needed by the ldtoken implementation in the JIT.
9553 rmb.nrefs = mb->nrefs;
9554 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9555 for (i = 0; i < mb->nrefs; i += 2) {
9556 MonoClass *handle_class;
9557 gpointer ref = resolve_object (mb->module->image,
9558 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9561 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9564 rmb.refs [i] = ref; /* FIXME: GC object stored in unamanged memory (change also resolve_object() signature) */
9565 rmb.refs [i + 1] = handle_class;
9569 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9573 /* ilgen is no longer needed */
9578 * mono_reflection_lookup_dynamic_token:
9580 * Finish the Builder object pointed to by TOKEN and return the corresponding
9581 * runtime structure. HANDLE_CLASS is set to the class required by
9585 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9587 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9590 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9593 return resolve_object (image, obj, handle_class);
9597 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9599 gpointer result = NULL;
9601 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9602 result = mono_string_intern ((MonoString*)obj);
9603 *handle_class = NULL;
9605 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9606 MonoReflectionType *tb = (MonoReflectionType*)obj;
9607 result = mono_class_from_mono_type (tb->type);
9608 *handle_class = mono_defaults.typehandle_class;
9610 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9611 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9612 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9613 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9614 result = ((MonoReflectionMethod*)obj)->method;
9615 *handle_class = mono_defaults.methodhandle_class;
9617 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9618 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9619 result = mb->mhandle;
9621 /* Type is not yet created */
9622 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9624 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9627 * Hopefully this has been filled in by calling CreateType() on the
9631 * TODO: This won't work if the application finishes another
9632 * TypeBuilder instance instead of this one.
9634 result = mb->mhandle;
9636 *handle_class = mono_defaults.methodhandle_class;
9637 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9638 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9640 result = cb->mhandle;
9642 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9644 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9645 result = cb->mhandle;
9647 *handle_class = mono_defaults.methodhandle_class;
9648 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9649 result = ((MonoReflectionField*)obj)->field;
9650 *handle_class = mono_defaults.fieldhandle_class;
9652 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9653 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9654 result = fb->handle;
9657 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9659 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9660 result = fb->handle;
9662 *handle_class = mono_defaults.fieldhandle_class;
9663 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9664 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9667 klass = tb->type.type->data.klass;
9668 if (klass->wastypebuilder) {
9669 /* Already created */
9673 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9674 result = tb->type.type->data.klass;
9677 *handle_class = mono_defaults.typehandle_class;
9678 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9679 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9680 MonoMethodSignature *sig;
9683 if (helper->arguments)
9684 nargs = mono_array_length (helper->arguments);
9688 sig = mono_metadata_signature_alloc (image, nargs);
9689 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9690 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9692 if (helper->call_conv == 0) /* unmanaged */
9693 sig->call_convention = helper->unmanaged_call_conv - 1;
9695 if (helper->call_conv & 0x02)
9696 sig->call_convention = MONO_CALL_VARARG;
9698 sig->call_convention = MONO_CALL_DEFAULT;
9700 sig->param_count = nargs;
9701 /* TODO: Copy type ? */
9702 sig->ret = helper->return_type->type;
9703 for (i = 0; i < nargs; ++i) {
9704 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9705 sig->params [i] = rt->type;
9709 *handle_class = NULL;
9711 g_print (obj->vtable->klass->name);
9712 g_assert_not_reached ();
9718 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9719 const static guint32 declsec_flags_map[] = {
9720 0x00000000, /* empty */
9721 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9722 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9723 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9724 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9725 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9726 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9727 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9728 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9729 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9730 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9731 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9732 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9733 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9734 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9735 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9736 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9737 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9738 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9742 * Returns flags that includes all available security action associated to the handle.
9743 * @token: metadata token (either for a class or a method)
9744 * @image: image where resides the metadata.
9747 mono_declsec_get_flags (MonoImage *image, guint32 token)
9749 guint32 index = mono_metadata_declsec_from_index (image, token);
9750 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9755 for (i = index; i < t->rows; i++) {
9756 guint32 cols [MONO_DECL_SECURITY_SIZE];
9758 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9759 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9762 action = cols [MONO_DECL_SECURITY_ACTION];
9763 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9764 result |= declsec_flags_map [action];
9766 g_assert_not_reached ();
9773 * Get the security actions (in the form of flags) associated with the specified method.
9775 * @method: The method for which we want the declarative security flags.
9776 * Return the declarative security flags for the method (only).
9778 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9779 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9782 mono_declsec_flags_from_method (MonoMethod *method)
9784 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9785 /* FIXME: No cache (for the moment) */
9786 guint32 idx = mono_method_get_index (method);
9787 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9788 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9789 return mono_declsec_get_flags (method->klass->image, idx);
9795 * Get the security actions (in the form of flags) associated with the specified class.
9797 * @klass: The class for which we want the declarative security flags.
9798 * Return the declarative security flags for the class.
9800 * Note: We cache the flags inside the MonoClass structure as this will get
9801 * called very often (at least for each method).
9804 mono_declsec_flags_from_class (MonoClass *klass)
9806 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9807 if (!klass->declsec_flags) {
9808 guint32 idx = mono_metadata_token_index (klass->type_token);
9809 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9810 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9811 /* we cache the flags on classes */
9812 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9814 return klass->declsec_flags;
9820 * Get the security actions (in the form of flags) associated with the specified assembly.
9822 * @assembly: The assembly for which we want the declarative security flags.
9823 * Return the declarative security flags for the assembly.
9826 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9828 guint32 idx = 1; /* there is only one assembly */
9829 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9830 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9831 return mono_declsec_get_flags (assembly->image, idx);
9836 * Fill actions for the specific index (which may either be an encoded class token or
9837 * an encoded method token) from the metadata image.
9838 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9841 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9842 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9844 MonoBoolean result = FALSE;
9846 guint32 cols [MONO_DECL_SECURITY_SIZE];
9847 int index = mono_metadata_declsec_from_index (image, token);
9850 t = &image->tables [MONO_TABLE_DECLSECURITY];
9851 for (i = index; i < t->rows; i++) {
9852 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9854 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9857 /* if present only replace (class) permissions with method permissions */
9858 /* if empty accept either class or method permissions */
9859 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9860 if (!actions->demand.blob) {
9861 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9862 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9863 actions->demand.blob = (char*) (blob + 2);
9864 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9867 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9868 if (!actions->noncasdemand.blob) {
9869 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9870 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9871 actions->noncasdemand.blob = (char*) (blob + 2);
9872 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9875 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9876 if (!actions->demandchoice.blob) {
9877 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9878 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9879 actions->demandchoice.blob = (char*) (blob + 2);
9880 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9890 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9891 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9893 guint32 idx = mono_metadata_token_index (klass->type_token);
9894 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9895 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9896 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9900 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9901 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9903 guint32 idx = mono_method_get_index (method);
9904 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9905 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9906 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9910 * Collect all actions (that requires to generate code in mini) assigned for
9911 * the specified method.
9912 * Note: Don't use the content of actions if the function return FALSE.
9915 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9917 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9918 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9919 MonoBoolean result = FALSE;
9922 /* quick exit if no declarative security is present in the metadata */
9923 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9926 /* we want the original as the wrapper is "free" of the security informations */
9927 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9928 method = mono_marshal_method_from_wrapper (method);
9933 /* First we look for method-level attributes */
9934 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9935 mono_class_init (method->klass);
9936 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9938 result = mono_declsec_get_method_demands_params (method, demands,
9939 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9942 /* Here we use (or create) the class declarative cache to look for demands */
9943 flags = mono_declsec_flags_from_class (method->klass);
9946 mono_class_init (method->klass);
9947 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9949 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9950 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9953 /* The boolean return value is used as a shortcut in case nothing needs to
9954 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9960 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9962 * Note: Don't use the content of actions if the function return FALSE.
9965 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9967 MonoBoolean result = FALSE;
9970 /* quick exit if no declarative security is present in the metadata */
9971 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9974 /* we want the original as the wrapper is "free" of the security informations */
9975 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9976 method = mono_marshal_method_from_wrapper (method);
9981 /* results are independant - zeroize both */
9982 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9983 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9985 /* First we look for method-level attributes */
9986 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9987 mono_class_init (method->klass);
9989 result = mono_declsec_get_method_demands_params (method, cmethod,
9990 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9993 /* Here we use (or create) the class declarative cache to look for demands */
9994 flags = mono_declsec_flags_from_class (method->klass);
9995 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9996 mono_class_init (method->klass);
9998 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9999 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
10006 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10008 * @klass The inherited class - this is the class that provides the security check (attributes)
10010 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
10012 * Note: Don't use the content of actions if the function return FALSE.
10015 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
10017 MonoBoolean result = FALSE;
10020 /* quick exit if no declarative security is present in the metadata */
10021 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10024 /* Here we use (or create) the class declarative cache to look for demands */
10025 flags = mono_declsec_flags_from_class (klass);
10026 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
10027 mono_class_init (klass);
10028 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10030 result |= mono_declsec_get_class_demands_params (klass, demands,
10031 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10038 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
10040 * Note: Don't use the content of actions if the function return FALSE.
10043 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
10045 /* quick exit if no declarative security is present in the metadata */
10046 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10049 /* we want the original as the wrapper is "free" of the security informations */
10050 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
10051 method = mono_marshal_method_from_wrapper (method);
10056 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10057 mono_class_init (method->klass);
10058 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10060 return mono_declsec_get_method_demands_params (method, demands,
10061 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10068 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10070 guint32 cols [MONO_DECL_SECURITY_SIZE];
10074 int index = mono_metadata_declsec_from_index (image, token);
10078 t = &image->tables [MONO_TABLE_DECLSECURITY];
10079 for (i = index; i < t->rows; i++) {
10080 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10082 /* shortcut - index are ordered */
10083 if (token != cols [MONO_DECL_SECURITY_PARENT])
10086 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10087 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10088 entry->blob = (char*) (metadata + 2);
10089 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10098 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10100 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10101 guint32 idx = mono_method_get_index (method);
10102 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10103 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10104 return get_declsec_action (method->klass->image, idx, action, entry);
10110 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10113 guint32 flags = mono_declsec_flags_from_class (klass);
10114 if (declsec_flags_map [action] & flags) {
10115 guint32 idx = mono_metadata_token_index (klass->type_token);
10116 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10117 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10118 return get_declsec_action (klass->image, idx, action, entry);
10124 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10126 guint32 idx = 1; /* there is only one assembly */
10127 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10128 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10130 return get_declsec_action (assembly->image, idx, action, entry);
10134 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10136 MonoObject *res, *exc;
10138 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10139 static MonoMethod *method = NULL;
10141 if (!System_Reflection_Emit_TypeBuilder) {
10142 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10143 g_assert (System_Reflection_Emit_TypeBuilder);
10145 if (method == NULL) {
10146 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10151 * The result of mono_type_get_object () might be a System.MonoType but we
10152 * need a TypeBuilder so use klass->reflection_info.
10154 g_assert (klass->reflection_info);
10155 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10157 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10159 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10163 return *(MonoBoolean*)mono_object_unbox (res);