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);
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 shortp = (guint16*)(fat_header + 2);
950 *shortp = GUINT16_TO_LE (max_stack);
951 intp = (guint32*)(fat_header + 4);
952 *intp = GUINT32_TO_LE (code_size);
953 intp = (guint32*)(fat_header + 8);
954 *intp = GUINT32_TO_LE (local_sig);
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;
1047 static MonoCustomAttrInfo*
1048 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1051 MonoCustomAttrInfo *ainfo;
1052 MonoReflectionCustomAttr *cattr;
1056 /* FIXME: check in assembly the Run flag is set */
1058 count = mono_array_length (cattrs);
1060 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1062 ainfo->image = image;
1063 ainfo->num_attrs = count;
1064 for (i = 0; i < count; ++i) {
1065 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1066 ainfo->attrs [i].ctor = cattr->ctor->method;
1067 /* FIXME: might want to memdup the data here */
1068 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1069 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1076 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1078 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1083 if (!dynamic_custom_attrs)
1084 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1086 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1087 ainfo->cached = TRUE;
1091 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1093 /* they are cached, so we don't free them */
1094 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1100 * idx is the table index of the object
1101 * type is one of MONO_CUSTOM_ATTR_*
1104 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1106 MonoDynamicTable *table;
1107 MonoReflectionCustomAttr *cattr;
1109 guint32 count, i, token;
1111 char *p = blob_size;
1113 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1116 count = mono_array_length (cattrs);
1117 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1118 table->rows += count;
1119 alloc_table (table, table->rows);
1120 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1121 idx <<= MONO_CUSTOM_ATTR_BITS;
1123 for (i = 0; i < count; ++i) {
1124 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1125 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1126 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1127 type = mono_metadata_token_index (token);
1128 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1129 switch (mono_metadata_token_table (token)) {
1130 case MONO_TABLE_METHOD:
1131 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1133 case MONO_TABLE_MEMBERREF:
1134 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1137 g_warning ("got wrong token in custom attr");
1140 values [MONO_CUSTOM_ATTR_TYPE] = type;
1142 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1143 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1144 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1145 values += MONO_CUSTOM_ATTR_SIZE;
1151 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1153 MonoDynamicTable *table;
1155 guint32 count, i, idx;
1156 MonoReflectionPermissionSet *perm;
1161 count = mono_array_length (permissions);
1162 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1163 table->rows += count;
1164 alloc_table (table, table->rows);
1166 for (i = 0; i < mono_array_length (permissions); ++i) {
1167 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1169 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1171 idx = mono_metadata_token_index (parent_token);
1172 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1173 switch (mono_metadata_token_table (parent_token)) {
1174 case MONO_TABLE_TYPEDEF:
1175 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1177 case MONO_TABLE_METHOD:
1178 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1180 case MONO_TABLE_ASSEMBLY:
1181 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1184 g_assert_not_reached ();
1187 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1188 values [MONO_DECL_SECURITY_PARENT] = idx;
1189 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1196 * Fill in the MethodDef and ParamDef tables for a method.
1197 * This is used for both normal methods and constructors.
1200 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1202 MonoDynamicTable *table;
1207 /* room in this table is already allocated */
1208 table = &assembly->tables [MONO_TABLE_METHOD];
1209 *mb->table_idx = table->next_idx ++;
1210 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1211 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1212 name = mono_string_to_utf8 (mb->name);
1213 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1215 values [MONO_METHOD_FLAGS] = mb->attrs;
1216 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1217 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1218 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1220 table = &assembly->tables [MONO_TABLE_PARAM];
1221 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1223 mono_image_add_decl_security (assembly,
1224 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1227 MonoDynamicTable *mtable;
1230 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1231 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1234 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1235 if (mono_array_get (mb->pinfo, gpointer, i))
1238 table->rows += count;
1239 alloc_table (table, table->rows);
1240 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1241 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1242 MonoReflectionParamBuilder *pb;
1243 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1244 values [MONO_PARAM_FLAGS] = pb->attrs;
1245 values [MONO_PARAM_SEQUENCE] = i;
1246 if (pb->name != NULL) {
1247 name = mono_string_to_utf8 (pb->name);
1248 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1251 values [MONO_PARAM_NAME] = 0;
1253 values += MONO_PARAM_SIZE;
1254 if (pb->marshal_info) {
1256 alloc_table (mtable, mtable->rows);
1257 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1258 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1259 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1261 pb->table_idx = table->next_idx++;
1262 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1263 guint32 field_type = 0;
1264 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1266 alloc_table (mtable, mtable->rows);
1267 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1268 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1269 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1270 mvalues [MONO_CONSTANT_TYPE] = field_type;
1271 mvalues [MONO_CONSTANT_PADDING] = 0;
1279 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1281 rmb->ilgen = mb->ilgen;
1282 rmb->rtype = mb->rtype;
1283 rmb->parameters = mb->parameters;
1284 rmb->generic_params = mb->generic_params;
1285 rmb->generic_container = mb->generic_container;
1286 rmb->opt_types = NULL;
1287 rmb->pinfo = mb->pinfo;
1288 rmb->attrs = mb->attrs;
1289 rmb->iattrs = mb->iattrs;
1290 rmb->call_conv = mb->call_conv;
1291 rmb->code = mb->code;
1292 rmb->type = mb->type;
1293 rmb->name = mb->name;
1294 rmb->table_idx = &mb->table_idx;
1295 rmb->init_locals = mb->init_locals;
1296 rmb->return_modreq = mb->return_modreq;
1297 rmb->return_modopt = mb->return_modopt;
1298 rmb->param_modreq = mb->param_modreq;
1299 rmb->param_modopt = mb->param_modopt;
1300 rmb->permissions = mb->permissions;
1301 rmb->mhandle = mb->mhandle;
1306 rmb->charset = mb->charset;
1307 rmb->extra_flags = mb->extra_flags;
1308 rmb->native_cc = mb->native_cc;
1309 rmb->dllentry = mb->dllentry;
1315 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1317 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1319 rmb->ilgen = mb->ilgen;
1320 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1321 rmb->parameters = mb->parameters;
1322 rmb->generic_params = NULL;
1323 rmb->generic_container = NULL;
1324 rmb->opt_types = NULL;
1325 rmb->pinfo = mb->pinfo;
1326 rmb->attrs = mb->attrs;
1327 rmb->iattrs = mb->iattrs;
1328 rmb->call_conv = mb->call_conv;
1330 rmb->type = mb->type;
1331 rmb->name = mono_string_new (mono_domain_get (), name);
1332 rmb->table_idx = &mb->table_idx;
1333 rmb->init_locals = mb->init_locals;
1334 rmb->return_modreq = NULL;
1335 rmb->return_modopt = NULL;
1336 rmb->param_modreq = mb->param_modreq;
1337 rmb->param_modopt = mb->param_modopt;
1338 rmb->permissions = mb->permissions;
1339 rmb->mhandle = mb->mhandle;
1345 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1347 rmb->ilgen = mb->ilgen;
1348 rmb->rtype = mb->rtype;
1349 rmb->parameters = mb->parameters;
1350 rmb->generic_params = NULL;
1351 rmb->generic_container = NULL;
1352 rmb->opt_types = NULL;
1354 rmb->attrs = mb->attrs;
1356 rmb->call_conv = mb->call_conv;
1359 rmb->name = mb->name;
1360 rmb->table_idx = NULL;
1361 rmb->init_locals = mb->init_locals;
1362 rmb->return_modreq = NULL;
1363 rmb->return_modopt = NULL;
1364 rmb->param_modreq = NULL;
1365 rmb->param_modopt = NULL;
1366 rmb->permissions = NULL;
1367 rmb->mhandle = mb->mhandle;
1373 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1375 MonoDynamicTable *table;
1378 ReflectionMethodBuilder rmb;
1381 reflection_methodbuilder_from_method_builder (&rmb, mb);
1383 mono_image_basic_method (&rmb, assembly);
1384 mb->table_idx = *rmb.table_idx;
1386 if (mb->dll) { /* It's a P/Invoke method */
1388 /* map CharSet values to on-disk values */
1389 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1390 int extra_flags = mb->extra_flags;
1391 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1393 alloc_table (table, table->rows);
1394 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1396 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1397 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1399 name = mono_string_to_utf8 (mb->dllentry);
1401 name = mono_string_to_utf8 (mb->name);
1402 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1404 name = mono_string_to_utf8 (mb->dll);
1405 moduleref = string_heap_insert (&assembly->sheap, name);
1407 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1408 table = &assembly->tables [MONO_TABLE_MODULEREF];
1410 alloc_table (table, table->rows);
1411 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1412 values [MONO_IMPLMAP_SCOPE] = table->rows;
1416 if (mb->override_method) {
1417 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1419 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1421 alloc_table (table, table->rows);
1422 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1423 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1424 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1426 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1427 switch (mono_metadata_token_table (tok)) {
1428 case MONO_TABLE_MEMBERREF:
1429 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1431 case MONO_TABLE_METHOD:
1432 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1435 g_assert_not_reached ();
1437 values [MONO_METHODIMPL_DECLARATION] = tok;
1440 if (mb->generic_params) {
1441 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1442 table->rows += mono_array_length (mb->generic_params);
1443 alloc_table (table, table->rows);
1444 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1445 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1447 mono_image_get_generic_param_info (
1448 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1455 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1457 ReflectionMethodBuilder rmb;
1459 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1461 mono_image_basic_method (&rmb, assembly);
1462 mb->table_idx = *rmb.table_idx;
1466 type_get_fully_qualified_name (MonoType *type)
1468 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1472 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1476 klass = my_mono_class_from_mono_type (type);
1478 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1479 ta = klass->image->assembly;
1480 if (ta->dynamic || (ta == ass))
1481 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1483 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1487 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1489 char blob_size [64];
1490 char *b = blob_size;
1495 if (!assembly->save)
1498 p = buf = g_malloc (256);
1500 mono_metadata_encode_value (0x06, p, &p);
1501 /* encode custom attributes before the type */
1502 encode_type (assembly, type, p, &p);
1503 g_assert (p-buf < 256);
1504 mono_metadata_encode_value (p-buf, b, &b);
1505 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1511 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1513 char blob_size [64];
1514 char *b = blob_size;
1519 p = buf = g_malloc (256);
1521 mono_metadata_encode_value (0x06, p, &p);
1522 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1523 /* encode custom attributes before the type */
1524 encode_reflection_type (assembly, fb->type, p, &p);
1525 g_assert (p-buf < 256);
1526 mono_metadata_encode_value (p-buf, b, &b);
1527 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1533 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1534 char blob_size [64];
1535 char *b = blob_size;
1538 guint32 idx = 0, len = 0, dummy = 0;
1540 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1541 guint32 fpa_double [2];
1546 p = buf = g_malloc (64);
1548 *ret_type = MONO_TYPE_CLASS;
1550 box_val = (char*)&dummy;
1552 box_val = ((char*)val) + sizeof (MonoObject);
1553 *ret_type = val->vtable->klass->byval_arg.type;
1556 switch (*ret_type) {
1557 case MONO_TYPE_BOOLEAN:
1562 case MONO_TYPE_CHAR:
1579 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1580 fpa_p = (guint32*)box_val;
1581 fpa_double [0] = fpa_p [1];
1582 fpa_double [1] = fpa_p [0];
1583 box_val = (char*)fpa_double;
1587 case MONO_TYPE_VALUETYPE:
1588 if (val->vtable->klass->enumtype) {
1589 *ret_type = val->vtable->klass->enum_basetype->type;
1592 g_error ("we can't encode valuetypes");
1593 case MONO_TYPE_CLASS:
1595 case MONO_TYPE_STRING: {
1596 MonoString *str = (MonoString*)val;
1597 /* there is no signature */
1598 len = str->length * 2;
1599 mono_metadata_encode_value (len, b, &b);
1600 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1602 char *swapped = g_malloc (2 * mono_string_length (str));
1603 const char *p = (const char*)mono_string_chars (str);
1605 swap_with_size (swapped, p, 2, mono_string_length (str));
1606 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1610 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1617 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1620 /* there is no signature */
1621 mono_metadata_encode_value (len, b, &b);
1622 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1623 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1624 swap_with_size (blob_size, box_val, len, 1);
1625 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1627 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1635 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1636 char blob_size [64];
1637 char *b = blob_size;
1638 char *p, *buf, *str;
1639 guint32 idx, len, bufsize = 256;
1641 p = buf = g_malloc (bufsize);
1643 mono_metadata_encode_value (minfo->type, p, &p);
1645 switch (minfo->type) {
1646 case MONO_NATIVE_BYVALTSTR:
1647 case MONO_NATIVE_BYVALARRAY:
1648 mono_metadata_encode_value (minfo->count, p, &p);
1650 case MONO_NATIVE_LPARRAY:
1651 if (minfo->eltype || minfo->has_size) {
1652 mono_metadata_encode_value (minfo->eltype, p, &p);
1653 if (minfo->has_size) {
1654 if (minfo->param_num != -1)
1655 mono_metadata_encode_value (minfo->param_num, p, &p);
1657 mono_metadata_encode_value (0, p, &p);
1658 if (minfo->count != -1)
1659 mono_metadata_encode_value (minfo->count, p, &p);
1661 mono_metadata_encode_value (0, p, &p);
1663 /* LAMESPEC: ElemMult is undocumented */
1664 if (minfo->param_num != -1)
1665 mono_metadata_encode_value (1, p, &p);
1667 mono_metadata_encode_value (0, p, &p);
1671 case MONO_NATIVE_CUSTOM:
1673 str = mono_string_to_utf8 (minfo->guid);
1675 mono_metadata_encode_value (len, p, &p);
1676 memcpy (p, str, len);
1680 mono_metadata_encode_value (0, p, &p);
1682 /* native type name */
1683 mono_metadata_encode_value (0, p, &p);
1684 /* custom marshaler type name */
1685 if (minfo->marshaltype || minfo->marshaltyperef) {
1686 if (minfo->marshaltyperef)
1687 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1689 str = mono_string_to_utf8 (minfo->marshaltype);
1691 mono_metadata_encode_value (len, p, &p);
1692 if (p + len >= buf + bufsize) {
1695 buf = g_realloc (buf, bufsize);
1698 memcpy (p, str, len);
1702 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1703 mono_metadata_encode_value (0, p, &p);
1705 if (minfo->mcookie) {
1706 str = mono_string_to_utf8 (minfo->mcookie);
1708 mono_metadata_encode_value (len, p, &p);
1709 if (p + len >= buf + bufsize) {
1712 buf = g_realloc (buf, bufsize);
1715 memcpy (p, str, len);
1719 mono_metadata_encode_value (0, p, &p);
1726 mono_metadata_encode_value (len, b, &b);
1727 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1733 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1735 MonoDynamicTable *table;
1739 /* maybe this fixup should be done in the C# code */
1740 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1741 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1742 table = &assembly->tables [MONO_TABLE_FIELD];
1743 fb->table_idx = table->next_idx ++;
1744 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1745 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1746 name = mono_string_to_utf8 (fb->name);
1747 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1749 values [MONO_FIELD_FLAGS] = fb->attrs;
1750 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1752 if (fb->offset != -1) {
1753 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1755 alloc_table (table, table->rows);
1756 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1757 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1758 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1760 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1761 guint32 field_type = 0;
1762 table = &assembly->tables [MONO_TABLE_CONSTANT];
1764 alloc_table (table, table->rows);
1765 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1766 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1767 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1768 values [MONO_CONSTANT_TYPE] = field_type;
1769 values [MONO_CONSTANT_PADDING] = 0;
1771 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1773 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1775 alloc_table (table, table->rows);
1776 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1777 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1779 * We store it in the code section because it's simpler for now.
1782 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1784 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1785 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1787 if (fb->marshal_info) {
1788 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1790 alloc_table (table, table->rows);
1791 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1792 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1793 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1798 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1802 char *b = blob_size;
1803 guint32 nparams = 0;
1804 MonoReflectionMethodBuilder *mb = fb->get_method;
1805 MonoReflectionMethodBuilder *smb = fb->set_method;
1806 guint32 idx, i, size;
1808 if (mb && mb->parameters)
1809 nparams = mono_array_length (mb->parameters);
1810 if (!mb && smb && smb->parameters)
1811 nparams = mono_array_length (smb->parameters) - 1;
1812 size = 24 + nparams * 10;
1813 buf = p = g_malloc (size);
1816 mono_metadata_encode_value (nparams, p, &p);
1818 encode_reflection_type (assembly, mb->rtype, p, &p);
1819 for (i = 0; i < nparams; ++i) {
1820 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1821 encode_reflection_type (assembly, pt, p, &p);
1824 /* the property type is the last param */
1825 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1826 for (i = 0; i < nparams; ++i) {
1827 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1828 encode_reflection_type (assembly, pt, p, &p);
1832 encode_reflection_type (assembly, fb->type, p, &p);
1836 g_assert (p - buf < size);
1837 mono_metadata_encode_value (p-buf, b, &b);
1838 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1844 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1846 MonoDynamicTable *table;
1849 guint num_methods = 0;
1853 * we need to set things in the following tables:
1854 * PROPERTYMAP (info already filled in _get_type_info ())
1855 * PROPERTY (rows already preallocated in _get_type_info ())
1856 * METHOD (method info already done with the generic method code)
1859 table = &assembly->tables [MONO_TABLE_PROPERTY];
1860 pb->table_idx = table->next_idx ++;
1861 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1862 name = mono_string_to_utf8 (pb->name);
1863 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1865 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1866 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1868 /* FIXME: we still don't handle 'other' methods */
1869 if (pb->get_method) num_methods ++;
1870 if (pb->set_method) num_methods ++;
1872 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1873 table->rows += num_methods;
1874 alloc_table (table, table->rows);
1876 if (pb->get_method) {
1877 semaidx = table->next_idx ++;
1878 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1879 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1880 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1881 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1883 if (pb->set_method) {
1884 semaidx = table->next_idx ++;
1885 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1886 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1887 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1888 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1893 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1895 MonoDynamicTable *table;
1898 guint num_methods = 0;
1902 * we need to set things in the following tables:
1903 * EVENTMAP (info already filled in _get_type_info ())
1904 * EVENT (rows already preallocated in _get_type_info ())
1905 * METHOD (method info already done with the generic method code)
1908 table = &assembly->tables [MONO_TABLE_EVENT];
1909 eb->table_idx = table->next_idx ++;
1910 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1911 name = mono_string_to_utf8 (eb->name);
1912 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1914 values [MONO_EVENT_FLAGS] = eb->attrs;
1915 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1918 * FIXME: we still don't handle 'other' methods
1920 if (eb->add_method) num_methods ++;
1921 if (eb->remove_method) num_methods ++;
1922 if (eb->raise_method) num_methods ++;
1924 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1925 table->rows += num_methods;
1926 alloc_table (table, table->rows);
1928 if (eb->add_method) {
1929 semaidx = table->next_idx ++;
1930 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1931 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1932 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1933 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1935 if (eb->remove_method) {
1936 semaidx = table->next_idx ++;
1937 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1938 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1939 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1940 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1942 if (eb->raise_method) {
1943 semaidx = table->next_idx ++;
1944 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1945 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1946 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1947 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1952 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1954 MonoDynamicTable *table;
1955 guint32 num_constraints, i;
1959 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1960 num_constraints = gparam->iface_constraints ?
1961 mono_array_length (gparam->iface_constraints) : 0;
1962 table->rows += num_constraints;
1963 if (gparam->base_type)
1965 alloc_table (table, table->rows);
1967 if (gparam->base_type) {
1968 table_idx = table->next_idx ++;
1969 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1971 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1972 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1973 assembly, gparam->base_type->type);
1976 for (i = 0; i < num_constraints; i++) {
1977 MonoReflectionType *constraint = mono_array_get (
1978 gparam->iface_constraints, gpointer, i);
1980 table_idx = table->next_idx ++;
1981 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1983 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1984 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1985 assembly, constraint->type);
1990 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1992 GenericParamTableEntry *entry;
1995 * The GenericParam table must be sorted according to the `owner' field.
1996 * We need to do this sorting prior to writing the GenericParamConstraint
1997 * table, since we have to use the final GenericParam table indices there
1998 * and they must also be sorted.
2001 entry = g_new0 (GenericParamTableEntry, 1);
2002 entry->owner = owner;
2003 entry->gparam = gparam;
2005 g_ptr_array_add (assembly->gen_params, entry);
2009 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2011 MonoDynamicTable *table;
2012 MonoGenericParam *param;
2016 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2017 table_idx = table->next_idx ++;
2018 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2020 param = entry->gparam->type.type->data.generic_param;
2022 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2023 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2024 values [MONO_GENERICPARAM_NUMBER] = param->num;
2025 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2027 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2029 encode_constraints (entry->gparam, table_idx, assembly);
2033 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2035 MonoDynamicTable *table;
2038 guint32 cols [MONO_ASSEMBLY_SIZE];
2042 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2045 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2046 table = &assembly->tables [MONO_TABLE_MODULEREF];
2047 token = table->next_idx ++;
2049 alloc_table (table, table->rows);
2050 values = table->values + token * MONO_MODULEREF_SIZE;
2051 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2053 token <<= MONO_RESOLTION_SCOPE_BITS;
2054 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2055 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2060 if (image->assembly->dynamic)
2062 memset (cols, 0, sizeof (cols));
2064 /* image->assembly->image is the manifest module */
2065 image = image->assembly->image;
2066 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2069 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2070 token = table->next_idx ++;
2072 alloc_table (table, table->rows);
2073 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2074 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2075 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2076 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2077 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2078 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2079 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2080 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2081 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2083 if (strcmp ("", image->assembly->aname.culture)) {
2084 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2085 image->assembly->aname.culture);
2088 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2089 guchar pubtoken [9];
2091 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2092 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2094 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2096 token <<= MONO_RESOLTION_SCOPE_BITS;
2097 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2098 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2103 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2105 MonoDynamicTable *table;
2111 char *b = blob_size;
2113 switch (type->type) {
2114 case MONO_TYPE_FNPTR:
2116 case MONO_TYPE_SZARRAY:
2117 case MONO_TYPE_ARRAY:
2119 case MONO_TYPE_MVAR:
2120 case MONO_TYPE_GENERICINST:
2121 encode_type (assembly, type, p, &p);
2123 case MONO_TYPE_CLASS:
2124 case MONO_TYPE_VALUETYPE: {
2125 MonoClass *k = mono_class_from_mono_type (type);
2126 if (!k || !k->generic_class)
2128 encode_generic_class (assembly, k->generic_class, p, &p);
2135 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2136 if (assembly->save) {
2137 g_assert (p-sig < 128);
2138 mono_metadata_encode_value (p-sig, b, &b);
2139 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2140 alloc_table (table, table->rows + 1);
2141 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2142 values [MONO_TYPESPEC_SIGNATURE] = token;
2145 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2146 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2152 * Despite the name, we handle also TypeSpec (with the above helper).
2155 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2157 MonoDynamicTable *table;
2159 guint32 token, scope, enclosing;
2162 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2165 token = create_typespec (assembly, type);
2168 klass = my_mono_class_from_mono_type (type);
2170 klass = mono_class_from_mono_type (type);
2173 * If it's in the same module and not a generic type parameter:
2175 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2176 (type->type != MONO_TYPE_MVAR)) {
2177 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2178 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2179 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2183 if (klass->nested_in) {
2184 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2185 /* get the typeref idx of the enclosing type */
2186 enclosing >>= MONO_TYPEDEFORREF_BITS;
2187 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2189 scope = resolution_scope_from_image (assembly, klass->image);
2191 table = &assembly->tables [MONO_TABLE_TYPEREF];
2192 if (assembly->save) {
2193 alloc_table (table, table->rows + 1);
2194 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2195 values [MONO_TYPEREF_SCOPE] = scope;
2196 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2197 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2199 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2200 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2202 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2207 * Insert a memberef row into the metadata: the token that point to the memberref
2208 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2209 * mono_image_get_fieldref_token()).
2210 * The sig param is an index to an already built signature.
2213 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2215 MonoDynamicTable *table;
2217 guint32 token, pclass;
2220 parent = mono_image_typedef_or_ref (assembly, type);
2221 switch (parent & MONO_TYPEDEFORREF_MASK) {
2222 case MONO_TYPEDEFORREF_TYPEREF:
2223 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2225 case MONO_TYPEDEFORREF_TYPESPEC:
2226 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2228 case MONO_TYPEDEFORREF_TYPEDEF:
2229 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2232 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2235 /* extract the index */
2236 parent >>= MONO_TYPEDEFORREF_BITS;
2238 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2240 if (assembly->save) {
2241 alloc_table (table, table->rows + 1);
2242 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2243 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2244 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2245 values [MONO_MEMBERREF_SIGNATURE] = sig;
2248 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2255 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2258 MonoMethodSignature *sig;
2260 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2265 * A methodref signature can't contain an unmanaged calling convention.
2267 sig = mono_metadata_signature_dup (mono_method_signature (method));
2268 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2269 sig->call_convention = MONO_CALL_DEFAULT;
2270 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2271 method->name, method_encode_signature (assembly, sig));
2273 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2278 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2279 const gchar *name, guint32 sig)
2281 MonoDynamicTable *table;
2285 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2287 if (assembly->save) {
2288 alloc_table (table, table->rows + 1);
2289 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2290 values [MONO_MEMBERREF_CLASS] = original;
2291 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2292 values [MONO_MEMBERREF_SIGNATURE] = sig;
2295 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2302 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2305 ReflectionMethodBuilder rmb;
2307 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2311 reflection_methodbuilder_from_method_builder (&rmb, mb);
2313 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2314 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2315 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2320 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2323 ReflectionMethodBuilder rmb;
2325 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2329 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2331 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2332 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2333 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2338 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2343 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2346 g_assert (f->field->parent);
2347 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2348 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2349 f->field->name, fieldref_encode_signature (assembly, type));
2350 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2355 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2360 guint32 nparams = gmethod->inst->type_argc;
2361 guint32 size = 10 + nparams * 30;
2364 char *b = blob_size;
2366 if (!assembly->save)
2369 p = buf = g_malloc (size);
2371 * FIXME: vararg, explicit_this, differenc call_conv values...
2373 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2374 mono_metadata_encode_value (nparams, p, &p);
2376 for (i = 0; i < nparams; i++)
2377 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2380 g_assert (p - buf < size);
2381 mono_metadata_encode_value (p-buf, b, &b);
2382 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2388 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2390 MonoDynamicTable *table;
2392 guint32 token, mtoken = 0, sig;
2393 MonoMethodInflated *imethod;
2394 MonoMethod *declaring;
2396 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2398 g_assert (method->is_inflated);
2399 method = mono_get_inflated_method (method);
2400 imethod = (MonoMethodInflated *) method;
2401 declaring = imethod->declaring;
2403 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2404 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2406 if (!mono_method_signature (declaring)->generic_param_count)
2409 switch (mono_metadata_token_table (mtoken)) {
2410 case MONO_TABLE_MEMBERREF:
2411 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2413 case MONO_TABLE_METHOD:
2414 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2417 g_assert_not_reached ();
2420 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2422 if (assembly->save) {
2423 alloc_table (table, table->rows + 1);
2424 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2425 values [MONO_METHODSPEC_METHOD] = mtoken;
2426 values [MONO_METHODSPEC_SIGNATURE] = sig;
2429 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2436 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2438 MonoMethodInflated *imethod;
2439 MonoMethod *inflated;
2442 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2446 g_assert (method->is_inflated);
2447 inflated = mono_get_inflated_method (method);
2448 imethod = (MonoMethodInflated *) inflated;
2450 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2451 token = method_encode_methodspec (assembly, inflated);
2453 guint32 sig = method_encode_signature (
2454 assembly, mono_method_signature (imethod->declaring));
2455 token = mono_image_get_memberref_token (
2456 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2459 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2464 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2466 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2469 m = mono_get_inflated_method (m);
2471 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2472 token = mono_image_get_memberref_token (
2473 assembly, &m->klass->byval_arg, m->name, sig);
2479 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2481 MonoDynamicTable *table;
2488 char *b = blob_size;
2492 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2493 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2494 * Because of this, we must not insert it into the `typeref' hash table.
2497 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2501 g_assert (tb->generic_params);
2502 klass = mono_class_from_mono_type (tb->type.type);
2504 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2505 encode_type (assembly, &klass->byval_arg, p, &p);
2507 count = mono_array_length (tb->generic_params);
2508 mono_metadata_encode_value (count, p, &p);
2509 for (i = 0; i < count; i++) {
2510 MonoReflectionGenericParam *gparam;
2512 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2514 encode_type (assembly, gparam->type.type, p, &p);
2517 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2518 g_assert (p-sig < 128);
2520 if (assembly->save) {
2521 mono_metadata_encode_value (p-sig, b, &b);
2522 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2523 alloc_table (table, table->rows + 1);
2524 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2525 values [MONO_TYPESPEC_SIGNATURE] = token;
2528 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2529 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2535 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2537 MonoDynamicTable *table;
2540 guint32 token, pclass, parent, sig;
2543 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2547 klass = mono_class_from_mono_type (fb->typeb->type);
2548 name = mono_string_to_utf8 (fb->name);
2550 sig = fieldref_encode_signature (assembly, fb->type->type);
2552 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2553 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2555 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2556 parent >>= MONO_TYPEDEFORREF_BITS;
2558 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2560 if (assembly->save) {
2561 alloc_table (table, table->rows + 1);
2562 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2563 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2564 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2565 values [MONO_MEMBERREF_SIGNATURE] = sig;
2568 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2570 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2575 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2583 char *b = blob_size;
2585 if (!assembly->save)
2589 g_assert (helper->type == 2);
2591 if (helper->arguments)
2592 nargs = mono_array_length (helper->arguments);
2596 size = 10 + (nargs * 10);
2598 p = buf = g_malloc (size);
2600 /* Encode calling convention */
2601 /* Change Any to Standard */
2602 if ((helper->call_conv & 0x03) == 0x03)
2603 helper->call_conv = 0x01;
2604 /* explicit_this implies has_this */
2605 if (helper->call_conv & 0x40)
2606 helper->call_conv &= 0x20;
2608 if (helper->call_conv == 0) { /* Unmanaged */
2609 *p = helper->unmanaged_call_conv - 1;
2612 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2613 if (helper->call_conv & 0x02) /* varargs */
2618 mono_metadata_encode_value (nargs, p, &p);
2619 encode_reflection_type (assembly, helper->return_type, p, &p);
2620 for (i = 0; i < nargs; ++i) {
2621 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2622 encode_reflection_type (assembly, pt, p, &p);
2625 g_assert (p - buf < size);
2626 mono_metadata_encode_value (p-buf, b, &b);
2627 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2634 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2637 MonoDynamicTable *table;
2640 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2641 idx = table->next_idx ++;
2643 alloc_table (table, table->rows);
2644 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2646 values [MONO_STAND_ALONE_SIGNATURE] =
2647 mono_reflection_encode_sighelper (assembly, helper);
2653 reflection_cc_to_file (int call_conv) {
2654 switch (call_conv & 0x3) {
2656 case 1: return MONO_CALL_DEFAULT;
2657 case 2: return MONO_CALL_VARARG;
2659 g_assert_not_reached ();
2666 MonoMethodSignature *sig;
2672 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2677 MonoMethodSignature *sig;
2680 name = mono_string_to_utf8 (m->name);
2681 nparams = mono_array_length (m->parameters);
2682 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2684 sig->sentinelpos = -1;
2685 sig->call_convention = reflection_cc_to_file (m->call_conv);
2686 sig->param_count = nparams;
2687 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2688 for (i = 0; i < nparams; ++i) {
2689 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2690 sig->params [i] = t->type;
2693 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2695 if (strcmp (name, am->name) == 0 &&
2696 mono_metadata_type_equal (am->parent, m->parent->type) &&
2697 mono_metadata_signature_equal (am->sig, sig)) {
2700 m->table_idx = am->token & 0xffffff;
2704 am = g_new0 (ArrayMethod, 1);
2707 am->parent = m->parent->type;
2708 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2709 method_encode_signature (assembly, sig));
2710 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2711 m->table_idx = am->token & 0xffffff;
2716 * Insert into the metadata tables all the info about the TypeBuilder tb.
2717 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2720 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2722 MonoDynamicTable *table;
2724 int i, is_object = 0, is_system = 0;
2727 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2728 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2729 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2730 n = mono_string_to_utf8 (tb->name);
2731 if (strcmp (n, "Object") == 0)
2733 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2735 n = mono_string_to_utf8 (tb->nspace);
2736 if (strcmp (n, "System") == 0)
2738 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2740 if (tb->parent && !(is_system && is_object) &&
2741 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2742 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2744 values [MONO_TYPEDEF_EXTENDS] = 0;
2746 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2747 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2750 * if we have explicitlayout or sequentiallayouts, output data in the
2751 * ClassLayout table.
2753 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2754 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2755 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2757 alloc_table (table, table->rows);
2758 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2759 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2760 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2761 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2764 /* handle interfaces */
2765 if (tb->interfaces) {
2766 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2768 table->rows += mono_array_length (tb->interfaces);
2769 alloc_table (table, table->rows);
2770 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2771 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2772 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2773 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2774 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2775 values += MONO_INTERFACEIMPL_SIZE;
2781 table = &assembly->tables [MONO_TABLE_FIELD];
2782 table->rows += tb->num_fields;
2783 alloc_table (table, table->rows);
2784 for (i = 0; i < tb->num_fields; ++i)
2785 mono_image_get_field_info (
2786 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2789 /* handle constructors */
2791 table = &assembly->tables [MONO_TABLE_METHOD];
2792 table->rows += mono_array_length (tb->ctors);
2793 alloc_table (table, table->rows);
2794 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2795 mono_image_get_ctor_info (domain,
2796 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2799 /* handle methods */
2801 table = &assembly->tables [MONO_TABLE_METHOD];
2802 table->rows += tb->num_methods;
2803 alloc_table (table, table->rows);
2804 for (i = 0; i < tb->num_methods; ++i)
2805 mono_image_get_method_info (
2806 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2809 /* Do the same with properties etc.. */
2810 if (tb->events && mono_array_length (tb->events)) {
2811 table = &assembly->tables [MONO_TABLE_EVENT];
2812 table->rows += mono_array_length (tb->events);
2813 alloc_table (table, table->rows);
2814 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2816 alloc_table (table, table->rows);
2817 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2818 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2819 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2820 for (i = 0; i < mono_array_length (tb->events); ++i)
2821 mono_image_get_event_info (
2822 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2824 if (tb->properties && mono_array_length (tb->properties)) {
2825 table = &assembly->tables [MONO_TABLE_PROPERTY];
2826 table->rows += mono_array_length (tb->properties);
2827 alloc_table (table, table->rows);
2828 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2830 alloc_table (table, table->rows);
2831 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2832 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2833 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2834 for (i = 0; i < mono_array_length (tb->properties); ++i)
2835 mono_image_get_property_info (
2836 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2839 /* handle generic parameters */
2840 if (tb->generic_params) {
2841 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2842 table->rows += mono_array_length (tb->generic_params);
2843 alloc_table (table, table->rows);
2844 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2845 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2847 mono_image_get_generic_param_info (
2848 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2852 mono_image_add_decl_security (assembly,
2853 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2856 MonoDynamicTable *ntable;
2858 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2859 ntable->rows += mono_array_length (tb->subtypes);
2860 alloc_table (ntable, ntable->rows);
2861 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2863 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2864 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2866 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2867 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2868 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2869 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2870 mono_string_to_utf8 (tb->name), tb->table_idx,
2871 ntable->next_idx, ntable->rows);*/
2872 values += MONO_NESTED_CLASS_SIZE;
2879 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2883 g_ptr_array_add (types, type);
2885 if (!type->subtypes)
2888 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2889 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2890 collect_types (types, subtype);
2895 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2897 if ((*type1)->table_idx < (*type2)->table_idx)
2900 if ((*type1)->table_idx > (*type2)->table_idx)
2907 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2912 for (i = 0; i < mono_array_length (pinfo); ++i) {
2913 MonoReflectionParamBuilder *pb;
2914 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2917 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2922 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2925 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2927 for (i = 0; i < tb->num_fields; ++i) {
2928 MonoReflectionFieldBuilder* fb;
2929 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2930 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2934 for (i = 0; i < mono_array_length (tb->events); ++i) {
2935 MonoReflectionEventBuilder* eb;
2936 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2937 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2940 if (tb->properties) {
2941 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2942 MonoReflectionPropertyBuilder* pb;
2943 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2944 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2948 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2949 MonoReflectionCtorBuilder* cb;
2950 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2951 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2952 params_add_cattrs (assembly, cb->pinfo);
2957 for (i = 0; i < tb->num_methods; ++i) {
2958 MonoReflectionMethodBuilder* mb;
2959 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2960 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2961 params_add_cattrs (assembly, mb->pinfo);
2966 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2967 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2972 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
2976 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
2978 if (moduleb->global_methods) {
2979 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
2980 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
2981 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2982 params_add_cattrs (assembly, mb->pinfo);
2986 if (moduleb->global_fields) {
2987 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
2988 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
2989 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2993 if (moduleb->types) {
2994 for (i = 0; i < moduleb->num_types; ++i)
2995 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3000 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3002 MonoDynamicTable *table;
3006 char *b = blob_size;
3009 table = &assembly->tables [MONO_TABLE_FILE];
3011 alloc_table (table, table->rows);
3012 values = table->values + table->next_idx * MONO_FILE_SIZE;
3013 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3014 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3015 if (module->image->dynamic) {
3016 /* This depends on the fact that the main module is emitted last */
3017 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3018 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3021 path = g_strdup (module->image->name);
3023 mono_sha1_get_digest_from_file (path, hash);
3026 mono_metadata_encode_value (20, b, &b);
3027 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3028 mono_image_add_stream_data (&assembly->blob, hash, 20);
3033 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3035 MonoDynamicTable *table;
3039 table = &assembly->tables [MONO_TABLE_MODULE];
3040 mb->table_idx = table->next_idx ++;
3041 name = mono_string_to_utf8 (mb->module.name);
3042 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3044 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3047 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3048 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3049 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3050 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3054 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3055 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3057 MonoDynamicTable *table;
3061 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3062 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3065 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3067 alloc_table (table, table->rows);
3068 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3070 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3071 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3072 if (klass->nested_in)
3073 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3075 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3076 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3077 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3079 res = table->next_idx;
3083 /* Emit nested types */
3084 if (klass->nested_classes) {
3087 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3088 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3095 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3096 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3101 klass = mono_class_from_mono_type (tb->type.type);
3103 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3105 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3106 parent_index, assembly);
3110 * We need to do this ourselves since klass->nested_classes is not set up.
3113 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3114 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3119 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3120 guint32 module_index, MonoDynamicImage *assembly)
3122 MonoImage *image = module->image;
3126 t = &image->tables [MONO_TABLE_TYPEDEF];
3128 for (i = 0; i < t->rows; ++i) {
3129 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3131 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3132 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3136 #define align_pointer(base,p)\
3138 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3140 (p) += 4 - (__diff & 3);\
3144 compare_constants (const void *a, const void *b)
3146 const guint32 *a_values = a;
3147 const guint32 *b_values = b;
3148 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3152 compare_semantics (const void *a, const void *b)
3154 const guint32 *a_values = a;
3155 const guint32 *b_values = b;
3156 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3159 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3163 compare_custom_attrs (const void *a, const void *b)
3165 const guint32 *a_values = a;
3166 const guint32 *b_values = b;
3168 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3172 compare_field_marshal (const void *a, const void *b)
3174 const guint32 *a_values = a;
3175 const guint32 *b_values = b;
3177 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3181 compare_nested (const void *a, const void *b)
3183 const guint32 *a_values = a;
3184 const guint32 *b_values = b;
3186 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3190 compare_genericparam (const void *a, const void *b)
3192 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3193 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3195 if ((*b_entry)->owner == (*a_entry)->owner)
3197 (*a_entry)->gparam->type.type->data.generic_param->num -
3198 (*b_entry)->gparam->type.type->data.generic_param->num;
3200 return (*a_entry)->owner - (*b_entry)->owner;
3204 compare_declsecurity_attrs (const void *a, const void *b)
3206 const guint32 *a_values = a;
3207 const guint32 *b_values = b;
3209 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3213 pad_heap (MonoDynamicStream *sh)
3215 if (sh->index & 3) {
3216 int sz = 4 - (sh->index & 3);
3217 memset (sh->data + sh->index, 0, sz);
3224 MonoDynamicStream *stream;
3228 * build_compressed_metadata() fills in the blob of data that represents the
3229 * raw metadata as it will be saved in the PE file. The five streams are output
3230 * and the metadata tables are comnpressed from the guint32 array representation,
3231 * to the compressed on-disk format.
3234 build_compressed_metadata (MonoDynamicImage *assembly)
3236 MonoDynamicTable *table;
3238 guint64 valid_mask = 0;
3239 guint64 sorted_mask;
3240 guint32 heapt_size = 0;
3241 guint32 meta_size = 256; /* allow for header and other stuff */
3242 guint32 table_offset;
3243 guint32 ntables = 0;
3249 struct StreamDesc stream_desc [5];
3251 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3252 for (i = 0; i < assembly->gen_params->len; i++){
3253 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3254 write_generic_param_entry (assembly, entry);
3257 stream_desc [0].name = "#~";
3258 stream_desc [0].stream = &assembly->tstream;
3259 stream_desc [1].name = "#Strings";
3260 stream_desc [1].stream = &assembly->sheap;
3261 stream_desc [2].name = "#US";
3262 stream_desc [2].stream = &assembly->us;
3263 stream_desc [3].name = "#Blob";
3264 stream_desc [3].stream = &assembly->blob;
3265 stream_desc [4].name = "#GUID";
3266 stream_desc [4].stream = &assembly->guid;
3268 /* tables that are sorted */
3269 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3270 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3271 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3272 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3273 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3274 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3276 /* Compute table sizes */
3277 /* the MonoImage has already been created in mono_image_basic_init() */
3278 meta = &assembly->image;
3280 /* sizes should be multiple of 4 */
3281 pad_heap (&assembly->blob);
3282 pad_heap (&assembly->guid);
3283 pad_heap (&assembly->sheap);
3284 pad_heap (&assembly->us);
3286 /* Setup the info used by compute_sizes () */
3287 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3288 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3289 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3291 meta_size += assembly->blob.index;
3292 meta_size += assembly->guid.index;
3293 meta_size += assembly->sheap.index;
3294 meta_size += assembly->us.index;
3296 for (i=0; i < MONO_TABLE_NUM; ++i)
3297 meta->tables [i].rows = assembly->tables [i].rows;
3299 for (i = 0; i < MONO_TABLE_NUM; i++){
3300 if (meta->tables [i].rows == 0)
3302 valid_mask |= (guint64)1 << i;
3304 meta->tables [i].row_size = mono_metadata_compute_size (
3305 meta, i, &meta->tables [i].size_bitfield);
3306 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3308 heapt_size += 24; /* #~ header size */
3309 heapt_size += ntables * 4;
3310 /* make multiple of 4 */
3313 meta_size += heapt_size;
3314 meta->raw_metadata = g_malloc0 (meta_size);
3315 p = meta->raw_metadata;
3316 /* the metadata signature */
3317 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3318 /* version numbers and 4 bytes reserved */
3319 int16val = (guint16*)p;
3320 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3321 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3323 /* version string */
3324 int32val = (guint32*)p;
3325 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3327 memcpy (p, meta->version, strlen (meta->version));
3328 p += GUINT32_FROM_LE (*int32val);
3329 align_pointer (meta->raw_metadata, p);
3330 int16val = (guint16*)p;
3331 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3332 *int16val = GUINT16_TO_LE (5); /* number of streams */
3336 * write the stream info.
3338 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3339 table_offset += 3; table_offset &= ~3;
3341 assembly->tstream.index = heapt_size;
3342 for (i = 0; i < 5; ++i) {
3343 int32val = (guint32*)p;
3344 stream_desc [i].stream->offset = table_offset;
3345 *int32val++ = GUINT32_TO_LE (table_offset);
3346 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3347 table_offset += GUINT32_FROM_LE (*int32val);
3348 table_offset += 3; table_offset &= ~3;
3350 strcpy (p, stream_desc [i].name);
3351 p += strlen (stream_desc [i].name) + 1;
3352 align_pointer (meta->raw_metadata, p);
3355 * now copy the data, the table stream header and contents goes first.
3357 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3358 p = meta->raw_metadata + assembly->tstream.offset;
3359 int32val = (guint32*)p;
3360 *int32val = GUINT32_TO_LE (0); /* reserved */
3363 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3364 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3365 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3366 *p++ = 2; /* version */
3369 *p++ = 1; /* version */
3373 if (meta->idx_string_wide)
3375 if (meta->idx_guid_wide)
3377 if (meta->idx_blob_wide)
3380 *p++ = 1; /* reserved */
3381 int64val = (guint64*)p;
3382 *int64val++ = GUINT64_TO_LE (valid_mask);
3383 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3385 int32val = (guint32*)p;
3386 for (i = 0; i < MONO_TABLE_NUM; i++){
3387 if (meta->tables [i].rows == 0)
3389 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3391 p = (unsigned char*)int32val;
3393 /* sort the tables that still need sorting */
3394 table = &assembly->tables [MONO_TABLE_CONSTANT];
3396 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3397 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3399 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3400 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3402 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3403 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3405 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3406 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3408 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3409 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3410 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3412 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3414 /* compress the tables */
3415 for (i = 0; i < MONO_TABLE_NUM; i++){
3418 guint32 bitfield = meta->tables [i].size_bitfield;
3419 if (!meta->tables [i].rows)
3421 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3422 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3423 meta->tables [i].base = p;
3424 for (row = 1; row <= meta->tables [i].rows; ++row) {
3425 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3426 for (col = 0; col < assembly->tables [i].columns; ++col) {
3427 switch (mono_metadata_table_size (bitfield, col)) {
3429 *p++ = values [col];
3432 *p++ = values [col] & 0xff;
3433 *p++ = (values [col] >> 8) & 0xff;
3436 *p++ = values [col] & 0xff;
3437 *p++ = (values [col] >> 8) & 0xff;
3438 *p++ = (values [col] >> 16) & 0xff;
3439 *p++ = (values [col] >> 24) & 0xff;
3442 g_assert_not_reached ();
3446 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3449 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3450 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3451 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3452 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3453 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3455 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3459 * Some tables in metadata need to be sorted according to some criteria, but
3460 * when methods and fields are first created with reflection, they may be assigned a token
3461 * that doesn't correspond to the final token they will get assigned after the sorting.
3462 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3463 * with the reflection objects that represent them. Once all the tables are set up, the
3464 * reflection objects will contains the correct table index. fixup_method() will fixup the
3465 * tokens for the method with ILGenerator @ilgen.
3468 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3469 guint32 code_idx = GPOINTER_TO_UINT (value);
3470 MonoReflectionILTokenInfo *iltoken;
3471 MonoReflectionFieldBuilder *field;
3472 MonoReflectionCtorBuilder *ctor;
3473 MonoReflectionMethodBuilder *method;
3474 MonoReflectionTypeBuilder *tb;
3475 MonoReflectionArrayMethod *am;
3477 unsigned char *target;
3479 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3480 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3481 target = assembly->code.data + code_idx + iltoken->code_pos;
3482 switch (target [3]) {
3483 case MONO_TABLE_FIELD:
3484 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3485 field = (MonoReflectionFieldBuilder *)iltoken->member;
3486 idx = field->table_idx;
3487 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3488 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3489 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3491 g_assert_not_reached ();
3494 case MONO_TABLE_METHOD:
3495 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3496 method = (MonoReflectionMethodBuilder *)iltoken->member;
3497 idx = method->table_idx;
3498 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3499 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3500 idx = ctor->table_idx;
3501 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3502 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3503 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3504 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3506 g_assert_not_reached ();
3509 case MONO_TABLE_TYPEDEF:
3510 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3511 g_assert_not_reached ();
3512 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3513 idx = tb->table_idx;
3515 case MONO_TABLE_MEMBERREF:
3516 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3517 am = (MonoReflectionArrayMethod*)iltoken->member;
3518 idx = am->table_idx;
3519 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3520 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3521 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3522 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3523 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3524 g_assert (m->klass->generic_class || m->klass->generic_container);
3526 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3528 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3529 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3530 g_assert (f->generic_info);
3532 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3535 g_assert_not_reached ();
3538 case MONO_TABLE_METHODSPEC:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3540 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3541 g_assert (mono_method_signature (m)->generic_param_count);
3544 g_assert_not_reached ();
3548 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3550 target [0] = idx & 0xff;
3551 target [1] = (idx >> 8) & 0xff;
3552 target [2] = (idx >> 16) & 0xff;
3559 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3560 * value is not known when the table is emitted.
3563 fixup_cattrs (MonoDynamicImage *assembly)
3565 MonoDynamicTable *table;
3567 guint32 type, i, idx, token;
3570 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3572 for (i = 0; i < table->rows; ++i) {
3573 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3575 type = values [MONO_CUSTOM_ATTR_TYPE];
3576 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3577 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3578 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3579 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3582 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3583 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3584 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3585 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3594 * The METHODIMPL table might contain METHODDEF tokens whose final
3595 * value is not known when the table is emitted.
3598 fixup_methodimpl (MonoDynamicImage *assembly)
3600 MonoDynamicTable *table;
3602 guint32 decl, i, idx, token;
3605 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3607 for (i = 0; i < table->rows; ++i) {
3608 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3609 decl = values [MONO_METHODIMPL_DECLARATION];
3611 idx = decl >> MONO_METHODDEFORREF_BITS;
3612 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3615 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3616 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3619 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3620 token = mono_image_create_token (assembly, method, FALSE);
3621 idx = mono_metadata_token_index (token);
3622 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3628 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3630 MonoDynamicTable *table;
3634 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3636 alloc_table (table, table->rows);
3637 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3638 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3639 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3640 name = mono_string_to_utf8 (rsrc->name);
3641 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3643 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3648 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3650 MonoDynamicTable *table;
3654 char *b = blob_size;
3656 guint32 idx, offset;
3658 if (rsrc->filename) {
3659 name = mono_string_to_utf8 (rsrc->filename);
3660 sname = g_path_get_basename (name);
3662 table = &assembly->tables [MONO_TABLE_FILE];
3664 alloc_table (table, table->rows);
3665 values = table->values + table->next_idx * MONO_FILE_SIZE;
3666 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3667 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3670 mono_sha1_get_digest_from_file (name, hash);
3671 mono_metadata_encode_value (20, b, &b);
3672 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3673 mono_image_add_stream_data (&assembly->blob, hash, 20);
3675 idx = table->next_idx++;
3677 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3680 offset = mono_array_length (rsrc->data);
3681 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3682 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3683 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3684 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3688 * The entry should be emitted into the MANIFESTRESOURCE table of
3689 * the main module, but that needs to reference the FILE table
3690 * which isn't emitted yet.
3697 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3701 set_version_from_string (MonoString *version, guint32 *values)
3703 gchar *ver, *p, *str;
3706 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3707 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3708 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3709 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3712 ver = str = mono_string_to_utf8 (version);
3713 for (i = 0; i < 4; ++i) {
3714 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3720 /* handle Revision and Build */
3730 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3734 char *b = blob_size;
3739 len = mono_array_length (pkey);
3740 mono_metadata_encode_value (len, b, &b);
3741 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3742 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3744 /* Special case: check for ECMA key (16 bytes) */
3745 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3746 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3747 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3748 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3749 /* minimum key size (in 2.0) is 384 bits */
3750 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3752 /* FIXME - verifier */
3753 g_warning ("Invalid public key length: %d bits (total: %d)", MONO_PUBLIC_KEY_BIT_SIZE (len), len);
3754 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3756 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3762 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3764 MonoDynamicTable *table;
3765 MonoDynamicImage *assembly;
3766 MonoReflectionAssemblyBuilder *assemblyb;
3771 guint32 module_index;
3773 assemblyb = moduleb->assemblyb;
3774 assembly = moduleb->dynamic_image;
3775 domain = mono_object_domain (assemblyb);
3777 /* Emit ASSEMBLY table */
3778 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3779 alloc_table (table, 1);
3780 values = table->values + MONO_ASSEMBLY_SIZE;
3781 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3782 name = mono_string_to_utf8 (assemblyb->name);
3783 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3785 if (assemblyb->culture) {
3786 name = mono_string_to_utf8 (assemblyb->culture);
3787 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3790 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3792 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3793 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3794 set_version_from_string (assemblyb->version, values);
3796 /* Emit FILE + EXPORTED_TYPE table */
3798 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3800 MonoReflectionModuleBuilder *file_module =
3801 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3802 if (file_module != moduleb) {
3803 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3805 if (file_module->types) {
3806 for (j = 0; j < file_module->num_types; ++j) {
3807 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3808 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3813 if (assemblyb->loaded_modules) {
3814 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3815 MonoReflectionModule *file_module =
3816 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3817 mono_image_fill_file_table (domain, file_module, assembly);
3819 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3823 /* Emit MANIFESTRESOURCE table */
3825 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3827 MonoReflectionModuleBuilder *file_module =
3828 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3829 /* The table for the main module is emitted later */
3830 if (file_module != moduleb) {
3832 if (file_module->resources) {
3833 int len = mono_array_length (file_module->resources);
3834 for (j = 0; j < len; ++j) {
3835 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3836 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3844 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3845 * for the modulebuilder @moduleb.
3846 * At the end of the process, method and field tokens are fixed up and the
3847 * on-disk compressed metadata representation is created.
3850 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3852 MonoDynamicTable *table;
3853 MonoDynamicImage *assembly;
3854 MonoReflectionAssemblyBuilder *assemblyb;
3859 assemblyb = moduleb->assemblyb;
3860 assembly = moduleb->dynamic_image;
3861 domain = mono_object_domain (assemblyb);
3863 if (assembly->text_rva)
3866 assembly->text_rva = START_TEXT_RVA;
3868 if (moduleb->is_main) {
3869 mono_image_emit_manifest (moduleb);
3872 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3873 table->rows = 1; /* .<Module> */
3875 alloc_table (table, table->rows);
3877 * Set the first entry.
3879 values = table->values + table->columns;
3880 values [MONO_TYPEDEF_FLAGS] = 0;
3881 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3882 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3883 values [MONO_TYPEDEF_EXTENDS] = 0;
3884 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3885 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3888 * handle global methods
3889 * FIXME: test what to do when global methods are defined in multiple modules.
3891 if (moduleb->global_methods) {
3892 table = &assembly->tables [MONO_TABLE_METHOD];
3893 table->rows += mono_array_length (moduleb->global_methods);
3894 alloc_table (table, table->rows);
3895 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3896 mono_image_get_method_info (
3897 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3899 if (moduleb->global_fields) {
3900 table = &assembly->tables [MONO_TABLE_FIELD];
3901 table->rows += mono_array_length (moduleb->global_fields);
3902 alloc_table (table, table->rows);
3903 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3904 mono_image_get_field_info (
3905 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3908 table = &assembly->tables [MONO_TABLE_MODULE];
3909 alloc_table (table, 1);
3910 mono_image_fill_module_table (domain, moduleb, assembly);
3914 /* Collect all types into a list sorted by their table_idx */
3915 GPtrArray *types = g_ptr_array_new ();
3918 for (i = 0; i < moduleb->num_types; ++i) {
3919 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3920 collect_types (types, type);
3923 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3924 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3925 table->rows += types->len;
3926 alloc_table (table, table->rows);
3929 * Emit type names + namespaces at one place inside the string heap,
3930 * so load_class_names () needs to touch fewer pages.
3932 for (i = 0; i < types->len; ++i) {
3933 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3936 n = mono_string_to_utf8 (tb->nspace);
3937 string_heap_insert (&assembly->sheap, n);
3940 for (i = 0; i < types->len; ++i) {
3941 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3944 n = mono_string_to_utf8 (tb->name);
3945 string_heap_insert (&assembly->sheap, n);
3949 for (i = 0; i < types->len; ++i) {
3950 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3951 mono_image_get_type_info (domain, type, assembly);
3953 g_ptr_array_free (types, TRUE);
3957 * table->rows is already set above and in mono_image_fill_module_table.
3959 /* add all the custom attributes at the end, once all the indexes are stable */
3960 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3962 /* CAS assembly permissions */
3963 if (assemblyb->permissions_minimum)
3964 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3965 if (assemblyb->permissions_optional)
3966 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3967 if (assemblyb->permissions_refused)
3968 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3970 module_add_cattrs (assembly, moduleb);
3973 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3974 fixup_cattrs (assembly);
3975 fixup_methodimpl (assembly);
3979 * mono_image_insert_string:
3980 * @module: module builder object
3983 * Insert @str into the user string stream of @module.
3986 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3988 MonoDynamicImage *assembly;
3993 MONO_ARCH_SAVE_REGS;
3995 if (!module->dynamic_image)
3996 mono_image_module_basic_init (module);
3998 assembly = module->dynamic_image;
4000 if (assembly->save) {
4001 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4002 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4003 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4005 char *swapped = g_malloc (2 * mono_string_length (str));
4006 const char *p = (const char*)mono_string_chars (str);
4008 swap_with_size (swapped, p, 2, mono_string_length (str));
4009 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4013 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4015 mono_image_add_stream_data (&assembly->us, "", 1);
4017 idx = assembly->us.index ++;
4020 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4022 return MONO_TOKEN_STRING | idx;
4026 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4031 klass = obj->vtable->klass;
4032 if (strcmp (klass->name, "MonoMethod") == 0) {
4033 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4034 MonoMethodSignature *sig, *old;
4035 guint32 sig_token, parent;
4038 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4040 nargs = mono_array_length (opt_param_types);
4041 old = mono_method_signature (method);
4042 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4044 sig->hasthis = old->hasthis;
4045 sig->explicit_this = old->explicit_this;
4046 sig->call_convention = old->call_convention;
4047 sig->generic_param_count = old->generic_param_count;
4048 sig->param_count = old->param_count + nargs;
4049 sig->sentinelpos = old->param_count;
4050 sig->ret = old->ret;
4052 for (i = 0; i < old->param_count; i++)
4053 sig->params [i] = old->params [i];
4055 for (i = 0; i < nargs; i++) {
4056 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4057 sig->params [old->param_count + i] = rt->type;
4060 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4061 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4062 parent >>= MONO_TYPEDEFORREF_BITS;
4064 parent <<= MONO_MEMBERREF_PARENT_BITS;
4065 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4067 sig_token = method_encode_signature (assembly, sig);
4068 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4069 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4070 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4071 ReflectionMethodBuilder rmb;
4072 guint32 parent, sig;
4074 reflection_methodbuilder_from_method_builder (&rmb, mb);
4075 rmb.opt_types = opt_param_types;
4077 sig = method_builder_encode_signature (assembly, &rmb);
4079 parent = mono_image_create_token (assembly, obj, TRUE);
4080 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4082 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4083 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4085 token = mono_image_get_varargs_method_token (
4086 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4088 g_error ("requested method token for %s\n", klass->name);
4095 * mono_image_create_token:
4096 * @assembly: a dynamic assembly
4099 * Get a token to insert in the IL code stream for the given MemberInfo.
4100 * @obj can be one of:
4101 * ConstructorBuilder
4111 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4116 klass = obj->vtable->klass;
4117 if (strcmp (klass->name, "MethodBuilder") == 0) {
4118 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4120 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4121 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4123 token = mono_image_get_methodbuilder_token (assembly, mb);
4124 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4125 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4126 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4128 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4129 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4131 token = mono_image_get_ctorbuilder_token (assembly, mb);
4132 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4133 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4134 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4135 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4136 if (tb->generic_params) {
4137 token = mono_image_get_generic_field_token (assembly, fb);
4139 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4141 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4142 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4143 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4144 } else if (strcmp (klass->name, "MonoType") == 0 ||
4145 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4146 MonoReflectionType *tb = (MonoReflectionType *)obj;
4147 token = mono_metadata_token_from_dor (
4148 mono_image_typedef_or_ref (assembly, tb->type));
4149 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4150 MonoReflectionType *tb = (MonoReflectionType *)obj;
4151 token = mono_metadata_token_from_dor (
4152 mono_image_typedef_or_ref (assembly, tb->type));
4153 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4154 strcmp (klass->name, "MonoMethod") == 0 ||
4155 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4156 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4157 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4158 if (m->method->is_inflated) {
4159 if (create_methodspec)
4160 token = mono_image_get_methodspec_token (assembly, m->method);
4162 token = mono_image_get_inflated_method_token (assembly, m->method);
4163 } else if ((m->method->klass->image == &assembly->image) &&
4164 !m->method->klass->generic_class) {
4165 static guint32 method_table_idx = 0xffffff;
4166 if (m->method->klass->wastypebuilder) {
4167 /* we use the same token as the one that was assigned
4168 * to the Methodbuilder.
4169 * FIXME: do the equivalent for Fields.
4171 token = m->method->token;
4174 * Each token should have a unique index, but the indexes are
4175 * assigned by managed code, so we don't know about them. An
4176 * easy solution is to count backwards...
4178 method_table_idx --;
4179 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4182 token = mono_image_get_methodref_token (assembly, m->method);
4184 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4185 } else if (strcmp (klass->name, "MonoField") == 0) {
4186 MonoReflectionField *f = (MonoReflectionField *)obj;
4187 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4188 static guint32 field_table_idx = 0xffffff;
4190 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4192 token = mono_image_get_fieldref_token (assembly, f);
4194 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4195 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4196 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4197 token = mono_image_get_array_token (assembly, m);
4198 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4199 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4200 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4202 g_error ("requested token for %s\n", klass->name);
4205 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4211 guint32 import_lookup_table;
4215 guint32 import_address_table_rva;
4223 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4225 static MonoDynamicImage*
4226 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4228 static const guchar entrycode [16] = {0xff, 0x25, 0};
4229 MonoDynamicImage *image;
4232 const char *version = mono_get_runtime_info ()->runtime_version;
4235 image = GC_MALLOC (sizeof (MonoDynamicImage));
4237 image = g_new0 (MonoDynamicImage, 1);
4240 /*g_print ("created image %p\n", image);*/
4241 /* keep in sync with image.c */
4242 image->image.name = assembly_name;
4243 image->image.assembly_name = image->image.name; /* they may be different */
4244 image->image.module_name = module_name;
4245 image->image.version = version;
4246 image->image.md_version_major = 1;
4247 image->image.md_version_minor = 1;
4248 image->image.dynamic = TRUE;
4249 image->image.ref_count = 1;
4251 image->image.references = g_new0 (MonoAssembly*, 1);
4252 image->image.references [0] = NULL;
4254 mono_image_init (&image->image);
4256 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4257 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4258 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4259 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4260 image->handleref = g_hash_table_new (NULL, NULL);
4261 image->tokens = mono_g_hash_table_new (NULL, NULL);
4262 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4263 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4264 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4265 image->gen_params = g_ptr_array_new ();
4267 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4268 string_heap_init (&image->sheap);
4269 mono_image_add_stream_data (&image->us, "", 1);
4270 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4271 /* import tables... */
4272 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4273 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4274 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4275 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4276 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4277 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4278 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4279 stream_data_align (&image->code);
4281 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4283 for (i=0; i < MONO_TABLE_NUM; ++i) {
4284 image->tables [i].next_idx = 1;
4285 image->tables [i].columns = table_sizes [i];
4288 image->image.assembly = (MonoAssembly*)assembly;
4289 image->run = assembly->run;
4290 image->save = assembly->save;
4291 image->pe_kind = 0x1; /* ILOnly */
4292 image->machine = 0x14c; /* I386 */
4298 * mono_image_basic_init:
4299 * @assembly: an assembly builder object
4301 * Create the MonoImage that represents the assembly builder and setup some
4302 * of the helper hash table and the basic metadata streams.
4305 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4307 MonoDynamicAssembly *assembly;
4308 MonoDynamicImage *image;
4309 MonoDomain *domain = mono_object_domain (assemblyb);
4311 MONO_ARCH_SAVE_REGS;
4313 if (assemblyb->dynamic_assembly)
4317 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4319 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4322 assembly->assembly.ref_count = 1;
4323 assembly->assembly.dynamic = TRUE;
4324 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4325 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4326 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4327 if (assemblyb->culture)
4328 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4330 assembly->assembly.aname.culture = g_strdup ("");
4332 if (assemblyb->version) {
4333 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4334 char **parts = version;
4335 assembly->assembly.aname.major = atoi (*parts++);
4336 assembly->assembly.aname.minor = atoi (*parts++);
4337 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4338 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4340 g_strfreev (version);
4342 assembly->assembly.aname.major = 0;
4343 assembly->assembly.aname.minor = 0;
4344 assembly->assembly.aname.build = 0;
4345 assembly->assembly.aname.revision = 0;
4348 assembly->run = assemblyb->access != 2;
4349 assembly->save = assemblyb->access != 1;
4351 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4352 image->initial_image = TRUE;
4353 assembly->assembly.aname.name = image->image.name;
4354 assembly->assembly.image = &image->image;
4356 mono_domain_assemblies_lock (domain);
4357 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4358 mono_domain_assemblies_unlock (domain);
4360 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4361 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4365 calc_section_size (MonoDynamicImage *assembly)
4369 /* alignment constraints */
4370 assembly->code.index += 3;
4371 assembly->code.index &= ~3;
4372 assembly->meta_size += 3;
4373 assembly->meta_size &= ~3;
4374 assembly->resources.index += 3;
4375 assembly->resources.index &= ~3;
4377 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4378 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4381 if (assembly->win32_res) {
4382 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4384 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4385 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4389 assembly->sections [MONO_SECTION_RELOC].size = 12;
4390 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4400 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4404 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4406 ResTreeNode *t1 = (ResTreeNode*)a;
4407 ResTreeNode *t2 = (ResTreeNode*)b;
4409 return t1->id - t2->id;
4413 * resource_tree_create:
4415 * Organize the resources into a resource tree.
4417 static ResTreeNode *
4418 resource_tree_create (MonoArray *win32_resources)
4420 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4424 tree = g_new0 (ResTreeNode, 1);
4426 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4427 MonoReflectionWin32Resource *win32_res =
4428 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4432 lang_node = g_new0 (ResTreeNode, 1);
4433 lang_node->id = win32_res->lang_id;
4434 lang_node->win32_res = win32_res;
4436 /* Create type node if neccesary */
4438 for (l = tree->children; l; l = l->next)
4439 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4440 type_node = (ResTreeNode*)l->data;
4445 type_node = g_new0 (ResTreeNode, 1);
4446 type_node->id = win32_res->res_type;
4449 * The resource types have to be sorted otherwise
4450 * Windows Explorer can't display the version information.
4452 tree->children = g_slist_insert_sorted (tree->children,
4453 type_node, resource_tree_compare_by_id);
4456 /* Create res node if neccesary */
4458 for (l = type_node->children; l; l = l->next)
4459 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4460 res_node = (ResTreeNode*)l->data;
4465 res_node = g_new0 (ResTreeNode, 1);
4466 res_node->id = win32_res->res_id;
4467 type_node->children = g_slist_append (type_node->children, res_node);
4470 res_node->children = g_slist_append (res_node->children, lang_node);
4477 * resource_tree_encode:
4479 * Encode the resource tree into the format used in the PE file.
4482 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4485 MonoPEResourceDir dir;
4486 MonoPEResourceDirEntry dir_entry;
4487 MonoPEResourceDataEntry data_entry;
4491 * For the format of the resource directory, see the article
4492 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4496 memset (&dir, 0, sizeof (dir));
4497 memset (&dir_entry, 0, sizeof (dir_entry));
4498 memset (&data_entry, 0, sizeof (data_entry));
4500 g_assert (sizeof (dir) == 16);
4501 g_assert (sizeof (dir_entry) == 8);
4502 g_assert (sizeof (data_entry) == 16);
4504 node->offset = p - begin;
4506 /* IMAGE_RESOURCE_DIRECTORY */
4507 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4509 memcpy (p, &dir, sizeof (dir));
4512 /* Reserve space for entries */
4514 p += sizeof (dir_entry) * dir.res_id_entries;
4516 /* Write children */
4517 for (l = node->children; l; l = l->next) {
4518 ResTreeNode *child = (ResTreeNode*)l->data;
4520 if (child->win32_res) {
4522 child->offset = p - begin;
4524 /* IMAGE_RESOURCE_DATA_ENTRY */
4525 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4526 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4528 memcpy (p, &data_entry, sizeof (data_entry));
4529 p += sizeof (data_entry);
4531 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4532 p += data_entry.rde_size;
4534 resource_tree_encode (child, begin, p, &p);
4538 /* IMAGE_RESOURCE_ENTRY */
4539 for (l = node->children; l; l = l->next) {
4540 ResTreeNode *child = (ResTreeNode*)l->data;
4541 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4543 dir_entry.is_dir = child->win32_res ? 0 : 1;
4544 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4546 memcpy (entries, &dir_entry, sizeof (dir_entry));
4547 entries += sizeof (dir_entry);
4554 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4559 MonoReflectionWin32Resource *win32_res;
4562 if (!assemblyb->win32_resources)
4566 * Resources are stored in a three level tree inside the PE file.
4567 * - level one contains a node for each type of resource
4568 * - level two contains a node for each resource
4569 * - level three contains a node for each instance of a resource for a
4570 * specific language.
4573 tree = resource_tree_create (assemblyb->win32_resources);
4575 /* Estimate the size of the encoded tree */
4577 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4578 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4579 size += mono_array_length (win32_res->res_data);
4581 /* Directory structure */
4582 size += mono_array_length (assemblyb->win32_resources) * 256;
4583 p = buf = g_malloc (size);
4585 resource_tree_encode (tree, p, p, &p);
4587 g_assert (p - buf < size);
4589 assembly->win32_res = g_malloc (p - buf);
4590 assembly->win32_res_size = p - buf;
4591 memcpy (assembly->win32_res, buf, p - buf);
4597 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4599 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4602 p += sizeof (MonoPEResourceDir);
4603 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4604 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4605 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4606 if (dir_entry->is_dir) {
4607 fixup_resource_directory (res_section, child, rva);
4609 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4610 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4613 p += sizeof (MonoPEResourceDirEntry);
4618 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4621 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4622 g_error ("WriteFile returned %d\n", GetLastError ());
4626 * mono_image_create_pefile:
4627 * @mb: a module builder object
4629 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4630 * assembly->pefile where it can be easily retrieved later in chunks.
4633 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4634 MonoMSDOSHeader *msdos;
4635 MonoDotNetHeader *header;
4636 MonoSectionTable *section;
4637 MonoCLIHeader *cli_header;
4638 guint32 size, image_size, virtual_base, text_offset;
4639 guint32 header_start, section_start, file_offset, virtual_offset;
4640 MonoDynamicImage *assembly;
4641 MonoReflectionAssemblyBuilder *assemblyb;
4642 MonoDynamicStream pefile_stream = {0};
4643 MonoDynamicStream *pefile = &pefile_stream;
4645 guint32 *rva, value;
4647 static const unsigned char msheader[] = {
4648 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4649 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4652 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4653 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4654 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4655 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4658 assemblyb = mb->assemblyb;
4660 mono_image_basic_init (assemblyb);
4661 assembly = mb->dynamic_image;
4663 assembly->pe_kind = assemblyb->pe_kind;
4664 assembly->machine = assemblyb->machine;
4665 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4666 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4668 mono_image_build_metadata (mb);
4670 if (mb->is_main && assemblyb->resources) {
4671 int len = mono_array_length (assemblyb->resources);
4672 for (i = 0; i < len; ++i)
4673 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4676 if (mb->resources) {
4677 int len = mono_array_length (mb->resources);
4678 for (i = 0; i < len; ++i)
4679 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4682 build_compressed_metadata (assembly);
4685 assembly_add_win32_resources (assembly, assemblyb);
4687 nsections = calc_section_size (assembly);
4689 /* The DOS header and stub */
4690 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4691 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4693 /* the dotnet header */
4694 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4696 /* the section tables */
4697 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4699 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4700 virtual_offset = VIRT_ALIGN;
4703 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4704 if (!assembly->sections [i].size)
4707 file_offset += FILE_ALIGN - 1;
4708 file_offset &= ~(FILE_ALIGN - 1);
4709 virtual_offset += VIRT_ALIGN - 1;
4710 virtual_offset &= ~(VIRT_ALIGN - 1);
4712 assembly->sections [i].offset = file_offset;
4713 assembly->sections [i].rva = virtual_offset;
4715 file_offset += assembly->sections [i].size;
4716 virtual_offset += assembly->sections [i].size;
4717 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4720 file_offset += FILE_ALIGN - 1;
4721 file_offset &= ~(FILE_ALIGN - 1);
4723 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4725 /* back-patch info */
4726 msdos = (MonoMSDOSHeader*)pefile->data;
4727 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4729 header = (MonoDotNetHeader*)(pefile->data + header_start);
4730 header->pesig [0] = 'P';
4731 header->pesig [1] = 'E';
4733 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4734 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4735 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4736 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4737 if (assemblyb->pekind == 1) {
4739 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4742 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4745 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4747 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4748 header->pe.pe_major = 6;
4749 header->pe.pe_minor = 0;
4750 size = assembly->sections [MONO_SECTION_TEXT].size;
4751 size += FILE_ALIGN - 1;
4752 size &= ~(FILE_ALIGN - 1);
4753 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4754 size = assembly->sections [MONO_SECTION_RSRC].size;
4755 size += FILE_ALIGN - 1;
4756 size &= ~(FILE_ALIGN - 1);
4757 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4758 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4759 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4760 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4761 /* pe_rva_entry_point always at the beginning of the text section */
4762 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4764 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4765 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4766 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4767 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4768 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4769 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4770 size = section_start;
4771 size += FILE_ALIGN - 1;
4772 size &= ~(FILE_ALIGN - 1);
4773 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4775 size += VIRT_ALIGN - 1;
4776 size &= ~(VIRT_ALIGN - 1);
4777 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4780 // Translate the PEFileKind value to the value expected by the Windows loader
4786 // PEFileKinds.Dll == 1
4787 // PEFileKinds.ConsoleApplication == 2
4788 // PEFileKinds.WindowApplication == 3
4791 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4792 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4794 if (assemblyb->pekind == 3)
4799 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4801 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4802 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4803 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4804 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4805 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4806 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4808 /* fill data directory entries */
4810 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4811 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4813 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4814 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4816 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4817 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4818 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4819 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4820 /* patch entrypoint name */
4821 if (assemblyb->pekind == 1)
4822 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4824 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4825 /* patch imported function RVA name */
4826 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4827 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4829 /* the import table */
4830 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4831 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4832 /* patch imported dll RVA name and other entries in the dir */
4833 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4834 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4835 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4836 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4837 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4838 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4840 p = (assembly->code.data + assembly->ilt_offset);
4841 value = (assembly->text_rva + assembly->imp_names_offset);
4842 *p++ = (value) & 0xff;
4843 *p++ = (value >> 8) & (0xff);
4844 *p++ = (value >> 16) & (0xff);
4845 *p++ = (value >> 24) & (0xff);
4847 /* the CLI header info */
4848 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4849 cli_header->ch_size = GUINT32_FROM_LE (72);
4850 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4851 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4852 if (assemblyb->entry_point) {
4853 guint32 table_idx = 0;
4854 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4855 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4856 table_idx = methodb->table_idx;
4858 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4860 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4862 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4864 /* The embedded managed resources */
4865 text_offset = assembly->text_rva + assembly->code.index;
4866 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4867 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4868 text_offset += assembly->resources.index;
4869 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4870 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4871 text_offset += assembly->meta_size;
4872 if (assembly->strong_name_size) {
4873 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4874 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4875 text_offset += assembly->strong_name_size;
4878 /* write the section tables and section content */
4879 section = (MonoSectionTable*)(pefile->data + section_start);
4880 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4881 static const char *section_names [] = {
4882 ".text", ".rsrc", ".reloc"
4884 if (!assembly->sections [i].size)
4886 strcpy (section->st_name, section_names [i]);
4887 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4888 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4889 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4890 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4891 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4892 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4893 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4897 checked_write_file (file, pefile->data, pefile->index);
4899 mono_dynamic_stream_reset (pefile);
4901 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4902 if (!assembly->sections [i].size)
4905 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4906 g_error ("SetFilePointer returned %d\n", GetLastError ());
4909 case MONO_SECTION_TEXT:
4910 /* patch entry point */
4911 p = (assembly->code.data + 2);
4912 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4913 *p++ = (value) & 0xff;
4914 *p++ = (value >> 8) & 0xff;
4915 *p++ = (value >> 16) & 0xff;
4916 *p++ = (value >> 24) & 0xff;
4918 checked_write_file (file, assembly->code.data, assembly->code.index);
4919 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4920 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4921 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4924 g_free (assembly->image.raw_metadata);
4926 case MONO_SECTION_RELOC: {
4930 guint16 type_and_offset;
4934 g_assert (sizeof (reloc) == 12);
4936 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4937 reloc.block_size = GUINT32_FROM_LE (12);
4940 * the entrypoint is always at the start of the text section
4941 * 3 is IMAGE_REL_BASED_HIGHLOW
4942 * 2 is patch_size_rva - text_rva
4944 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4947 checked_write_file (file, &reloc, sizeof (reloc));
4951 case MONO_SECTION_RSRC:
4952 if (assembly->win32_res) {
4954 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4955 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4956 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4960 g_assert_not_reached ();
4964 /* check that the file is properly padded */
4965 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4966 g_error ("SetFilePointer returned %d\n", GetLastError ());
4967 if (! SetEndOfFile (file))
4968 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4970 mono_dynamic_stream_reset (&assembly->code);
4971 mono_dynamic_stream_reset (&assembly->us);
4972 mono_dynamic_stream_reset (&assembly->blob);
4973 mono_dynamic_stream_reset (&assembly->guid);
4974 mono_dynamic_stream_reset (&assembly->sheap);
4976 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4977 g_hash_table_destroy (assembly->blob_cache);
4978 assembly->blob_cache = NULL;
4981 MonoReflectionModule *
4982 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4986 MonoImageOpenStatus status;
4987 MonoDynamicAssembly *assembly;
4988 guint32 module_count;
4989 MonoImage **new_modules;
4991 name = mono_string_to_utf8 (fileName);
4993 image = mono_image_open (name, &status);
4996 if (status == MONO_IMAGE_ERROR_ERRNO)
4997 exc = mono_get_exception_file_not_found (fileName);
4999 exc = mono_get_exception_bad_image_format (name);
5001 mono_raise_exception (exc);
5006 assembly = ab->dynamic_assembly;
5007 image->assembly = (MonoAssembly*)assembly;
5009 module_count = image->assembly->image->module_count;
5010 new_modules = g_new0 (MonoImage *, module_count + 1);
5012 if (image->assembly->image->modules)
5013 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5014 new_modules [module_count] = image;
5016 g_free (image->assembly->image->modules);
5017 image->assembly->image->modules = new_modules;
5018 image->assembly->image->module_count ++;
5020 mono_assembly_load_references (image, &status);
5022 mono_image_close (image);
5023 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5026 return mono_module_get_object (mono_domain_get (), image);
5030 * We need to return always the same object for MethodInfo, FieldInfo etc..
5031 * but we need to consider the reflected type.
5032 * type uses a different hash, since it uses custom hash/equal functions.
5037 MonoClass *refclass;
5041 reflected_equal (gconstpointer a, gconstpointer b) {
5042 const ReflectedEntry *ea = a;
5043 const ReflectedEntry *eb = b;
5045 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5049 reflected_hash (gconstpointer a) {
5050 const ReflectedEntry *ea = a;
5051 return GPOINTER_TO_UINT (ea->item);
5054 #define CHECK_OBJECT(t,p,k) \
5060 mono_domain_lock (domain); \
5061 if (!domain->refobject_hash) \
5062 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5063 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5064 mono_domain_unlock (domain); \
5067 mono_domain_unlock (domain); \
5071 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5073 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5076 #define CACHE_OBJECT(t,p,o,k) \
5079 ReflectedEntry pe; \
5081 pe.refclass = (k); \
5082 mono_domain_lock (domain); \
5083 if (!domain->refobject_hash) \
5084 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5085 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5087 ReflectedEntry *e = ALLOC_REFENTRY; \
5089 e->refclass = (k); \
5090 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5093 mono_domain_unlock (domain); \
5098 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5100 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5104 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5106 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5110 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5112 MonoDynamicImage *image = moduleb->dynamic_image;
5113 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5116 MonoImage **new_modules;
5119 * FIXME: we already created an image in mono_image_basic_init (), but
5120 * we don't know which module it belongs to, since that is only
5121 * determined at assembly save time.
5123 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5124 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5126 moduleb->module.image = &image->image;
5127 moduleb->dynamic_image = image;
5128 register_module (mono_object_domain (moduleb), moduleb, image);
5130 /* register the module with the assembly */
5131 ass = ab->dynamic_assembly->assembly.image;
5132 module_count = ass->module_count;
5133 new_modules = g_new0 (MonoImage *, module_count + 1);
5136 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5137 new_modules [module_count] = &image->image;
5139 g_free (ass->modules);
5140 ass->modules = new_modules;
5141 ass->module_count ++;
5146 * mono_assembly_get_object:
5147 * @domain: an app domain
5148 * @assembly: an assembly
5150 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5152 MonoReflectionAssembly*
5153 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5155 static MonoClass *System_Reflection_Assembly;
5156 MonoReflectionAssembly *res;
5158 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5159 if (!System_Reflection_Assembly)
5160 System_Reflection_Assembly = mono_class_from_name (
5161 mono_defaults.corlib, "System.Reflection", "Assembly");
5162 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5163 res->assembly = assembly;
5165 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5170 MonoReflectionModule*
5171 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5173 static MonoClass *System_Reflection_Module;
5174 MonoReflectionModule *res;
5177 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5178 if (!System_Reflection_Module)
5179 System_Reflection_Module = mono_class_from_name (
5180 mono_defaults.corlib, "System.Reflection", "Module");
5181 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5184 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5186 res->fqname = mono_string_new (domain, image->name);
5187 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5188 res->scopename = mono_string_new (domain, image->module_name);
5192 if (image->assembly->image == image) {
5193 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5196 g_assert (image->assembly->image->modules);
5198 for (i = 0; i < image->assembly->image->module_count; i++) {
5199 if (image->assembly->image->modules [i] == image)
5200 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5202 g_assert (res->token);
5205 mono_image_addref (image);
5207 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5210 MonoReflectionModule*
5211 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5213 static MonoClass *System_Reflection_Module;
5214 MonoReflectionModule *res;
5215 MonoTableInfo *table;
5216 guint32 cols [MONO_FILE_SIZE];
5218 guint32 i, name_idx;
5221 if (!System_Reflection_Module)
5222 System_Reflection_Module = mono_class_from_name (
5223 mono_defaults.corlib, "System.Reflection", "Module");
5224 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5226 table = &image->tables [MONO_TABLE_FILE];
5227 g_assert (table_index < table->rows);
5228 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5231 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5232 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5234 /* Check whenever the row has a corresponding row in the moduleref table */
5235 table = &image->tables [MONO_TABLE_MODULEREF];
5236 for (i = 0; i < table->rows; ++i) {
5237 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5238 val = mono_metadata_string_heap (image, name_idx);
5239 if (strcmp (val, name) == 0)
5240 res->image = image->modules [i];
5243 res->fqname = mono_string_new (domain, name);
5244 res->name = mono_string_new (domain, name);
5245 res->scopename = mono_string_new (domain, name);
5246 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5247 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5253 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5255 if ((t1->type != t2->type) ||
5256 (t1->byref != t2->byref))
5260 case MONO_TYPE_VOID:
5261 case MONO_TYPE_BOOLEAN:
5262 case MONO_TYPE_CHAR:
5273 case MONO_TYPE_STRING:
5276 case MONO_TYPE_OBJECT:
5277 case MONO_TYPE_TYPEDBYREF:
5279 case MONO_TYPE_VALUETYPE:
5280 case MONO_TYPE_CLASS:
5281 case MONO_TYPE_SZARRAY:
5282 return t1->data.klass == t2->data.klass;
5284 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5285 case MONO_TYPE_ARRAY:
5286 if (t1->data.array->rank != t2->data.array->rank)
5288 return t1->data.array->eklass == t2->data.array->eklass;
5289 case MONO_TYPE_GENERICINST: {
5291 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5293 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5294 &t2->data.generic_class->container_class->byval_arg))
5296 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5297 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5303 case MONO_TYPE_MVAR:
5304 return t1->data.generic_param == t2->data.generic_param;
5306 g_error ("implement type compare for %0x!", t1->type);
5314 mymono_metadata_type_hash (MonoType *t1)
5320 hash |= t1->byref << 6; /* do not collide with t1->type values */
5322 case MONO_TYPE_VALUETYPE:
5323 case MONO_TYPE_CLASS:
5324 case MONO_TYPE_SZARRAY:
5325 /* check if the distribution is good enough */
5326 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5328 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5329 case MONO_TYPE_GENERICINST: {
5331 MonoGenericInst *inst = t1->data.generic_class->inst;
5332 hash += g_str_hash (t1->data.generic_class->container_class->name);
5334 for (i = 0; i < inst->type_argc; ++i) {
5335 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5344 static MonoReflectionGenericClass*
5345 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5347 static MonoClass *System_Reflection_MonoGenericClass;
5348 MonoReflectionGenericClass *res;
5349 MonoInflatedGenericClass *gclass;
5352 if (!System_Reflection_MonoGenericClass) {
5353 System_Reflection_MonoGenericClass = mono_class_from_name (
5354 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5355 g_assert (System_Reflection_MonoGenericClass);
5358 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5359 gklass = gclass->generic_class.container_class;
5361 mono_class_init (gclass->klass);
5363 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5365 res->type.type = geninst;
5366 if (gklass->wastypebuilder && gklass->reflection_info)
5367 res->generic_type = gklass->reflection_info;
5369 res->generic_type = mono_type_get_object (
5370 domain, &gclass->generic_class.container_class->byval_arg);
5376 * mono_type_get_object:
5377 * @domain: an app domain
5380 * Return an System.MonoType object representing the type @type.
5383 mono_type_get_object (MonoDomain *domain, MonoType *type)
5385 MonoReflectionType *res;
5386 MonoClass *klass = mono_class_from_mono_type (type);
5388 mono_domain_lock (domain);
5389 if (!domain->type_hash)
5390 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5391 (GCompareFunc)mymono_metadata_type_equal);
5392 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5393 mono_domain_unlock (domain);
5396 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5397 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5398 mono_g_hash_table_insert (domain->type_hash, type, res);
5399 mono_domain_unlock (domain);
5402 if (klass->reflection_info && !klass->wastypebuilder) {
5403 /* g_assert_not_reached (); */
5404 /* should this be considered an error condition? */
5406 mono_domain_unlock (domain);
5407 return klass->reflection_info;
5410 mono_class_init (klass);
5411 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5413 mono_g_hash_table_insert (domain->type_hash, type, res);
5414 mono_domain_unlock (domain);
5419 * mono_method_get_object:
5420 * @domain: an app domain
5422 * @refclass: the reflected type (can be NULL)
5424 * Return an System.Reflection.MonoMethod object representing the method @method.
5426 MonoReflectionMethod*
5427 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5430 * We use the same C representation for methods and constructors, but the type
5431 * name in C# is different.
5435 MonoReflectionMethod *ret;
5437 if (method->is_inflated) {
5438 MonoReflectionGenericMethod *gret;
5440 refclass = method->klass;
5441 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5442 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5443 cname = "MonoGenericCMethod";
5445 cname = "MonoGenericMethod";
5446 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5448 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5449 gret->method.method = method;
5450 gret->method.name = mono_string_new (domain, method->name);
5451 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5452 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5456 refclass = method->klass;
5458 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5459 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5460 cname = "MonoCMethod";
5462 cname = "MonoMethod";
5463 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5465 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5466 ret->method = method;
5467 ret->name = mono_string_new (domain, method->name);
5468 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5469 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5473 * mono_field_get_object:
5474 * @domain: an app domain
5478 * Return an System.Reflection.MonoField object representing the field @field
5481 MonoReflectionField*
5482 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5484 MonoReflectionField *res;
5487 CHECK_OBJECT (MonoReflectionField *, field, klass);
5488 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5489 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5492 res->name = mono_string_new (domain, field->name);
5493 if (field->generic_info)
5494 res->attrs = field->generic_info->generic_type->attrs;
5496 res->attrs = field->type->attrs;
5497 res->type = mono_type_get_object (domain, field->type);
5498 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5502 * mono_property_get_object:
5503 * @domain: an app domain
5505 * @property: a property
5507 * Return an System.Reflection.MonoProperty object representing the property @property
5510 MonoReflectionProperty*
5511 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5513 MonoReflectionProperty *res;
5516 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5517 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5518 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5520 res->property = property;
5521 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5525 * mono_event_get_object:
5526 * @domain: an app domain
5530 * Return an System.Reflection.MonoEvent object representing the event @event
5533 MonoReflectionEvent*
5534 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5536 MonoReflectionEvent *res;
5539 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5540 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5541 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5544 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5548 * mono_param_get_objects:
5549 * @domain: an app domain
5552 * Return an System.Reflection.ParameterInfo array object representing the parameters
5553 * in the method @method.
5556 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5558 static MonoClass *System_Reflection_ParameterInfo;
5559 MonoArray *res = NULL;
5560 MonoReflectionMethod *member = NULL;
5561 MonoReflectionParameter *param = NULL;
5562 char **names, **blobs = NULL;
5563 guint32 *types = NULL;
5564 MonoType *type = NULL;
5565 MonoObject *dbnull = mono_get_dbnull_object (domain);
5566 MonoMarshalSpec **mspecs;
5569 if (!System_Reflection_ParameterInfo)
5570 System_Reflection_ParameterInfo = mono_class_from_name (
5571 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5573 if (!mono_method_signature (method)->param_count)
5574 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5576 /* Note: the cache is based on the address of the signature into the method
5577 * since we already cache MethodInfos with the method as keys.
5579 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5581 member = mono_method_get_object (domain, method, NULL);
5582 names = g_new (char *, mono_method_signature (method)->param_count);
5583 mono_method_get_param_names (method, (const char **) names);
5585 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5586 mono_method_get_marshal_info (method, mspecs);
5588 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5589 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5590 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5591 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5592 param->MemberImpl = (MonoObject*)member;
5593 param->NameImpl = mono_string_new (domain, names [i]);
5594 param->PositionImpl = i;
5595 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5597 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5598 param->DefaultValueImpl = dbnull;
5602 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5603 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5604 get_default_param_value_blobs (method, blobs, types);
5607 /* Build MonoType for the type from the Constant Table */
5609 type = g_new0 (MonoType, 1);
5610 type->type = types [i];
5611 type->data.klass = NULL;
5612 if (types [i] == MONO_TYPE_CLASS)
5613 type->data.klass = mono_defaults.object_class;
5615 type->data.klass = mono_class_from_mono_type (type);
5617 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5619 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5620 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5621 param->DefaultValueImpl = dbnull;
5626 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5628 mono_array_set (res, gpointer, i, param);
5635 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5637 mono_metadata_free_marshal_spec (mspecs [i]);
5640 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5644 * mono_method_body_get_object:
5645 * @domain: an app domain
5648 * Return an System.Reflection.MethodBody object representing the method @method.
5650 MonoReflectionMethodBody*
5651 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5653 static MonoClass *System_Reflection_MethodBody = NULL;
5654 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5655 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5656 MonoReflectionMethodBody *ret;
5657 MonoMethodNormal *mn;
5658 MonoMethodHeader *header;
5659 guint32 method_rva, local_var_sig_token;
5661 unsigned char format, flags;
5664 if (!System_Reflection_MethodBody)
5665 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5666 if (!System_Reflection_LocalVariableInfo)
5667 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5668 if (!System_Reflection_ExceptionHandlingClause)
5669 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5671 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5673 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5674 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5675 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5676 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5678 mn = (MonoMethodNormal *)method;
5679 header = mono_method_get_header (method);
5681 /* Obtain local vars signature token */
5682 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5683 ptr = mono_image_rva_map (method->klass->image, method_rva);
5684 flags = *(const unsigned char *) ptr;
5685 format = flags & METHOD_HEADER_FORMAT_MASK;
5687 case METHOD_HEADER_TINY_FORMAT:
5688 case METHOD_HEADER_TINY_FORMAT1:
5689 local_var_sig_token = 0;
5691 case METHOD_HEADER_FAT_FORMAT:
5695 local_var_sig_token = read32 (ptr);
5698 g_assert_not_reached ();
5701 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5703 ret->init_locals = header->init_locals;
5704 ret->max_stack = header->max_stack;
5705 ret->local_var_sig_token = local_var_sig_token;
5706 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5707 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5710 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5711 for (i = 0; i < header->num_locals; ++i) {
5712 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5713 info->local_type = mono_type_get_object (domain, header->locals [i]);
5714 info->is_pinned = header->locals [i]->pinned;
5715 info->local_index = i;
5716 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5720 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5721 for (i = 0; i < header->num_clauses; ++i) {
5722 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5723 MonoExceptionClause *clause = &header->clauses [i];
5725 info->flags = clause->flags;
5726 info->try_offset = clause->try_offset;
5727 info->try_length = clause->try_len;
5728 info->handler_offset = clause->handler_offset;
5729 info->handler_length = clause->handler_len;
5730 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5731 info->filter_offset = clause->data.filter_offset;
5732 else if (clause->data.catch_class)
5733 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5735 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5738 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5743 mono_get_dbnull_object (MonoDomain *domain)
5747 static MonoClassField *dbnull_value_field = NULL;
5749 if (!dbnull_value_field) {
5750 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5751 mono_class_init (klass);
5752 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5753 g_assert (dbnull_value_field);
5755 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5762 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5764 guint32 param_index, i, lastp, crow = 0;
5765 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5768 MonoClass *klass = method->klass;
5769 MonoImage *image = klass->image;
5770 MonoMethodSignature *methodsig = mono_method_signature (method);
5772 MonoTableInfo *constt;
5773 MonoTableInfo *methodt;
5774 MonoTableInfo *paramt;
5776 if (!methodsig->param_count)
5779 mono_class_init (klass);
5781 if (klass->image->dynamic) {
5782 MonoReflectionMethodAux *aux;
5783 if (method->is_inflated)
5784 method = ((MonoMethodInflated*)method)->declaring;
5785 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5786 if (aux && aux->param_defaults) {
5787 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5788 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5793 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5794 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5795 constt = &image->tables [MONO_TABLE_CONSTANT];
5797 idx = mono_method_get_index (method) - 1;
5798 g_assert (idx != -1);
5800 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5801 if (idx + 1 < methodt->rows)
5802 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5804 lastp = paramt->rows + 1;
5806 for (i = param_index; i < lastp; ++i) {
5809 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5810 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5812 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5815 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5820 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5821 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5822 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5829 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5834 MonoType *basetype = type;
5839 klass = mono_class_from_mono_type (type);
5840 if (klass->valuetype) {
5841 object = mono_object_new (domain, klass);
5842 retval = ((gchar *) object + sizeof (MonoObject));
5843 if (klass->enumtype)
5844 basetype = klass->enum_basetype;
5849 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5856 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5860 memset (assembly, 0, sizeof (MonoAssemblyName));
5862 assembly->culture = "";
5863 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5865 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5868 while (g_ascii_isspace (*p) || *p == ',') {
5877 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5879 assembly->major = strtoul (p, &s, 10);
5880 if (s == p || *s != '.')
5883 assembly->minor = strtoul (p, &s, 10);
5884 if (s == p || *s != '.')
5887 assembly->build = strtoul (p, &s, 10);
5888 if (s == p || *s != '.')
5891 assembly->revision = strtoul (p, &s, 10);
5895 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5897 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5898 assembly->culture = "";
5901 assembly->culture = p;
5902 while (*p && *p != ',') {
5906 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5908 if (strncmp (p, "null", 4) == 0) {
5913 while (*p && *p != ',') {
5916 len = (p - start + 1);
5917 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5918 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5919 g_strlcpy (assembly->public_key_token, start, len);
5922 while (*p && *p != ',')
5926 while (g_ascii_isspace (*p) || *p == ',') {
5940 * mono_reflection_parse_type:
5943 * Parse a type name as accepted by the GetType () method and output the info
5944 * extracted in the info structure.
5945 * the name param will be mangled, so, make a copy before passing it to this function.
5946 * The fields in info will be valid until the memory pointed to by name is valid.
5948 * See also mono_type_get_name () below.
5950 * Returns: 0 on parse error.
5953 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5954 MonoTypeNameParse *info)
5956 char *start, *p, *w, *temp, *last_point, *startn;
5957 int in_modifiers = 0;
5958 int isbyref = 0, rank, arity = 0, i;
5960 start = p = w = name;
5962 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5963 info->name = info->name_space = NULL;
5964 info->nested = NULL;
5965 info->modifiers = NULL;
5966 info->type_arguments = NULL;
5968 /* last_point separates the namespace from the name */
5974 *p = 0; /* NULL terminate the name */
5976 info->nested = g_list_append (info->nested, startn);
5977 /* we have parsed the nesting namespace + name */
5981 info->name_space = start;
5983 info->name = last_point + 1;
5985 info->name_space = (char *)"";
6004 i = strtol (p, &temp, 10);
6021 info->name_space = start;
6023 info->name = last_point + 1;
6025 info->name_space = (char *)"";
6032 if (isbyref) /* only one level allowed by the spec */
6035 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6039 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6045 info->type_arguments = g_ptr_array_new ();
6046 for (i = 0; i < arity; i++) {
6047 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6048 gboolean fqname = FALSE;
6050 g_ptr_array_add (info->type_arguments, subinfo);
6057 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6068 while (*p && (*p != ']'))
6076 if (g_ascii_isspace (*aname)) {
6083 !assembly_name_to_aname (&subinfo->assembly, aname))
6087 if (i + 1 < arity) {
6107 else if (*p != '*') /* '*' means unknown lower bound */
6113 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6124 if (g_ascii_isspace (*p)) {
6131 return 0; /* missing assembly name */
6132 if (!assembly_name_to_aname (&info->assembly, p))
6138 if (info->assembly.name)
6141 // *w = 0; /* terminate class name */
6143 if (!info->name || !*info->name)
6147 /* add other consistency checks */
6152 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6154 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6158 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6160 gboolean type_resolve = FALSE;
6163 if (info->assembly.name) {
6164 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6166 /* then we must load the assembly ourselve - see #60439 */
6167 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6171 image = assembly->image;
6172 } else if (!image) {
6173 image = mono_defaults.corlib;
6176 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6177 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6178 image = mono_defaults.corlib;
6179 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6186 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6193 image = mono_defaults.corlib;
6196 klass = mono_class_from_name_case (image, info->name_space, info->name);
6198 klass = mono_class_from_name (image, info->name_space, info->name);
6201 for (mod = info->nested; mod; mod = mod->next) {
6204 mono_class_init (klass);
6205 nested = klass->nested_classes;
6208 klass = nested->data;
6210 if (g_strcasecmp (klass->name, mod->data) == 0)
6213 if (strcmp (klass->name, mod->data) == 0)
6217 nested = nested->next;
6224 mono_class_init (klass);
6226 if (info->type_arguments) {
6227 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6228 MonoReflectionType *the_type;
6232 for (i = 0; i < info->type_arguments->len; i++) {
6233 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6235 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6236 if (!type_args [i]) {
6242 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6244 instance = mono_reflection_bind_generic_parameters (
6245 the_type, info->type_arguments->len, type_args);
6252 klass = mono_class_from_mono_type (instance);
6255 for (mod = info->modifiers; mod; mod = mod->next) {
6256 modval = GPOINTER_TO_UINT (mod->data);
6257 if (!modval) { /* byref: must be last modifier */
6258 return &klass->this_arg;
6259 } else if (modval == -1) {
6260 klass = mono_ptr_class_get (&klass->byval_arg);
6261 } else { /* array rank */
6262 klass = mono_array_class_get (klass, modval);
6264 mono_class_init (klass);
6267 return &klass->byval_arg;
6271 * mono_reflection_get_type:
6272 * @image: a metadata context
6273 * @info: type description structure
6274 * @ignorecase: flag for case-insensitive string compares
6275 * @type_resolve: whenever type resolve was already tried
6277 * Build a MonoType from the type description in @info.
6282 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6285 MonoReflectionAssembly *assembly;
6289 type = mono_reflection_get_type_internal (image, info, ignorecase);
6292 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6299 *type_resolve = TRUE;
6302 /* Reconstruct the type name */
6303 fullName = g_string_new ("");
6304 if (info->name_space && (info->name_space [0] != '\0'))
6305 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6307 g_string_printf (fullName, info->name);
6308 for (mod = info->nested; mod; mod = mod->next)
6309 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6311 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6313 if (assembly->assembly->dynamic) {
6314 /* Enumerate all modules */
6315 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6319 if (abuilder->modules) {
6320 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6321 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6322 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6328 if (!type && abuilder->loaded_modules) {
6329 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6330 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6331 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6338 type = mono_reflection_get_type_internal (assembly->assembly->image,
6341 g_string_free (fullName, TRUE);
6346 free_type_info (MonoTypeNameParse *info)
6348 g_list_free (info->modifiers);
6349 g_list_free (info->nested);
6351 if (info->type_arguments) {
6354 for (i = 0; i < info->type_arguments->len; i++) {
6355 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6357 free_type_info (subinfo);
6360 g_ptr_array_free (info->type_arguments, TRUE);
6365 * mono_reflection_type_from_name:
6367 * @image: a metadata context (can be NULL).
6369 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6370 * it defaults to get the type from @image or, if @image is NULL or loading
6371 * from it fails, uses corlib.
6375 mono_reflection_type_from_name (char *name, MonoImage *image)
6377 MonoType *type = NULL;
6378 MonoTypeNameParse info;
6381 /* Make a copy since parse_type modifies its argument */
6382 tmp = g_strdup (name);
6384 /*g_print ("requested type %s\n", str);*/
6385 if (mono_reflection_parse_type (tmp, &info)) {
6386 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6390 free_type_info (&info);
6395 * mono_reflection_get_token:
6397 * Return the metadata token of OBJ which should be an object
6398 * representing a metadata element.
6401 mono_reflection_get_token (MonoObject *obj)
6406 klass = obj->vtable->klass;
6408 if (strcmp (klass->name, "MethodBuilder") == 0) {
6409 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6411 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6412 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6413 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6415 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6416 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6417 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6418 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6419 if (tb->generic_params) {
6420 g_assert_not_reached ();
6422 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6424 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6425 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6426 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6427 } else if (strcmp (klass->name, "MonoType") == 0) {
6428 MonoReflectionType *tb = (MonoReflectionType *)obj;
6429 token = mono_class_from_mono_type (tb->type)->type_token;
6430 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6431 strcmp (klass->name, "MonoMethod") == 0) {
6432 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6433 if (m->method->is_inflated) {
6434 g_assert_not_reached ();
6435 } else if (mono_method_signature (m->method)->generic_param_count) {
6436 g_assert_not_reached ();
6437 } else if (m->method->klass->generic_class) {
6438 g_assert_not_reached ();
6440 token = m->method->token;
6442 } else if (strcmp (klass->name, "MonoField") == 0) {
6443 MonoReflectionField *f = (MonoReflectionField*)obj;
6445 token = mono_class_get_field_token (f->field);
6446 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6447 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6449 token = mono_class_get_property_token (p->property);
6450 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6451 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6453 token = mono_class_get_event_token (p->event);
6454 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6455 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6457 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6458 } else if (strcmp (klass->name, "Module") == 0) {
6459 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6462 } else if (strcmp (klass->name, "Assembly") == 0) {
6463 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6465 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6466 MonoException *ex = mono_get_exception_not_implemented (msg);
6468 mono_raise_exception (ex);
6475 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6477 int slen, type = t->type;
6482 case MONO_TYPE_BOOLEAN: {
6483 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6488 case MONO_TYPE_CHAR:
6490 case MONO_TYPE_I2: {
6491 guint16 *val = g_malloc (sizeof (guint16));
6496 #if SIZEOF_VOID_P == 4
6502 case MONO_TYPE_I4: {
6503 guint32 *val = g_malloc (sizeof (guint32));
6508 #if SIZEOF_VOID_P == 8
6509 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6514 case MONO_TYPE_I8: {
6515 guint64 *val = g_malloc (sizeof (guint64));
6520 case MONO_TYPE_VALUETYPE:
6521 if (t->data.klass->enumtype) {
6522 type = t->data.klass->enum_basetype->type;
6525 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6528 case MONO_TYPE_STRING:
6529 if (*p == (char)0xFF) {
6533 slen = mono_metadata_decode_value (p, &p);
6535 return mono_string_new_len (mono_domain_get (), p, slen);
6536 case MONO_TYPE_CLASS: {
6539 if (*p == (char)0xFF) {
6544 slen = mono_metadata_decode_value (p, &p);
6545 n = g_memdup (p, slen + 1);
6547 t = mono_reflection_type_from_name (n, image);
6549 g_warning ("Cannot load type '%s'", n);
6553 return mono_type_get_object (mono_domain_get (), t);
6557 case MONO_TYPE_OBJECT: {
6560 MonoClass *subc = NULL;
6565 } else if (subt == 0x0E) {
6566 type = MONO_TYPE_STRING;
6568 } else if (subt == 0x55) {
6571 slen = mono_metadata_decode_value (p, &p);
6572 n = g_memdup (p, slen + 1);
6574 t = mono_reflection_type_from_name (n, image);
6576 g_warning ("Cannot load type '%s'", n);
6579 subc = mono_class_from_mono_type (t);
6580 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6581 MonoType simple_type = {{0}};
6582 simple_type.type = subt;
6583 subc = mono_class_from_mono_type (&simple_type);
6585 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6587 val = load_cattr_value (image, &subc->byval_arg, p, end);
6588 obj = mono_object_new (mono_domain_get (), subc);
6589 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6593 case MONO_TYPE_SZARRAY: {
6595 guint32 i, alen, basetype;
6598 if (alen == 0xffffffff) {
6602 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6603 basetype = t->data.klass->byval_arg.type;
6608 case MONO_TYPE_BOOLEAN:
6609 for (i = 0; i < alen; i++) {
6610 MonoBoolean val = *p++;
6611 mono_array_set (arr, MonoBoolean, i, val);
6614 case MONO_TYPE_CHAR:
6617 for (i = 0; i < alen; i++) {
6618 guint16 val = read16 (p);
6619 mono_array_set (arr, guint16, i, val);
6626 for (i = 0; i < alen; i++) {
6627 guint32 val = read32 (p);
6628 mono_array_set (arr, guint32, i, val);
6635 for (i = 0; i < alen; i++) {
6636 guint64 val = read64 (p);
6637 mono_array_set (arr, guint64, i, val);
6641 case MONO_TYPE_CLASS:
6642 case MONO_TYPE_OBJECT:
6643 case MONO_TYPE_STRING:
6644 for (i = 0; i < alen; i++) {
6645 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6646 mono_array_set (arr, gpointer, i, item);
6650 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6656 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6662 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6664 static MonoClass *klass;
6665 static MonoMethod *ctor;
6667 void *params [2], *unboxed;
6670 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6672 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6674 params [0] = mono_type_get_object (mono_domain_get (), t);
6676 retval = mono_object_new (mono_domain_get (), klass);
6677 unboxed = mono_object_unbox (retval);
6678 mono_runtime_invoke (ctor, unboxed, params, NULL);
6684 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6686 static MonoClass *klass;
6687 static MonoMethod *ctor;
6689 void *unboxed, *params [2];
6692 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6694 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6697 params [1] = typedarg;
6698 retval = mono_object_new (mono_domain_get (), klass);
6699 unboxed = mono_object_unbox (retval);
6700 mono_runtime_invoke (ctor, unboxed, params, NULL);
6706 type_is_reference (MonoType *type)
6708 switch (type->type) {
6709 case MONO_TYPE_BOOLEAN:
6710 case MONO_TYPE_CHAR:
6723 case MONO_TYPE_VALUETYPE:
6731 free_param_data (MonoMethodSignature *sig, void **params) {
6733 for (i = 0; i < sig->param_count; ++i) {
6734 if (!type_is_reference (sig->params [i]))
6735 g_free (params [i]);
6740 * Find the field index in the metadata FieldDef table.
6743 find_field_index (MonoClass *klass, MonoClassField *field) {
6746 for (i = 0; i < klass->field.count; ++i) {
6747 if (field == &klass->fields [i])
6748 return klass->field.first + 1 + i;
6754 * Find the property index in the metadata Property table.
6757 find_property_index (MonoClass *klass, MonoProperty *property) {
6760 for (i = 0; i < klass->property.count; ++i) {
6761 if (property == &klass->properties [i])
6762 return klass->property.first + 1 + i;
6768 * Find the event index in the metadata Event table.
6771 find_event_index (MonoClass *klass, MonoEvent *event) {
6774 for (i = 0; i < klass->event.count; ++i) {
6775 if (event == &klass->events [i])
6776 return klass->event.first + 1 + i;
6782 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6784 const char *p = data;
6786 guint32 i, j, num_named;
6790 mono_class_init (method->klass);
6793 attr = mono_object_new (mono_domain_get (), method->klass);
6794 mono_runtime_invoke (method, attr, NULL, NULL);
6798 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6801 /*g_print ("got attr %s\n", method->klass->name);*/
6803 /* Allocate using alloca so it gets GC tracking */
6804 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6808 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6809 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6813 attr = mono_object_new (mono_domain_get (), method->klass);
6814 mono_runtime_invoke (method, attr, params, NULL);
6815 free_param_data (method->signature, params);
6816 num_named = read16 (named);
6818 for (j = 0; j < num_named; j++) {
6820 gboolean is_boxed = FALSE;
6821 char *name, named_type, data_type;
6822 named_type = *named++;
6823 data_type = *named++; /* type of data */
6824 if (data_type == 0x51)
6827 if (data_type == 0x55) {
6830 type_len = mono_metadata_decode_blob_size (named, &named);
6831 type_name = g_malloc (type_len + 1);
6832 memcpy (type_name, named, type_len);
6833 type_name [type_len] = 0;
6835 /* FIXME: lookup the type and check type consistency */
6837 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6838 /* this seems to be the type of the element of the array */
6839 /* g_print ("skipping 0x%02x after prop\n", *named); */
6842 name_len = mono_metadata_decode_blob_size (named, &named);
6843 name = g_malloc (name_len + 1);
6844 memcpy (name, named, name_len);
6845 name [name_len] = 0;
6847 if (named_type == 0x53) {
6848 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6849 void *val = load_cattr_value (image, field->type, named, &named);
6850 mono_field_set_value (attr, field, val);
6851 if (!type_is_reference (field->type))
6853 } else if (named_type == 0x54) {
6856 MonoType *prop_type;
6858 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6859 /* can we have more that 1 arg in a custom attr named property? */
6860 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6861 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6862 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6863 mono_property_set_value (prop, attr, pparams, NULL);
6864 if (!type_is_reference (prop_type))
6865 g_free (pparams [0]);
6874 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6876 MonoArray *typedargs, *namedargs;
6877 MonoClass *attrklass;
6878 static MonoClass *klass;
6879 static MonoMethod *ctor;
6882 const char *p = data;
6884 guint32 i, j, num_named;
6887 mono_class_init (method->klass);
6890 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6892 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6894 domain = mono_domain_get ();
6896 /* This is for Attributes with no parameters */
6897 attr = mono_object_new (domain, klass);
6898 params [0] = mono_method_get_object (domain, method, NULL);
6899 params [1] = params [2] = NULL;
6900 mono_runtime_invoke (method, attr, params, NULL);
6904 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6907 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6911 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6912 MonoObject *obj, *typedarg;
6915 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6916 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6917 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6918 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6919 mono_array_set (typedargs, void*, i, typedarg);
6921 if (!type_is_reference (mono_method_signature (method)->params [i]))
6926 num_named = read16 (named);
6927 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6929 attrklass = method->klass;
6930 for (j = 0; j < num_named; j++) {
6932 char *name, named_type, data_type;
6933 named_type = *named++;
6934 data_type = *named++; /* type of data */
6935 if (data_type == 0x55) {
6938 type_len = mono_metadata_decode_blob_size (named, &named);
6939 type_name = g_malloc (type_len + 1);
6940 memcpy (type_name, named, type_len);
6941 type_name [type_len] = 0;
6943 /* FIXME: lookup the type and check type consistency */
6945 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6946 /* this seems to be the type of the element of the array */
6947 /* g_print ("skipping 0x%02x after prop\n", *named); */
6950 name_len = mono_metadata_decode_blob_size (named, &named);
6951 name = g_malloc (name_len + 1);
6952 memcpy (name, named, name_len);
6953 name [name_len] = 0;
6955 if (named_type == 0x53) {
6956 MonoObject *obj, *typedarg, *namedarg;
6957 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6958 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6960 minfo = mono_field_get_object (domain, NULL, field);
6961 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6962 typedarg = create_cattr_typed_arg (field->type, obj);
6963 namedarg = create_cattr_named_arg (minfo, typedarg);
6964 mono_array_set (namedargs, void*, j, namedarg);
6965 if (!type_is_reference (field->type))
6967 } else if (named_type == 0x54) {
6968 MonoObject *obj, *typedarg, *namedarg;
6969 MonoType *prop_type;
6971 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
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 minfo = mono_property_get_object (domain, NULL, prop);
6976 val = load_cattr_value (image, prop_type, named, &named);
6977 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6978 typedarg = create_cattr_typed_arg (prop_type, obj);
6979 namedarg = create_cattr_named_arg (minfo, typedarg);
6980 mono_array_set (namedargs, void*, j, namedarg);
6981 if (!type_is_reference (prop_type))
6986 attr = mono_object_new (domain, klass);
6987 params [0] = mono_method_get_object (domain, method, NULL);
6988 params [1] = typedargs;
6989 params [2] = namedargs;
6990 mono_runtime_invoke (ctor, attr, params, NULL);
6995 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7002 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7003 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7004 for (i = 0; i < cinfo->num_attrs; ++i) {
7005 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7006 mono_array_set (result, gpointer, i, attr);
7012 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7020 for (i = 0; i < cinfo->num_attrs; ++i) {
7021 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
7025 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7026 result = mono_array_new (mono_domain_get (), klass, n);
7028 for (i = 0; i < cinfo->num_attrs; ++i) {
7029 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass)) {
7030 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7031 mono_array_set (result, gpointer, n, attr);
7039 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7042 static MonoClass *klass;
7047 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7049 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7050 for (i = 0; i < cinfo->num_attrs; ++i) {
7051 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7052 mono_array_set (result, gpointer, i, attr);
7058 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7060 guint32 mtoken, i, len;
7061 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7063 MonoCustomAttrInfo *ainfo;
7064 GList *tmp, *list = NULL;
7067 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7069 i = mono_metadata_custom_attrs_from_index (image, idx);
7073 while (i < ca->rows) {
7074 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7076 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7079 len = g_list_length (list);
7082 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7083 ainfo->num_attrs = len;
7084 ainfo->image = image;
7085 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7086 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7087 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7088 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7089 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7090 mtoken |= MONO_TOKEN_METHOD_DEF;
7092 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7093 mtoken |= MONO_TOKEN_MEMBER_REF;
7096 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7099 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7100 if (!ainfo->attrs [i].ctor)
7101 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7102 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7103 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7104 ainfo->attrs [i].data = data;
7112 mono_custom_attrs_from_method (MonoMethod *method)
7114 MonoCustomAttrInfo *cinfo;
7117 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7119 idx = mono_method_get_index (method);
7120 idx <<= MONO_CUSTOM_ATTR_BITS;
7121 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7122 return mono_custom_attrs_from_index (method->klass->image, idx);
7126 mono_custom_attrs_from_class (MonoClass *klass)
7128 MonoCustomAttrInfo *cinfo;
7131 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7133 idx = mono_metadata_token_index (klass->type_token);
7134 idx <<= MONO_CUSTOM_ATTR_BITS;
7135 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7136 return mono_custom_attrs_from_index (klass->image, idx);
7140 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7142 MonoCustomAttrInfo *cinfo;
7145 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7147 idx = 1; /* there is only one assembly */
7148 idx <<= MONO_CUSTOM_ATTR_BITS;
7149 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7150 return mono_custom_attrs_from_index (assembly->image, idx);
7153 static MonoCustomAttrInfo*
7154 mono_custom_attrs_from_module (MonoImage *image)
7156 MonoCustomAttrInfo *cinfo;
7159 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7161 idx = 1; /* there is only one module */
7162 idx <<= MONO_CUSTOM_ATTR_BITS;
7163 idx |= MONO_CUSTOM_ATTR_MODULE;
7164 return mono_custom_attrs_from_index (image, idx);
7168 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7170 MonoCustomAttrInfo *cinfo;
7173 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7175 idx = find_property_index (klass, property);
7176 idx <<= MONO_CUSTOM_ATTR_BITS;
7177 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7178 return mono_custom_attrs_from_index (klass->image, idx);
7182 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7184 MonoCustomAttrInfo *cinfo;
7187 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7189 idx = find_event_index (klass, event);
7190 idx <<= MONO_CUSTOM_ATTR_BITS;
7191 idx |= MONO_CUSTOM_ATTR_EVENT;
7192 return mono_custom_attrs_from_index (klass->image, idx);
7196 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7198 MonoCustomAttrInfo *cinfo;
7201 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7203 idx = find_field_index (klass, field);
7204 idx <<= MONO_CUSTOM_ATTR_BITS;
7205 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7206 return mono_custom_attrs_from_index (klass->image, idx);
7210 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7213 guint32 i, idx, method_index;
7214 guint32 param_list, param_last, param_pos, found;
7216 MonoReflectionMethodAux *aux;
7218 if (method->klass->image->dynamic) {
7219 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7220 if (!aux || !aux->param_cattr)
7222 return aux->param_cattr [param];
7225 image = method->klass->image;
7226 method_index = mono_method_get_index (method);
7227 ca = &image->tables [MONO_TABLE_METHOD];
7229 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7230 /* FIXME FIXME FIXME */
7234 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7235 if (method_index == ca->rows) {
7236 ca = &image->tables [MONO_TABLE_PARAM];
7237 param_last = ca->rows + 1;
7239 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7240 ca = &image->tables [MONO_TABLE_PARAM];
7243 for (i = param_list; i < param_last; ++i) {
7244 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7245 if (param_pos == param) {
7253 idx <<= MONO_CUSTOM_ATTR_BITS;
7254 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7255 return mono_custom_attrs_from_index (image, idx);
7259 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7263 for (i = 0; i < ainfo->num_attrs; ++i) {
7264 klass = ainfo->attrs [i].ctor->klass;
7265 if (mono_class_has_parent (klass, attr_klass))
7272 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7279 for (i = 0; i < ainfo->num_attrs; ++i) {
7280 klass = ainfo->attrs [i].ctor->klass;
7281 if (mono_class_has_parent (klass, attr_klass)) {
7286 if (attr_index == -1)
7289 attrs = mono_custom_attrs_construct (ainfo);
7291 return mono_array_get (attrs, MonoObject*, attr_index);
7297 * mono_reflection_get_custom_attrs_info:
7298 * @obj: a reflection object handle
7300 * Return the custom attribute info for attributes defined for the
7301 * reflection handle @obj. The objects.
7304 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7307 MonoCustomAttrInfo *cinfo = NULL;
7309 klass = obj->vtable->klass;
7310 if (klass == mono_defaults.monotype_class) {
7311 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7312 klass = mono_class_from_mono_type (rtype->type);
7313 cinfo = mono_custom_attrs_from_class (klass);
7314 } else if (strcmp ("Assembly", klass->name) == 0) {
7315 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7316 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7317 } else if (strcmp ("Module", klass->name) == 0) {
7318 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7319 cinfo = mono_custom_attrs_from_module (module->image);
7320 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7321 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7322 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7323 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7324 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7325 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7326 } else if (strcmp ("MonoField", klass->name) == 0) {
7327 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7328 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7329 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7330 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7331 cinfo = mono_custom_attrs_from_method (rmethod->method);
7332 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7333 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7334 cinfo = mono_custom_attrs_from_method (method);
7335 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7336 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7337 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7338 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7339 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7340 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7341 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7342 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7343 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7344 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7345 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7346 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7347 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7348 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7349 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7350 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7351 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7352 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7353 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7354 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7355 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7356 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7357 } else { /* handle other types here... */
7358 g_error ("get custom attrs not yet supported for %s", klass->name);
7365 * mono_reflection_get_custom_attrs_by_type:
7366 * @obj: a reflection object handle
7368 * Return an array with all the custom attributes defined of the
7369 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7370 * of that type are returned. The objects are fully build.
7373 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7376 MonoCustomAttrInfo *cinfo;
7378 cinfo = mono_reflection_get_custom_attrs_info (obj);
7381 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7383 result = mono_custom_attrs_construct (cinfo);
7385 mono_custom_attrs_free (cinfo);
7388 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7389 result = mono_array_new (mono_domain_get (), klass, 0);
7396 * mono_reflection_get_custom_attrs:
7397 * @obj: a reflection object handle
7399 * Return an array with all the custom attributes defined of the
7400 * reflection handle @obj. The objects are fully build.
7403 mono_reflection_get_custom_attrs (MonoObject *obj)
7405 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7409 * mono_reflection_get_custom_attrs_data:
7410 * @obj: a reflection obj handle
7412 * Returns an array of System.Reflection.CustomAttributeData,
7413 * which include information about attributes reflected on
7414 * types loaded using the Reflection Only methods
7417 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7420 MonoCustomAttrInfo *cinfo;
7422 cinfo = mono_reflection_get_custom_attrs_info (obj);
7424 result = mono_custom_attrs_data_construct (cinfo);
7426 mono_custom_attrs_free (cinfo);
7429 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7430 result = mono_array_new (mono_domain_get (), klass, 0);
7436 static MonoMethodSignature*
7437 parameters_to_signature (MonoArray *parameters) {
7438 MonoMethodSignature *sig;
7441 count = parameters? mono_array_length (parameters): 0;
7443 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7444 sig->param_count = count;
7445 sig->sentinelpos = -1; /* FIXME */
7446 for (i = 0; i < count; ++i) {
7447 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7448 sig->params [i] = pt->type;
7453 static MonoMethodSignature*
7454 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7455 MonoMethodSignature *sig;
7457 sig = parameters_to_signature (ctor->parameters);
7458 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7459 sig->ret = &mono_defaults.void_class->byval_arg;
7463 static MonoMethodSignature*
7464 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7465 MonoMethodSignature *sig;
7467 sig = parameters_to_signature (method->parameters);
7468 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7469 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7470 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7474 static MonoMethodSignature*
7475 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7476 MonoMethodSignature *sig;
7478 sig = parameters_to_signature (method->parameters);
7479 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7480 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7481 sig->generic_param_count = 0;
7486 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7488 MonoClass *klass = mono_object_class (prop);
7489 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7490 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7491 *name = mono_string_to_utf8 (pb->name);
7492 *type = pb->type->type;
7494 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7495 *name = g_strdup (p->property->name);
7496 if (p->property->get)
7497 *type = mono_method_signature (p->property->get)->ret;
7499 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7504 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7506 MonoClass *klass = mono_object_class (field);
7507 if (strcmp (klass->name, "FieldBuilder") == 0) {
7508 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7509 *name = mono_string_to_utf8 (fb->name);
7510 *type = fb->type->type;
7512 MonoReflectionField *f = (MonoReflectionField *)field;
7513 *name = g_strdup (f->field->name);
7514 *type = f->field->type;
7519 * Encode a value in a custom attribute stream of bytes.
7520 * The value to encode is either supplied as an object in argument val
7521 * (valuetypes are boxed), or as a pointer to the data in the
7523 * @type represents the type of the value
7524 * @buffer is the start of the buffer
7525 * @p the current position in the buffer
7526 * @buflen contains the size of the buffer and is used to return the new buffer size
7527 * if this needs to be realloced.
7528 * @retbuffer and @retp return the start and the position of the buffer
7531 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7533 MonoTypeEnum simple_type;
7535 if ((p-buffer) + 10 >= *buflen) {
7538 newbuf = g_realloc (buffer, *buflen);
7539 p = newbuf + (p-buffer);
7543 argval = ((char*)arg + sizeof (MonoObject));
7544 simple_type = type->type;
7546 switch (simple_type) {
7547 case MONO_TYPE_BOOLEAN:
7552 case MONO_TYPE_CHAR:
7555 swap_with_size (p, argval, 2, 1);
7561 swap_with_size (p, argval, 4, 1);
7567 swap_with_size (p, argval, 8, 1);
7570 case MONO_TYPE_VALUETYPE:
7571 if (type->data.klass->enumtype) {
7572 simple_type = type->data.klass->enum_basetype->type;
7575 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7578 case MONO_TYPE_STRING: {
7585 str = mono_string_to_utf8 ((MonoString*)arg);
7586 slen = strlen (str);
7587 if ((p-buffer) + 10 + slen >= *buflen) {
7591 newbuf = g_realloc (buffer, *buflen);
7592 p = newbuf + (p-buffer);
7595 mono_metadata_encode_value (slen, p, &p);
7596 memcpy (p, str, slen);
7601 case MONO_TYPE_CLASS: {
7609 k = mono_object_class (arg);
7610 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7611 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7612 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7614 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7615 slen = strlen (str);
7616 if ((p-buffer) + 10 + slen >= *buflen) {
7620 newbuf = g_realloc (buffer, *buflen);
7621 p = newbuf + (p-buffer);
7624 mono_metadata_encode_value (slen, p, &p);
7625 memcpy (p, str, slen);
7630 case MONO_TYPE_SZARRAY: {
7632 MonoClass *eclass, *arg_eclass;
7635 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7638 len = mono_array_length ((MonoArray*)arg);
7640 *p++ = (len >> 8) & 0xff;
7641 *p++ = (len >> 16) & 0xff;
7642 *p++ = (len >> 24) & 0xff;
7644 *retbuffer = buffer;
7645 eclass = type->data.klass;
7646 arg_eclass = mono_object_class (arg)->element_class;
7647 if (eclass->valuetype && arg_eclass->valuetype) {
7648 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7649 int elsize = mono_class_array_element_size (eclass);
7650 for (i = 0; i < len; ++i) {
7651 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7655 for (i = 0; i < len; ++i) {
7656 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7661 /* it may be a boxed value or a Type */
7662 case MONO_TYPE_OBJECT: {
7668 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7673 klass = mono_object_class (arg);
7675 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7678 } else if (klass->enumtype) {
7680 } else if (klass == mono_defaults.string_class) {
7681 simple_type = MONO_TYPE_STRING;
7684 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7685 *p++ = simple_type = klass->byval_arg.type;
7688 g_error ("unhandled type in custom attr");
7690 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7691 slen = strlen (str);
7692 if ((p-buffer) + 10 + slen >= *buflen) {
7696 newbuf = g_realloc (buffer, *buflen);
7697 p = newbuf + (p-buffer);
7700 mono_metadata_encode_value (slen, p, &p);
7701 memcpy (p, str, slen);
7704 simple_type = klass->enum_basetype->type;
7708 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7711 *retbuffer = buffer;
7715 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7718 /* Preallocate a large enough buffer */
7719 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7720 char *str = type_get_qualified_name (type, NULL);
7726 len += strlen (name);
7728 if ((p-buffer) + 20 + len >= *buflen) {
7732 newbuf = g_realloc (buffer, *buflen);
7733 p = newbuf + (p-buffer);
7737 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7738 char *str = type_get_qualified_name (type, NULL);
7739 int slen = strlen (str);
7743 * This seems to be optional...
7746 mono_metadata_encode_value (slen, p, &p);
7747 memcpy (p, str, slen);
7750 } else if (type->type == MONO_TYPE_OBJECT) {
7752 } else if (type->type == MONO_TYPE_CLASS) {
7753 /* it should be a type: encode_cattr_value () has the check */
7756 mono_metadata_encode_value (type->type, p, &p);
7757 if (type->type == MONO_TYPE_SZARRAY)
7758 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7760 len = strlen (name);
7761 mono_metadata_encode_value (len, p, &p);
7762 memcpy (p, name, len);
7764 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7766 *retbuffer = buffer;
7770 * mono_reflection_get_custom_attrs_blob:
7771 * @ctor: custom attribute constructor
7772 * @ctorArgs: arguments o the constructor
7778 * Creates the blob of data that needs to be saved in the metadata and that represents
7779 * the custom attributed described by @ctor, @ctorArgs etc.
7780 * Returns: a Byte array representing the blob of data.
7783 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7786 MonoMethodSignature *sig;
7791 MONO_ARCH_SAVE_REGS;
7793 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7794 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7796 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7798 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7800 p = buffer = g_malloc (buflen);
7801 /* write the prolog */
7804 for (i = 0; i < sig->param_count; ++i) {
7805 arg = mono_array_get (ctorArgs, MonoObject*, i);
7806 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7810 i += mono_array_length (properties);
7812 i += mono_array_length (fields);
7814 *p++ = (i >> 8) & 0xff;
7817 for (i = 0; i < mono_array_length (properties); ++i) {
7821 prop = mono_array_get (properties, gpointer, i);
7822 get_prop_name_and_type (prop, &pname, &ptype);
7823 *p++ = 0x54; /* PROPERTY signature */
7824 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7831 for (i = 0; i < mono_array_length (fields); ++i) {
7835 field = mono_array_get (fields, gpointer, i);
7836 get_field_name_and_type (field, &fname, &ftype);
7837 *p++ = 0x53; /* FIELD signature */
7838 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7843 g_assert (p - buffer <= buflen);
7844 buflen = p - buffer;
7845 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7846 p = mono_array_addr (result, char, 0);
7847 memcpy (p, buffer, buflen);
7849 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7855 * mono_reflection_setup_internal_class:
7856 * @tb: a TypeBuilder object
7858 * Creates a MonoClass that represents the TypeBuilder.
7859 * This is a trick that lets us simplify a lot of reflection code
7860 * (and will allow us to support Build and Run assemblies easier).
7863 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7865 MonoClass *klass, *parent;
7867 MONO_ARCH_SAVE_REGS;
7869 mono_loader_lock ();
7872 /* check so we can compile corlib correctly */
7873 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7874 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7875 parent = tb->parent->type->data.klass;
7877 parent = my_mono_class_from_mono_type (tb->parent->type);
7883 /* the type has already being created: it means we just have to change the parent */
7884 if (tb->type.type) {
7885 klass = mono_class_from_mono_type (tb->type.type);
7886 klass->parent = NULL;
7887 /* fool mono_class_setup_parent */
7888 g_free (klass->supertypes);
7889 klass->supertypes = NULL;
7890 mono_class_setup_parent (klass, parent);
7891 mono_class_setup_mono_type (klass);
7892 mono_loader_unlock ();
7896 klass = g_new0 (MonoClass, 1);
7898 klass->image = &tb->module->dynamic_image->image;
7900 klass->inited = 1; /* we lie to the runtime */
7901 klass->name = mono_string_to_utf8 (tb->name);
7902 klass->name_space = mono_string_to_utf8 (tb->nspace);
7903 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7904 klass->flags = tb->attrs;
7906 klass->element_class = klass;
7907 klass->reflection_info = tb; /* need to pin. */
7909 /* Put into cache so mono_class_get () will find it */
7910 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7912 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7913 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7915 if (parent != NULL) {
7916 mono_class_setup_parent (klass, parent);
7917 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7918 const char *old_n = klass->name;
7919 /* trick to get relative numbering right when compiling corlib */
7920 klass->name = "BuildingObject";
7921 mono_class_setup_parent (klass, mono_defaults.object_class);
7922 klass->name = old_n;
7925 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7926 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7927 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7928 klass->instance_size = sizeof (MonoObject);
7929 klass->size_inited = 1;
7930 mono_class_setup_vtable_general (klass, NULL, 0);
7933 mono_class_setup_mono_type (klass);
7935 mono_class_setup_supertypes (klass);
7938 * FIXME: handle interfaces.
7941 tb->type.type = &klass->byval_arg;
7943 if (tb->nesting_type) {
7944 g_assert (tb->nesting_type->type);
7945 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7948 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7950 mono_loader_unlock ();
7954 * mono_reflection_setup_generic_class:
7955 * @tb: a TypeBuilder object
7957 * Setup the generic class before adding the first generic parameter.
7960 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7964 MONO_ARCH_SAVE_REGS;
7966 klass = my_mono_class_from_mono_type (tb->type.type);
7967 if (tb->generic_container)
7970 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7971 tb->generic_container->klass = klass;
7973 tb->generic_container->context.container = tb->generic_container;
7977 * mono_reflection_create_generic_class:
7978 * @tb: a TypeBuilder object
7980 * Creates the generic class after all generic parameters have been added.
7983 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7988 MONO_ARCH_SAVE_REGS;
7990 klass = my_mono_class_from_mono_type (tb->type.type);
7992 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7994 if (klass->generic_container || (count == 0))
7997 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7999 klass->generic_container = tb->generic_container;
8001 klass->generic_container->type_argc = count;
8002 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8004 for (i = 0; i < count; i++) {
8005 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8006 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8007 g_assert (klass->generic_container->type_params [i].owner);
8010 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8014 * mono_reflection_create_internal_class:
8015 * @tb: a TypeBuilder object
8017 * Actually create the MonoClass that is associated with the TypeBuilder.
8020 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8024 MONO_ARCH_SAVE_REGS;
8026 klass = my_mono_class_from_mono_type (tb->type.type);
8028 mono_loader_lock ();
8029 if (klass->enumtype && klass->enum_basetype == NULL) {
8030 MonoReflectionFieldBuilder *fb;
8033 g_assert (tb->fields != NULL);
8034 g_assert (mono_array_length (tb->fields) >= 1);
8036 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8038 klass->enum_basetype = fb->type->type;
8039 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8040 if (!klass->element_class)
8041 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8044 * get the element_class from the current corlib.
8046 ec = default_class_from_mono_type (klass->enum_basetype);
8047 klass->instance_size = ec->instance_size;
8048 klass->size_inited = 1;
8050 * this is almost safe to do with enums and it's needed to be able
8051 * to create objects of the enum type (for use in SetConstant).
8053 /* FIXME: Does this mean enums can't have method overrides ? */
8054 mono_class_setup_vtable_general (klass, NULL, 0);
8056 mono_loader_unlock ();
8059 static MonoMarshalSpec*
8060 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8061 MonoReflectionMarshal *minfo)
8063 MonoMarshalSpec *res;
8065 res = g_new0 (MonoMarshalSpec, 1);
8066 res->native = minfo->type;
8068 switch (minfo->type) {
8069 case MONO_NATIVE_LPARRAY:
8070 res->data.array_data.elem_type = minfo->eltype;
8071 if (minfo->has_size) {
8072 res->data.array_data.param_num = minfo->param_num;
8073 res->data.array_data.num_elem = minfo->count;
8074 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8077 res->data.array_data.param_num = -1;
8078 res->data.array_data.num_elem = -1;
8079 res->data.array_data.elem_mult = -1;
8083 case MONO_NATIVE_BYVALTSTR:
8084 case MONO_NATIVE_BYVALARRAY:
8085 res->data.array_data.num_elem = minfo->count;
8088 case MONO_NATIVE_CUSTOM:
8089 if (minfo->marshaltyperef)
8090 res->data.custom_data.custom_name =
8091 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8093 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8103 MonoReflectionMarshal*
8104 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8105 MonoMarshalSpec *spec)
8107 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8108 MonoReflectionMarshal *minfo;
8111 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8112 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8113 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8114 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8117 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8118 minfo->type = spec->native;
8120 switch (minfo->type) {
8121 case MONO_NATIVE_LPARRAY:
8122 minfo->eltype = spec->data.array_data.elem_type;
8123 minfo->count = spec->data.array_data.num_elem;
8124 minfo->param_num = spec->data.array_data.param_num;
8127 case MONO_NATIVE_BYVALTSTR:
8128 case MONO_NATIVE_BYVALARRAY:
8129 minfo->count = spec->data.array_data.num_elem;
8132 case MONO_NATIVE_CUSTOM:
8133 if (spec->data.custom_data.custom_name) {
8134 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8136 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8138 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8140 if (spec->data.custom_data.cookie)
8141 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8152 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8153 ReflectionMethodBuilder *rmb,
8154 MonoMethodSignature *sig)
8157 MonoMethodNormal *pm;
8158 MonoMarshalSpec **specs;
8159 MonoReflectionMethodAux *method_aux;
8162 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8163 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8164 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8166 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8168 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8170 pm = (MonoMethodNormal*)m;
8173 m->flags = rmb->attrs;
8174 m->iflags = rmb->iattrs;
8175 m->name = mono_string_to_utf8 (rmb->name);
8179 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8181 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8182 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8185 m->signature->pinvoke = 1;
8186 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8187 m->signature->pinvoke = 1;
8189 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8191 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8192 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8194 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8196 if (klass->image->dynamic)
8197 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8200 } else if (!m->klass->dummy &&
8201 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8202 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8203 MonoMethodHeader *header;
8205 gint32 max_stack, i;
8206 gint32 num_locals = 0;
8207 gint32 num_clauses = 0;
8211 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8212 code_size = rmb->ilgen->code_len;
8213 max_stack = rmb->ilgen->max_stack;
8214 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8215 if (rmb->ilgen->ex_handlers)
8216 num_clauses = method_count_clauses (rmb->ilgen);
8219 code = mono_array_addr (rmb->code, guint8, 0);
8220 code_size = mono_array_length (rmb->code);
8221 /* we probably need to run a verifier on the code... */
8231 header = g_malloc0 (sizeof (MonoMethodHeader) +
8232 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8233 header->code_size = code_size;
8234 header->code = g_malloc (code_size);
8235 memcpy ((char*)header->code, code, code_size);
8236 header->max_stack = max_stack;
8237 header->init_locals = rmb->init_locals;
8238 header->num_locals = num_locals;
8240 for (i = 0; i < num_locals; ++i) {
8241 MonoReflectionLocalBuilder *lb =
8242 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8244 header->locals [i] = g_new0 (MonoType, 1);
8245 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8248 header->num_clauses = num_clauses;
8250 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8251 rmb->ilgen, num_clauses);
8254 pm->header = header;
8257 if (rmb->generic_params) {
8258 int count = mono_array_length (rmb->generic_params);
8259 MonoGenericContainer *container;
8261 m->generic_container = container = rmb->generic_container;
8262 container->type_argc = count;
8263 container->type_params = g_new0 (MonoGenericParam, count);
8265 for (i = 0; i < count; i++) {
8266 MonoReflectionGenericParam *gp =
8267 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8269 container->type_params [i] = *gp->type.type->data.generic_param;
8274 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8278 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8280 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8281 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8282 for (i = 0; i < rmb->nrefs; ++i)
8283 data [i + 1] = rmb->refs [i];
8288 /* Parameter info */
8291 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8292 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8293 for (i = 0; i <= m->signature->param_count; ++i) {
8294 MonoReflectionParamBuilder *pb;
8295 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8296 if ((i > 0) && (pb->attrs)) {
8297 /* Make a copy since it might point to a shared type structure */
8298 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)));
8299 m->signature->params [i - 1]->attrs = pb->attrs;
8302 if (pb->def_value) {
8303 MonoDynamicImage *assembly;
8304 guint32 idx, def_type, len;
8308 if (!method_aux->param_defaults) {
8309 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8310 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8312 assembly = (MonoDynamicImage*)klass->image;
8313 idx = encode_constant (assembly, pb->def_value, &def_type);
8314 /* Copy the data from the blob since it might get realloc-ed */
8315 p = assembly->blob.data + idx;
8316 len = mono_metadata_decode_blob_size (p, &p2);
8318 method_aux->param_defaults [i] = g_malloc (len);
8319 method_aux->param_default_types [i] = def_type;
8320 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8324 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8326 if (!method_aux->param_cattr)
8327 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8328 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8334 /* Parameter marshalling */
8337 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8338 MonoReflectionParamBuilder *pb;
8339 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8340 if (pb->marshal_info) {
8342 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8343 specs [pb->position] =
8344 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8348 if (specs != NULL) {
8350 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8351 method_aux->param_marshall = specs;
8354 if (klass->image->dynamic && method_aux)
8355 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8361 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8363 ReflectionMethodBuilder rmb;
8364 MonoMethodSignature *sig;
8366 sig = ctor_builder_to_signature (mb);
8368 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8370 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8371 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8373 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8374 /* ilgen is no longer needed */
8382 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8384 ReflectionMethodBuilder rmb;
8385 MonoMethodSignature *sig;
8387 sig = method_builder_to_signature (mb);
8389 reflection_methodbuilder_from_method_builder (&rmb, mb);
8391 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8392 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8394 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8395 /* ilgen is no longer needed */
8401 static MonoClassField*
8402 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8404 MonoClassField *field;
8411 field = g_new0 (MonoClassField, 1);
8413 field->name = mono_string_to_utf8 (fb->name);
8415 /* FIXME: handle type modifiers */
8416 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8417 field->type->attrs = fb->attrs;
8419 field->type = fb->type->type;
8421 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8422 field->data = mono_array_addr (fb->rva_data, char, 0);
8423 if (fb->offset != -1)
8424 field->offset = fb->offset;
8425 field->parent = klass;
8427 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8429 if (fb->def_value) {
8430 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8431 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8432 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8433 /* Copy the data from the blob since it might get realloc-ed */
8434 p = assembly->blob.data + idx;
8435 len = mono_metadata_decode_blob_size (p, &p2);
8437 field->data = g_malloc (len);
8438 memcpy ((gpointer)field->data, p, len);
8445 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8449 MonoReflectionTypeBuilder *tb = NULL;
8450 MonoGenericClass *gclass, *cached;
8451 MonoInflatedGenericClass *igclass;
8452 MonoDynamicGenericClass *dgclass = NULL;
8453 gboolean is_dynamic = FALSE;
8458 klass = mono_class_from_mono_type (type->type);
8459 if (!klass->generic_container && !klass->generic_class &&
8460 !(klass->nested_in && klass->nested_in->generic_container))
8463 mono_loader_lock ();
8465 domain = mono_object_domain (type);
8467 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8468 tb = (MonoReflectionTypeBuilder *) type;
8470 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8472 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8473 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8474 MonoReflectionType *rgt = rgi->generic_type;
8476 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8477 tb = (MonoReflectionTypeBuilder *) rgt;
8479 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8481 } else if (klass->wastypebuilder) {
8482 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8484 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8487 icount = klass->interface_count;
8491 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8492 igclass = &dgclass->generic_class;
8493 gclass = &igclass->generic_class;
8494 gclass->is_dynamic = TRUE;
8495 gclass->is_inflated = TRUE;
8497 igclass = g_new0 (MonoInflatedGenericClass, 1);
8498 gclass = &igclass->generic_class;
8499 gclass->is_inflated = TRUE;
8502 gclass->inst = g_new0 (MonoGenericInst, 1);
8504 gclass->inst->type_argc = type_argc;
8505 gclass->inst->type_argv = types;
8506 gclass->inst->is_reference = 1;
8508 for (i = 0; i < gclass->inst->type_argc; ++i) {
8509 if (!gclass->inst->is_open)
8510 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8511 if (gclass->inst->is_reference)
8512 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8515 gclass->container_class = klass;
8517 if (klass->generic_class) {
8518 MonoGenericClass *kgclass = klass->generic_class;
8519 MonoGenericClass *ogclass = gclass;
8521 ogclass->context = g_new0 (MonoGenericContext, 1);
8522 ogclass->context->container = gclass->container_class->generic_container;
8523 ogclass->context->gclass = gclass;
8526 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8527 igclass = &dgclass->generic_class;
8528 gclass = &igclass->generic_class;
8529 gclass->is_dynamic = TRUE;
8530 gclass->is_inflated = TRUE;
8532 igclass = g_new0 (MonoInflatedGenericClass, 1);
8533 gclass = &igclass->generic_class;
8534 gclass->is_inflated = TRUE;
8537 gclass->inst = g_new0 (MonoGenericInst, 1);
8539 gclass->inst->type_argc = kgclass->inst->type_argc;
8540 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8541 gclass->inst->is_reference = 1;
8543 for (i = 0; i < gclass->inst->type_argc; i++) {
8544 MonoType *t = kgclass->inst->type_argv [i];
8546 t = mono_class_inflate_generic_type (t, ogclass->context);
8548 if (!gclass->inst->is_open)
8549 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8550 if (gclass->inst->is_reference)
8551 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8553 gclass->inst->type_argv [i] = t;
8556 gclass->container_class = kgclass->container_class;
8559 geninst = g_new0 (MonoType, 1);
8560 geninst->type = MONO_TYPE_GENERICINST;
8562 cached = mono_metadata_lookup_generic_class (gclass);
8565 mono_loader_unlock ();
8566 geninst->data.generic_class = cached;
8570 geninst->data.generic_class = gclass;
8572 gclass->context = g_new0 (MonoGenericContext, 1);
8573 gclass->context->container = gclass->container_class->generic_container;
8574 gclass->context->gclass = gclass;
8577 dgclass->parent = parent;
8578 dgclass->ifaces = g_new0 (MonoType *, icount);
8579 dgclass->count_ifaces = icount;
8581 for (i = 0; i < icount; i++) {
8582 MonoReflectionType *itype;
8585 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8587 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8588 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8589 if (!dgclass->ifaces [i])
8590 dgclass->ifaces [i] = itype->type;
8594 mono_loader_unlock ();
8600 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8602 MonoClass *klass, *pklass = NULL;
8603 MonoReflectionType *parent = NULL;
8604 MonoType *the_parent = NULL, *geninst;
8605 MonoReflectionTypeBuilder *tb = NULL;
8606 MonoGenericClass *gclass;
8609 domain = mono_object_domain (type);
8610 klass = mono_class_from_mono_type (type->type);
8612 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8613 tb = (MonoReflectionTypeBuilder *) type;
8616 parent = tb->parent;
8617 pklass = mono_class_from_mono_type (parent->type);
8619 } else if (klass->wastypebuilder) {
8620 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8622 parent = tb->parent;
8623 pklass = mono_class_from_mono_type (parent->type);
8626 pklass = klass->parent;
8628 parent = mono_type_get_object (domain, &pklass->byval_arg);
8629 else if (klass->generic_class && klass->generic_class->is_dynamic) {
8630 MonoDynamicGenericClass *dgclass;
8632 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8633 if (dgclass->parent) {
8634 parent = mono_type_get_object (domain, dgclass->parent);
8635 pklass = mono_class_from_mono_type (dgclass->parent);
8640 if (pklass && pklass->generic_class)
8641 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8643 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8647 gclass = geninst->data.generic_class;
8653 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8656 MonoGenericClass *gclass, *cached;
8657 MonoInflatedGenericClass *igclass;
8661 klass = mono_class_from_mono_type (type);
8662 if (!klass->generic_container && !klass->generic_class &&
8663 !(klass->nested_in && klass->nested_in->generic_container))
8666 mono_loader_lock ();
8668 icount = klass->interface_count;
8670 igclass = g_new0 (MonoInflatedGenericClass, 1);
8671 gclass = &igclass->generic_class;
8672 gclass->is_inflated = TRUE;
8674 gclass->inst = g_new0 (MonoGenericInst, 1);
8675 gclass->inst->type_argc = type_argc;
8676 gclass->inst->type_argv = types;
8677 gclass->inst->is_reference = 1;
8679 for (i = 0; i < gclass->inst->type_argc; ++i) {
8680 if (!gclass->inst->is_open)
8681 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8682 if (gclass->inst->is_reference)
8683 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8686 gclass->container_class = klass;
8688 if (klass->generic_class) {
8689 MonoGenericClass *kgclass = klass->generic_class;
8690 MonoGenericClass *ogclass = gclass;
8692 gclass->context = g_new0 (MonoGenericContext, 1);
8693 gclass->context->container = gclass->container_class->generic_container;
8694 gclass->context->gclass = gclass;
8696 igclass = g_new0 (MonoInflatedGenericClass, 1);
8697 gclass = &igclass->generic_class;
8698 gclass->is_inflated = TRUE;
8700 gclass->inst = g_new0 (MonoGenericInst, 1);
8701 gclass->inst->type_argc = kgclass->inst->type_argc;
8702 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8703 gclass->inst->is_reference = 1;
8705 for (i = 0; i < gclass->inst->type_argc; i++) {
8706 MonoType *t = kgclass->inst->type_argv [i];
8708 t = mono_class_inflate_generic_type (t, ogclass->context);
8710 if (!gclass->inst->is_open)
8711 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8712 if (gclass->inst->is_reference)
8713 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8715 gclass->inst->type_argv [i] = t;
8718 gclass->container_class = kgclass->container_class;
8721 geninst = g_new0 (MonoType, 1);
8722 geninst->type = MONO_TYPE_GENERICINST;
8724 cached = mono_metadata_lookup_generic_class (gclass);
8727 mono_loader_unlock ();
8728 geninst->data.generic_class = cached;
8732 geninst->data.generic_class = gclass;
8734 gclass->context = g_new0 (MonoGenericContext, 1);
8735 gclass->context->container = gclass->container_class->generic_container;
8736 gclass->context->gclass = gclass;
8738 mono_loader_unlock ();
8743 static inline MonoType*
8744 dup_type (const MonoType *original)
8746 MonoType *r = g_new0 (MonoType, 1);
8748 r->attrs = original->attrs;
8749 r->byref = original->byref;
8750 if (original->type == MONO_TYPE_PTR)
8751 r->data.type = dup_type (original->data.type);
8752 else if (original->type == MONO_TYPE_ARRAY)
8753 r->data.array = mono_dup_array_type (original->data.array);
8754 else if (original->type == MONO_TYPE_FNPTR)
8755 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8756 mono_stats.generics_metadata_size += sizeof (MonoType);
8760 MonoReflectionMethod*
8761 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8763 MonoMethod *method, *inflated;
8764 MonoReflectionMethodBuilder *mb = NULL;
8765 MonoGenericContainer *container;
8766 MonoGenericMethod *gmethod;
8767 MonoGenericContext *context;
8768 MonoGenericInst *ginst;
8771 MONO_ARCH_SAVE_REGS;
8772 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8773 MonoReflectionTypeBuilder *tb;
8776 mb = (MonoReflectionMethodBuilder *) rmethod;
8777 tb = (MonoReflectionTypeBuilder *) mb->type;
8778 klass = mono_class_from_mono_type (tb->type.type);
8780 method = methodbuilder_to_mono_method (klass, mb);
8782 method = rmethod->method;
8785 method = mono_get_inflated_method (method);
8787 count = mono_method_signature (method)->generic_param_count;
8788 if (count != mono_array_length (types))
8791 container = method->generic_container;
8792 g_assert (container);
8794 if (!container->method_hash)
8795 container->method_hash = g_hash_table_new (
8796 (GHashFunc) mono_metadata_generic_method_hash,
8797 (GCompareFunc) mono_metadata_generic_method_equal);
8799 ginst = g_new0 (MonoGenericInst,1 );
8800 ginst->type_argc = count;
8801 ginst->type_argv = g_new0 (MonoType *, count);
8802 ginst->is_reference = 1;
8803 for (i = 0; i < count; i++) {
8804 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8805 ginst->type_argv [i] = dup_type (garg->type);
8807 if (!ginst->is_open)
8808 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8809 if (ginst->is_reference)
8810 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8812 ginst = mono_metadata_lookup_generic_inst (ginst);
8814 gmethod = g_new0 (MonoGenericMethod, 1);
8815 gmethod->generic_class = method->klass->generic_class;
8816 gmethod->container = container;
8817 gmethod->inst = ginst;
8819 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8823 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8826 gmethod->reflection_info = rmethod;
8828 context = g_new0 (MonoGenericContext, 1);
8829 context->container = container;
8830 context->gclass = method->klass->generic_class;
8831 context->gmethod = gmethod;
8833 if (method->is_inflated)
8834 method = ((MonoMethodInflated *) method)->declaring;
8836 inflated = mono_class_inflate_generic_method (method, context);
8837 g_hash_table_insert (container->method_hash, gmethod, inflated);
8839 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8843 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8845 MonoGenericMethod *gmethod;
8846 MonoInflatedGenericClass *gclass;
8847 MonoGenericContext *context;
8850 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8852 gmethod = g_new0 (MonoGenericMethod, 1);
8853 gmethod->generic_class = &gclass->generic_class;
8854 gmethod->inst = g_new0 (MonoGenericInst, 1);
8855 gmethod->reflection_info = obj;
8857 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8858 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8860 for (i = 0; i < gmethod->inst->type_argc; i++) {
8861 MonoGenericParam *gparam = &method->generic_container->type_params [i];
8863 g_assert (gparam->pklass);
8864 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8867 context = g_new0 (MonoGenericContext, 1);
8868 context->container = gclass->generic_class.container_class->generic_container;
8869 context->gclass = &gclass->generic_class;
8870 context->gmethod = gmethod;
8872 return mono_class_inflate_generic_method (method, context);
8876 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8881 klass = mono_class_from_mono_type (type->type.type);
8883 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8884 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8885 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8886 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8887 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8888 method = ((MonoReflectionMethod *) obj)->method;
8890 method = NULL; /* prevent compiler warning */
8891 g_assert_not_reached ();
8894 return inflate_mono_method (type, method, obj);
8898 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8899 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8902 MonoGenericClass *gclass;
8903 MonoDynamicGenericClass *dgclass;
8904 MonoClass *klass, *gklass, *pklass;
8907 MONO_ARCH_SAVE_REGS;
8909 klass = mono_class_from_mono_type (type->type.type);
8910 gclass = type->type.type->data.generic_class;
8912 g_assert (gclass->is_dynamic);
8913 dgclass = (MonoDynamicGenericClass *) gclass;
8915 if (dgclass->initialized)
8918 gklass = gclass->container_class;
8919 mono_class_init (gklass);
8921 if (dgclass->parent)
8922 pklass = mono_class_from_mono_type (dgclass->parent);
8924 pklass = gklass->parent;
8926 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8927 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8928 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8929 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8930 dgclass->count_events = events ? mono_array_length (events) : 0;
8932 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8933 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8934 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8935 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8936 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8938 for (i = 0; i < dgclass->count_methods; i++) {
8939 MonoObject *obj = mono_array_get (methods, gpointer, i);
8941 dgclass->methods [i] = inflate_method (type, obj);
8944 for (i = 0; i < dgclass->count_ctors; i++) {
8945 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8947 dgclass->ctors [i] = inflate_method (type, obj);
8950 for (i = 0; i < dgclass->count_fields; i++) {
8951 MonoObject *obj = mono_array_get (fields, gpointer, i);
8952 MonoClassField *field;
8953 MonoInflatedField *ifield;
8955 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8956 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8957 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8958 field = ((MonoReflectionField *) obj)->field;
8960 field = NULL; /* prevent compiler warning */
8961 g_assert_not_reached ();
8964 ifield = g_new0 (MonoInflatedField, 1);
8965 ifield->generic_type = field->type;
8966 ifield->reflection_info = obj;
8968 dgclass->fields [i] = *field;
8969 dgclass->fields [i].parent = klass;
8970 dgclass->fields [i].generic_info = ifield;
8971 dgclass->fields [i].type = mono_class_inflate_generic_type (
8972 field->type, dgclass->generic_class.generic_class.context);
8975 for (i = 0; i < dgclass->count_properties; i++) {
8976 MonoObject *obj = mono_array_get (properties, gpointer, i);
8977 MonoProperty *property = &dgclass->properties [i];
8979 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8980 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8982 property->parent = klass;
8983 property->attrs = pb->attrs;
8984 property->name = mono_string_to_utf8 (pb->name);
8986 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8988 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8989 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8990 *property = *((MonoReflectionProperty *) obj)->property;
8993 property->get = inflate_mono_method (type, property->get, NULL);
8995 property->set = inflate_mono_method (type, property->set, NULL);
8997 g_assert_not_reached ();
9000 for (i = 0; i < dgclass->count_events; i++) {
9001 MonoObject *obj = mono_array_get (events, gpointer, i);
9002 MonoEvent *event = &dgclass->events [i];
9004 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9005 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9007 event->parent = klass;
9008 event->attrs = eb->attrs;
9009 event->name = mono_string_to_utf8 (eb->name);
9011 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9012 if (eb->remove_method)
9013 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9014 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9015 *event = *((MonoReflectionEvent *) obj)->event;
9018 event->add = inflate_mono_method (type, event->add, NULL);
9020 event->remove = inflate_mono_method (type, event->remove, NULL);
9022 g_assert_not_reached ();
9025 dgclass->initialized = TRUE;
9029 ensure_runtime_vtable (MonoClass *klass)
9031 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9032 int i, num, j, onum;
9033 MonoMethod **overrides;
9035 if (!tb || klass->wastypebuilder)
9038 ensure_runtime_vtable (klass->parent);
9040 num = tb->ctors? mono_array_length (tb->ctors): 0;
9041 num += tb->num_methods;
9042 klass->method.count = num;
9043 klass->methods = g_new (MonoMethod*, num);
9044 num = tb->ctors? mono_array_length (tb->ctors): 0;
9045 for (i = 0; i < num; ++i)
9046 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9047 num = tb->num_methods;
9049 for (i = 0; i < num; ++i)
9050 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9052 if (tb->interfaces) {
9053 klass->interface_count = mono_array_length (tb->interfaces);
9054 klass->interfaces = g_new (MonoClass*, klass->interface_count);
9055 for (i = 0; i < klass->interface_count; ++i) {
9056 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9057 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9061 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9062 for (i = 0; i < klass->method.count; ++i)
9063 klass->methods [i]->slot = i;
9065 if (!((MonoDynamicImage*)klass->image)->run)
9066 /* No need to create a generic vtable */
9072 for (i = 0; i < tb->num_methods; ++i) {
9073 MonoReflectionMethodBuilder *mb =
9074 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9075 if (mb->override_method)
9080 overrides = g_new0 (MonoMethod*, onum * 2);
9084 for (i = 0; i < tb->num_methods; ++i) {
9085 MonoReflectionMethodBuilder *mb =
9086 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9087 if (mb->override_method) {
9088 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9089 overrides [onum * 2] =
9090 mb->override_method->method;
9091 overrides [onum * 2 + 1] =
9094 g_assert (mb->mhandle);
9101 mono_class_setup_vtable_general (klass, overrides, onum);
9106 typebuilder_setup_fields (MonoClass *klass)
9108 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9109 MonoReflectionFieldBuilder *fb;
9110 MonoClassField *field;
9115 klass->field.count = tb->num_fields;
9116 klass->field.first = 0;
9118 if (!klass->field.count)
9121 klass->fields = g_new0 (MonoClassField, klass->field.count);
9123 for (i = 0; i < klass->field.count; ++i) {
9124 fb = mono_array_get (tb->fields, gpointer, i);
9125 field = &klass->fields [i];
9126 field->name = mono_string_to_utf8 (fb->name);
9128 /* FIXME: handle type modifiers */
9129 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9130 field->type->attrs = fb->attrs;
9132 field->type = fb->type->type;
9134 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9135 field->data = mono_array_addr (fb->rva_data, char, 0);
9136 if (fb->offset != -1)
9137 field->offset = fb->offset;
9138 field->parent = klass;
9140 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9142 if (fb->def_value) {
9143 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9144 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9145 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9146 /* Copy the data from the blob since it might get realloc-ed */
9147 p = assembly->blob.data + idx;
9148 len = mono_metadata_decode_blob_size (p, &p2);
9150 field->data = g_malloc (len);
9151 memcpy ((gpointer)field->data, p, len);
9154 mono_class_layout_fields (klass);
9158 typebuilder_setup_properties (MonoClass *klass)
9160 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9161 MonoReflectionPropertyBuilder *pb;
9164 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9165 klass->property.first = 0;
9167 klass->properties = g_new0 (MonoProperty, klass->property.count);
9168 for (i = 0; i < klass->property.count; ++i) {
9169 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9170 klass->properties [i].parent = klass;
9171 klass->properties [i].attrs = pb->attrs;
9172 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9174 klass->properties [i].get = pb->get_method->mhandle;
9176 klass->properties [i].set = pb->set_method->mhandle;
9180 MonoReflectionEvent *
9181 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9183 MonoEvent *event = g_new0 (MonoEvent, 1);
9187 klass = my_mono_class_from_mono_type (tb->type.type);
9189 event->parent = klass;
9190 event->attrs = eb->attrs;
9191 event->name = mono_string_to_utf8 (eb->name);
9193 event->add = eb->add_method->mhandle;
9194 if (eb->remove_method)
9195 event->remove = eb->remove_method->mhandle;
9196 if (eb->raise_method)
9197 event->raise = eb->raise_method->mhandle;
9199 if (eb->other_methods) {
9200 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9201 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9202 MonoReflectionMethodBuilder *mb =
9203 mono_array_get (eb->other_methods,
9204 MonoReflectionMethodBuilder*, j);
9205 event->other [j] = mb->mhandle;
9209 return mono_event_get_object (mono_object_domain (tb), klass, event);
9213 typebuilder_setup_events (MonoClass *klass)
9215 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9216 MonoReflectionEventBuilder *eb;
9219 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9220 klass->event.first = 0;
9222 klass->events = g_new0 (MonoEvent, klass->event.count);
9223 for (i = 0; i < klass->event.count; ++i) {
9224 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9225 klass->events [i].parent = klass;
9226 klass->events [i].attrs = eb->attrs;
9227 klass->events [i].name = mono_string_to_utf8 (eb->name);
9229 klass->events [i].add = eb->add_method->mhandle;
9230 if (eb->remove_method)
9231 klass->events [i].remove = eb->remove_method->mhandle;
9232 if (eb->raise_method)
9233 klass->events [i].raise = eb->raise_method->mhandle;
9235 if (eb->other_methods) {
9236 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9237 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9238 MonoReflectionMethodBuilder *mb =
9239 mono_array_get (eb->other_methods,
9240 MonoReflectionMethodBuilder*, j);
9241 klass->events [i].other [j] = mb->mhandle;
9248 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9252 MonoReflectionType* res;
9255 MONO_ARCH_SAVE_REGS;
9257 domain = mono_object_domain (tb);
9258 klass = my_mono_class_from_mono_type (tb->type.type);
9260 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9263 * we need to lock the domain because the lock will be taken inside
9264 * So, we need to keep the locking order correct.
9266 mono_domain_lock (domain);
9267 mono_loader_lock ();
9268 if (klass->wastypebuilder) {
9269 mono_loader_unlock ();
9270 mono_domain_unlock (domain);
9271 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9274 * Fields to set in klass:
9275 * the various flags: delegate/unicode/contextbound etc.
9277 klass->flags = tb->attrs;
9278 klass->has_cctor = 1;
9279 klass->has_finalize = 1;
9282 if (!((MonoDynamicImage*)klass->image)->run) {
9283 if (klass->generic_container) {
9284 /* FIXME: The code below can't handle generic classes */
9285 klass->wastypebuilder = TRUE;
9286 mono_loader_unlock ();
9287 mono_domain_unlock (domain);
9288 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9293 /* enums are done right away */
9294 if (!klass->enumtype)
9295 ensure_runtime_vtable (klass);
9298 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9299 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9300 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9304 /* fields and object layout */
9305 if (klass->parent) {
9306 if (!klass->parent->size_inited)
9307 mono_class_init (klass->parent);
9308 klass->instance_size += klass->parent->instance_size;
9309 klass->class_size += klass->parent->class_size;
9310 klass->min_align = klass->parent->min_align;
9311 /* if the type has no fields we won't call the field_setup
9312 * routine which sets up klass->has_references.
9314 klass->has_references |= klass->parent->has_references;
9316 klass->instance_size = sizeof (MonoObject);
9317 klass->min_align = 1;
9320 /* FIXME: handle packing_size and instance_size */
9321 typebuilder_setup_fields (klass);
9323 typebuilder_setup_properties (klass);
9325 typebuilder_setup_events (klass);
9327 klass->wastypebuilder = TRUE;
9328 mono_loader_unlock ();
9329 mono_domain_unlock (domain);
9331 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9332 g_assert (res != (MonoReflectionType*)tb);
9337 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9339 MonoGenericParam *param;
9342 MONO_ARCH_SAVE_REGS;
9344 param = g_new0 (MonoGenericParam, 1);
9346 if (gparam->mbuilder) {
9347 if (!gparam->mbuilder->generic_container)
9348 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9349 param->owner = gparam->mbuilder->generic_container;
9350 } else if (gparam->tbuilder) {
9351 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9352 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9357 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9358 if (gparam->index >= count)
9361 container = nesting->generic_container;
9362 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9365 g_assert (container);
9366 param->owner = container;
9369 param->method = NULL;
9370 param->name = mono_string_to_utf8 (gparam->name);
9371 param->num = gparam->index;
9373 image = &gparam->tbuilder->module->dynamic_image->image;
9374 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9376 param->pklass->reflection_info = gparam;
9378 gparam->type.type = g_new0 (MonoType, 1);
9379 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9380 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9381 gparam->type.type->data.generic_param = param;
9385 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9387 MonoDynamicImage *assembly = sig->module->dynamic_image;
9388 guint32 na = mono_array_length (sig->arguments);
9389 guint32 buflen, i, size;
9393 MONO_ARCH_SAVE_REGS;
9395 p = buf = g_malloc (size = 50 + na * 50);
9397 mono_metadata_encode_value (0x07, p, &p);
9398 mono_metadata_encode_value (na, p, &p);
9399 for (i = 0; i < na; ++i) {
9400 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9401 encode_reflection_type (assembly, type, p, &p);
9405 g_assert (buflen < size);
9406 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9407 p = mono_array_addr (result, char, 0);
9408 memcpy (p, buf, buflen);
9415 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9417 MonoDynamicImage *assembly = sig->module->dynamic_image;
9418 guint32 na = mono_array_length (sig->arguments);
9419 guint32 buflen, i, size;
9423 MONO_ARCH_SAVE_REGS;
9425 p = buf = g_malloc (size = 10 + na * 10);
9427 mono_metadata_encode_value (0x06, p, &p);
9428 for (i = 0; i < na; ++i) {
9429 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9430 encode_reflection_type (assembly, type, p, &p);
9434 g_assert (buflen < size);
9435 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9436 p = mono_array_addr (result, char, 0);
9437 memcpy (p, buf, buflen);
9444 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9446 ReflectionMethodBuilder rmb;
9447 MonoMethodSignature *sig;
9450 sig = dynamic_method_to_signature (mb);
9452 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9455 * Resolve references.
9458 * Every second entry in the refs array is reserved for storing handle_class,
9459 * which is needed by the ldtoken implementation in the JIT.
9461 rmb.nrefs = mb->nrefs;
9462 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9463 for (i = 0; i < mb->nrefs; i += 2) {
9464 MonoClass *handle_class;
9465 gpointer ref = resolve_object (mb->module->image,
9466 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9469 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9473 rmb.refs [i + 1] = handle_class;
9477 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9481 /* ilgen is no longer needed */
9486 * mono_reflection_lookup_dynamic_token:
9488 * Finish the Builder object pointed to by TOKEN and return the corresponding
9489 * runtime structure. HANDLE_CLASS is set to the class required by
9493 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9495 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9498 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9501 return resolve_object (image, obj, handle_class);
9505 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9507 gpointer result = NULL;
9509 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9510 result = mono_string_intern ((MonoString*)obj);
9511 *handle_class = NULL;
9513 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9514 MonoReflectionType *tb = (MonoReflectionType*)obj;
9515 result = mono_class_from_mono_type (tb->type);
9516 *handle_class = mono_defaults.typehandle_class;
9518 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9519 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9520 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9521 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9522 result = ((MonoReflectionMethod*)obj)->method;
9523 *handle_class = mono_defaults.methodhandle_class;
9525 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9526 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9527 result = mb->mhandle;
9529 /* Type is not yet created */
9530 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9532 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9535 * Hopefully this has been filled in by calling CreateType() on the
9539 * TODO: This won't work if the application finishes another
9540 * TypeBuilder instance instead of this one.
9542 result = mb->mhandle;
9544 *handle_class = mono_defaults.methodhandle_class;
9545 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9546 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9548 result = cb->mhandle;
9550 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9552 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9553 result = cb->mhandle;
9555 *handle_class = mono_defaults.methodhandle_class;
9556 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9557 result = ((MonoReflectionField*)obj)->field;
9558 *handle_class = mono_defaults.fieldhandle_class;
9560 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9561 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9562 result = fb->handle;
9565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9567 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9568 result = fb->handle;
9570 *handle_class = mono_defaults.fieldhandle_class;
9571 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9572 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9575 klass = tb->type.type->data.klass;
9576 if (klass->wastypebuilder) {
9577 /* Already created */
9581 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9582 result = tb->type.type->data.klass;
9585 *handle_class = mono_defaults.typehandle_class;
9586 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9587 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9588 MonoMethodSignature *sig;
9591 if (helper->arguments)
9592 nargs = mono_array_length (helper->arguments);
9596 sig = mono_metadata_signature_alloc (image, nargs);
9597 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9598 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9600 if (helper->call_conv == 0) /* unmanaged */
9601 sig->call_convention = helper->unmanaged_call_conv - 1;
9603 if (helper->call_conv & 0x02)
9604 sig->call_convention = MONO_CALL_VARARG;
9606 sig->call_convention = MONO_CALL_DEFAULT;
9608 sig->param_count = nargs;
9609 /* TODO: Copy type ? */
9610 sig->ret = helper->return_type->type;
9611 for (i = 0; i < nargs; ++i) {
9612 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9613 sig->params [i] = rt->type;
9617 *handle_class = NULL;
9619 g_print (obj->vtable->klass->name);
9620 g_assert_not_reached ();
9626 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9627 const static guint32 declsec_flags_map[] = {
9628 0x00000000, /* empty */
9629 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9630 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9631 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9632 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9633 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9634 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9635 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9636 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9637 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9638 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9639 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9640 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9641 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9642 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9643 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9644 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9645 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9646 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9650 * Returns flags that includes all available security action associated to the handle.
9651 * @token: metadata token (either for a class or a method)
9652 * @image: image where resides the metadata.
9655 mono_declsec_get_flags (MonoImage *image, guint32 token)
9657 guint32 index = mono_metadata_declsec_from_index (image, token);
9658 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9663 for (i = index; i < t->rows; i++) {
9664 guint32 cols [MONO_DECL_SECURITY_SIZE];
9666 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9667 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9670 action = cols [MONO_DECL_SECURITY_ACTION];
9671 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9672 result |= declsec_flags_map [action];
9674 g_assert_not_reached ();
9681 * Get the security actions (in the form of flags) associated with the specified method.
9683 * @method: The method for which we want the declarative security flags.
9684 * Return the declarative security flags for the method (only).
9686 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9687 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9690 mono_declsec_flags_from_method (MonoMethod *method)
9692 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9693 /* FIXME: No cache (for the moment) */
9694 guint32 idx = mono_method_get_index (method);
9695 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9696 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9697 return mono_declsec_get_flags (method->klass->image, idx);
9703 * Get the security actions (in the form of flags) associated with the specified class.
9705 * @klass: The class for which we want the declarative security flags.
9706 * Return the declarative security flags for the class.
9708 * Note: We cache the flags inside the MonoClass structure as this will get
9709 * called very often (at least for each method).
9712 mono_declsec_flags_from_class (MonoClass *klass)
9714 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9715 if (!klass->declsec_flags) {
9716 guint32 idx = mono_metadata_token_index (klass->type_token);
9717 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9718 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9719 /* we cache the flags on classes */
9720 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9722 return klass->declsec_flags;
9728 * Get the security actions (in the form of flags) associated with the specified assembly.
9730 * @assembly: The assembly for which we want the declarative security flags.
9731 * Return the declarative security flags for the assembly.
9734 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9736 guint32 idx = 1; /* there is only one assembly */
9737 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9738 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9739 return mono_declsec_get_flags (assembly->image, idx);
9744 * Fill actions for the specific index (which may either be an encoded class token or
9745 * an encoded method token) from the metadata image.
9746 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9749 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9750 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9752 MonoBoolean result = FALSE;
9754 guint32 cols [MONO_DECL_SECURITY_SIZE];
9755 int index = mono_metadata_declsec_from_index (image, token);
9758 t = &image->tables [MONO_TABLE_DECLSECURITY];
9759 for (i = index; i < t->rows; i++) {
9760 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9762 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9765 /* if present only replace (class) permissions with method permissions */
9766 /* if empty accept either class or method permissions */
9767 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9768 if (!actions->demand.blob) {
9769 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9770 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9771 actions->demand.blob = (char*) (blob + 2);
9772 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9775 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9776 if (!actions->noncasdemand.blob) {
9777 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9778 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9779 actions->noncasdemand.blob = (char*) (blob + 2);
9780 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9783 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9784 if (!actions->demandchoice.blob) {
9785 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9786 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9787 actions->demandchoice.blob = (char*) (blob + 2);
9788 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9798 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9799 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9801 guint32 idx = mono_metadata_token_index (klass->type_token);
9802 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9803 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9804 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9808 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9809 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9811 guint32 idx = mono_method_get_index (method);
9812 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9813 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9814 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9818 * Collect all actions (that requires to generate code in mini) assigned for
9819 * the specified method.
9820 * Note: Don't use the content of actions if the function return FALSE.
9823 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9825 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9826 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9827 MonoBoolean result = FALSE;
9830 /* quick exit if no declarative security is present in the metadata */
9831 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9834 /* we want the original as the wrapper is "free" of the security informations */
9835 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9836 method = mono_marshal_method_from_wrapper (method);
9841 /* First we look for method-level attributes */
9842 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9843 mono_class_init (method->klass);
9844 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9846 result = mono_declsec_get_method_demands_params (method, demands,
9847 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9850 /* Here we use (or create) the class declarative cache to look for demands */
9851 flags = mono_declsec_flags_from_class (method->klass);
9854 mono_class_init (method->klass);
9855 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9857 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9858 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9861 /* The boolean return value is used as a shortcut in case nothing needs to
9862 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9868 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9870 * Note: Don't use the content of actions if the function return FALSE.
9873 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9875 MonoBoolean result = FALSE;
9878 /* quick exit if no declarative security is present in the metadata */
9879 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9882 /* we want the original as the wrapper is "free" of the security informations */
9883 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9884 method = mono_marshal_method_from_wrapper (method);
9889 /* results are independant - zeroize both */
9890 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9891 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9893 /* First we look for method-level attributes */
9894 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9895 mono_class_init (method->klass);
9897 result = mono_declsec_get_method_demands_params (method, cmethod,
9898 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9901 /* Here we use (or create) the class declarative cache to look for demands */
9902 flags = mono_declsec_flags_from_class (method->klass);
9903 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9904 mono_class_init (method->klass);
9906 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9907 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9914 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9916 * @klass The inherited class - this is the class that provides the security check (attributes)
9918 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9920 * Note: Don't use the content of actions if the function return FALSE.
9923 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9925 MonoBoolean result = FALSE;
9928 /* quick exit if no declarative security is present in the metadata */
9929 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9932 /* Here we use (or create) the class declarative cache to look for demands */
9933 flags = mono_declsec_flags_from_class (klass);
9934 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9935 mono_class_init (klass);
9936 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9938 result |= mono_declsec_get_class_demands_params (klass, demands,
9939 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9946 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9948 * Note: Don't use the content of actions if the function return FALSE.
9951 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9953 /* quick exit if no declarative security is present in the metadata */
9954 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9957 /* we want the original as the wrapper is "free" of the security informations */
9958 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9959 method = mono_marshal_method_from_wrapper (method);
9964 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9965 mono_class_init (method->klass);
9966 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9968 return mono_declsec_get_method_demands_params (method, demands,
9969 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9976 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9978 guint32 cols [MONO_DECL_SECURITY_SIZE];
9982 int index = mono_metadata_declsec_from_index (image, token);
9986 t = &image->tables [MONO_TABLE_DECLSECURITY];
9987 for (i = index; i < t->rows; i++) {
9988 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9990 /* shortcut - index are ordered */
9991 if (token != cols [MONO_DECL_SECURITY_PARENT])
9994 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9995 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9996 entry->blob = (char*) (metadata + 2);
9997 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10006 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10008 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10009 guint32 idx = mono_method_get_index (method);
10010 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10011 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10012 return get_declsec_action (method->klass->image, idx, action, entry);
10018 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10021 guint32 flags = mono_declsec_flags_from_class (klass);
10022 if (declsec_flags_map [action] & flags) {
10023 guint32 idx = mono_metadata_token_index (klass->type_token);
10024 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10025 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10026 return get_declsec_action (klass->image, idx, action, entry);
10032 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10034 guint32 idx = 1; /* there is only one assembly */
10035 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10036 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10038 return get_declsec_action (assembly->image, idx, action, entry);
10042 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10044 MonoObject *res, *exc;
10046 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10047 static MonoMethod *method = NULL;
10049 if (!System_Reflection_Emit_TypeBuilder) {
10050 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10051 g_assert (System_Reflection_Emit_TypeBuilder);
10053 if (method == NULL) {
10054 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10059 * The result of mono_type_get_object () might be a System.MonoType but we
10060 * need a TypeBuilder so use klass->reflection_info.
10062 g_assert (klass->reflection_info);
10063 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10065 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10067 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10071 return *(MonoBoolean*)mono_object_unbox (res);