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 p = buf = g_malloc (64);
1542 *ret_type = MONO_TYPE_CLASS;
1544 box_val = (char*)&dummy;
1546 box_val = ((char*)val) + sizeof (MonoObject);
1547 *ret_type = val->vtable->klass->byval_arg.type;
1550 switch (*ret_type) {
1551 case MONO_TYPE_BOOLEAN:
1556 case MONO_TYPE_CHAR:
1571 case MONO_TYPE_VALUETYPE:
1572 if (val->vtable->klass->enumtype) {
1573 *ret_type = val->vtable->klass->enum_basetype->type;
1576 g_error ("we can't encode valuetypes");
1577 case MONO_TYPE_CLASS:
1579 case MONO_TYPE_STRING: {
1580 MonoString *str = (MonoString*)val;
1581 /* there is no signature */
1582 len = str->length * 2;
1583 mono_metadata_encode_value (len, b, &b);
1584 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1586 char *swapped = g_malloc (2 * mono_string_length (str));
1587 const char *p = (const char*)mono_string_chars (str);
1589 swap_with_size (swapped, p, 2, mono_string_length (str));
1590 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1594 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1601 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1604 /* there is no signature */
1605 mono_metadata_encode_value (len, b, &b);
1606 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1607 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1608 swap_with_size (blob_size, box_val, len, 1);
1609 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1611 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1619 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1620 char blob_size [64];
1621 char *b = blob_size;
1622 char *p, *buf, *str;
1623 guint32 idx, len, bufsize = 256;
1625 p = buf = g_malloc (bufsize);
1627 mono_metadata_encode_value (minfo->type, p, &p);
1629 switch (minfo->type) {
1630 case MONO_NATIVE_BYVALTSTR:
1631 case MONO_NATIVE_BYVALARRAY:
1632 mono_metadata_encode_value (minfo->count, p, &p);
1634 case MONO_NATIVE_LPARRAY:
1635 if (minfo->eltype || minfo->has_size) {
1636 mono_metadata_encode_value (minfo->eltype, p, &p);
1637 if (minfo->has_size) {
1638 if (minfo->param_num != -1)
1639 mono_metadata_encode_value (minfo->param_num, p, &p);
1641 mono_metadata_encode_value (0, p, &p);
1642 if (minfo->count != -1)
1643 mono_metadata_encode_value (minfo->count, p, &p);
1645 mono_metadata_encode_value (0, p, &p);
1647 /* LAMESPEC: ElemMult is undocumented */
1648 if (minfo->param_num != -1)
1649 mono_metadata_encode_value (1, p, &p);
1651 mono_metadata_encode_value (0, p, &p);
1655 case MONO_NATIVE_CUSTOM:
1657 str = mono_string_to_utf8 (minfo->guid);
1659 mono_metadata_encode_value (len, p, &p);
1660 memcpy (p, str, len);
1664 mono_metadata_encode_value (0, p, &p);
1666 /* native type name */
1667 mono_metadata_encode_value (0, p, &p);
1668 /* custom marshaler type name */
1669 if (minfo->marshaltype || minfo->marshaltyperef) {
1670 if (minfo->marshaltyperef)
1671 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1673 str = mono_string_to_utf8 (minfo->marshaltype);
1675 mono_metadata_encode_value (len, p, &p);
1676 if (p + len >= buf + bufsize) {
1679 buf = g_realloc (buf, bufsize);
1682 memcpy (p, str, len);
1686 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1687 mono_metadata_encode_value (0, p, &p);
1689 if (minfo->mcookie) {
1690 str = mono_string_to_utf8 (minfo->mcookie);
1692 mono_metadata_encode_value (len, p, &p);
1693 if (p + len >= buf + bufsize) {
1696 buf = g_realloc (buf, bufsize);
1699 memcpy (p, str, len);
1703 mono_metadata_encode_value (0, p, &p);
1710 mono_metadata_encode_value (len, b, &b);
1711 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1717 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1719 MonoDynamicTable *table;
1723 /* maybe this fixup should be done in the C# code */
1724 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1725 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1726 table = &assembly->tables [MONO_TABLE_FIELD];
1727 fb->table_idx = table->next_idx ++;
1728 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1729 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1730 name = mono_string_to_utf8 (fb->name);
1731 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1733 values [MONO_FIELD_FLAGS] = fb->attrs;
1734 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1736 if (fb->offset != -1) {
1737 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1739 alloc_table (table, table->rows);
1740 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1741 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1742 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1744 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1745 guint32 field_type = 0;
1746 table = &assembly->tables [MONO_TABLE_CONSTANT];
1748 alloc_table (table, table->rows);
1749 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1750 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1751 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1752 values [MONO_CONSTANT_TYPE] = field_type;
1753 values [MONO_CONSTANT_PADDING] = 0;
1755 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1757 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1759 alloc_table (table, table->rows);
1760 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1761 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1763 * We store it in the code section because it's simpler for now.
1766 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1768 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1769 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1771 if (fb->marshal_info) {
1772 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1774 alloc_table (table, table->rows);
1775 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1776 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1777 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1782 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1786 char *b = blob_size;
1787 guint32 nparams = 0;
1788 MonoReflectionMethodBuilder *mb = fb->get_method;
1789 MonoReflectionMethodBuilder *smb = fb->set_method;
1790 guint32 idx, i, size;
1792 if (mb && mb->parameters)
1793 nparams = mono_array_length (mb->parameters);
1794 if (!mb && smb && smb->parameters)
1795 nparams = mono_array_length (smb->parameters) - 1;
1796 size = 24 + nparams * 10;
1797 buf = p = g_malloc (size);
1800 mono_metadata_encode_value (nparams, p, &p);
1802 encode_reflection_type (assembly, mb->rtype, p, &p);
1803 for (i = 0; i < nparams; ++i) {
1804 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1805 encode_reflection_type (assembly, pt, p, &p);
1808 /* the property type is the last param */
1809 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1810 for (i = 0; i < nparams; ++i) {
1811 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1812 encode_reflection_type (assembly, pt, p, &p);
1816 encode_reflection_type (assembly, fb->type, p, &p);
1820 g_assert (p - buf < size);
1821 mono_metadata_encode_value (p-buf, b, &b);
1822 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1828 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1830 MonoDynamicTable *table;
1833 guint num_methods = 0;
1837 * we need to set things in the following tables:
1838 * PROPERTYMAP (info already filled in _get_type_info ())
1839 * PROPERTY (rows already preallocated in _get_type_info ())
1840 * METHOD (method info already done with the generic method code)
1843 table = &assembly->tables [MONO_TABLE_PROPERTY];
1844 pb->table_idx = table->next_idx ++;
1845 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1846 name = mono_string_to_utf8 (pb->name);
1847 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1849 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1850 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1852 /* FIXME: we still don't handle 'other' methods */
1853 if (pb->get_method) num_methods ++;
1854 if (pb->set_method) num_methods ++;
1856 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1857 table->rows += num_methods;
1858 alloc_table (table, table->rows);
1860 if (pb->get_method) {
1861 semaidx = table->next_idx ++;
1862 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1863 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1864 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1865 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1867 if (pb->set_method) {
1868 semaidx = table->next_idx ++;
1869 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1870 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1871 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1872 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1877 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1879 MonoDynamicTable *table;
1882 guint num_methods = 0;
1886 * we need to set things in the following tables:
1887 * EVENTMAP (info already filled in _get_type_info ())
1888 * EVENT (rows already preallocated in _get_type_info ())
1889 * METHOD (method info already done with the generic method code)
1892 table = &assembly->tables [MONO_TABLE_EVENT];
1893 eb->table_idx = table->next_idx ++;
1894 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1895 name = mono_string_to_utf8 (eb->name);
1896 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1898 values [MONO_EVENT_FLAGS] = eb->attrs;
1899 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1902 * FIXME: we still don't handle 'other' methods
1904 if (eb->add_method) num_methods ++;
1905 if (eb->remove_method) num_methods ++;
1906 if (eb->raise_method) num_methods ++;
1908 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1909 table->rows += num_methods;
1910 alloc_table (table, table->rows);
1912 if (eb->add_method) {
1913 semaidx = table->next_idx ++;
1914 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1915 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1916 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1917 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1919 if (eb->remove_method) {
1920 semaidx = table->next_idx ++;
1921 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1922 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1923 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1924 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1926 if (eb->raise_method) {
1927 semaidx = table->next_idx ++;
1928 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1929 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1930 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1931 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1936 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1938 static MonoClass *NewConstraintAttr;
1939 static MonoMethod *NewConstraintAttr_ctor;
1940 MonoDynamicTable *table;
1942 guint32 token, type;
1943 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1946 if (!NewConstraintAttr)
1947 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1948 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1949 g_assert (NewConstraintAttr);
1951 if (!NewConstraintAttr_ctor) {
1952 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1953 g_assert (NewConstraintAttr_ctor);
1956 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1958 alloc_table (table, table->rows);
1960 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1961 owner <<= MONO_CUSTOM_ATTR_BITS;
1962 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1963 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1965 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1967 type = mono_metadata_token_index (token);
1968 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1969 switch (mono_metadata_token_table (token)) {
1970 case MONO_TABLE_METHOD:
1971 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1973 case MONO_TABLE_MEMBERREF:
1974 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1977 g_warning ("got wrong token in custom attr");
1980 values [MONO_CUSTOM_ATTR_TYPE] = type;
1982 buf = p = g_malloc (1);
1983 mono_metadata_encode_value (4, p, &p);
1984 g_assert (p-buf == 1);
1986 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1988 values += MONO_CUSTOM_ATTR_SIZE;
1993 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1995 MonoDynamicTable *table;
1996 guint32 num_constraints, i;
2000 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2001 num_constraints = gparam->iface_constraints ?
2002 mono_array_length (gparam->iface_constraints) : 0;
2003 table->rows += num_constraints;
2004 if (gparam->base_type)
2006 alloc_table (table, table->rows);
2008 if (gparam->base_type) {
2009 table_idx = table->next_idx ++;
2010 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2012 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2013 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2014 assembly, gparam->base_type->type);
2017 for (i = 0; i < num_constraints; i++) {
2018 MonoReflectionType *constraint = mono_array_get (
2019 gparam->iface_constraints, gpointer, i);
2021 table_idx = table->next_idx ++;
2022 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2024 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2025 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2026 assembly, constraint->type);
2029 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2030 encode_new_constraint (assembly, owner);
2034 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2036 GenericParamTableEntry *entry;
2039 * The GenericParam table must be sorted according to the `owner' field.
2040 * We need to do this sorting prior to writing the GenericParamConstraint
2041 * table, since we have to use the final GenericParam table indices there
2042 * and they must also be sorted.
2045 entry = g_new0 (GenericParamTableEntry, 1);
2046 entry->owner = owner;
2047 entry->gparam = gparam;
2049 g_ptr_array_add (assembly->gen_params, entry);
2053 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2055 MonoDynamicTable *table;
2056 MonoGenericParam *param;
2060 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2061 table_idx = table->next_idx ++;
2062 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2064 param = entry->gparam->type.type->data.generic_param;
2066 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2067 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2068 values [MONO_GENERICPARAM_NUMBER] = param->num;
2069 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2071 encode_constraints (entry->gparam, table_idx, assembly);
2075 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2077 MonoDynamicTable *table;
2080 guint32 cols [MONO_ASSEMBLY_SIZE];
2084 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2087 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2088 table = &assembly->tables [MONO_TABLE_MODULEREF];
2089 token = table->next_idx ++;
2091 alloc_table (table, table->rows);
2092 values = table->values + token * MONO_MODULEREF_SIZE;
2093 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2095 token <<= MONO_RESOLTION_SCOPE_BITS;
2096 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2097 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2102 if (image->assembly->dynamic)
2104 memset (cols, 0, sizeof (cols));
2106 /* image->assembly->image is the manifest module */
2107 image = image->assembly->image;
2108 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2111 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2112 token = table->next_idx ++;
2114 alloc_table (table, table->rows);
2115 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2116 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2117 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2118 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2119 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2120 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2121 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2122 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2123 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2125 if (strcmp ("", image->assembly->aname.culture)) {
2126 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2127 image->assembly->aname.culture);
2130 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2131 guchar pubtoken [9];
2133 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2134 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2136 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2138 token <<= MONO_RESOLTION_SCOPE_BITS;
2139 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2140 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2145 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2147 MonoDynamicTable *table;
2153 char *b = blob_size;
2155 switch (type->type) {
2156 case MONO_TYPE_FNPTR:
2158 case MONO_TYPE_SZARRAY:
2159 case MONO_TYPE_ARRAY:
2161 case MONO_TYPE_MVAR:
2162 case MONO_TYPE_GENERICINST:
2163 encode_type (assembly, type, p, &p);
2165 case MONO_TYPE_CLASS:
2166 case MONO_TYPE_VALUETYPE: {
2167 MonoClass *k = mono_class_from_mono_type (type);
2168 if (!k || !k->generic_class)
2170 encode_generic_class (assembly, k->generic_class, p, &p);
2177 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2178 if (assembly->save) {
2179 g_assert (p-sig < 128);
2180 mono_metadata_encode_value (p-sig, b, &b);
2181 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2182 alloc_table (table, table->rows + 1);
2183 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2184 values [MONO_TYPESPEC_SIGNATURE] = token;
2187 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2188 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2194 * Despite the name, we handle also TypeSpec (with the above helper).
2197 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2199 MonoDynamicTable *table;
2201 guint32 token, scope, enclosing;
2204 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2207 token = create_typespec (assembly, type);
2210 klass = my_mono_class_from_mono_type (type);
2212 klass = mono_class_from_mono_type (type);
2215 * If it's in the same module and not a generic type parameter:
2217 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2218 (type->type != MONO_TYPE_MVAR)) {
2219 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2220 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2221 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2225 if (klass->nested_in) {
2226 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2227 /* get the typeref idx of the enclosing type */
2228 enclosing >>= MONO_TYPEDEFORREF_BITS;
2229 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2231 scope = resolution_scope_from_image (assembly, klass->image);
2233 table = &assembly->tables [MONO_TABLE_TYPEREF];
2234 if (assembly->save) {
2235 alloc_table (table, table->rows + 1);
2236 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2237 values [MONO_TYPEREF_SCOPE] = scope;
2238 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2239 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2241 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2242 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2249 * Insert a memberef row into the metadata: the token that point to the memberref
2250 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2251 * mono_image_get_fieldref_token()).
2252 * The sig param is an index to an already built signature.
2255 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2257 MonoDynamicTable *table;
2259 guint32 token, pclass;
2262 parent = mono_image_typedef_or_ref (assembly, type);
2263 switch (parent & MONO_TYPEDEFORREF_MASK) {
2264 case MONO_TYPEDEFORREF_TYPEREF:
2265 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2267 case MONO_TYPEDEFORREF_TYPESPEC:
2268 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2270 case MONO_TYPEDEFORREF_TYPEDEF:
2271 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2274 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2277 /* extract the index */
2278 parent >>= MONO_TYPEDEFORREF_BITS;
2280 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2282 if (assembly->save) {
2283 alloc_table (table, table->rows + 1);
2284 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2285 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2286 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2287 values [MONO_MEMBERREF_SIGNATURE] = sig;
2290 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2297 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2300 MonoMethodSignature *sig;
2302 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2307 * A methodref signature can't contain an unmanaged calling convention.
2309 sig = mono_metadata_signature_dup (mono_method_signature (method));
2310 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2311 sig->call_convention = MONO_CALL_DEFAULT;
2312 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2313 method->name, method_encode_signature (assembly, sig));
2315 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2320 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2321 const gchar *name, guint32 sig)
2323 MonoDynamicTable *table;
2327 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2329 if (assembly->save) {
2330 alloc_table (table, table->rows + 1);
2331 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2332 values [MONO_MEMBERREF_CLASS] = original;
2333 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2334 values [MONO_MEMBERREF_SIGNATURE] = sig;
2337 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2344 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2347 ReflectionMethodBuilder rmb;
2349 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2353 reflection_methodbuilder_from_method_builder (&rmb, mb);
2355 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2356 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2357 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2362 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2365 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2371 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2373 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2374 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2375 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2380 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2385 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2388 g_assert (f->field->parent);
2389 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2390 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2391 f->field->name, fieldref_encode_signature (assembly, type));
2392 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2397 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2402 guint32 nparams = gmethod->inst->type_argc;
2403 guint32 size = 10 + nparams * 30;
2406 char *b = blob_size;
2408 if (!assembly->save)
2411 p = buf = g_malloc (size);
2413 * FIXME: vararg, explicit_this, differenc call_conv values...
2415 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2416 mono_metadata_encode_value (nparams, p, &p);
2418 for (i = 0; i < nparams; i++)
2419 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2422 g_assert (p - buf < size);
2423 mono_metadata_encode_value (p-buf, b, &b);
2424 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2430 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2432 MonoDynamicTable *table;
2434 guint32 token, mtoken = 0, sig;
2435 MonoMethodInflated *imethod;
2436 MonoMethod *declaring;
2438 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2440 g_assert (method->is_inflated);
2441 method = mono_get_inflated_method (method);
2442 imethod = (MonoMethodInflated *) method;
2443 declaring = imethod->declaring;
2445 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2446 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2448 if (!mono_method_signature (declaring)->generic_param_count)
2451 switch (mono_metadata_token_table (mtoken)) {
2452 case MONO_TABLE_MEMBERREF:
2453 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2455 case MONO_TABLE_METHOD:
2456 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2459 g_assert_not_reached ();
2462 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2464 if (assembly->save) {
2465 alloc_table (table, table->rows + 1);
2466 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2467 values [MONO_METHODSPEC_METHOD] = mtoken;
2468 values [MONO_METHODSPEC_SIGNATURE] = sig;
2471 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2478 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
2480 MonoMethodInflated *imethod;
2481 MonoMethod *inflated;
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2488 g_assert (method->is_inflated);
2489 inflated = mono_get_inflated_method (method);
2490 imethod = (MonoMethodInflated *) inflated;
2492 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2493 token = method_encode_methodspec (assembly, inflated);
2495 guint32 sig = method_encode_signature (
2496 assembly, mono_method_signature (imethod->declaring));
2497 token = mono_image_get_memberref_token (
2498 assembly, &inflated->klass->byval_arg, inflated->name, sig);
2501 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2506 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2508 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2511 m = mono_get_inflated_method (m);
2513 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2514 token = mono_image_get_memberref_token (
2515 assembly, &m->klass->byval_arg, m->name, sig);
2521 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2523 MonoDynamicTable *table;
2530 char *b = blob_size;
2534 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2535 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2536 * Because of this, we must not insert it into the `typeref' hash table.
2539 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2543 g_assert (tb->generic_params);
2544 klass = mono_class_from_mono_type (tb->type.type);
2546 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2547 encode_type (assembly, &klass->byval_arg, p, &p);
2549 count = mono_array_length (tb->generic_params);
2550 mono_metadata_encode_value (count, p, &p);
2551 for (i = 0; i < count; i++) {
2552 MonoReflectionGenericParam *gparam;
2554 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2556 encode_type (assembly, gparam->type.type, p, &p);
2559 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2560 g_assert (p-sig < 128);
2562 if (assembly->save) {
2563 mono_metadata_encode_value (p-sig, b, &b);
2564 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2567 values [MONO_TYPESPEC_SIGNATURE] = token;
2570 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2571 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2577 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2579 MonoDynamicTable *table;
2582 guint32 token, pclass, parent, sig;
2585 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2589 klass = mono_class_from_mono_type (fb->typeb->type);
2590 name = mono_string_to_utf8 (fb->name);
2592 sig = fieldref_encode_signature (assembly, fb->type->type);
2594 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2595 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2597 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2598 parent >>= MONO_TYPEDEFORREF_BITS;
2600 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2602 if (assembly->save) {
2603 alloc_table (table, table->rows + 1);
2604 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2605 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2606 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2607 values [MONO_MEMBERREF_SIGNATURE] = sig;
2610 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2612 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2617 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2625 char *b = blob_size;
2627 if (!assembly->save)
2631 g_assert (helper->type == 2);
2633 if (helper->arguments)
2634 nargs = mono_array_length (helper->arguments);
2638 size = 10 + (nargs * 10);
2640 p = buf = g_malloc (size);
2642 /* Encode calling convention */
2643 /* Change Any to Standard */
2644 if ((helper->call_conv & 0x03) == 0x03)
2645 helper->call_conv = 0x01;
2646 /* explicit_this implies has_this */
2647 if (helper->call_conv & 0x40)
2648 helper->call_conv &= 0x20;
2650 if (helper->call_conv == 0) { /* Unmanaged */
2651 *p = helper->unmanaged_call_conv - 1;
2654 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2655 if (helper->call_conv & 0x02) /* varargs */
2660 mono_metadata_encode_value (nargs, p, &p);
2661 encode_reflection_type (assembly, helper->return_type, p, &p);
2662 for (i = 0; i < nargs; ++i) {
2663 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2664 encode_reflection_type (assembly, pt, p, &p);
2667 g_assert (p - buf < size);
2668 mono_metadata_encode_value (p-buf, b, &b);
2669 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2676 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2679 MonoDynamicTable *table;
2682 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2683 idx = table->next_idx ++;
2685 alloc_table (table, table->rows);
2686 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2688 values [MONO_STAND_ALONE_SIGNATURE] =
2689 mono_reflection_encode_sighelper (assembly, helper);
2695 reflection_cc_to_file (int call_conv) {
2696 switch (call_conv & 0x3) {
2698 case 1: return MONO_CALL_DEFAULT;
2699 case 2: return MONO_CALL_VARARG;
2701 g_assert_not_reached ();
2708 MonoMethodSignature *sig;
2714 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2719 MonoMethodSignature *sig;
2722 name = mono_string_to_utf8 (m->name);
2723 nparams = mono_array_length (m->parameters);
2724 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2726 sig->sentinelpos = -1;
2727 sig->call_convention = reflection_cc_to_file (m->call_conv);
2728 sig->param_count = nparams;
2729 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2730 for (i = 0; i < nparams; ++i) {
2731 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2732 sig->params [i] = t->type;
2735 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2737 if (strcmp (name, am->name) == 0 &&
2738 mono_metadata_type_equal (am->parent, m->parent->type) &&
2739 mono_metadata_signature_equal (am->sig, sig)) {
2742 m->table_idx = am->token & 0xffffff;
2746 am = g_new0 (ArrayMethod, 1);
2749 am->parent = m->parent->type;
2750 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2751 method_encode_signature (assembly, sig));
2752 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2753 m->table_idx = am->token & 0xffffff;
2758 * Insert into the metadata tables all the info about the TypeBuilder tb.
2759 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2762 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2764 MonoDynamicTable *table;
2766 int i, is_object = 0, is_system = 0;
2769 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2770 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2771 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2772 n = mono_string_to_utf8 (tb->name);
2773 if (strcmp (n, "Object") == 0)
2775 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2777 n = mono_string_to_utf8 (tb->nspace);
2778 if (strcmp (n, "System") == 0)
2780 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2782 if (tb->parent && !(is_system && is_object) &&
2783 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2784 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2786 values [MONO_TYPEDEF_EXTENDS] = 0;
2788 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2789 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2792 * if we have explicitlayout or sequentiallayouts, output data in the
2793 * ClassLayout table.
2795 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2796 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2797 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2799 alloc_table (table, table->rows);
2800 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2801 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2802 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2803 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2806 /* handle interfaces */
2807 if (tb->interfaces) {
2808 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2810 table->rows += mono_array_length (tb->interfaces);
2811 alloc_table (table, table->rows);
2812 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2813 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2814 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2815 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2816 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2817 values += MONO_INTERFACEIMPL_SIZE;
2823 table = &assembly->tables [MONO_TABLE_FIELD];
2824 table->rows += tb->num_fields;
2825 alloc_table (table, table->rows);
2826 for (i = 0; i < tb->num_fields; ++i)
2827 mono_image_get_field_info (
2828 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2831 /* handle constructors */
2833 table = &assembly->tables [MONO_TABLE_METHOD];
2834 table->rows += mono_array_length (tb->ctors);
2835 alloc_table (table, table->rows);
2836 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2837 mono_image_get_ctor_info (domain,
2838 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2841 /* handle methods */
2843 table = &assembly->tables [MONO_TABLE_METHOD];
2844 table->rows += tb->num_methods;
2845 alloc_table (table, table->rows);
2846 for (i = 0; i < tb->num_methods; ++i)
2847 mono_image_get_method_info (
2848 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2851 /* Do the same with properties etc.. */
2852 if (tb->events && mono_array_length (tb->events)) {
2853 table = &assembly->tables [MONO_TABLE_EVENT];
2854 table->rows += mono_array_length (tb->events);
2855 alloc_table (table, table->rows);
2856 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2858 alloc_table (table, table->rows);
2859 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2860 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2861 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2862 for (i = 0; i < mono_array_length (tb->events); ++i)
2863 mono_image_get_event_info (
2864 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2866 if (tb->properties && mono_array_length (tb->properties)) {
2867 table = &assembly->tables [MONO_TABLE_PROPERTY];
2868 table->rows += mono_array_length (tb->properties);
2869 alloc_table (table, table->rows);
2870 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2872 alloc_table (table, table->rows);
2873 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2874 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2875 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2876 for (i = 0; i < mono_array_length (tb->properties); ++i)
2877 mono_image_get_property_info (
2878 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2881 /* handle generic parameters */
2882 if (tb->generic_params) {
2883 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2884 table->rows += mono_array_length (tb->generic_params);
2885 alloc_table (table, table->rows);
2886 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2887 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2889 mono_image_get_generic_param_info (
2890 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2894 mono_image_add_decl_security (assembly,
2895 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2898 MonoDynamicTable *ntable;
2900 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2901 ntable->rows += mono_array_length (tb->subtypes);
2902 alloc_table (ntable, ntable->rows);
2903 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2905 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2906 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2908 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2909 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2910 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2911 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2912 mono_string_to_utf8 (tb->name), tb->table_idx,
2913 ntable->next_idx, ntable->rows);*/
2914 values += MONO_NESTED_CLASS_SIZE;
2921 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2925 g_ptr_array_add (types, type);
2927 if (!type->subtypes)
2930 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2932 collect_types (types, subtype);
2937 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2939 if ((*type1)->table_idx < (*type2)->table_idx)
2942 if ((*type1)->table_idx > (*type2)->table_idx)
2949 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2954 for (i = 0; i < mono_array_length (pinfo); ++i) {
2955 MonoReflectionParamBuilder *pb;
2956 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2959 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2964 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2967 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2969 for (i = 0; i < tb->num_fields; ++i) {
2970 MonoReflectionFieldBuilder* fb;
2971 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2972 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2976 for (i = 0; i < mono_array_length (tb->events); ++i) {
2977 MonoReflectionEventBuilder* eb;
2978 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2979 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2982 if (tb->properties) {
2983 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2984 MonoReflectionPropertyBuilder* pb;
2985 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2986 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2990 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2991 MonoReflectionCtorBuilder* cb;
2992 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2993 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2994 params_add_cattrs (assembly, cb->pinfo);
2999 for (i = 0; i < tb->num_methods; ++i) {
3000 MonoReflectionMethodBuilder* mb;
3001 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3002 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3003 params_add_cattrs (assembly, mb->pinfo);
3008 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3009 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3014 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3018 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3020 if (moduleb->global_methods) {
3021 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3022 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3023 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3024 params_add_cattrs (assembly, mb->pinfo);
3028 if (moduleb->global_fields) {
3029 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3030 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3031 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3035 if (moduleb->types) {
3036 for (i = 0; i < moduleb->num_types; ++i)
3037 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3042 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3044 MonoDynamicTable *table;
3048 char *b = blob_size;
3051 table = &assembly->tables [MONO_TABLE_FILE];
3053 alloc_table (table, table->rows);
3054 values = table->values + table->next_idx * MONO_FILE_SIZE;
3055 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3056 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3057 if (module->image->dynamic) {
3058 /* This depends on the fact that the main module is emitted last */
3059 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3060 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3063 path = g_strdup (module->image->name);
3065 mono_sha1_get_digest_from_file (path, hash);
3068 mono_metadata_encode_value (20, b, &b);
3069 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3070 mono_image_add_stream_data (&assembly->blob, hash, 20);
3075 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3077 MonoDynamicTable *table;
3081 table = &assembly->tables [MONO_TABLE_MODULE];
3082 mb->table_idx = table->next_idx ++;
3083 name = mono_string_to_utf8 (mb->module.name);
3084 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3086 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3090 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3091 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3092 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3096 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3097 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3099 MonoDynamicTable *table;
3103 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3104 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3107 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3109 alloc_table (table, table->rows);
3110 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3112 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3113 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3114 if (klass->nested_in)
3115 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3117 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3118 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3119 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3121 res = table->next_idx;
3125 /* Emit nested types */
3126 if (klass->nested_classes) {
3129 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3130 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3137 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3138 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3143 klass = mono_class_from_mono_type (tb->type.type);
3145 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3147 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3148 parent_index, assembly);
3152 * We need to do this ourselves since klass->nested_classes is not set up.
3155 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3156 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3161 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3162 guint32 module_index, MonoDynamicImage *assembly)
3164 MonoImage *image = module->image;
3168 t = &image->tables [MONO_TABLE_TYPEDEF];
3170 for (i = 0; i < t->rows; ++i) {
3171 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3173 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3174 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3178 #define align_pointer(base,p)\
3180 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3182 (p) += 4 - (__diff & 3);\
3186 compare_constants (const void *a, const void *b)
3188 const guint32 *a_values = a;
3189 const guint32 *b_values = b;
3190 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3194 compare_semantics (const void *a, const void *b)
3196 const guint32 *a_values = a;
3197 const guint32 *b_values = b;
3198 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3201 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3205 compare_custom_attrs (const void *a, const void *b)
3207 const guint32 *a_values = a;
3208 const guint32 *b_values = b;
3210 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3214 compare_field_marshal (const void *a, const void *b)
3216 const guint32 *a_values = a;
3217 const guint32 *b_values = b;
3219 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3223 compare_nested (const void *a, const void *b)
3225 const guint32 *a_values = a;
3226 const guint32 *b_values = b;
3228 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3232 compare_genericparam (const void *a, const void *b)
3234 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3235 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3237 if ((*b_entry)->owner == (*a_entry)->owner)
3239 (*a_entry)->gparam->type.type->data.generic_param->num -
3240 (*b_entry)->gparam->type.type->data.generic_param->num;
3242 return (*a_entry)->owner - (*b_entry)->owner;
3246 compare_declsecurity_attrs (const void *a, const void *b)
3248 const guint32 *a_values = a;
3249 const guint32 *b_values = b;
3251 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3255 pad_heap (MonoDynamicStream *sh)
3257 if (sh->index & 3) {
3258 int sz = 4 - (sh->index & 3);
3259 memset (sh->data + sh->index, 0, sz);
3266 MonoDynamicStream *stream;
3270 * build_compressed_metadata() fills in the blob of data that represents the
3271 * raw metadata as it will be saved in the PE file. The five streams are output
3272 * and the metadata tables are comnpressed from the guint32 array representation,
3273 * to the compressed on-disk format.
3276 build_compressed_metadata (MonoDynamicImage *assembly)
3278 MonoDynamicTable *table;
3280 guint64 valid_mask = 0;
3281 guint64 sorted_mask;
3282 guint32 heapt_size = 0;
3283 guint32 meta_size = 256; /* allow for header and other stuff */
3284 guint32 table_offset;
3285 guint32 ntables = 0;
3291 struct StreamDesc stream_desc [5];
3293 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3294 for (i = 0; i < assembly->gen_params->len; i++){
3295 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3296 write_generic_param_entry (assembly, entry);
3299 stream_desc [0].name = "#~";
3300 stream_desc [0].stream = &assembly->tstream;
3301 stream_desc [1].name = "#Strings";
3302 stream_desc [1].stream = &assembly->sheap;
3303 stream_desc [2].name = "#US";
3304 stream_desc [2].stream = &assembly->us;
3305 stream_desc [3].name = "#Blob";
3306 stream_desc [3].stream = &assembly->blob;
3307 stream_desc [4].name = "#GUID";
3308 stream_desc [4].stream = &assembly->guid;
3310 /* tables that are sorted */
3311 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3312 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3313 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3314 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3315 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3316 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3318 /* Compute table sizes */
3319 /* the MonoImage has already been created in mono_image_basic_init() */
3320 meta = &assembly->image;
3322 /* sizes should be multiple of 4 */
3323 pad_heap (&assembly->blob);
3324 pad_heap (&assembly->guid);
3325 pad_heap (&assembly->sheap);
3326 pad_heap (&assembly->us);
3328 /* Setup the info used by compute_sizes () */
3329 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3330 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3331 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3333 meta_size += assembly->blob.index;
3334 meta_size += assembly->guid.index;
3335 meta_size += assembly->sheap.index;
3336 meta_size += assembly->us.index;
3338 for (i=0; i < MONO_TABLE_NUM; ++i)
3339 meta->tables [i].rows = assembly->tables [i].rows;
3341 for (i = 0; i < MONO_TABLE_NUM; i++){
3342 if (meta->tables [i].rows == 0)
3344 valid_mask |= (guint64)1 << i;
3346 meta->tables [i].row_size = mono_metadata_compute_size (
3347 meta, i, &meta->tables [i].size_bitfield);
3348 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3350 heapt_size += 24; /* #~ header size */
3351 heapt_size += ntables * 4;
3352 /* make multiple of 4 */
3355 meta_size += heapt_size;
3356 meta->raw_metadata = g_malloc0 (meta_size);
3357 p = meta->raw_metadata;
3358 /* the metadata signature */
3359 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3360 /* version numbers and 4 bytes reserved */
3361 int16val = (guint16*)p;
3362 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
3363 *int16val = GUINT16_TO_LE (meta->md_version_minor);
3365 /* version string */
3366 int32val = (guint32*)p;
3367 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3369 memcpy (p, meta->version, strlen (meta->version));
3370 p += GUINT32_FROM_LE (*int32val);
3371 align_pointer (meta->raw_metadata, p);
3372 int16val = (guint16*)p;
3373 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3374 *int16val = GUINT16_TO_LE (5); /* number of streams */
3378 * write the stream info.
3380 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3381 table_offset += 3; table_offset &= ~3;
3383 assembly->tstream.index = heapt_size;
3384 for (i = 0; i < 5; ++i) {
3385 int32val = (guint32*)p;
3386 stream_desc [i].stream->offset = table_offset;
3387 *int32val++ = GUINT32_TO_LE (table_offset);
3388 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3389 table_offset += GUINT32_FROM_LE (*int32val);
3390 table_offset += 3; table_offset &= ~3;
3392 strcpy (p, stream_desc [i].name);
3393 p += strlen (stream_desc [i].name) + 1;
3394 align_pointer (meta->raw_metadata, p);
3397 * now copy the data, the table stream header and contents goes first.
3399 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3400 p = meta->raw_metadata + assembly->tstream.offset;
3401 int32val = (guint32*)p;
3402 *int32val = GUINT32_TO_LE (0); /* reserved */
3405 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3406 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3407 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3408 *p++ = 2; /* version */
3411 *p++ = 1; /* version */
3415 if (meta->idx_string_wide)
3417 if (meta->idx_guid_wide)
3419 if (meta->idx_blob_wide)
3422 *p++ = 1; /* reserved */
3423 int64val = (guint64*)p;
3424 *int64val++ = GUINT64_TO_LE (valid_mask);
3425 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3427 int32val = (guint32*)p;
3428 for (i = 0; i < MONO_TABLE_NUM; i++){
3429 if (meta->tables [i].rows == 0)
3431 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3433 p = (unsigned char*)int32val;
3435 /* sort the tables that still need sorting */
3436 table = &assembly->tables [MONO_TABLE_CONSTANT];
3438 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3439 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3441 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3442 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3444 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3445 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3447 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3448 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3450 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3451 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3452 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3454 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3456 /* compress the tables */
3457 for (i = 0; i < MONO_TABLE_NUM; i++){
3460 guint32 bitfield = meta->tables [i].size_bitfield;
3461 if (!meta->tables [i].rows)
3463 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3464 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3465 meta->tables [i].base = p;
3466 for (row = 1; row <= meta->tables [i].rows; ++row) {
3467 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3468 for (col = 0; col < assembly->tables [i].columns; ++col) {
3469 switch (mono_metadata_table_size (bitfield, col)) {
3471 *p++ = values [col];
3474 *p++ = values [col] & 0xff;
3475 *p++ = (values [col] >> 8) & 0xff;
3478 *p++ = values [col] & 0xff;
3479 *p++ = (values [col] >> 8) & 0xff;
3480 *p++ = (values [col] >> 16) & 0xff;
3481 *p++ = (values [col] >> 24) & 0xff;
3484 g_assert_not_reached ();
3488 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3491 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3492 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3493 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3494 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3495 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3497 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3501 * Some tables in metadata need to be sorted according to some criteria, but
3502 * when methods and fields are first created with reflection, they may be assigned a token
3503 * that doesn't correspond to the final token they will get assigned after the sorting.
3504 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3505 * with the reflection objects that represent them. Once all the tables are set up, the
3506 * reflection objects will contains the correct table index. fixup_method() will fixup the
3507 * tokens for the method with ILGenerator @ilgen.
3510 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3511 guint32 code_idx = GPOINTER_TO_UINT (value);
3512 MonoReflectionILTokenInfo *iltoken;
3513 MonoReflectionFieldBuilder *field;
3514 MonoReflectionCtorBuilder *ctor;
3515 MonoReflectionMethodBuilder *method;
3516 MonoReflectionTypeBuilder *tb;
3517 MonoReflectionArrayMethod *am;
3519 unsigned char *target;
3521 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3522 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3523 target = assembly->code.data + code_idx + iltoken->code_pos;
3524 switch (target [3]) {
3525 case MONO_TABLE_FIELD:
3526 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3527 field = (MonoReflectionFieldBuilder *)iltoken->member;
3528 idx = field->table_idx;
3529 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3530 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3531 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3533 g_assert_not_reached ();
3536 case MONO_TABLE_METHOD:
3537 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3538 method = (MonoReflectionMethodBuilder *)iltoken->member;
3539 idx = method->table_idx;
3540 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3541 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3542 idx = ctor->table_idx;
3543 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3544 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3545 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3546 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3548 g_assert_not_reached ();
3551 case MONO_TABLE_TYPEDEF:
3552 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3553 g_assert_not_reached ();
3554 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3555 idx = tb->table_idx;
3557 case MONO_TABLE_MEMBERREF:
3558 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3559 am = (MonoReflectionArrayMethod*)iltoken->member;
3560 idx = am->table_idx;
3561 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3562 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3563 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3564 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3565 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3566 g_assert (m->klass->generic_class || m->klass->generic_container);
3568 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3570 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3571 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3572 g_assert (f->generic_info);
3574 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3577 g_assert_not_reached ();
3580 case MONO_TABLE_METHODSPEC:
3581 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3582 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3583 g_assert (mono_method_signature (m)->generic_param_count);
3586 g_assert_not_reached ();
3590 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3592 target [0] = idx & 0xff;
3593 target [1] = (idx >> 8) & 0xff;
3594 target [2] = (idx >> 16) & 0xff;
3601 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3602 * value is not known when the table is emitted.
3605 fixup_cattrs (MonoDynamicImage *assembly)
3607 MonoDynamicTable *table;
3609 guint32 type, i, idx, token;
3612 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3614 for (i = 0; i < table->rows; ++i) {
3615 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3617 type = values [MONO_CUSTOM_ATTR_TYPE];
3618 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3619 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3620 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3621 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3624 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3625 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3626 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3627 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3636 * The METHODIMPL table might contain METHODDEF tokens whose final
3637 * value is not known when the table is emitted.
3640 fixup_methodimpl (MonoDynamicImage *assembly)
3642 MonoDynamicTable *table;
3644 guint32 decl, i, idx, token;
3647 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3649 for (i = 0; i < table->rows; ++i) {
3650 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3651 decl = values [MONO_METHODIMPL_DECLARATION];
3653 idx = decl >> MONO_METHODDEFORREF_BITS;
3654 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3657 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3658 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3661 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3662 token = mono_image_create_token (assembly, method, FALSE);
3663 idx = mono_metadata_token_index (token);
3664 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3670 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3672 MonoDynamicTable *table;
3676 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3678 alloc_table (table, table->rows);
3679 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3680 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3681 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3682 name = mono_string_to_utf8 (rsrc->name);
3683 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3685 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3690 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3692 MonoDynamicTable *table;
3696 char *b = blob_size;
3698 guint32 idx, offset;
3700 if (rsrc->filename) {
3701 name = mono_string_to_utf8 (rsrc->filename);
3702 sname = g_path_get_basename (name);
3704 table = &assembly->tables [MONO_TABLE_FILE];
3706 alloc_table (table, table->rows);
3707 values = table->values + table->next_idx * MONO_FILE_SIZE;
3708 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3709 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3712 mono_sha1_get_digest_from_file (name, hash);
3713 mono_metadata_encode_value (20, b, &b);
3714 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3715 mono_image_add_stream_data (&assembly->blob, hash, 20);
3717 idx = table->next_idx++;
3719 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3722 offset = mono_array_length (rsrc->data);
3723 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3724 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3725 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3726 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3730 * The entry should be emitted into the MANIFESTRESOURCE table of
3731 * the main module, but that needs to reference the FILE table
3732 * which isn't emitted yet.
3739 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3743 set_version_from_string (MonoString *version, guint32 *values)
3745 gchar *ver, *p, *str;
3748 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3749 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3750 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3751 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3754 ver = str = mono_string_to_utf8 (version);
3755 for (i = 0; i < 4; ++i) {
3756 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3762 /* handle Revision and Build */
3772 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3776 char *b = blob_size;
3781 len = mono_array_length (pkey);
3782 mono_metadata_encode_value (len, b, &b);
3783 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3784 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3786 /* Special case: check for ECMA key (16 bytes) */
3787 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, guint8, 0), len)) {
3788 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
3789 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
3790 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
3791 /* minimum key size (in 2.0) is 384 bits */
3792 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
3794 /* FIXME - verifier */
3795 g_warning ("Invalid public key length: %d bits (total: %d)", MONO_PUBLIC_KEY_BIT_SIZE (len), len);
3796 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
3798 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3804 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3806 MonoDynamicTable *table;
3807 MonoDynamicImage *assembly;
3808 MonoReflectionAssemblyBuilder *assemblyb;
3813 guint32 module_index;
3815 assemblyb = moduleb->assemblyb;
3816 assembly = moduleb->dynamic_image;
3817 domain = mono_object_domain (assemblyb);
3819 /* Emit ASSEMBLY table */
3820 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3821 alloc_table (table, 1);
3822 values = table->values + MONO_ASSEMBLY_SIZE;
3823 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3824 name = mono_string_to_utf8 (assemblyb->name);
3825 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3827 if (assemblyb->culture) {
3828 name = mono_string_to_utf8 (assemblyb->culture);
3829 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3832 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3834 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3835 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3836 set_version_from_string (assemblyb->version, values);
3838 /* Emit FILE + EXPORTED_TYPE table */
3840 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3842 MonoReflectionModuleBuilder *file_module =
3843 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3844 if (file_module != moduleb) {
3845 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3847 if (file_module->types) {
3848 for (j = 0; j < file_module->num_types; ++j) {
3849 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3850 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3855 if (assemblyb->loaded_modules) {
3856 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3857 MonoReflectionModule *file_module =
3858 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3859 mono_image_fill_file_table (domain, file_module, assembly);
3861 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3865 /* Emit MANIFESTRESOURCE table */
3867 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3869 MonoReflectionModuleBuilder *file_module =
3870 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3871 /* The table for the main module is emitted later */
3872 if (file_module != moduleb) {
3874 if (file_module->resources) {
3875 int len = mono_array_length (file_module->resources);
3876 for (j = 0; j < len; ++j) {
3877 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3878 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3886 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3887 * for the modulebuilder @moduleb.
3888 * At the end of the process, method and field tokens are fixed up and the
3889 * on-disk compressed metadata representation is created.
3892 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3894 MonoDynamicTable *table;
3895 MonoDynamicImage *assembly;
3896 MonoReflectionAssemblyBuilder *assemblyb;
3901 assemblyb = moduleb->assemblyb;
3902 assembly = moduleb->dynamic_image;
3903 domain = mono_object_domain (assemblyb);
3905 if (assembly->text_rva)
3908 assembly->text_rva = START_TEXT_RVA;
3910 if (moduleb->is_main) {
3911 mono_image_emit_manifest (moduleb);
3914 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3915 table->rows = 1; /* .<Module> */
3917 alloc_table (table, table->rows);
3919 * Set the first entry.
3921 values = table->values + table->columns;
3922 values [MONO_TYPEDEF_FLAGS] = 0;
3923 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3924 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3925 values [MONO_TYPEDEF_EXTENDS] = 0;
3926 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3927 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3930 * handle global methods
3931 * FIXME: test what to do when global methods are defined in multiple modules.
3933 if (moduleb->global_methods) {
3934 table = &assembly->tables [MONO_TABLE_METHOD];
3935 table->rows += mono_array_length (moduleb->global_methods);
3936 alloc_table (table, table->rows);
3937 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3938 mono_image_get_method_info (
3939 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3941 if (moduleb->global_fields) {
3942 table = &assembly->tables [MONO_TABLE_FIELD];
3943 table->rows += mono_array_length (moduleb->global_fields);
3944 alloc_table (table, table->rows);
3945 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3946 mono_image_get_field_info (
3947 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3950 table = &assembly->tables [MONO_TABLE_MODULE];
3951 alloc_table (table, 1);
3952 mono_image_fill_module_table (domain, moduleb, assembly);
3956 /* Collect all types into a list sorted by their table_idx */
3957 GPtrArray *types = g_ptr_array_new ();
3960 for (i = 0; i < moduleb->num_types; ++i) {
3961 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3962 collect_types (types, type);
3965 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3966 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3967 table->rows += types->len;
3968 alloc_table (table, table->rows);
3971 * Emit type names + namespaces at one place inside the string heap,
3972 * so load_class_names () needs to touch fewer pages.
3974 for (i = 0; i < types->len; ++i) {
3975 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3978 n = mono_string_to_utf8 (tb->nspace);
3979 string_heap_insert (&assembly->sheap, n);
3982 for (i = 0; i < types->len; ++i) {
3983 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3986 n = mono_string_to_utf8 (tb->name);
3987 string_heap_insert (&assembly->sheap, n);
3991 for (i = 0; i < types->len; ++i) {
3992 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3993 mono_image_get_type_info (domain, type, assembly);
3995 g_ptr_array_free (types, TRUE);
3999 * table->rows is already set above and in mono_image_fill_module_table.
4001 /* add all the custom attributes at the end, once all the indexes are stable */
4002 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4004 /* CAS assembly permissions */
4005 if (assemblyb->permissions_minimum)
4006 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4007 if (assemblyb->permissions_optional)
4008 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4009 if (assemblyb->permissions_refused)
4010 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4012 module_add_cattrs (assembly, moduleb);
4015 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4016 fixup_cattrs (assembly);
4017 fixup_methodimpl (assembly);
4021 * mono_image_insert_string:
4022 * @module: module builder object
4025 * Insert @str into the user string stream of @module.
4028 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4030 MonoDynamicImage *assembly;
4035 MONO_ARCH_SAVE_REGS;
4037 if (!module->dynamic_image)
4038 mono_image_module_basic_init (module);
4040 assembly = module->dynamic_image;
4042 if (assembly->save) {
4043 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4044 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4045 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4047 char *swapped = g_malloc (2 * mono_string_length (str));
4048 const char *p = (const char*)mono_string_chars (str);
4050 swap_with_size (swapped, p, 2, mono_string_length (str));
4051 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4055 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4057 mono_image_add_stream_data (&assembly->us, "", 1);
4059 idx = assembly->us.index ++;
4062 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4064 return MONO_TOKEN_STRING | idx;
4068 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4073 klass = obj->vtable->klass;
4074 if (strcmp (klass->name, "MonoMethod") == 0) {
4075 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4076 MonoMethodSignature *sig, *old;
4077 guint32 sig_token, parent;
4080 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4082 nargs = mono_array_length (opt_param_types);
4083 old = mono_method_signature (method);
4084 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4086 sig->hasthis = old->hasthis;
4087 sig->explicit_this = old->explicit_this;
4088 sig->call_convention = old->call_convention;
4089 sig->generic_param_count = old->generic_param_count;
4090 sig->param_count = old->param_count + nargs;
4091 sig->sentinelpos = old->param_count;
4092 sig->ret = old->ret;
4094 for (i = 0; i < old->param_count; i++)
4095 sig->params [i] = old->params [i];
4097 for (i = 0; i < nargs; i++) {
4098 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4099 sig->params [old->param_count + i] = rt->type;
4102 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4103 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4104 parent >>= MONO_TYPEDEFORREF_BITS;
4106 parent <<= MONO_MEMBERREF_PARENT_BITS;
4107 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4109 sig_token = method_encode_signature (assembly, sig);
4110 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4111 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4112 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4113 ReflectionMethodBuilder rmb;
4114 guint32 parent, sig;
4116 reflection_methodbuilder_from_method_builder (&rmb, mb);
4117 rmb.opt_types = opt_param_types;
4119 sig = method_builder_encode_signature (assembly, &rmb);
4121 parent = mono_image_create_token (assembly, obj, TRUE);
4122 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4124 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4125 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4127 token = mono_image_get_varargs_method_token (
4128 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4130 g_error ("requested method token for %s\n", klass->name);
4137 * mono_image_create_token:
4138 * @assembly: a dynamic assembly
4141 * Get a token to insert in the IL code stream for the given MemberInfo.
4142 * @obj can be one of:
4143 * ConstructorBuilder
4153 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4158 klass = obj->vtable->klass;
4159 if (strcmp (klass->name, "MethodBuilder") == 0) {
4160 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4162 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4163 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4165 token = mono_image_get_methodbuilder_token (assembly, mb);
4166 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4167 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4168 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4170 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4171 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4173 token = mono_image_get_ctorbuilder_token (assembly, mb);
4174 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4175 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4176 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4177 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4178 if (tb->generic_params) {
4179 token = mono_image_get_generic_field_token (assembly, fb);
4181 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4183 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4185 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4186 } else if (strcmp (klass->name, "MonoType") == 0 ||
4187 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4188 MonoReflectionType *tb = (MonoReflectionType *)obj;
4189 token = mono_metadata_token_from_dor (
4190 mono_image_typedef_or_ref (assembly, tb->type));
4191 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4192 MonoReflectionType *tb = (MonoReflectionType *)obj;
4193 token = mono_metadata_token_from_dor (
4194 mono_image_typedef_or_ref (assembly, tb->type));
4195 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4196 strcmp (klass->name, "MonoMethod") == 0 ||
4197 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4198 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4199 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4200 if (m->method->is_inflated) {
4201 if (create_methodspec)
4202 token = mono_image_get_methodspec_token (assembly, m->method);
4204 token = mono_image_get_inflated_method_token (assembly, m->method);
4205 } else if ((m->method->klass->image == &assembly->image) &&
4206 !m->method->klass->generic_class) {
4207 static guint32 method_table_idx = 0xffffff;
4208 if (m->method->klass->wastypebuilder) {
4209 /* we use the same token as the one that was assigned
4210 * to the Methodbuilder.
4211 * FIXME: do the equivalent for Fields.
4213 token = m->method->token;
4216 * Each token should have a unique index, but the indexes are
4217 * assigned by managed code, so we don't know about them. An
4218 * easy solution is to count backwards...
4220 method_table_idx --;
4221 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4224 token = mono_image_get_methodref_token (assembly, m->method);
4226 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4227 } else if (strcmp (klass->name, "MonoField") == 0) {
4228 MonoReflectionField *f = (MonoReflectionField *)obj;
4229 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4230 static guint32 field_table_idx = 0xffffff;
4232 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4234 token = mono_image_get_fieldref_token (assembly, f);
4236 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4237 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4238 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4239 token = mono_image_get_array_token (assembly, m);
4240 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4241 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4242 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4244 g_error ("requested token for %s\n", klass->name);
4247 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4253 guint32 import_lookup_table;
4257 guint32 import_address_table_rva;
4265 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4267 static MonoDynamicImage*
4268 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4270 static const guchar entrycode [16] = {0xff, 0x25, 0};
4271 MonoDynamicImage *image;
4274 const char *version = mono_get_runtime_info ()->runtime_version;
4277 image = GC_MALLOC (sizeof (MonoDynamicImage));
4279 image = g_new0 (MonoDynamicImage, 1);
4282 /*g_print ("created image %p\n", image);*/
4283 /* keep in sync with image.c */
4284 image->image.name = assembly_name;
4285 image->image.assembly_name = image->image.name; /* they may be different */
4286 image->image.module_name = module_name;
4287 image->image.version = version;
4288 image->image.md_version_major = 1;
4289 image->image.md_version_minor = 1;
4290 image->image.dynamic = TRUE;
4291 image->image.ref_count = 1;
4293 image->image.references = g_new0 (MonoAssembly*, 1);
4294 image->image.references [0] = NULL;
4296 mono_image_init (&image->image);
4298 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4299 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4300 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4301 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4302 image->handleref = g_hash_table_new (NULL, NULL);
4303 image->tokens = mono_g_hash_table_new (NULL, NULL);
4304 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4305 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4306 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4307 image->gen_params = g_ptr_array_new ();
4309 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4310 string_heap_init (&image->sheap);
4311 mono_image_add_stream_data (&image->us, "", 1);
4312 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4313 /* import tables... */
4314 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4315 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4316 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4317 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4318 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4319 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4320 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4321 stream_data_align (&image->code);
4323 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4325 for (i=0; i < MONO_TABLE_NUM; ++i) {
4326 image->tables [i].next_idx = 1;
4327 image->tables [i].columns = table_sizes [i];
4330 image->image.assembly = (MonoAssembly*)assembly;
4331 image->run = assembly->run;
4332 image->save = assembly->save;
4333 image->pe_kind = 0x1; /* ILOnly */
4334 image->machine = 0x14c; /* I386 */
4340 * mono_image_basic_init:
4341 * @assembly: an assembly builder object
4343 * Create the MonoImage that represents the assembly builder and setup some
4344 * of the helper hash table and the basic metadata streams.
4347 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4349 MonoDynamicAssembly *assembly;
4350 MonoDynamicImage *image;
4351 MonoDomain *domain = mono_object_domain (assemblyb);
4353 MONO_ARCH_SAVE_REGS;
4355 if (assemblyb->dynamic_assembly)
4359 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4361 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4364 assembly->assembly.ref_count = 1;
4365 assembly->assembly.dynamic = TRUE;
4366 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4367 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4368 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4369 if (assemblyb->culture)
4370 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4372 assembly->assembly.aname.culture = g_strdup ("");
4374 if (assemblyb->version) {
4375 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4376 char **parts = version;
4377 assembly->assembly.aname.major = atoi (*parts++);
4378 assembly->assembly.aname.minor = atoi (*parts++);
4379 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4380 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4382 g_strfreev (version);
4384 assembly->assembly.aname.major = 0;
4385 assembly->assembly.aname.minor = 0;
4386 assembly->assembly.aname.build = 0;
4387 assembly->assembly.aname.revision = 0;
4390 assembly->run = assemblyb->access != 2;
4391 assembly->save = assemblyb->access != 1;
4393 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4394 image->initial_image = TRUE;
4395 assembly->assembly.aname.name = image->image.name;
4396 assembly->assembly.image = &image->image;
4398 mono_domain_assemblies_lock (domain);
4399 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4400 mono_domain_assemblies_unlock (domain);
4402 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4403 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4407 calc_section_size (MonoDynamicImage *assembly)
4411 /* alignment constraints */
4412 assembly->code.index += 3;
4413 assembly->code.index &= ~3;
4414 assembly->meta_size += 3;
4415 assembly->meta_size &= ~3;
4416 assembly->resources.index += 3;
4417 assembly->resources.index &= ~3;
4419 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4420 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4423 if (assembly->win32_res) {
4424 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4426 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4427 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4431 assembly->sections [MONO_SECTION_RELOC].size = 12;
4432 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4442 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4446 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4448 ResTreeNode *t1 = (ResTreeNode*)a;
4449 ResTreeNode *t2 = (ResTreeNode*)b;
4451 return t1->id - t2->id;
4455 * resource_tree_create:
4457 * Organize the resources into a resource tree.
4459 static ResTreeNode *
4460 resource_tree_create (MonoArray *win32_resources)
4462 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4466 tree = g_new0 (ResTreeNode, 1);
4468 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4469 MonoReflectionWin32Resource *win32_res =
4470 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4474 lang_node = g_new0 (ResTreeNode, 1);
4475 lang_node->id = win32_res->lang_id;
4476 lang_node->win32_res = win32_res;
4478 /* Create type node if neccesary */
4480 for (l = tree->children; l; l = l->next)
4481 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4482 type_node = (ResTreeNode*)l->data;
4487 type_node = g_new0 (ResTreeNode, 1);
4488 type_node->id = win32_res->res_type;
4491 * The resource types have to be sorted otherwise
4492 * Windows Explorer can't display the version information.
4494 tree->children = g_slist_insert_sorted (tree->children,
4495 type_node, resource_tree_compare_by_id);
4498 /* Create res node if neccesary */
4500 for (l = type_node->children; l; l = l->next)
4501 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4502 res_node = (ResTreeNode*)l->data;
4507 res_node = g_new0 (ResTreeNode, 1);
4508 res_node->id = win32_res->res_id;
4509 type_node->children = g_slist_append (type_node->children, res_node);
4512 res_node->children = g_slist_append (res_node->children, lang_node);
4519 * resource_tree_encode:
4521 * Encode the resource tree into the format used in the PE file.
4524 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4527 MonoPEResourceDir dir;
4528 MonoPEResourceDirEntry dir_entry;
4529 MonoPEResourceDataEntry data_entry;
4533 * For the format of the resource directory, see the article
4534 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4538 memset (&dir, 0, sizeof (dir));
4539 memset (&dir_entry, 0, sizeof (dir_entry));
4540 memset (&data_entry, 0, sizeof (data_entry));
4542 g_assert (sizeof (dir) == 16);
4543 g_assert (sizeof (dir_entry) == 8);
4544 g_assert (sizeof (data_entry) == 16);
4546 node->offset = p - begin;
4548 /* IMAGE_RESOURCE_DIRECTORY */
4549 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4551 memcpy (p, &dir, sizeof (dir));
4554 /* Reserve space for entries */
4556 p += sizeof (dir_entry) * dir.res_id_entries;
4558 /* Write children */
4559 for (l = node->children; l; l = l->next) {
4560 ResTreeNode *child = (ResTreeNode*)l->data;
4562 if (child->win32_res) {
4564 child->offset = p - begin;
4566 /* IMAGE_RESOURCE_DATA_ENTRY */
4567 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4568 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4570 memcpy (p, &data_entry, sizeof (data_entry));
4571 p += sizeof (data_entry);
4573 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4574 p += data_entry.rde_size;
4576 resource_tree_encode (child, begin, p, &p);
4580 /* IMAGE_RESOURCE_ENTRY */
4581 for (l = node->children; l; l = l->next) {
4582 ResTreeNode *child = (ResTreeNode*)l->data;
4583 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4585 dir_entry.is_dir = child->win32_res ? 0 : 1;
4586 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4588 memcpy (entries, &dir_entry, sizeof (dir_entry));
4589 entries += sizeof (dir_entry);
4596 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4601 MonoReflectionWin32Resource *win32_res;
4604 if (!assemblyb->win32_resources)
4608 * Resources are stored in a three level tree inside the PE file.
4609 * - level one contains a node for each type of resource
4610 * - level two contains a node for each resource
4611 * - level three contains a node for each instance of a resource for a
4612 * specific language.
4615 tree = resource_tree_create (assemblyb->win32_resources);
4617 /* Estimate the size of the encoded tree */
4619 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4620 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4621 size += mono_array_length (win32_res->res_data);
4623 /* Directory structure */
4624 size += mono_array_length (assemblyb->win32_resources) * 256;
4625 p = buf = g_malloc (size);
4627 resource_tree_encode (tree, p, p, &p);
4629 g_assert (p - buf < size);
4631 assembly->win32_res = g_malloc (p - buf);
4632 assembly->win32_res_size = p - buf;
4633 memcpy (assembly->win32_res, buf, p - buf);
4639 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4641 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4644 p += sizeof (MonoPEResourceDir);
4645 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4646 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4647 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4648 if (dir_entry->is_dir) {
4649 fixup_resource_directory (res_section, child, rva);
4651 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4652 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4655 p += sizeof (MonoPEResourceDirEntry);
4660 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4663 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4664 g_error ("WriteFile returned %d\n", GetLastError ());
4668 * mono_image_create_pefile:
4669 * @mb: a module builder object
4671 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4672 * assembly->pefile where it can be easily retrieved later in chunks.
4675 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4676 MonoMSDOSHeader *msdos;
4677 MonoDotNetHeader *header;
4678 MonoSectionTable *section;
4679 MonoCLIHeader *cli_header;
4680 guint32 size, image_size, virtual_base, text_offset;
4681 guint32 header_start, section_start, file_offset, virtual_offset;
4682 MonoDynamicImage *assembly;
4683 MonoReflectionAssemblyBuilder *assemblyb;
4684 MonoDynamicStream pefile_stream = {0};
4685 MonoDynamicStream *pefile = &pefile_stream;
4687 guint32 *rva, value;
4689 static const unsigned char msheader[] = {
4690 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4691 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4692 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4694 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4695 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4696 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4697 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4700 assemblyb = mb->assemblyb;
4702 mono_image_basic_init (assemblyb);
4703 assembly = mb->dynamic_image;
4705 assembly->pe_kind = assemblyb->pe_kind;
4706 assembly->machine = assemblyb->machine;
4707 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4708 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4710 mono_image_build_metadata (mb);
4712 if (mb->is_main && assemblyb->resources) {
4713 int len = mono_array_length (assemblyb->resources);
4714 for (i = 0; i < len; ++i)
4715 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4718 if (mb->resources) {
4719 int len = mono_array_length (mb->resources);
4720 for (i = 0; i < len; ++i)
4721 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4724 build_compressed_metadata (assembly);
4727 assembly_add_win32_resources (assembly, assemblyb);
4729 nsections = calc_section_size (assembly);
4731 /* The DOS header and stub */
4732 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4733 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4735 /* the dotnet header */
4736 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4738 /* the section tables */
4739 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4741 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4742 virtual_offset = VIRT_ALIGN;
4745 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4746 if (!assembly->sections [i].size)
4749 file_offset += FILE_ALIGN - 1;
4750 file_offset &= ~(FILE_ALIGN - 1);
4751 virtual_offset += VIRT_ALIGN - 1;
4752 virtual_offset &= ~(VIRT_ALIGN - 1);
4754 assembly->sections [i].offset = file_offset;
4755 assembly->sections [i].rva = virtual_offset;
4757 file_offset += assembly->sections [i].size;
4758 virtual_offset += assembly->sections [i].size;
4759 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4762 file_offset += FILE_ALIGN - 1;
4763 file_offset &= ~(FILE_ALIGN - 1);
4765 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4767 /* back-patch info */
4768 msdos = (MonoMSDOSHeader*)pefile->data;
4769 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4771 header = (MonoDotNetHeader*)(pefile->data + header_start);
4772 header->pesig [0] = 'P';
4773 header->pesig [1] = 'E';
4775 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4776 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4777 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4778 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4779 if (assemblyb->pekind == 1) {
4781 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4784 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4787 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4789 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4790 header->pe.pe_major = 6;
4791 header->pe.pe_minor = 0;
4792 size = assembly->sections [MONO_SECTION_TEXT].size;
4793 size += FILE_ALIGN - 1;
4794 size &= ~(FILE_ALIGN - 1);
4795 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4796 size = assembly->sections [MONO_SECTION_RSRC].size;
4797 size += FILE_ALIGN - 1;
4798 size &= ~(FILE_ALIGN - 1);
4799 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4800 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4801 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4802 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4803 /* pe_rva_entry_point always at the beginning of the text section */
4804 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4806 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4807 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4808 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4809 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4810 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4811 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4812 size = section_start;
4813 size += FILE_ALIGN - 1;
4814 size &= ~(FILE_ALIGN - 1);
4815 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4817 size += VIRT_ALIGN - 1;
4818 size &= ~(VIRT_ALIGN - 1);
4819 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4822 // Translate the PEFileKind value to the value expected by the Windows loader
4828 // PEFileKinds.Dll == 1
4829 // PEFileKinds.ConsoleApplication == 2
4830 // PEFileKinds.WindowApplication == 3
4833 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4834 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4836 if (assemblyb->pekind == 3)
4841 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4843 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4844 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4845 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4846 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4847 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4848 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4850 /* fill data directory entries */
4852 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4853 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4855 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4856 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4858 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4859 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4860 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4861 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4862 /* patch entrypoint name */
4863 if (assemblyb->pekind == 1)
4864 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4866 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4867 /* patch imported function RVA name */
4868 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4869 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4871 /* the import table */
4872 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4873 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4874 /* patch imported dll RVA name and other entries in the dir */
4875 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4876 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4877 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4878 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4879 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4880 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4882 p = (assembly->code.data + assembly->ilt_offset);
4883 value = (assembly->text_rva + assembly->imp_names_offset);
4884 *p++ = (value) & 0xff;
4885 *p++ = (value >> 8) & (0xff);
4886 *p++ = (value >> 16) & (0xff);
4887 *p++ = (value >> 24) & (0xff);
4889 /* the CLI header info */
4890 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4891 cli_header->ch_size = GUINT32_FROM_LE (72);
4892 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4893 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4894 if (assemblyb->entry_point) {
4895 guint32 table_idx = 0;
4896 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4897 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4898 table_idx = methodb->table_idx;
4900 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4902 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4904 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4906 /* The embedded managed resources */
4907 text_offset = assembly->text_rva + assembly->code.index;
4908 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4909 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4910 text_offset += assembly->resources.index;
4911 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4912 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4913 text_offset += assembly->meta_size;
4914 if (assembly->strong_name_size) {
4915 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4916 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4917 text_offset += assembly->strong_name_size;
4920 /* write the section tables and section content */
4921 section = (MonoSectionTable*)(pefile->data + section_start);
4922 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4923 static const char *section_names [] = {
4924 ".text", ".rsrc", ".reloc"
4926 if (!assembly->sections [i].size)
4928 strcpy (section->st_name, section_names [i]);
4929 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4930 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4931 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4932 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4933 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4934 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4935 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4939 checked_write_file (file, pefile->data, pefile->index);
4941 mono_dynamic_stream_reset (pefile);
4943 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4944 if (!assembly->sections [i].size)
4947 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4948 g_error ("SetFilePointer returned %d\n", GetLastError ());
4951 case MONO_SECTION_TEXT:
4952 /* patch entry point */
4953 p = (assembly->code.data + 2);
4954 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4955 *p++ = (value) & 0xff;
4956 *p++ = (value >> 8) & 0xff;
4957 *p++ = (value >> 16) & 0xff;
4958 *p++ = (value >> 24) & 0xff;
4960 checked_write_file (file, assembly->code.data, assembly->code.index);
4961 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4962 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4963 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4966 g_free (assembly->image.raw_metadata);
4968 case MONO_SECTION_RELOC: {
4972 guint16 type_and_offset;
4976 g_assert (sizeof (reloc) == 12);
4978 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4979 reloc.block_size = GUINT32_FROM_LE (12);
4982 * the entrypoint is always at the start of the text section
4983 * 3 is IMAGE_REL_BASED_HIGHLOW
4984 * 2 is patch_size_rva - text_rva
4986 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4989 checked_write_file (file, &reloc, sizeof (reloc));
4993 case MONO_SECTION_RSRC:
4994 if (assembly->win32_res) {
4996 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4997 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4998 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5002 g_assert_not_reached ();
5006 /* check that the file is properly padded */
5007 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5008 g_error ("SetFilePointer returned %d\n", GetLastError ());
5009 if (! SetEndOfFile (file))
5010 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5012 mono_dynamic_stream_reset (&assembly->code);
5013 mono_dynamic_stream_reset (&assembly->us);
5014 mono_dynamic_stream_reset (&assembly->blob);
5015 mono_dynamic_stream_reset (&assembly->guid);
5016 mono_dynamic_stream_reset (&assembly->sheap);
5018 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5019 g_hash_table_destroy (assembly->blob_cache);
5020 assembly->blob_cache = NULL;
5023 MonoReflectionModule *
5024 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5028 MonoImageOpenStatus status;
5029 MonoDynamicAssembly *assembly;
5030 guint32 module_count;
5031 MonoImage **new_modules;
5033 name = mono_string_to_utf8 (fileName);
5035 image = mono_image_open (name, &status);
5038 if (status == MONO_IMAGE_ERROR_ERRNO)
5039 exc = mono_get_exception_file_not_found (fileName);
5041 exc = mono_get_exception_bad_image_format (name);
5043 mono_raise_exception (exc);
5048 assembly = ab->dynamic_assembly;
5049 image->assembly = (MonoAssembly*)assembly;
5051 module_count = image->assembly->image->module_count;
5052 new_modules = g_new0 (MonoImage *, module_count + 1);
5054 if (image->assembly->image->modules)
5055 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5056 new_modules [module_count] = image;
5058 g_free (image->assembly->image->modules);
5059 image->assembly->image->modules = new_modules;
5060 image->assembly->image->module_count ++;
5062 mono_assembly_load_references (image, &status);
5064 mono_image_close (image);
5065 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5068 return mono_module_get_object (mono_domain_get (), image);
5072 * We need to return always the same object for MethodInfo, FieldInfo etc..
5073 * but we need to consider the reflected type.
5074 * type uses a different hash, since it uses custom hash/equal functions.
5079 MonoClass *refclass;
5083 reflected_equal (gconstpointer a, gconstpointer b) {
5084 const ReflectedEntry *ea = a;
5085 const ReflectedEntry *eb = b;
5087 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5091 reflected_hash (gconstpointer a) {
5092 const ReflectedEntry *ea = a;
5093 return GPOINTER_TO_UINT (ea->item);
5096 #define CHECK_OBJECT(t,p,k) \
5102 mono_domain_lock (domain); \
5103 if (!domain->refobject_hash) \
5104 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5105 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5106 mono_domain_unlock (domain); \
5109 mono_domain_unlock (domain); \
5113 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5115 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5118 #define CACHE_OBJECT(t,p,o,k) \
5121 ReflectedEntry pe; \
5123 pe.refclass = (k); \
5124 mono_domain_lock (domain); \
5125 if (!domain->refobject_hash) \
5126 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5127 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5129 ReflectedEntry *e = ALLOC_REFENTRY; \
5131 e->refclass = (k); \
5132 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5135 mono_domain_unlock (domain); \
5140 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5142 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5146 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5148 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5152 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5154 MonoDynamicImage *image = moduleb->dynamic_image;
5155 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5158 MonoImage **new_modules;
5161 * FIXME: we already created an image in mono_image_basic_init (), but
5162 * we don't know which module it belongs to, since that is only
5163 * determined at assembly save time.
5165 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5166 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5168 moduleb->module.image = &image->image;
5169 moduleb->dynamic_image = image;
5170 register_module (mono_object_domain (moduleb), moduleb, image);
5172 /* register the module with the assembly */
5173 ass = ab->dynamic_assembly->assembly.image;
5174 module_count = ass->module_count;
5175 new_modules = g_new0 (MonoImage *, module_count + 1);
5178 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5179 new_modules [module_count] = &image->image;
5181 g_free (ass->modules);
5182 ass->modules = new_modules;
5183 ass->module_count ++;
5188 * mono_assembly_get_object:
5189 * @domain: an app domain
5190 * @assembly: an assembly
5192 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5194 MonoReflectionAssembly*
5195 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5197 static MonoClass *System_Reflection_Assembly;
5198 MonoReflectionAssembly *res;
5200 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5201 if (!System_Reflection_Assembly)
5202 System_Reflection_Assembly = mono_class_from_name (
5203 mono_defaults.corlib, "System.Reflection", "Assembly");
5204 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5205 res->assembly = assembly;
5207 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5212 MonoReflectionModule*
5213 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5215 static MonoClass *System_Reflection_Module;
5216 MonoReflectionModule *res;
5219 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5220 if (!System_Reflection_Module)
5221 System_Reflection_Module = mono_class_from_name (
5222 mono_defaults.corlib, "System.Reflection", "Module");
5223 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5226 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5228 res->fqname = mono_string_new (domain, image->name);
5229 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5230 res->scopename = mono_string_new (domain, image->module_name);
5234 if (image->assembly->image == image) {
5235 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5238 g_assert (image->assembly->image->modules);
5240 for (i = 0; i < image->assembly->image->module_count; i++) {
5241 if (image->assembly->image->modules [i] == image)
5242 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5244 g_assert (res->token);
5247 mono_image_addref (image);
5249 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5252 MonoReflectionModule*
5253 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5255 static MonoClass *System_Reflection_Module;
5256 MonoReflectionModule *res;
5257 MonoTableInfo *table;
5258 guint32 cols [MONO_FILE_SIZE];
5260 guint32 i, name_idx;
5263 if (!System_Reflection_Module)
5264 System_Reflection_Module = mono_class_from_name (
5265 mono_defaults.corlib, "System.Reflection", "Module");
5266 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5268 table = &image->tables [MONO_TABLE_FILE];
5269 g_assert (table_index < table->rows);
5270 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5273 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5274 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5276 /* Check whenever the row has a corresponding row in the moduleref table */
5277 table = &image->tables [MONO_TABLE_MODULEREF];
5278 for (i = 0; i < table->rows; ++i) {
5279 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5280 val = mono_metadata_string_heap (image, name_idx);
5281 if (strcmp (val, name) == 0)
5282 res->image = image->modules [i];
5285 res->fqname = mono_string_new (domain, name);
5286 res->name = mono_string_new (domain, name);
5287 res->scopename = mono_string_new (domain, name);
5288 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5289 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5295 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5297 if ((t1->type != t2->type) ||
5298 (t1->byref != t2->byref))
5302 case MONO_TYPE_VOID:
5303 case MONO_TYPE_BOOLEAN:
5304 case MONO_TYPE_CHAR:
5315 case MONO_TYPE_STRING:
5318 case MONO_TYPE_OBJECT:
5319 case MONO_TYPE_TYPEDBYREF:
5321 case MONO_TYPE_VALUETYPE:
5322 case MONO_TYPE_CLASS:
5323 case MONO_TYPE_SZARRAY:
5324 return t1->data.klass == t2->data.klass;
5326 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5327 case MONO_TYPE_ARRAY:
5328 if (t1->data.array->rank != t2->data.array->rank)
5330 return t1->data.array->eklass == t2->data.array->eklass;
5331 case MONO_TYPE_GENERICINST: {
5333 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5335 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5336 &t2->data.generic_class->container_class->byval_arg))
5338 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5339 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5345 case MONO_TYPE_MVAR:
5346 return t1->data.generic_param == t2->data.generic_param;
5348 g_error ("implement type compare for %0x!", t1->type);
5356 mymono_metadata_type_hash (MonoType *t1)
5362 hash |= t1->byref << 6; /* do not collide with t1->type values */
5364 case MONO_TYPE_VALUETYPE:
5365 case MONO_TYPE_CLASS:
5366 case MONO_TYPE_SZARRAY:
5367 /* check if the distribution is good enough */
5368 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5370 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5371 case MONO_TYPE_GENERICINST: {
5373 MonoGenericInst *inst = t1->data.generic_class->inst;
5374 hash += g_str_hash (t1->data.generic_class->container_class->name);
5376 for (i = 0; i < inst->type_argc; ++i) {
5377 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5386 static MonoReflectionGenericClass*
5387 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5389 static MonoClass *System_Reflection_MonoGenericClass;
5390 MonoReflectionGenericClass *res;
5391 MonoInflatedGenericClass *gclass;
5394 if (!System_Reflection_MonoGenericClass) {
5395 System_Reflection_MonoGenericClass = mono_class_from_name (
5396 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5397 g_assert (System_Reflection_MonoGenericClass);
5400 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5401 gklass = gclass->generic_class.container_class;
5403 mono_class_init (gclass->klass);
5405 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5407 res->type.type = geninst;
5408 if (gklass->wastypebuilder && gklass->reflection_info)
5409 res->generic_type = gklass->reflection_info;
5411 res->generic_type = mono_type_get_object (
5412 domain, &gclass->generic_class.container_class->byval_arg);
5418 * mono_type_get_object:
5419 * @domain: an app domain
5422 * Return an System.MonoType object representing the type @type.
5425 mono_type_get_object (MonoDomain *domain, MonoType *type)
5427 MonoReflectionType *res;
5428 MonoClass *klass = mono_class_from_mono_type (type);
5430 mono_domain_lock (domain);
5431 if (!domain->type_hash)
5432 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5433 (GCompareFunc)mymono_metadata_type_equal);
5434 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5435 mono_domain_unlock (domain);
5438 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5439 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5440 mono_g_hash_table_insert (domain->type_hash, type, res);
5441 mono_domain_unlock (domain);
5444 if (klass->reflection_info && !klass->wastypebuilder) {
5445 /* g_assert_not_reached (); */
5446 /* should this be considered an error condition? */
5448 mono_domain_unlock (domain);
5449 return klass->reflection_info;
5452 mono_class_init (klass);
5453 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5455 mono_g_hash_table_insert (domain->type_hash, type, res);
5456 mono_domain_unlock (domain);
5461 * mono_method_get_object:
5462 * @domain: an app domain
5464 * @refclass: the reflected type (can be NULL)
5466 * Return an System.Reflection.MonoMethod object representing the method @method.
5468 MonoReflectionMethod*
5469 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5472 * We use the same C representation for methods and constructors, but the type
5473 * name in C# is different.
5477 MonoReflectionMethod *ret;
5479 if (method->is_inflated) {
5480 MonoReflectionGenericMethod *gret;
5482 refclass = method->klass;
5483 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5484 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5485 cname = "MonoGenericCMethod";
5487 cname = "MonoGenericMethod";
5488 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5490 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5491 gret->method.method = method;
5492 gret->method.name = mono_string_new (domain, method->name);
5493 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5494 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5498 refclass = method->klass;
5500 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5501 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5502 cname = "MonoCMethod";
5504 cname = "MonoMethod";
5505 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5507 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5508 ret->method = method;
5509 ret->name = mono_string_new (domain, method->name);
5510 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5511 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5515 * mono_field_get_object:
5516 * @domain: an app domain
5520 * Return an System.Reflection.MonoField object representing the field @field
5523 MonoReflectionField*
5524 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5526 MonoReflectionField *res;
5529 CHECK_OBJECT (MonoReflectionField *, field, klass);
5530 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5531 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5534 res->name = mono_string_new (domain, field->name);
5535 if (field->generic_info)
5536 res->attrs = field->generic_info->generic_type->attrs;
5538 res->attrs = field->type->attrs;
5539 res->type = mono_type_get_object (domain, field->type);
5540 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5544 * mono_property_get_object:
5545 * @domain: an app domain
5547 * @property: a property
5549 * Return an System.Reflection.MonoProperty object representing the property @property
5552 MonoReflectionProperty*
5553 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5555 MonoReflectionProperty *res;
5558 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5559 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5560 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5562 res->property = property;
5563 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5567 * mono_event_get_object:
5568 * @domain: an app domain
5572 * Return an System.Reflection.MonoEvent object representing the event @event
5575 MonoReflectionEvent*
5576 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5578 MonoReflectionEvent *res;
5581 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5582 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5583 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5586 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5590 * mono_param_get_objects:
5591 * @domain: an app domain
5594 * Return an System.Reflection.ParameterInfo array object representing the parameters
5595 * in the method @method.
5598 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5600 static MonoClass *System_Reflection_ParameterInfo;
5601 MonoArray *res = NULL;
5602 MonoReflectionMethod *member = NULL;
5603 MonoReflectionParameter *param = NULL;
5604 char **names, **blobs = NULL;
5605 guint32 *types = NULL;
5606 MonoType *type = NULL;
5607 MonoObject *dbnull = mono_get_dbnull_object (domain);
5608 MonoMarshalSpec **mspecs;
5611 if (!System_Reflection_ParameterInfo)
5612 System_Reflection_ParameterInfo = mono_class_from_name (
5613 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5615 if (!mono_method_signature (method)->param_count)
5616 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5618 /* Note: the cache is based on the address of the signature into the method
5619 * since we already cache MethodInfos with the method as keys.
5621 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5623 member = mono_method_get_object (domain, method, NULL);
5624 names = g_new (char *, mono_method_signature (method)->param_count);
5625 mono_method_get_param_names (method, (const char **) names);
5627 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5628 mono_method_get_marshal_info (method, mspecs);
5630 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5631 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5632 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5633 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5634 param->MemberImpl = (MonoObject*)member;
5635 param->NameImpl = mono_string_new (domain, names [i]);
5636 param->PositionImpl = i;
5637 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5639 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5640 param->DefaultValueImpl = dbnull;
5644 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5645 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5646 get_default_param_value_blobs (method, blobs, types);
5649 /* Build MonoType for the type from the Constant Table */
5651 type = g_new0 (MonoType, 1);
5652 type->type = types [i];
5653 type->data.klass = NULL;
5654 if (types [i] == MONO_TYPE_CLASS)
5655 type->data.klass = mono_defaults.object_class;
5657 type->data.klass = mono_class_from_mono_type (type);
5659 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5661 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5662 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5663 param->DefaultValueImpl = dbnull;
5668 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5670 mono_array_set (res, gpointer, i, param);
5677 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5679 mono_metadata_free_marshal_spec (mspecs [i]);
5682 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5686 * mono_method_body_get_object:
5687 * @domain: an app domain
5690 * Return an System.Reflection.MethodBody object representing the method @method.
5692 MonoReflectionMethodBody*
5693 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5695 static MonoClass *System_Reflection_MethodBody = NULL;
5696 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5697 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5698 MonoReflectionMethodBody *ret;
5699 MonoMethodNormal *mn;
5700 MonoMethodHeader *header;
5701 guint32 method_rva, local_var_sig_token;
5703 unsigned char format, flags;
5706 if (!System_Reflection_MethodBody)
5707 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5708 if (!System_Reflection_LocalVariableInfo)
5709 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5710 if (!System_Reflection_ExceptionHandlingClause)
5711 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5713 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5715 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5716 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5717 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5718 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5720 mn = (MonoMethodNormal *)method;
5721 header = mono_method_get_header (method);
5723 /* Obtain local vars signature token */
5724 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5725 ptr = mono_image_rva_map (method->klass->image, method_rva);
5726 flags = *(const unsigned char *) ptr;
5727 format = flags & METHOD_HEADER_FORMAT_MASK;
5729 case METHOD_HEADER_TINY_FORMAT:
5730 case METHOD_HEADER_TINY_FORMAT1:
5731 local_var_sig_token = 0;
5733 case METHOD_HEADER_FAT_FORMAT:
5737 local_var_sig_token = read32 (ptr);
5740 g_assert_not_reached ();
5743 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5745 ret->init_locals = header->init_locals;
5746 ret->max_stack = header->max_stack;
5747 ret->local_var_sig_token = local_var_sig_token;
5748 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5749 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5752 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5753 for (i = 0; i < header->num_locals; ++i) {
5754 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5755 info->local_type = mono_type_get_object (domain, header->locals [i]);
5756 info->is_pinned = header->locals [i]->pinned;
5757 info->local_index = i;
5758 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5762 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5763 for (i = 0; i < header->num_clauses; ++i) {
5764 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5765 MonoExceptionClause *clause = &header->clauses [i];
5767 info->flags = clause->flags;
5768 info->try_offset = clause->try_offset;
5769 info->try_length = clause->try_len;
5770 info->handler_offset = clause->handler_offset;
5771 info->handler_length = clause->handler_len;
5772 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5773 info->filter_offset = clause->data.filter_offset;
5774 else if (clause->data.catch_class)
5775 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5777 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5780 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5785 mono_get_dbnull_object (MonoDomain *domain)
5789 static MonoClassField *dbnull_value_field = NULL;
5791 if (!dbnull_value_field) {
5792 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5793 mono_class_init (klass);
5794 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5795 g_assert (dbnull_value_field);
5797 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5804 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5806 guint32 param_index, i, lastp, crow = 0;
5807 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5810 MonoClass *klass = method->klass;
5811 MonoImage *image = klass->image;
5812 MonoMethodSignature *methodsig = mono_method_signature (method);
5814 MonoTableInfo *constt;
5815 MonoTableInfo *methodt;
5816 MonoTableInfo *paramt;
5818 if (!methodsig->param_count)
5821 mono_class_init (klass);
5823 if (klass->image->dynamic) {
5824 MonoReflectionMethodAux *aux;
5825 if (method->is_inflated)
5826 method = ((MonoMethodInflated*)method)->declaring;
5827 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5828 if (aux && aux->param_defaults) {
5829 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5830 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5835 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5836 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5837 constt = &image->tables [MONO_TABLE_CONSTANT];
5839 idx = mono_method_get_index (method) - 1;
5840 g_assert (idx != -1);
5842 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5843 if (idx + 1 < methodt->rows)
5844 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5846 lastp = paramt->rows + 1;
5848 for (i = param_index; i < lastp; ++i) {
5851 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5852 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5854 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5857 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5862 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5863 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5864 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5871 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5876 MonoType *basetype = type;
5881 klass = mono_class_from_mono_type (type);
5882 if (klass->valuetype) {
5883 object = mono_object_new (domain, klass);
5884 retval = ((gchar *) object + sizeof (MonoObject));
5885 if (klass->enumtype)
5886 basetype = klass->enum_basetype;
5891 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5898 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5902 memset (assembly, 0, sizeof (MonoAssemblyName));
5904 assembly->culture = "";
5905 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5907 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5910 while (g_ascii_isspace (*p) || *p == ',') {
5919 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5921 assembly->major = strtoul (p, &s, 10);
5922 if (s == p || *s != '.')
5925 assembly->minor = strtoul (p, &s, 10);
5926 if (s == p || *s != '.')
5929 assembly->build = strtoul (p, &s, 10);
5930 if (s == p || *s != '.')
5933 assembly->revision = strtoul (p, &s, 10);
5937 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5939 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5940 assembly->culture = "";
5943 assembly->culture = p;
5944 while (*p && *p != ',') {
5948 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5950 if (strncmp (p, "null", 4) == 0) {
5955 while (*p && *p != ',') {
5958 len = (p - start + 1);
5959 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5960 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5961 g_strlcpy (assembly->public_key_token, start, len);
5964 while (*p && *p != ',')
5968 while (g_ascii_isspace (*p) || *p == ',') {
5982 * mono_reflection_parse_type:
5985 * Parse a type name as accepted by the GetType () method and output the info
5986 * extracted in the info structure.
5987 * the name param will be mangled, so, make a copy before passing it to this function.
5988 * The fields in info will be valid until the memory pointed to by name is valid.
5990 * See also mono_type_get_name () below.
5992 * Returns: 0 on parse error.
5995 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5996 MonoTypeNameParse *info)
5998 char *start, *p, *w, *temp, *last_point, *startn;
5999 int in_modifiers = 0;
6000 int isbyref = 0, rank, arity = 0, i;
6002 start = p = w = name;
6004 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
6005 info->name = info->name_space = NULL;
6006 info->nested = NULL;
6007 info->modifiers = NULL;
6008 info->type_arguments = NULL;
6010 /* last_point separates the namespace from the name */
6016 *p = 0; /* NULL terminate the name */
6018 info->nested = g_list_append (info->nested, startn);
6019 /* we have parsed the nesting namespace + name */
6023 info->name_space = start;
6025 info->name = last_point + 1;
6027 info->name_space = (char *)"";
6046 i = strtol (p, &temp, 10);
6063 info->name_space = start;
6065 info->name = last_point + 1;
6067 info->name_space = (char *)"";
6074 if (isbyref) /* only one level allowed by the spec */
6077 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6081 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6087 info->type_arguments = g_ptr_array_new ();
6088 for (i = 0; i < arity; i++) {
6089 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6090 gboolean fqname = FALSE;
6092 g_ptr_array_add (info->type_arguments, subinfo);
6099 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6110 while (*p && (*p != ']'))
6118 if (g_ascii_isspace (*aname)) {
6125 !assembly_name_to_aname (&subinfo->assembly, aname))
6129 if (i + 1 < arity) {
6149 else if (*p != '*') /* '*' means unknown lower bound */
6155 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6166 if (g_ascii_isspace (*p)) {
6173 return 0; /* missing assembly name */
6174 if (!assembly_name_to_aname (&info->assembly, p))
6180 if (info->assembly.name)
6183 // *w = 0; /* terminate class name */
6185 if (!info->name || !*info->name)
6189 /* add other consistency checks */
6194 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6196 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6200 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6202 gboolean type_resolve = FALSE;
6205 if (info->assembly.name) {
6206 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6208 /* then we must load the assembly ourselve - see #60439 */
6209 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6213 image = assembly->image;
6214 } else if (!image) {
6215 image = mono_defaults.corlib;
6218 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6219 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6220 image = mono_defaults.corlib;
6221 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6228 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6235 image = mono_defaults.corlib;
6238 klass = mono_class_from_name_case (image, info->name_space, info->name);
6240 klass = mono_class_from_name (image, info->name_space, info->name);
6243 for (mod = info->nested; mod; mod = mod->next) {
6246 mono_class_init (klass);
6247 nested = klass->nested_classes;
6250 klass = nested->data;
6252 if (g_strcasecmp (klass->name, mod->data) == 0)
6255 if (strcmp (klass->name, mod->data) == 0)
6259 nested = nested->next;
6266 mono_class_init (klass);
6268 if (info->type_arguments) {
6269 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6270 MonoReflectionType *the_type;
6274 for (i = 0; i < info->type_arguments->len; i++) {
6275 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6277 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6278 if (!type_args [i]) {
6284 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6286 instance = mono_reflection_bind_generic_parameters (
6287 the_type, info->type_arguments->len, type_args);
6294 klass = mono_class_from_mono_type (instance);
6297 for (mod = info->modifiers; mod; mod = mod->next) {
6298 modval = GPOINTER_TO_UINT (mod->data);
6299 if (!modval) { /* byref: must be last modifier */
6300 return &klass->this_arg;
6301 } else if (modval == -1) {
6302 klass = mono_ptr_class_get (&klass->byval_arg);
6303 } else { /* array rank */
6304 klass = mono_array_class_get (klass, modval);
6306 mono_class_init (klass);
6309 return &klass->byval_arg;
6313 * mono_reflection_get_type:
6314 * @image: a metadata context
6315 * @info: type description structure
6316 * @ignorecase: flag for case-insensitive string compares
6317 * @type_resolve: whenever type resolve was already tried
6319 * Build a MonoType from the type description in @info.
6324 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6327 MonoReflectionAssembly *assembly;
6331 type = mono_reflection_get_type_internal (image, info, ignorecase);
6334 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6341 *type_resolve = TRUE;
6344 /* Reconstruct the type name */
6345 fullName = g_string_new ("");
6346 if (info->name_space && (info->name_space [0] != '\0'))
6347 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6349 g_string_printf (fullName, info->name);
6350 for (mod = info->nested; mod; mod = mod->next)
6351 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6353 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6355 if (assembly->assembly->dynamic) {
6356 /* Enumerate all modules */
6357 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6361 if (abuilder->modules) {
6362 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6363 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6364 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6370 if (!type && abuilder->loaded_modules) {
6371 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6372 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6373 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6380 type = mono_reflection_get_type_internal (assembly->assembly->image,
6383 g_string_free (fullName, TRUE);
6388 free_type_info (MonoTypeNameParse *info)
6390 g_list_free (info->modifiers);
6391 g_list_free (info->nested);
6393 if (info->type_arguments) {
6396 for (i = 0; i < info->type_arguments->len; i++) {
6397 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6399 free_type_info (subinfo);
6402 g_ptr_array_free (info->type_arguments, TRUE);
6407 * mono_reflection_type_from_name:
6409 * @image: a metadata context (can be NULL).
6411 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6412 * it defaults to get the type from @image or, if @image is NULL or loading
6413 * from it fails, uses corlib.
6417 mono_reflection_type_from_name (char *name, MonoImage *image)
6419 MonoType *type = NULL;
6420 MonoTypeNameParse info;
6423 /* Make a copy since parse_type modifies its argument */
6424 tmp = g_strdup (name);
6426 /*g_print ("requested type %s\n", str);*/
6427 if (mono_reflection_parse_type (tmp, &info)) {
6428 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6432 free_type_info (&info);
6437 * mono_reflection_get_token:
6439 * Return the metadata token of OBJ which should be an object
6440 * representing a metadata element.
6443 mono_reflection_get_token (MonoObject *obj)
6448 klass = obj->vtable->klass;
6450 if (strcmp (klass->name, "MethodBuilder") == 0) {
6451 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6453 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6454 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6455 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6457 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6458 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6459 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6460 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6461 if (tb->generic_params) {
6462 g_assert_not_reached ();
6464 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6466 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6467 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6468 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6469 } else if (strcmp (klass->name, "MonoType") == 0) {
6470 MonoReflectionType *tb = (MonoReflectionType *)obj;
6471 token = mono_class_from_mono_type (tb->type)->type_token;
6472 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6473 strcmp (klass->name, "MonoMethod") == 0) {
6474 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6475 if (m->method->is_inflated) {
6476 g_assert_not_reached ();
6477 } else if (mono_method_signature (m->method)->generic_param_count) {
6478 g_assert_not_reached ();
6479 } else if (m->method->klass->generic_class) {
6480 g_assert_not_reached ();
6482 token = m->method->token;
6484 } else if (strcmp (klass->name, "MonoField") == 0) {
6485 MonoReflectionField *f = (MonoReflectionField*)obj;
6487 token = mono_class_get_field_token (f->field);
6488 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6489 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6491 token = mono_class_get_property_token (p->property);
6492 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6493 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6495 token = mono_class_get_event_token (p->event);
6496 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6497 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6499 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6500 } else if (strcmp (klass->name, "Module") == 0) {
6501 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6504 } else if (strcmp (klass->name, "Assembly") == 0) {
6505 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6507 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6508 MonoException *ex = mono_get_exception_not_implemented (msg);
6510 mono_raise_exception (ex);
6517 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6519 int slen, type = t->type;
6524 case MONO_TYPE_BOOLEAN: {
6525 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6530 case MONO_TYPE_CHAR:
6532 case MONO_TYPE_I2: {
6533 guint16 *val = g_malloc (sizeof (guint16));
6538 #if SIZEOF_VOID_P == 4
6544 case MONO_TYPE_I4: {
6545 guint32 *val = g_malloc (sizeof (guint32));
6550 #if SIZEOF_VOID_P == 8
6551 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6556 case MONO_TYPE_I8: {
6557 guint64 *val = g_malloc (sizeof (guint64));
6562 case MONO_TYPE_VALUETYPE:
6563 if (t->data.klass->enumtype) {
6564 type = t->data.klass->enum_basetype->type;
6567 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6570 case MONO_TYPE_STRING:
6571 if (*p == (char)0xFF) {
6575 slen = mono_metadata_decode_value (p, &p);
6577 return mono_string_new_len (mono_domain_get (), p, slen);
6578 case MONO_TYPE_CLASS: {
6581 if (*p == (char)0xFF) {
6586 slen = mono_metadata_decode_value (p, &p);
6587 n = g_memdup (p, slen + 1);
6589 t = mono_reflection_type_from_name (n, image);
6591 g_warning ("Cannot load type '%s'", n);
6595 return mono_type_get_object (mono_domain_get (), t);
6599 case MONO_TYPE_OBJECT: {
6602 MonoClass *subc = NULL;
6607 } else if (subt == 0x0E) {
6608 type = MONO_TYPE_STRING;
6610 } else if (subt == 0x55) {
6613 slen = mono_metadata_decode_value (p, &p);
6614 n = g_memdup (p, slen + 1);
6616 t = mono_reflection_type_from_name (n, image);
6618 g_warning ("Cannot load type '%s'", n);
6621 subc = mono_class_from_mono_type (t);
6622 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6623 MonoType simple_type = {{0}};
6624 simple_type.type = subt;
6625 subc = mono_class_from_mono_type (&simple_type);
6627 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6629 val = load_cattr_value (image, &subc->byval_arg, p, end);
6630 obj = mono_object_new (mono_domain_get (), subc);
6631 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6635 case MONO_TYPE_SZARRAY: {
6637 guint32 i, alen, basetype;
6640 if (alen == 0xffffffff) {
6644 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6645 basetype = t->data.klass->byval_arg.type;
6650 case MONO_TYPE_BOOLEAN:
6651 for (i = 0; i < alen; i++) {
6652 MonoBoolean val = *p++;
6653 mono_array_set (arr, MonoBoolean, i, val);
6656 case MONO_TYPE_CHAR:
6659 for (i = 0; i < alen; i++) {
6660 guint16 val = read16 (p);
6661 mono_array_set (arr, guint16, i, val);
6668 for (i = 0; i < alen; i++) {
6669 guint32 val = read32 (p);
6670 mono_array_set (arr, guint32, i, val);
6677 for (i = 0; i < alen; i++) {
6678 guint64 val = read64 (p);
6679 mono_array_set (arr, guint64, i, val);
6683 case MONO_TYPE_CLASS:
6684 case MONO_TYPE_OBJECT:
6685 case MONO_TYPE_STRING:
6686 for (i = 0; i < alen; i++) {
6687 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6688 mono_array_set (arr, gpointer, i, item);
6692 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6698 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6704 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6706 static MonoClass *klass;
6707 static MonoMethod *ctor;
6709 void *params [2], *unboxed;
6712 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6714 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6716 params [0] = mono_type_get_object (mono_domain_get (), t);
6718 retval = mono_object_new (mono_domain_get (), klass);
6719 unboxed = mono_object_unbox (retval);
6720 mono_runtime_invoke (ctor, unboxed, params, NULL);
6726 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6728 static MonoClass *klass;
6729 static MonoMethod *ctor;
6731 void *unboxed, *params [2];
6734 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6736 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6739 params [1] = typedarg;
6740 retval = mono_object_new (mono_domain_get (), klass);
6741 unboxed = mono_object_unbox (retval);
6742 mono_runtime_invoke (ctor, unboxed, params, NULL);
6748 type_is_reference (MonoType *type)
6750 switch (type->type) {
6751 case MONO_TYPE_BOOLEAN:
6752 case MONO_TYPE_CHAR:
6765 case MONO_TYPE_VALUETYPE:
6773 free_param_data (MonoMethodSignature *sig, void **params) {
6775 for (i = 0; i < sig->param_count; ++i) {
6776 if (!type_is_reference (sig->params [i]))
6777 g_free (params [i]);
6782 * Find the field index in the metadata FieldDef table.
6785 find_field_index (MonoClass *klass, MonoClassField *field) {
6788 for (i = 0; i < klass->field.count; ++i) {
6789 if (field == &klass->fields [i])
6790 return klass->field.first + 1 + i;
6796 * Find the property index in the metadata Property table.
6799 find_property_index (MonoClass *klass, MonoProperty *property) {
6802 for (i = 0; i < klass->property.count; ++i) {
6803 if (property == &klass->properties [i])
6804 return klass->property.first + 1 + i;
6810 * Find the event index in the metadata Event table.
6813 find_event_index (MonoClass *klass, MonoEvent *event) {
6816 for (i = 0; i < klass->event.count; ++i) {
6817 if (event == &klass->events [i])
6818 return klass->event.first + 1 + i;
6824 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6826 const char *p = data;
6828 guint32 i, j, num_named;
6832 mono_class_init (method->klass);
6835 attr = mono_object_new (mono_domain_get (), method->klass);
6836 mono_runtime_invoke (method, attr, NULL, NULL);
6840 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6843 /*g_print ("got attr %s\n", method->klass->name);*/
6845 /* Allocate using alloca so it gets GC tracking */
6846 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6850 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6851 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6855 attr = mono_object_new (mono_domain_get (), method->klass);
6856 mono_runtime_invoke (method, attr, params, NULL);
6857 free_param_data (method->signature, params);
6858 num_named = read16 (named);
6860 for (j = 0; j < num_named; j++) {
6862 gboolean is_boxed = FALSE;
6863 char *name, named_type, data_type;
6864 named_type = *named++;
6865 data_type = *named++; /* type of data */
6866 if (data_type == 0x51)
6869 if (data_type == 0x55) {
6872 type_len = mono_metadata_decode_blob_size (named, &named);
6873 type_name = g_malloc (type_len + 1);
6874 memcpy (type_name, named, type_len);
6875 type_name [type_len] = 0;
6877 /* FIXME: lookup the type and check type consistency */
6879 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6880 /* this seems to be the type of the element of the array */
6881 /* g_print ("skipping 0x%02x after prop\n", *named); */
6884 name_len = mono_metadata_decode_blob_size (named, &named);
6885 name = g_malloc (name_len + 1);
6886 memcpy (name, named, name_len);
6887 name [name_len] = 0;
6889 if (named_type == 0x53) {
6890 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6891 void *val = load_cattr_value (image, field->type, named, &named);
6892 mono_field_set_value (attr, field, val);
6893 if (!type_is_reference (field->type))
6895 } else if (named_type == 0x54) {
6898 MonoType *prop_type;
6900 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6901 /* can we have more that 1 arg in a custom attr named property? */
6902 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6903 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6904 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6905 mono_property_set_value (prop, attr, pparams, NULL);
6906 if (!type_is_reference (prop_type))
6907 g_free (pparams [0]);
6916 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6918 MonoArray *typedargs, *namedargs;
6919 MonoClass *attrklass;
6920 static MonoClass *klass;
6921 static MonoMethod *ctor;
6924 const char *p = data;
6926 guint32 i, j, num_named;
6929 mono_class_init (method->klass);
6932 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6934 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6936 domain = mono_domain_get ();
6938 /* This is for Attributes with no parameters */
6939 attr = mono_object_new (domain, klass);
6940 params [0] = mono_method_get_object (domain, method, NULL);
6941 params [1] = params [2] = NULL;
6942 mono_runtime_invoke (method, attr, params, NULL);
6946 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6949 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6953 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6954 MonoObject *obj, *typedarg;
6957 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6958 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6959 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6960 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6961 mono_array_set (typedargs, void*, i, typedarg);
6963 if (!type_is_reference (mono_method_signature (method)->params [i]))
6968 num_named = read16 (named);
6969 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6971 attrklass = method->klass;
6972 for (j = 0; j < num_named; j++) {
6974 char *name, named_type, data_type;
6975 named_type = *named++;
6976 data_type = *named++; /* type of data */
6977 if (data_type == 0x55) {
6980 type_len = mono_metadata_decode_blob_size (named, &named);
6981 type_name = g_malloc (type_len + 1);
6982 memcpy (type_name, named, type_len);
6983 type_name [type_len] = 0;
6985 /* FIXME: lookup the type and check type consistency */
6987 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6988 /* this seems to be the type of the element of the array */
6989 /* g_print ("skipping 0x%02x after prop\n", *named); */
6992 name_len = mono_metadata_decode_blob_size (named, &named);
6993 name = g_malloc (name_len + 1);
6994 memcpy (name, named, name_len);
6995 name [name_len] = 0;
6997 if (named_type == 0x53) {
6998 MonoObject *obj, *typedarg, *namedarg;
6999 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
7000 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
7002 minfo = mono_field_get_object (domain, NULL, field);
7003 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
7004 typedarg = create_cattr_typed_arg (field->type, obj);
7005 namedarg = create_cattr_named_arg (minfo, typedarg);
7006 mono_array_set (namedargs, void*, j, namedarg);
7007 if (!type_is_reference (field->type))
7009 } else if (named_type == 0x54) {
7010 MonoObject *obj, *typedarg, *namedarg;
7011 MonoType *prop_type;
7013 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
7015 prop_type = prop->get? mono_method_signature (prop->get)->ret :
7016 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
7017 minfo = mono_property_get_object (domain, NULL, prop);
7018 val = load_cattr_value (image, prop_type, named, &named);
7019 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
7020 typedarg = create_cattr_typed_arg (prop_type, obj);
7021 namedarg = create_cattr_named_arg (minfo, typedarg);
7022 mono_array_set (namedargs, void*, j, namedarg);
7023 if (!type_is_reference (prop_type))
7028 attr = mono_object_new (domain, klass);
7029 params [0] = mono_method_get_object (domain, method, NULL);
7030 params [1] = typedargs;
7031 params [2] = namedargs;
7032 mono_runtime_invoke (ctor, attr, params, NULL);
7037 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7044 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7045 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7046 for (i = 0; i < cinfo->num_attrs; ++i) {
7047 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7048 mono_array_set (result, gpointer, i, attr);
7054 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7062 for (i = 0; i < cinfo->num_attrs; ++i) {
7063 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
7067 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7068 result = mono_array_new (mono_domain_get (), klass, n);
7070 for (i = 0; i < cinfo->num_attrs; ++i) {
7071 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass)) {
7072 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7073 mono_array_set (result, gpointer, n, attr);
7081 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7084 static MonoClass *klass;
7089 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7091 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7092 for (i = 0; i < cinfo->num_attrs; ++i) {
7093 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7094 mono_array_set (result, gpointer, i, attr);
7100 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7102 guint32 mtoken, i, len;
7103 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7105 MonoCustomAttrInfo *ainfo;
7106 GList *tmp, *list = NULL;
7109 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7111 i = mono_metadata_custom_attrs_from_index (image, idx);
7115 while (i < ca->rows) {
7116 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7118 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7121 len = g_list_length (list);
7124 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7125 ainfo->num_attrs = len;
7126 ainfo->image = image;
7127 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7128 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7129 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7130 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7131 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7132 mtoken |= MONO_TOKEN_METHOD_DEF;
7134 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7135 mtoken |= MONO_TOKEN_MEMBER_REF;
7138 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7141 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7142 if (!ainfo->attrs [i].ctor)
7143 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7144 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7145 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7146 ainfo->attrs [i].data = data;
7154 mono_custom_attrs_from_method (MonoMethod *method)
7156 MonoCustomAttrInfo *cinfo;
7159 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7161 idx = mono_method_get_index (method);
7162 idx <<= MONO_CUSTOM_ATTR_BITS;
7163 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7164 return mono_custom_attrs_from_index (method->klass->image, idx);
7168 mono_custom_attrs_from_class (MonoClass *klass)
7170 MonoCustomAttrInfo *cinfo;
7173 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7175 idx = mono_metadata_token_index (klass->type_token);
7176 idx <<= MONO_CUSTOM_ATTR_BITS;
7177 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7178 return mono_custom_attrs_from_index (klass->image, idx);
7182 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7184 MonoCustomAttrInfo *cinfo;
7187 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7189 idx = 1; /* there is only one assembly */
7190 idx <<= MONO_CUSTOM_ATTR_BITS;
7191 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7192 return mono_custom_attrs_from_index (assembly->image, idx);
7195 static MonoCustomAttrInfo*
7196 mono_custom_attrs_from_module (MonoImage *image)
7198 MonoCustomAttrInfo *cinfo;
7201 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7203 idx = 1; /* there is only one module */
7204 idx <<= MONO_CUSTOM_ATTR_BITS;
7205 idx |= MONO_CUSTOM_ATTR_MODULE;
7206 return mono_custom_attrs_from_index (image, idx);
7210 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7212 MonoCustomAttrInfo *cinfo;
7215 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7217 idx = find_property_index (klass, property);
7218 idx <<= MONO_CUSTOM_ATTR_BITS;
7219 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7220 return mono_custom_attrs_from_index (klass->image, idx);
7224 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7226 MonoCustomAttrInfo *cinfo;
7229 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7231 idx = find_event_index (klass, event);
7232 idx <<= MONO_CUSTOM_ATTR_BITS;
7233 idx |= MONO_CUSTOM_ATTR_EVENT;
7234 return mono_custom_attrs_from_index (klass->image, idx);
7238 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7240 MonoCustomAttrInfo *cinfo;
7243 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7245 idx = find_field_index (klass, field);
7246 idx <<= MONO_CUSTOM_ATTR_BITS;
7247 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7248 return mono_custom_attrs_from_index (klass->image, idx);
7252 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7255 guint32 i, idx, method_index;
7256 guint32 param_list, param_last, param_pos, found;
7258 MonoReflectionMethodAux *aux;
7260 if (method->klass->image->dynamic) {
7261 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7262 if (!aux || !aux->param_cattr)
7264 return aux->param_cattr [param];
7267 image = method->klass->image;
7268 method_index = mono_method_get_index (method);
7269 ca = &image->tables [MONO_TABLE_METHOD];
7271 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7272 /* FIXME FIXME FIXME */
7276 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7277 if (method_index == ca->rows) {
7278 ca = &image->tables [MONO_TABLE_PARAM];
7279 param_last = ca->rows + 1;
7281 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7282 ca = &image->tables [MONO_TABLE_PARAM];
7285 for (i = param_list; i < param_last; ++i) {
7286 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7287 if (param_pos == param) {
7295 idx <<= MONO_CUSTOM_ATTR_BITS;
7296 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7297 return mono_custom_attrs_from_index (image, idx);
7301 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7305 for (i = 0; i < ainfo->num_attrs; ++i) {
7306 klass = ainfo->attrs [i].ctor->klass;
7307 if (mono_class_has_parent (klass, attr_klass))
7314 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7321 for (i = 0; i < ainfo->num_attrs; ++i) {
7322 klass = ainfo->attrs [i].ctor->klass;
7323 if (mono_class_has_parent (klass, attr_klass)) {
7328 if (attr_index == -1)
7331 attrs = mono_custom_attrs_construct (ainfo);
7333 return mono_array_get (attrs, MonoObject*, attr_index);
7339 * mono_reflection_get_custom_attrs_info:
7340 * @obj: a reflection object handle
7342 * Return the custom attribute info for attributes defined for the
7343 * reflection handle @obj. The objects.
7346 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7349 MonoCustomAttrInfo *cinfo = NULL;
7351 klass = obj->vtable->klass;
7352 if (klass == mono_defaults.monotype_class) {
7353 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7354 klass = mono_class_from_mono_type (rtype->type);
7355 cinfo = mono_custom_attrs_from_class (klass);
7356 } else if (strcmp ("Assembly", klass->name) == 0) {
7357 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7358 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7359 } else if (strcmp ("Module", klass->name) == 0) {
7360 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7361 cinfo = mono_custom_attrs_from_module (module->image);
7362 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7363 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7364 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7365 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7366 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7367 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7368 } else if (strcmp ("MonoField", klass->name) == 0) {
7369 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7370 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7371 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7372 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7373 cinfo = mono_custom_attrs_from_method (rmethod->method);
7374 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7375 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7376 cinfo = mono_custom_attrs_from_method (method);
7377 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7378 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7379 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7380 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7381 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7382 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7383 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7384 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7385 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7386 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7387 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7388 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7389 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7390 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
7391 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7392 cinfo = mono_custom_attrs_from_builders (cb->mhandle->klass->image, cb->cattrs);
7393 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
7394 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7395 cinfo = mono_custom_attrs_from_builders (mb->mhandle->klass->image, mb->cattrs);
7396 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
7397 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7398 cinfo = mono_custom_attrs_from_builders (&((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
7399 } else { /* handle other types here... */
7400 g_error ("get custom attrs not yet supported for %s", klass->name);
7407 * mono_reflection_get_custom_attrs_by_type:
7408 * @obj: a reflection object handle
7410 * Return an array with all the custom attributes defined of the
7411 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7412 * of that type are returned. The objects are fully build.
7415 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7418 MonoCustomAttrInfo *cinfo;
7420 cinfo = mono_reflection_get_custom_attrs_info (obj);
7423 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7425 result = mono_custom_attrs_construct (cinfo);
7427 mono_custom_attrs_free (cinfo);
7430 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7431 result = mono_array_new (mono_domain_get (), klass, 0);
7438 * mono_reflection_get_custom_attrs:
7439 * @obj: a reflection object handle
7441 * Return an array with all the custom attributes defined of the
7442 * reflection handle @obj. The objects are fully build.
7445 mono_reflection_get_custom_attrs (MonoObject *obj)
7447 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7451 * mono_reflection_get_custom_attrs_data:
7452 * @obj: a reflection obj handle
7454 * Returns an array of System.Reflection.CustomAttributeData,
7455 * which include information about attributes reflected on
7456 * types loaded using the Reflection Only methods
7459 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7462 MonoCustomAttrInfo *cinfo;
7464 cinfo = mono_reflection_get_custom_attrs_info (obj);
7466 result = mono_custom_attrs_data_construct (cinfo);
7468 mono_custom_attrs_free (cinfo);
7471 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7472 result = mono_array_new (mono_domain_get (), klass, 0);
7478 static MonoMethodSignature*
7479 parameters_to_signature (MonoArray *parameters) {
7480 MonoMethodSignature *sig;
7483 count = parameters? mono_array_length (parameters): 0;
7485 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7486 sig->param_count = count;
7487 sig->sentinelpos = -1; /* FIXME */
7488 for (i = 0; i < count; ++i) {
7489 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7490 sig->params [i] = pt->type;
7495 static MonoMethodSignature*
7496 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7497 MonoMethodSignature *sig;
7499 sig = parameters_to_signature (ctor->parameters);
7500 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7501 sig->ret = &mono_defaults.void_class->byval_arg;
7505 static MonoMethodSignature*
7506 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7507 MonoMethodSignature *sig;
7509 sig = parameters_to_signature (method->parameters);
7510 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7511 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7512 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7516 static MonoMethodSignature*
7517 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7518 MonoMethodSignature *sig;
7520 sig = parameters_to_signature (method->parameters);
7521 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7522 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7523 sig->generic_param_count = 0;
7528 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7530 MonoClass *klass = mono_object_class (prop);
7531 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7532 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7533 *name = mono_string_to_utf8 (pb->name);
7534 *type = pb->type->type;
7536 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7537 *name = g_strdup (p->property->name);
7538 if (p->property->get)
7539 *type = mono_method_signature (p->property->get)->ret;
7541 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7546 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7548 MonoClass *klass = mono_object_class (field);
7549 if (strcmp (klass->name, "FieldBuilder") == 0) {
7550 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7551 *name = mono_string_to_utf8 (fb->name);
7552 *type = fb->type->type;
7554 MonoReflectionField *f = (MonoReflectionField *)field;
7555 *name = g_strdup (f->field->name);
7556 *type = f->field->type;
7561 * Encode a value in a custom attribute stream of bytes.
7562 * The value to encode is either supplied as an object in argument val
7563 * (valuetypes are boxed), or as a pointer to the data in the
7565 * @type represents the type of the value
7566 * @buffer is the start of the buffer
7567 * @p the current position in the buffer
7568 * @buflen contains the size of the buffer and is used to return the new buffer size
7569 * if this needs to be realloced.
7570 * @retbuffer and @retp return the start and the position of the buffer
7573 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7575 MonoTypeEnum simple_type;
7577 if ((p-buffer) + 10 >= *buflen) {
7580 newbuf = g_realloc (buffer, *buflen);
7581 p = newbuf + (p-buffer);
7585 argval = ((char*)arg + sizeof (MonoObject));
7586 simple_type = type->type;
7588 switch (simple_type) {
7589 case MONO_TYPE_BOOLEAN:
7594 case MONO_TYPE_CHAR:
7597 swap_with_size (p, argval, 2, 1);
7603 swap_with_size (p, argval, 4, 1);
7609 swap_with_size (p, argval, 8, 1);
7612 case MONO_TYPE_VALUETYPE:
7613 if (type->data.klass->enumtype) {
7614 simple_type = type->data.klass->enum_basetype->type;
7617 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7620 case MONO_TYPE_STRING: {
7627 str = mono_string_to_utf8 ((MonoString*)arg);
7628 slen = strlen (str);
7629 if ((p-buffer) + 10 + slen >= *buflen) {
7633 newbuf = g_realloc (buffer, *buflen);
7634 p = newbuf + (p-buffer);
7637 mono_metadata_encode_value (slen, p, &p);
7638 memcpy (p, str, slen);
7643 case MONO_TYPE_CLASS: {
7651 k = mono_object_class (arg);
7652 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7653 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7654 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7656 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7657 slen = strlen (str);
7658 if ((p-buffer) + 10 + slen >= *buflen) {
7662 newbuf = g_realloc (buffer, *buflen);
7663 p = newbuf + (p-buffer);
7666 mono_metadata_encode_value (slen, p, &p);
7667 memcpy (p, str, slen);
7672 case MONO_TYPE_SZARRAY: {
7674 MonoClass *eclass, *arg_eclass;
7677 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7680 len = mono_array_length ((MonoArray*)arg);
7682 *p++ = (len >> 8) & 0xff;
7683 *p++ = (len >> 16) & 0xff;
7684 *p++ = (len >> 24) & 0xff;
7686 *retbuffer = buffer;
7687 eclass = type->data.klass;
7688 arg_eclass = mono_object_class (arg)->element_class;
7689 if (eclass->valuetype && arg_eclass->valuetype) {
7690 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7691 int elsize = mono_class_array_element_size (eclass);
7692 for (i = 0; i < len; ++i) {
7693 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7697 for (i = 0; i < len; ++i) {
7698 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7703 /* it may be a boxed value or a Type */
7704 case MONO_TYPE_OBJECT: {
7710 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7715 klass = mono_object_class (arg);
7717 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7720 } else if (klass->enumtype) {
7722 } else if (klass == mono_defaults.string_class) {
7723 simple_type = MONO_TYPE_STRING;
7726 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7727 *p++ = simple_type = klass->byval_arg.type;
7730 g_error ("unhandled type in custom attr");
7732 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7733 slen = strlen (str);
7734 if ((p-buffer) + 10 + slen >= *buflen) {
7738 newbuf = g_realloc (buffer, *buflen);
7739 p = newbuf + (p-buffer);
7742 mono_metadata_encode_value (slen, p, &p);
7743 memcpy (p, str, slen);
7746 simple_type = klass->enum_basetype->type;
7750 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7753 *retbuffer = buffer;
7757 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7760 /* Preallocate a large enough buffer */
7761 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7762 char *str = type_get_qualified_name (type, NULL);
7768 len += strlen (name);
7770 if ((p-buffer) + 20 + len >= *buflen) {
7774 newbuf = g_realloc (buffer, *buflen);
7775 p = newbuf + (p-buffer);
7779 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7780 char *str = type_get_qualified_name (type, NULL);
7781 int slen = strlen (str);
7785 * This seems to be optional...
7788 mono_metadata_encode_value (slen, p, &p);
7789 memcpy (p, str, slen);
7792 } else if (type->type == MONO_TYPE_OBJECT) {
7794 } else if (type->type == MONO_TYPE_CLASS) {
7795 /* it should be a type: encode_cattr_value () has the check */
7798 mono_metadata_encode_value (type->type, p, &p);
7799 if (type->type == MONO_TYPE_SZARRAY)
7800 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7802 len = strlen (name);
7803 mono_metadata_encode_value (len, p, &p);
7804 memcpy (p, name, len);
7806 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7808 *retbuffer = buffer;
7812 * mono_reflection_get_custom_attrs_blob:
7813 * @ctor: custom attribute constructor
7814 * @ctorArgs: arguments o the constructor
7820 * Creates the blob of data that needs to be saved in the metadata and that represents
7821 * the custom attributed described by @ctor, @ctorArgs etc.
7822 * Returns: a Byte array representing the blob of data.
7825 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7828 MonoMethodSignature *sig;
7833 MONO_ARCH_SAVE_REGS;
7835 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7836 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7838 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7840 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7842 p = buffer = g_malloc (buflen);
7843 /* write the prolog */
7846 for (i = 0; i < sig->param_count; ++i) {
7847 arg = mono_array_get (ctorArgs, MonoObject*, i);
7848 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7852 i += mono_array_length (properties);
7854 i += mono_array_length (fields);
7856 *p++ = (i >> 8) & 0xff;
7859 for (i = 0; i < mono_array_length (properties); ++i) {
7863 prop = mono_array_get (properties, gpointer, i);
7864 get_prop_name_and_type (prop, &pname, &ptype);
7865 *p++ = 0x54; /* PROPERTY signature */
7866 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7873 for (i = 0; i < mono_array_length (fields); ++i) {
7877 field = mono_array_get (fields, gpointer, i);
7878 get_field_name_and_type (field, &fname, &ftype);
7879 *p++ = 0x53; /* FIELD signature */
7880 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7885 g_assert (p - buffer <= buflen);
7886 buflen = p - buffer;
7887 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7888 p = mono_array_addr (result, char, 0);
7889 memcpy (p, buffer, buflen);
7891 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7897 * mono_reflection_setup_internal_class:
7898 * @tb: a TypeBuilder object
7900 * Creates a MonoClass that represents the TypeBuilder.
7901 * This is a trick that lets us simplify a lot of reflection code
7902 * (and will allow us to support Build and Run assemblies easier).
7905 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7907 MonoClass *klass, *parent;
7909 MONO_ARCH_SAVE_REGS;
7911 mono_loader_lock ();
7914 /* check so we can compile corlib correctly */
7915 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7916 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7917 parent = tb->parent->type->data.klass;
7919 parent = my_mono_class_from_mono_type (tb->parent->type);
7925 /* the type has already being created: it means we just have to change the parent */
7926 if (tb->type.type) {
7927 klass = mono_class_from_mono_type (tb->type.type);
7928 klass->parent = NULL;
7929 /* fool mono_class_setup_parent */
7930 g_free (klass->supertypes);
7931 klass->supertypes = NULL;
7932 mono_class_setup_parent (klass, parent);
7933 mono_class_setup_mono_type (klass);
7934 mono_loader_unlock ();
7938 klass = g_new0 (MonoClass, 1);
7940 klass->image = &tb->module->dynamic_image->image;
7942 klass->inited = 1; /* we lie to the runtime */
7943 klass->name = mono_string_to_utf8 (tb->name);
7944 klass->name_space = mono_string_to_utf8 (tb->nspace);
7945 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7946 klass->flags = tb->attrs;
7948 klass->element_class = klass;
7949 klass->reflection_info = tb; /* need to pin. */
7951 /* Put into cache so mono_class_get () will find it */
7952 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7954 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7955 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7957 if (parent != NULL) {
7958 mono_class_setup_parent (klass, parent);
7959 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7960 const char *old_n = klass->name;
7961 /* trick to get relative numbering right when compiling corlib */
7962 klass->name = "BuildingObject";
7963 mono_class_setup_parent (klass, mono_defaults.object_class);
7964 klass->name = old_n;
7967 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7968 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7969 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7970 klass->instance_size = sizeof (MonoObject);
7971 klass->size_inited = 1;
7972 mono_class_setup_vtable_general (klass, NULL, 0);
7975 mono_class_setup_mono_type (klass);
7977 mono_class_setup_supertypes (klass);
7980 * FIXME: handle interfaces.
7983 tb->type.type = &klass->byval_arg;
7985 if (tb->nesting_type) {
7986 g_assert (tb->nesting_type->type);
7987 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7990 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7992 mono_loader_unlock ();
7996 * mono_reflection_setup_generic_class:
7997 * @tb: a TypeBuilder object
7999 * Setup the generic class before adding the first generic parameter.
8002 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
8006 MONO_ARCH_SAVE_REGS;
8008 klass = my_mono_class_from_mono_type (tb->type.type);
8009 if (tb->generic_container)
8012 tb->generic_container = g_new0 (MonoGenericContainer, 1);
8013 tb->generic_container->klass = klass;
8015 tb->generic_container->context.container = tb->generic_container;
8019 * mono_reflection_create_generic_class:
8020 * @tb: a TypeBuilder object
8022 * Creates the generic class after all generic parameters have been added.
8025 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
8030 MONO_ARCH_SAVE_REGS;
8032 klass = my_mono_class_from_mono_type (tb->type.type);
8034 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
8036 if (klass->generic_container || (count == 0))
8039 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8041 klass->generic_container = tb->generic_container;
8043 klass->generic_container->type_argc = count;
8044 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8046 for (i = 0; i < count; i++) {
8047 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8048 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8049 g_assert (klass->generic_container->type_params [i].owner);
8052 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8056 * mono_reflection_create_internal_class:
8057 * @tb: a TypeBuilder object
8059 * Actually create the MonoClass that is associated with the TypeBuilder.
8062 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8066 MONO_ARCH_SAVE_REGS;
8068 klass = my_mono_class_from_mono_type (tb->type.type);
8070 mono_loader_lock ();
8071 if (klass->enumtype && klass->enum_basetype == NULL) {
8072 MonoReflectionFieldBuilder *fb;
8075 g_assert (tb->fields != NULL);
8076 g_assert (mono_array_length (tb->fields) >= 1);
8078 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8080 klass->enum_basetype = fb->type->type;
8081 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8082 if (!klass->element_class)
8083 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8086 * get the element_class from the current corlib.
8088 ec = default_class_from_mono_type (klass->enum_basetype);
8089 klass->instance_size = ec->instance_size;
8090 klass->size_inited = 1;
8092 * this is almost safe to do with enums and it's needed to be able
8093 * to create objects of the enum type (for use in SetConstant).
8095 /* FIXME: Does this mean enums can't have method overrides ? */
8096 mono_class_setup_vtable_general (klass, NULL, 0);
8098 mono_loader_unlock ();
8101 static MonoMarshalSpec*
8102 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8103 MonoReflectionMarshal *minfo)
8105 MonoMarshalSpec *res;
8107 res = g_new0 (MonoMarshalSpec, 1);
8108 res->native = minfo->type;
8110 switch (minfo->type) {
8111 case MONO_NATIVE_LPARRAY:
8112 res->data.array_data.elem_type = minfo->eltype;
8113 if (minfo->has_size) {
8114 res->data.array_data.param_num = minfo->param_num;
8115 res->data.array_data.num_elem = minfo->count;
8116 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8119 res->data.array_data.param_num = -1;
8120 res->data.array_data.num_elem = -1;
8121 res->data.array_data.elem_mult = -1;
8125 case MONO_NATIVE_BYVALTSTR:
8126 case MONO_NATIVE_BYVALARRAY:
8127 res->data.array_data.num_elem = minfo->count;
8130 case MONO_NATIVE_CUSTOM:
8131 if (minfo->marshaltyperef)
8132 res->data.custom_data.custom_name =
8133 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8135 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8145 MonoReflectionMarshal*
8146 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8147 MonoMarshalSpec *spec)
8149 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8150 MonoReflectionMarshal *minfo;
8153 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8154 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8155 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8156 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8159 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8160 minfo->type = spec->native;
8162 switch (minfo->type) {
8163 case MONO_NATIVE_LPARRAY:
8164 minfo->eltype = spec->data.array_data.elem_type;
8165 minfo->count = spec->data.array_data.num_elem;
8166 minfo->param_num = spec->data.array_data.param_num;
8169 case MONO_NATIVE_BYVALTSTR:
8170 case MONO_NATIVE_BYVALARRAY:
8171 minfo->count = spec->data.array_data.num_elem;
8174 case MONO_NATIVE_CUSTOM:
8175 if (spec->data.custom_data.custom_name) {
8176 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8178 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8180 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8182 if (spec->data.custom_data.cookie)
8183 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8194 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8195 ReflectionMethodBuilder *rmb,
8196 MonoMethodSignature *sig)
8199 MonoMethodNormal *pm;
8200 MonoMarshalSpec **specs;
8201 MonoReflectionMethodAux *method_aux;
8204 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8205 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8206 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8208 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8210 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8212 pm = (MonoMethodNormal*)m;
8215 m->flags = rmb->attrs;
8216 m->iflags = rmb->iattrs;
8217 m->name = mono_string_to_utf8 (rmb->name);
8221 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8223 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8224 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8227 m->signature->pinvoke = 1;
8228 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8229 m->signature->pinvoke = 1;
8231 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8233 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8234 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8236 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8238 if (klass->image->dynamic)
8239 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8242 } else if (!m->klass->dummy &&
8243 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8244 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8245 MonoMethodHeader *header;
8247 gint32 max_stack, i;
8248 gint32 num_locals = 0;
8249 gint32 num_clauses = 0;
8253 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8254 code_size = rmb->ilgen->code_len;
8255 max_stack = rmb->ilgen->max_stack;
8256 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8257 if (rmb->ilgen->ex_handlers)
8258 num_clauses = method_count_clauses (rmb->ilgen);
8261 code = mono_array_addr (rmb->code, guint8, 0);
8262 code_size = mono_array_length (rmb->code);
8263 /* we probably need to run a verifier on the code... */
8273 header = g_malloc0 (sizeof (MonoMethodHeader) +
8274 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8275 header->code_size = code_size;
8276 header->code = g_malloc (code_size);
8277 memcpy ((char*)header->code, code, code_size);
8278 header->max_stack = max_stack;
8279 header->init_locals = rmb->init_locals;
8280 header->num_locals = num_locals;
8282 for (i = 0; i < num_locals; ++i) {
8283 MonoReflectionLocalBuilder *lb =
8284 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8286 header->locals [i] = g_new0 (MonoType, 1);
8287 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8290 header->num_clauses = num_clauses;
8292 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8293 rmb->ilgen, num_clauses);
8296 pm->header = header;
8299 if (rmb->generic_params) {
8300 int count = mono_array_length (rmb->generic_params);
8301 MonoGenericContainer *container;
8303 pm->generic_container = container = rmb->generic_container;
8304 container->type_argc = count;
8305 container->type_params = g_new0 (MonoGenericParam, count);
8307 for (i = 0; i < count; i++) {
8308 MonoReflectionGenericParam *gp =
8309 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8311 container->type_params [i] = *gp->type.type->data.generic_param;
8316 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8320 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8322 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8323 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8324 for (i = 0; i < rmb->nrefs; ++i)
8325 data [i + 1] = rmb->refs [i];
8330 /* Parameter info */
8333 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8334 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8335 for (i = 0; i <= m->signature->param_count; ++i) {
8336 MonoReflectionParamBuilder *pb;
8337 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8338 if ((i > 0) && (pb->attrs)) {
8339 /* Make a copy since it might point to a shared type structure */
8340 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)));
8341 m->signature->params [i - 1]->attrs = pb->attrs;
8344 if (pb->def_value) {
8345 MonoDynamicImage *assembly;
8346 guint32 idx, def_type, len;
8350 if (!method_aux->param_defaults) {
8351 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8352 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8354 assembly = (MonoDynamicImage*)klass->image;
8355 idx = encode_constant (assembly, pb->def_value, &def_type);
8356 /* Copy the data from the blob since it might get realloc-ed */
8357 p = assembly->blob.data + idx;
8358 len = mono_metadata_decode_blob_size (p, &p2);
8360 method_aux->param_defaults [i] = g_malloc (len);
8361 method_aux->param_default_types [i] = def_type;
8362 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8366 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8368 if (!method_aux->param_cattr)
8369 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8370 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8376 /* Parameter marshalling */
8379 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8380 MonoReflectionParamBuilder *pb;
8381 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8382 if (pb->marshal_info) {
8384 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8385 specs [pb->position] =
8386 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8390 if (specs != NULL) {
8392 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8393 method_aux->param_marshall = specs;
8396 if (klass->image->dynamic && method_aux)
8397 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8403 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8405 ReflectionMethodBuilder rmb;
8406 MonoMethodSignature *sig;
8408 sig = ctor_builder_to_signature (mb);
8410 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8412 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8413 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8415 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8416 /* ilgen is no longer needed */
8424 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8426 ReflectionMethodBuilder rmb;
8427 MonoMethodSignature *sig;
8429 sig = method_builder_to_signature (mb);
8431 reflection_methodbuilder_from_method_builder (&rmb, mb);
8433 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8434 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8436 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8437 /* ilgen is no longer needed */
8443 static MonoClassField*
8444 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8446 MonoClassField *field;
8453 field = g_new0 (MonoClassField, 1);
8455 field->name = mono_string_to_utf8 (fb->name);
8457 /* FIXME: handle type modifiers */
8458 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8459 field->type->attrs = fb->attrs;
8461 field->type = fb->type->type;
8463 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8464 field->data = mono_array_addr (fb->rva_data, char, 0);
8465 if (fb->offset != -1)
8466 field->offset = fb->offset;
8467 field->parent = klass;
8469 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8471 if (fb->def_value) {
8472 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8473 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8474 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8475 /* Copy the data from the blob since it might get realloc-ed */
8476 p = assembly->blob.data + idx;
8477 len = mono_metadata_decode_blob_size (p, &p2);
8479 field->data = g_malloc (len);
8480 memcpy ((gpointer)field->data, p, len);
8487 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8491 MonoReflectionTypeBuilder *tb = NULL;
8492 MonoGenericClass *gclass, *cached;
8493 MonoInflatedGenericClass *igclass;
8494 MonoDynamicGenericClass *dgclass = NULL;
8495 gboolean is_dynamic = FALSE;
8500 klass = mono_class_from_mono_type (type->type);
8501 if (!klass->generic_container && !klass->generic_class &&
8502 !(klass->nested_in && klass->nested_in->generic_container))
8505 mono_loader_lock ();
8507 domain = mono_object_domain (type);
8509 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8510 tb = (MonoReflectionTypeBuilder *) type;
8512 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8514 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8515 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8516 MonoReflectionType *rgt = rgi->generic_type;
8518 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8519 tb = (MonoReflectionTypeBuilder *) rgt;
8521 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8523 } else if (klass->wastypebuilder) {
8524 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8526 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8529 icount = klass->interface_count;
8533 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8534 igclass = &dgclass->generic_class;
8535 gclass = &igclass->generic_class;
8536 gclass->is_dynamic = TRUE;
8537 gclass->is_inflated = TRUE;
8539 igclass = g_new0 (MonoInflatedGenericClass, 1);
8540 gclass = &igclass->generic_class;
8541 gclass->is_inflated = TRUE;
8544 gclass->inst = g_new0 (MonoGenericInst, 1);
8546 gclass->inst->type_argc = type_argc;
8547 gclass->inst->type_argv = types;
8548 gclass->inst->is_reference = 1;
8550 for (i = 0; i < gclass->inst->type_argc; ++i) {
8551 if (!gclass->inst->is_open)
8552 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8553 if (gclass->inst->is_reference)
8554 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8557 gclass->container_class = klass;
8559 if (klass->generic_class) {
8560 MonoGenericClass *kgclass = klass->generic_class;
8561 MonoGenericClass *ogclass = gclass;
8563 ogclass->context = g_new0 (MonoGenericContext, 1);
8564 ogclass->context->container = gclass->container_class->generic_container;
8565 ogclass->context->gclass = gclass;
8568 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8569 igclass = &dgclass->generic_class;
8570 gclass = &igclass->generic_class;
8571 gclass->is_dynamic = TRUE;
8572 gclass->is_inflated = TRUE;
8574 igclass = g_new0 (MonoInflatedGenericClass, 1);
8575 gclass = &igclass->generic_class;
8576 gclass->is_inflated = TRUE;
8579 gclass->inst = g_new0 (MonoGenericInst, 1);
8581 gclass->inst->type_argc = kgclass->inst->type_argc;
8582 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8583 gclass->inst->is_reference = 1;
8585 for (i = 0; i < gclass->inst->type_argc; i++) {
8586 MonoType *t = kgclass->inst->type_argv [i];
8588 t = mono_class_inflate_generic_type (t, ogclass->context);
8590 if (!gclass->inst->is_open)
8591 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8592 if (gclass->inst->is_reference)
8593 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8595 gclass->inst->type_argv [i] = t;
8598 gclass->container_class = kgclass->container_class;
8601 geninst = g_new0 (MonoType, 1);
8602 geninst->type = MONO_TYPE_GENERICINST;
8604 cached = mono_metadata_lookup_generic_class (gclass);
8607 mono_loader_unlock ();
8608 geninst->data.generic_class = cached;
8612 geninst->data.generic_class = gclass;
8614 gclass->context = g_new0 (MonoGenericContext, 1);
8615 gclass->context->container = gclass->container_class->generic_container;
8616 gclass->context->gclass = gclass;
8619 dgclass->parent = parent;
8620 dgclass->ifaces = g_new0 (MonoType *, icount);
8621 dgclass->count_ifaces = icount;
8623 for (i = 0; i < icount; i++) {
8624 MonoReflectionType *itype;
8627 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8629 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8630 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8631 if (!dgclass->ifaces [i])
8632 dgclass->ifaces [i] = itype->type;
8636 mono_loader_unlock ();
8642 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8644 MonoClass *klass, *pklass = NULL;
8645 MonoReflectionType *parent = NULL;
8646 MonoType *the_parent = NULL, *geninst;
8647 MonoReflectionTypeBuilder *tb = NULL;
8648 MonoGenericClass *gclass;
8651 domain = mono_object_domain (type);
8652 klass = mono_class_from_mono_type (type->type);
8654 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8655 tb = (MonoReflectionTypeBuilder *) type;
8658 parent = tb->parent;
8659 pklass = mono_class_from_mono_type (parent->type);
8661 } else if (klass->wastypebuilder) {
8662 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8664 parent = tb->parent;
8665 pklass = mono_class_from_mono_type (parent->type);
8668 pklass = klass->parent;
8670 parent = mono_type_get_object (domain, &pklass->byval_arg);
8671 else if (klass->generic_class && klass->generic_class->is_dynamic) {
8672 MonoDynamicGenericClass *dgclass;
8674 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8675 if (dgclass->parent) {
8676 parent = mono_type_get_object (domain, dgclass->parent);
8677 pklass = mono_class_from_mono_type (dgclass->parent);
8682 if (pklass && pklass->generic_class)
8683 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8685 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8689 gclass = geninst->data.generic_class;
8695 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8698 MonoGenericClass *gclass, *cached;
8699 MonoInflatedGenericClass *igclass;
8703 klass = mono_class_from_mono_type (type);
8704 if (!klass->generic_container && !klass->generic_class &&
8705 !(klass->nested_in && klass->nested_in->generic_container))
8708 mono_loader_lock ();
8710 icount = klass->interface_count;
8712 igclass = g_new0 (MonoInflatedGenericClass, 1);
8713 gclass = &igclass->generic_class;
8714 gclass->is_inflated = TRUE;
8716 gclass->inst = g_new0 (MonoGenericInst, 1);
8717 gclass->inst->type_argc = type_argc;
8718 gclass->inst->type_argv = types;
8719 gclass->inst->is_reference = 1;
8721 for (i = 0; i < gclass->inst->type_argc; ++i) {
8722 if (!gclass->inst->is_open)
8723 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8724 if (gclass->inst->is_reference)
8725 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8728 gclass->container_class = klass;
8730 if (klass->generic_class) {
8731 MonoGenericClass *kgclass = klass->generic_class;
8732 MonoGenericClass *ogclass = gclass;
8734 gclass->context = g_new0 (MonoGenericContext, 1);
8735 gclass->context->container = gclass->container_class->generic_container;
8736 gclass->context->gclass = gclass;
8738 igclass = g_new0 (MonoInflatedGenericClass, 1);
8739 gclass = &igclass->generic_class;
8740 gclass->is_inflated = TRUE;
8742 gclass->inst = g_new0 (MonoGenericInst, 1);
8743 gclass->inst->type_argc = kgclass->inst->type_argc;
8744 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8745 gclass->inst->is_reference = 1;
8747 for (i = 0; i < gclass->inst->type_argc; i++) {
8748 MonoType *t = kgclass->inst->type_argv [i];
8750 t = mono_class_inflate_generic_type (t, ogclass->context);
8752 if (!gclass->inst->is_open)
8753 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8754 if (gclass->inst->is_reference)
8755 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8757 gclass->inst->type_argv [i] = t;
8760 gclass->container_class = kgclass->container_class;
8763 geninst = g_new0 (MonoType, 1);
8764 geninst->type = MONO_TYPE_GENERICINST;
8766 cached = mono_metadata_lookup_generic_class (gclass);
8769 mono_loader_unlock ();
8770 geninst->data.generic_class = cached;
8774 geninst->data.generic_class = gclass;
8776 gclass->context = g_new0 (MonoGenericContext, 1);
8777 gclass->context->container = gclass->container_class->generic_container;
8778 gclass->context->gclass = gclass;
8780 mono_loader_unlock ();
8785 static inline MonoType*
8786 dup_type (const MonoType *original)
8788 MonoType *r = g_new0 (MonoType, 1);
8790 r->attrs = original->attrs;
8791 r->byref = original->byref;
8792 if (original->type == MONO_TYPE_PTR)
8793 r->data.type = dup_type (original->data.type);
8794 else if (original->type == MONO_TYPE_ARRAY)
8795 r->data.array = mono_dup_array_type (original->data.array);
8796 else if (original->type == MONO_TYPE_FNPTR)
8797 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8798 mono_stats.generics_metadata_size += sizeof (MonoType);
8802 MonoReflectionMethod*
8803 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8805 MonoMethod *method, *inflated;
8806 MonoReflectionMethodBuilder *mb = NULL;
8807 MonoGenericContainer *container;
8808 MonoGenericMethod *gmethod;
8809 MonoGenericContext *context;
8810 MonoGenericInst *ginst;
8813 MONO_ARCH_SAVE_REGS;
8814 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8815 MonoReflectionTypeBuilder *tb;
8818 mb = (MonoReflectionMethodBuilder *) rmethod;
8819 tb = (MonoReflectionTypeBuilder *) mb->type;
8820 klass = mono_class_from_mono_type (tb->type.type);
8822 method = methodbuilder_to_mono_method (klass, mb);
8824 method = rmethod->method;
8827 method = mono_get_inflated_method (method);
8829 count = mono_method_signature (method)->generic_param_count;
8830 if (count != mono_array_length (types))
8833 container = ((MonoMethodNormal*) method)->generic_container;
8834 g_assert (container);
8836 if (!container->method_hash)
8837 container->method_hash = g_hash_table_new (
8838 (GHashFunc) mono_metadata_generic_method_hash,
8839 (GCompareFunc) mono_metadata_generic_method_equal);
8841 ginst = g_new0 (MonoGenericInst,1 );
8842 ginst->type_argc = count;
8843 ginst->type_argv = g_new0 (MonoType *, count);
8844 ginst->is_reference = 1;
8845 for (i = 0; i < count; i++) {
8846 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8847 ginst->type_argv [i] = dup_type (garg->type);
8849 if (!ginst->is_open)
8850 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8851 if (ginst->is_reference)
8852 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8854 ginst = mono_metadata_lookup_generic_inst (ginst);
8856 gmethod = g_new0 (MonoGenericMethod, 1);
8857 gmethod->generic_class = method->klass->generic_class;
8858 gmethod->container = container;
8859 gmethod->inst = ginst;
8861 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8865 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8868 gmethod->reflection_info = rmethod;
8870 context = g_new0 (MonoGenericContext, 1);
8871 context->container = container;
8872 context->gclass = method->klass->generic_class;
8873 context->gmethod = gmethod;
8875 if (method->is_inflated)
8876 method = ((MonoMethodInflated *) method)->declaring;
8878 inflated = mono_class_inflate_generic_method (method, context);
8879 g_hash_table_insert (container->method_hash, gmethod, inflated);
8881 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8885 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8887 MonoGenericMethod *gmethod;
8888 MonoInflatedGenericClass *gclass;
8889 MonoGenericContext *context;
8892 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8894 gmethod = g_new0 (MonoGenericMethod, 1);
8895 gmethod->generic_class = &gclass->generic_class;
8896 gmethod->inst = g_new0 (MonoGenericInst, 1);
8897 gmethod->reflection_info = obj;
8899 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8900 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8902 for (i = 0; i < gmethod->inst->type_argc; i++) {
8903 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8904 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8906 g_assert (gparam->pklass);
8907 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8910 context = g_new0 (MonoGenericContext, 1);
8911 context->container = gclass->generic_class.container_class->generic_container;
8912 context->gclass = &gclass->generic_class;
8913 context->gmethod = gmethod;
8915 return mono_class_inflate_generic_method (method, context);
8919 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8924 klass = mono_class_from_mono_type (type->type.type);
8926 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8927 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8928 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8929 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8930 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8931 method = ((MonoReflectionMethod *) obj)->method;
8933 method = NULL; /* prevent compiler warning */
8934 g_assert_not_reached ();
8937 return inflate_mono_method (type, method, obj);
8941 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8942 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8945 MonoGenericClass *gclass;
8946 MonoDynamicGenericClass *dgclass;
8947 MonoClass *klass, *gklass, *pklass;
8950 MONO_ARCH_SAVE_REGS;
8952 klass = mono_class_from_mono_type (type->type.type);
8953 gclass = type->type.type->data.generic_class;
8955 g_assert (gclass->is_dynamic);
8956 dgclass = (MonoDynamicGenericClass *) gclass;
8958 if (dgclass->initialized)
8961 gklass = gclass->container_class;
8962 mono_class_init (gklass);
8964 if (dgclass->parent)
8965 pklass = mono_class_from_mono_type (dgclass->parent);
8967 pklass = gklass->parent;
8969 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8970 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8971 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8972 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8973 dgclass->count_events = events ? mono_array_length (events) : 0;
8975 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8976 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8977 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8978 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8979 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8981 for (i = 0; i < dgclass->count_methods; i++) {
8982 MonoObject *obj = mono_array_get (methods, gpointer, i);
8984 dgclass->methods [i] = inflate_method (type, obj);
8987 for (i = 0; i < dgclass->count_ctors; i++) {
8988 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8990 dgclass->ctors [i] = inflate_method (type, obj);
8993 for (i = 0; i < dgclass->count_fields; i++) {
8994 MonoObject *obj = mono_array_get (fields, gpointer, i);
8995 MonoClassField *field;
8996 MonoInflatedField *ifield;
8998 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8999 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
9000 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
9001 field = ((MonoReflectionField *) obj)->field;
9003 field = NULL; /* prevent compiler warning */
9004 g_assert_not_reached ();
9007 ifield = g_new0 (MonoInflatedField, 1);
9008 ifield->generic_type = field->type;
9009 ifield->reflection_info = obj;
9011 dgclass->fields [i] = *field;
9012 dgclass->fields [i].parent = klass;
9013 dgclass->fields [i].generic_info = ifield;
9014 dgclass->fields [i].type = mono_class_inflate_generic_type (
9015 field->type, dgclass->generic_class.generic_class.context);
9018 for (i = 0; i < dgclass->count_properties; i++) {
9019 MonoObject *obj = mono_array_get (properties, gpointer, i);
9020 MonoProperty *property = &dgclass->properties [i];
9022 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
9023 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
9025 property->parent = klass;
9026 property->attrs = pb->attrs;
9027 property->name = mono_string_to_utf8 (pb->name);
9029 property->get = inflate_method (type, (MonoObject *) pb->get_method);
9031 property->set = inflate_method (type, (MonoObject *) pb->set_method);
9032 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
9033 *property = *((MonoReflectionProperty *) obj)->property;
9036 property->get = inflate_mono_method (type, property->get, NULL);
9038 property->set = inflate_mono_method (type, property->set, NULL);
9040 g_assert_not_reached ();
9043 for (i = 0; i < dgclass->count_events; i++) {
9044 MonoObject *obj = mono_array_get (events, gpointer, i);
9045 MonoEvent *event = &dgclass->events [i];
9047 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9048 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9050 event->parent = klass;
9051 event->attrs = eb->attrs;
9052 event->name = mono_string_to_utf8 (eb->name);
9054 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9055 if (eb->remove_method)
9056 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9057 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9058 *event = *((MonoReflectionEvent *) obj)->event;
9061 event->add = inflate_mono_method (type, event->add, NULL);
9063 event->remove = inflate_mono_method (type, event->remove, NULL);
9065 g_assert_not_reached ();
9068 dgclass->initialized = TRUE;
9072 ensure_runtime_vtable (MonoClass *klass)
9074 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9075 int i, num, j, onum;
9076 MonoMethod **overrides;
9078 if (!tb || klass->wastypebuilder)
9081 ensure_runtime_vtable (klass->parent);
9083 num = tb->ctors? mono_array_length (tb->ctors): 0;
9084 num += tb->num_methods;
9085 klass->method.count = num;
9086 klass->methods = g_new (MonoMethod*, num);
9087 num = tb->ctors? mono_array_length (tb->ctors): 0;
9088 for (i = 0; i < num; ++i)
9089 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9090 num = tb->num_methods;
9092 for (i = 0; i < num; ++i)
9093 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9095 if (tb->interfaces) {
9096 klass->interface_count = mono_array_length (tb->interfaces);
9097 klass->interfaces = g_new (MonoClass*, klass->interface_count);
9098 for (i = 0; i < klass->interface_count; ++i) {
9099 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9100 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9104 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9105 for (i = 0; i < klass->method.count; ++i)
9106 klass->methods [i]->slot = i;
9108 if (!((MonoDynamicImage*)klass->image)->run)
9109 /* No need to create a generic vtable */
9115 for (i = 0; i < tb->num_methods; ++i) {
9116 MonoReflectionMethodBuilder *mb =
9117 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9118 if (mb->override_method)
9123 overrides = g_new0 (MonoMethod*, onum * 2);
9127 for (i = 0; i < tb->num_methods; ++i) {
9128 MonoReflectionMethodBuilder *mb =
9129 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9130 if (mb->override_method) {
9131 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9132 overrides [onum * 2] =
9133 mb->override_method->method;
9134 overrides [onum * 2 + 1] =
9137 g_assert (mb->mhandle);
9144 mono_class_setup_vtable_general (klass, overrides, onum);
9149 typebuilder_setup_fields (MonoClass *klass)
9151 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9152 MonoReflectionFieldBuilder *fb;
9153 MonoClassField *field;
9158 klass->field.count = tb->num_fields;
9159 klass->field.first = 0;
9161 if (!klass->field.count)
9164 klass->fields = g_new0 (MonoClassField, klass->field.count);
9166 for (i = 0; i < klass->field.count; ++i) {
9167 fb = mono_array_get (tb->fields, gpointer, i);
9168 field = &klass->fields [i];
9169 field->name = mono_string_to_utf8 (fb->name);
9171 /* FIXME: handle type modifiers */
9172 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9173 field->type->attrs = fb->attrs;
9175 field->type = fb->type->type;
9177 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9178 field->data = mono_array_addr (fb->rva_data, char, 0);
9179 if (fb->offset != -1)
9180 field->offset = fb->offset;
9181 field->parent = klass;
9183 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9185 if (fb->def_value) {
9186 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9187 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9188 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9189 /* Copy the data from the blob since it might get realloc-ed */
9190 p = assembly->blob.data + idx;
9191 len = mono_metadata_decode_blob_size (p, &p2);
9193 field->data = g_malloc (len);
9194 memcpy ((gpointer)field->data, p, len);
9197 mono_class_layout_fields (klass);
9201 typebuilder_setup_properties (MonoClass *klass)
9203 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9204 MonoReflectionPropertyBuilder *pb;
9207 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9208 klass->property.first = 0;
9210 klass->properties = g_new0 (MonoProperty, klass->property.count);
9211 for (i = 0; i < klass->property.count; ++i) {
9212 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9213 klass->properties [i].parent = klass;
9214 klass->properties [i].attrs = pb->attrs;
9215 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9217 klass->properties [i].get = pb->get_method->mhandle;
9219 klass->properties [i].set = pb->set_method->mhandle;
9223 MonoReflectionEvent *
9224 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9226 MonoEvent *event = g_new0 (MonoEvent, 1);
9230 klass = my_mono_class_from_mono_type (tb->type.type);
9232 event->parent = klass;
9233 event->attrs = eb->attrs;
9234 event->name = mono_string_to_utf8 (eb->name);
9236 event->add = eb->add_method->mhandle;
9237 if (eb->remove_method)
9238 event->remove = eb->remove_method->mhandle;
9239 if (eb->raise_method)
9240 event->raise = eb->raise_method->mhandle;
9242 if (eb->other_methods) {
9243 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9244 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9245 MonoReflectionMethodBuilder *mb =
9246 mono_array_get (eb->other_methods,
9247 MonoReflectionMethodBuilder*, j);
9248 event->other [j] = mb->mhandle;
9252 return mono_event_get_object (mono_object_domain (tb), klass, event);
9256 typebuilder_setup_events (MonoClass *klass)
9258 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9259 MonoReflectionEventBuilder *eb;
9262 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9263 klass->event.first = 0;
9265 klass->events = g_new0 (MonoEvent, klass->event.count);
9266 for (i = 0; i < klass->event.count; ++i) {
9267 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9268 klass->events [i].parent = klass;
9269 klass->events [i].attrs = eb->attrs;
9270 klass->events [i].name = mono_string_to_utf8 (eb->name);
9272 klass->events [i].add = eb->add_method->mhandle;
9273 if (eb->remove_method)
9274 klass->events [i].remove = eb->remove_method->mhandle;
9275 if (eb->raise_method)
9276 klass->events [i].raise = eb->raise_method->mhandle;
9278 if (eb->other_methods) {
9279 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9280 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9281 MonoReflectionMethodBuilder *mb =
9282 mono_array_get (eb->other_methods,
9283 MonoReflectionMethodBuilder*, j);
9284 klass->events [i].other [j] = mb->mhandle;
9291 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9295 MonoReflectionType* res;
9298 MONO_ARCH_SAVE_REGS;
9300 domain = mono_object_domain (tb);
9301 klass = my_mono_class_from_mono_type (tb->type.type);
9303 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9306 * we need to lock the domain because the lock will be taken inside
9307 * So, we need to keep the locking order correct.
9309 mono_domain_lock (domain);
9310 mono_loader_lock ();
9311 if (klass->wastypebuilder) {
9312 mono_loader_unlock ();
9313 mono_domain_unlock (domain);
9314 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9317 * Fields to set in klass:
9318 * the various flags: delegate/unicode/contextbound etc.
9320 klass->flags = tb->attrs;
9321 klass->has_cctor = 1;
9322 klass->has_finalize = 1;
9325 if (!((MonoDynamicImage*)klass->image)->run) {
9326 if (klass->generic_container) {
9327 /* FIXME: The code below can't handle generic classes */
9328 klass->wastypebuilder = TRUE;
9329 mono_loader_unlock ();
9330 mono_domain_unlock (domain);
9331 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9336 /* enums are done right away */
9337 if (!klass->enumtype)
9338 ensure_runtime_vtable (klass);
9341 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9342 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9343 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9347 /* fields and object layout */
9348 if (klass->parent) {
9349 if (!klass->parent->size_inited)
9350 mono_class_init (klass->parent);
9351 klass->instance_size += klass->parent->instance_size;
9352 klass->class_size += klass->parent->class_size;
9353 klass->min_align = klass->parent->min_align;
9354 /* if the type has no fields we won't call the field_setup
9355 * routine which sets up klass->has_references.
9357 klass->has_references |= klass->parent->has_references;
9359 klass->instance_size = sizeof (MonoObject);
9360 klass->min_align = 1;
9363 /* FIXME: handle packing_size and instance_size */
9364 typebuilder_setup_fields (klass);
9366 typebuilder_setup_properties (klass);
9368 typebuilder_setup_events (klass);
9370 klass->wastypebuilder = TRUE;
9371 mono_loader_unlock ();
9372 mono_domain_unlock (domain);
9374 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9375 g_assert (res != (MonoReflectionType*)tb);
9380 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9382 MonoGenericParam *param;
9385 MONO_ARCH_SAVE_REGS;
9387 param = g_new0 (MonoGenericParam, 1);
9389 if (gparam->mbuilder) {
9390 if (!gparam->mbuilder->generic_container)
9391 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9392 param->owner = gparam->mbuilder->generic_container;
9393 } else if (gparam->tbuilder) {
9394 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9395 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9400 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9401 if (gparam->index >= count)
9404 container = nesting->generic_container;
9405 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9408 g_assert (container);
9409 param->owner = container;
9412 param->method = NULL;
9413 param->name = mono_string_to_utf8 (gparam->name);
9414 param->num = gparam->index;
9416 image = &gparam->tbuilder->module->dynamic_image->image;
9417 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9419 param->pklass->reflection_info = gparam;
9421 gparam->type.type = g_new0 (MonoType, 1);
9422 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9423 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9424 gparam->type.type->data.generic_param = param;
9428 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9430 MonoDynamicImage *assembly = sig->module->dynamic_image;
9431 guint32 na = mono_array_length (sig->arguments);
9432 guint32 buflen, i, size;
9436 MONO_ARCH_SAVE_REGS;
9438 p = buf = g_malloc (size = 50 + na * 50);
9440 mono_metadata_encode_value (0x07, p, &p);
9441 mono_metadata_encode_value (na, p, &p);
9442 for (i = 0; i < na; ++i) {
9443 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9444 encode_reflection_type (assembly, type, p, &p);
9448 g_assert (buflen < size);
9449 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9450 p = mono_array_addr (result, char, 0);
9451 memcpy (p, buf, buflen);
9458 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9460 MonoDynamicImage *assembly = sig->module->dynamic_image;
9461 guint32 na = mono_array_length (sig->arguments);
9462 guint32 buflen, i, size;
9466 MONO_ARCH_SAVE_REGS;
9468 p = buf = g_malloc (size = 10 + na * 10);
9470 mono_metadata_encode_value (0x06, p, &p);
9471 for (i = 0; i < na; ++i) {
9472 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9473 encode_reflection_type (assembly, type, p, &p);
9477 g_assert (buflen < size);
9478 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9479 p = mono_array_addr (result, char, 0);
9480 memcpy (p, buf, buflen);
9487 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9489 ReflectionMethodBuilder rmb;
9490 MonoMethodSignature *sig;
9493 sig = dynamic_method_to_signature (mb);
9495 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9498 * Resolve references.
9501 * Every second entry in the refs array is reserved for storing handle_class,
9502 * which is needed by the ldtoken implementation in the JIT.
9504 rmb.nrefs = mb->nrefs;
9505 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9506 for (i = 0; i < mb->nrefs; i += 2) {
9507 MonoClass *handle_class;
9508 gpointer ref = resolve_object (mb->module->image,
9509 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9512 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9516 rmb.refs [i + 1] = handle_class;
9520 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9524 /* ilgen is no longer needed */
9529 * mono_reflection_lookup_dynamic_token:
9531 * Finish the Builder object pointed to by TOKEN and return the corresponding
9532 * runtime structure. HANDLE_CLASS is set to the class required by
9536 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9538 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9541 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9544 return resolve_object (image, obj, handle_class);
9548 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9550 gpointer result = NULL;
9552 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9553 result = mono_string_intern ((MonoString*)obj);
9554 *handle_class = NULL;
9556 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9557 MonoReflectionType *tb = (MonoReflectionType*)obj;
9558 result = mono_class_from_mono_type (tb->type);
9559 *handle_class = mono_defaults.typehandle_class;
9561 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9562 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9563 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9564 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9565 result = ((MonoReflectionMethod*)obj)->method;
9566 *handle_class = mono_defaults.methodhandle_class;
9568 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9569 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9570 result = mb->mhandle;
9572 /* Type is not yet created */
9573 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9575 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9578 * Hopefully this has been filled in by calling CreateType() on the
9582 * TODO: This won't work if the application finishes another
9583 * TypeBuilder instance instead of this one.
9585 result = mb->mhandle;
9587 *handle_class = mono_defaults.methodhandle_class;
9588 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9589 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9591 result = cb->mhandle;
9593 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9595 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9596 result = cb->mhandle;
9598 *handle_class = mono_defaults.methodhandle_class;
9599 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9600 result = ((MonoReflectionField*)obj)->field;
9601 *handle_class = mono_defaults.fieldhandle_class;
9603 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9604 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9605 result = fb->handle;
9608 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9610 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9611 result = fb->handle;
9613 *handle_class = mono_defaults.fieldhandle_class;
9614 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9615 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9618 klass = tb->type.type->data.klass;
9619 if (klass->wastypebuilder) {
9620 /* Already created */
9624 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9625 result = tb->type.type->data.klass;
9628 *handle_class = mono_defaults.typehandle_class;
9629 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9630 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9631 MonoMethodSignature *sig;
9634 if (helper->arguments)
9635 nargs = mono_array_length (helper->arguments);
9639 sig = mono_metadata_signature_alloc (image, nargs);
9640 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9641 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9643 if (helper->call_conv == 0) /* unmanaged */
9644 sig->call_convention = helper->unmanaged_call_conv - 1;
9646 if (helper->call_conv & 0x02)
9647 sig->call_convention = MONO_CALL_VARARG;
9649 sig->call_convention = MONO_CALL_DEFAULT;
9651 sig->param_count = nargs;
9652 /* TODO: Copy type ? */
9653 sig->ret = helper->return_type->type;
9654 for (i = 0; i < nargs; ++i) {
9655 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9656 sig->params [i] = rt->type;
9660 *handle_class = NULL;
9662 g_print (obj->vtable->klass->name);
9663 g_assert_not_reached ();
9669 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9670 const static guint32 declsec_flags_map[] = {
9671 0x00000000, /* empty */
9672 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9673 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9674 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9675 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9676 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9677 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9678 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9679 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9680 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9681 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9682 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9683 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9684 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9685 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9686 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9687 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9688 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9689 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9693 * Returns flags that includes all available security action associated to the handle.
9694 * @token: metadata token (either for a class or a method)
9695 * @image: image where resides the metadata.
9698 mono_declsec_get_flags (MonoImage *image, guint32 token)
9700 guint32 index = mono_metadata_declsec_from_index (image, token);
9701 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9706 for (i = index; i < t->rows; i++) {
9707 guint32 cols [MONO_DECL_SECURITY_SIZE];
9709 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9710 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9713 action = cols [MONO_DECL_SECURITY_ACTION];
9714 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9715 result |= declsec_flags_map [action];
9717 g_assert_not_reached ();
9724 * Get the security actions (in the form of flags) associated with the specified method.
9726 * @method: The method for which we want the declarative security flags.
9727 * Return the declarative security flags for the method (only).
9729 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9730 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9733 mono_declsec_flags_from_method (MonoMethod *method)
9735 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9736 /* FIXME: No cache (for the moment) */
9737 guint32 idx = mono_method_get_index (method);
9738 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9739 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9740 return mono_declsec_get_flags (method->klass->image, idx);
9746 * Get the security actions (in the form of flags) associated with the specified class.
9748 * @klass: The class for which we want the declarative security flags.
9749 * Return the declarative security flags for the class.
9751 * Note: We cache the flags inside the MonoClass structure as this will get
9752 * called very often (at least for each method).
9755 mono_declsec_flags_from_class (MonoClass *klass)
9757 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9758 if (!klass->declsec_flags) {
9759 guint32 idx = mono_metadata_token_index (klass->type_token);
9760 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9761 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9762 /* we cache the flags on classes */
9763 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9765 return klass->declsec_flags;
9771 * Get the security actions (in the form of flags) associated with the specified assembly.
9773 * @assembly: The assembly for which we want the declarative security flags.
9774 * Return the declarative security flags for the assembly.
9777 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9779 guint32 idx = 1; /* there is only one assembly */
9780 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9781 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9782 return mono_declsec_get_flags (assembly->image, idx);
9787 * Fill actions for the specific index (which may either be an encoded class token or
9788 * an encoded method token) from the metadata image.
9789 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9792 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9793 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9795 MonoBoolean result = FALSE;
9797 guint32 cols [MONO_DECL_SECURITY_SIZE];
9798 int index = mono_metadata_declsec_from_index (image, token);
9801 t = &image->tables [MONO_TABLE_DECLSECURITY];
9802 for (i = index; i < t->rows; i++) {
9803 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9805 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9808 /* if present only replace (class) permissions with method permissions */
9809 /* if empty accept either class or method permissions */
9810 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9811 if (!actions->demand.blob) {
9812 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9813 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9814 actions->demand.blob = (char*) (blob + 2);
9815 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9818 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9819 if (!actions->noncasdemand.blob) {
9820 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9821 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9822 actions->noncasdemand.blob = (char*) (blob + 2);
9823 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9826 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9827 if (!actions->demandchoice.blob) {
9828 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9829 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9830 actions->demandchoice.blob = (char*) (blob + 2);
9831 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9841 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9842 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9844 guint32 idx = mono_metadata_token_index (klass->type_token);
9845 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9846 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9847 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9851 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9852 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9854 guint32 idx = mono_method_get_index (method);
9855 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9856 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9857 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9861 * Collect all actions (that requires to generate code in mini) assigned for
9862 * the specified method.
9863 * Note: Don't use the content of actions if the function return FALSE.
9866 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9868 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9869 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9870 MonoBoolean result = FALSE;
9873 /* quick exit if no declarative security is present in the metadata */
9874 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9877 /* we want the original as the wrapper is "free" of the security informations */
9878 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9879 method = mono_marshal_method_from_wrapper (method);
9884 /* First we look for method-level attributes */
9885 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9886 mono_class_init (method->klass);
9887 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9889 result = mono_declsec_get_method_demands_params (method, demands,
9890 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9893 /* Here we use (or create) the class declarative cache to look for demands */
9894 flags = mono_declsec_flags_from_class (method->klass);
9897 mono_class_init (method->klass);
9898 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9900 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9901 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9904 /* The boolean return value is used as a shortcut in case nothing needs to
9905 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9911 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9913 * Note: Don't use the content of actions if the function return FALSE.
9916 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9918 MonoBoolean result = FALSE;
9921 /* quick exit if no declarative security is present in the metadata */
9922 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9925 /* we want the original as the wrapper is "free" of the security informations */
9926 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9927 method = mono_marshal_method_from_wrapper (method);
9932 /* results are independant - zeroize both */
9933 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9934 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9936 /* First we look for method-level attributes */
9937 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9938 mono_class_init (method->klass);
9940 result = mono_declsec_get_method_demands_params (method, cmethod,
9941 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9944 /* Here we use (or create) the class declarative cache to look for demands */
9945 flags = mono_declsec_flags_from_class (method->klass);
9946 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9947 mono_class_init (method->klass);
9949 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9950 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9957 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9959 * @klass The inherited class - this is the class that provides the security check (attributes)
9961 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9963 * Note: Don't use the content of actions if the function return FALSE.
9966 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9968 MonoBoolean result = FALSE;
9971 /* quick exit if no declarative security is present in the metadata */
9972 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9975 /* Here we use (or create) the class declarative cache to look for demands */
9976 flags = mono_declsec_flags_from_class (klass);
9977 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9978 mono_class_init (klass);
9979 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9981 result |= mono_declsec_get_class_demands_params (klass, demands,
9982 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9989 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9991 * Note: Don't use the content of actions if the function return FALSE.
9994 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9996 /* quick exit if no declarative security is present in the metadata */
9997 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
10000 /* we want the original as the wrapper is "free" of the security informations */
10001 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
10002 method = mono_marshal_method_from_wrapper (method);
10007 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10008 mono_class_init (method->klass);
10009 memset (demands, 0, sizeof (MonoDeclSecurityActions));
10011 return mono_declsec_get_method_demands_params (method, demands,
10012 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
10019 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
10021 guint32 cols [MONO_DECL_SECURITY_SIZE];
10025 int index = mono_metadata_declsec_from_index (image, token);
10029 t = &image->tables [MONO_TABLE_DECLSECURITY];
10030 for (i = index; i < t->rows; i++) {
10031 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
10033 /* shortcut - index are ordered */
10034 if (token != cols [MONO_DECL_SECURITY_PARENT])
10037 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10038 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10039 entry->blob = (char*) (metadata + 2);
10040 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10049 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10051 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10052 guint32 idx = mono_method_get_index (method);
10053 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10054 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10055 return get_declsec_action (method->klass->image, idx, action, entry);
10061 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10064 guint32 flags = mono_declsec_flags_from_class (klass);
10065 if (declsec_flags_map [action] & flags) {
10066 guint32 idx = mono_metadata_token_index (klass->type_token);
10067 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10068 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10069 return get_declsec_action (klass->image, idx, action, entry);
10075 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10077 guint32 idx = 1; /* there is only one assembly */
10078 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10079 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10081 return get_declsec_action (assembly->image, idx, action, entry);
10085 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10087 MonoObject *res, *exc;
10089 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10090 static MonoMethod *method = NULL;
10092 if (!System_Reflection_Emit_TypeBuilder) {
10093 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10094 g_assert (System_Reflection_Emit_TypeBuilder);
10096 if (method == NULL) {
10097 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10102 * The result of mono_type_get_object () might be a System.MonoType but we
10103 * need a TypeBuilder so use klass->reflection_info.
10105 g_assert (klass->reflection_info);
10106 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10108 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10110 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10114 return *(MonoBoolean*)mono_object_unbox (res);