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>
31 #include "rawbuffer.h"
32 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
46 MonoGenericContainer *generic_container;
52 guint32 *table_idx; /* note: it's a pointer */
56 MonoBoolean init_locals;
57 MonoArray *return_modreq;
58 MonoArray *return_modopt;
59 MonoArray *param_modreq;
60 MonoArray *param_modopt;
61 MonoArray *permissions;
66 int charset, extra_flags, native_cc;
67 MonoString *dll, *dllentry;
68 } ReflectionMethodBuilder;
72 MonoReflectionGenericParam *gparam;
73 } GenericParamTableEntry;
75 const unsigned char table_sizes [MONO_TABLE_NUM] = {
85 MONO_INTERFACEIMPL_SIZE,
86 MONO_MEMBERREF_SIZE, /* 0x0A */
88 MONO_CUSTOM_ATTR_SIZE,
89 MONO_FIELD_MARSHAL_SIZE,
90 MONO_DECL_SECURITY_SIZE,
91 MONO_CLASS_LAYOUT_SIZE,
92 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
93 MONO_STAND_ALONE_SIGNATURE_SIZE,
97 MONO_PROPERTY_MAP_SIZE,
100 MONO_METHOD_SEMA_SIZE,
101 MONO_METHODIMPL_SIZE,
102 MONO_MODULEREF_SIZE, /* 0x1A */
108 MONO_ASSEMBLY_SIZE, /* 0x20 */
109 MONO_ASSEMBLY_PROCESSOR_SIZE,
110 MONO_ASSEMBLYOS_SIZE,
111 MONO_ASSEMBLYREF_SIZE,
112 MONO_ASSEMBLYREFPROC_SIZE,
113 MONO_ASSEMBLYREFOS_SIZE,
117 MONO_NESTED_CLASS_SIZE,
119 MONO_GENERICPARAM_SIZE, /* 0x2A */
120 MONO_METHODSPEC_SIZE,
121 MONO_GENPARCONSTRAINT_SIZE
125 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
126 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
127 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
128 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
129 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
130 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
131 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
132 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
133 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
134 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
135 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
136 static void ensure_runtime_vtable (MonoClass *klass);
137 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
138 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
139 static guint32 type_get_signature_size (MonoType *type);
140 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
141 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows) {
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
162 make_room_in_stream (MonoDynamicStream *stream, int size)
164 if (size <= stream->alloc_size)
167 while (stream->alloc_size <= size) {
168 if (stream->alloc_size < 4096)
169 stream->alloc_size = 4096;
171 stream->alloc_size *= 2;
174 stream->data = g_realloc (stream->data, stream->alloc_size);
178 string_heap_insert (MonoDynamicStream *sh, const char *str)
182 gpointer oldkey, oldval;
184 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
185 return GPOINTER_TO_UINT (oldval);
187 len = strlen (str) + 1;
190 make_room_in_stream (sh, idx + len);
193 * We strdup the string even if we already copy them in sh->data
194 * so that the string pointers in the hash remain valid even if
195 * we need to realloc sh->data. We may want to avoid that later.
197 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
198 memcpy (sh->data + idx, str, len);
204 string_heap_init (MonoDynamicStream *sh)
207 sh->alloc_size = 4096;
208 sh->data = g_malloc (4096);
209 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
210 string_heap_insert (sh, "");
214 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
218 make_room_in_stream (stream, stream->index + len);
219 memcpy (stream->data + stream->index, data, len);
221 stream->index += len;
223 * align index? Not without adding an additional param that controls it since
224 * we may store a blob value in pieces.
230 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
234 make_room_in_stream (stream, stream->index + len);
235 memset (stream->data + stream->index, 0, len);
237 stream->index += len;
242 stream_data_align (MonoDynamicStream *stream)
245 guint32 count = stream->index % 4;
247 /* we assume the stream data will be aligned */
249 mono_image_add_stream_data (stream, buf, 4 - count);
253 mono_blob_entry_hash (const char* str)
257 len = mono_metadata_decode_blob_size (str, &str);
261 for (str += 1; str < end; str++)
262 h = (h << 5) - h + *str;
270 mono_blob_entry_equal (const char *str1, const char *str2) {
274 len = mono_metadata_decode_blob_size (str1, &end1);
275 len2 = mono_metadata_decode_blob_size (str2, &end2);
278 return memcmp (end1, end2, len) == 0;
282 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
286 gpointer oldkey, oldval;
288 copy = g_malloc (s1+s2);
289 memcpy (copy, b1, s1);
290 memcpy (copy + s1, b2, s2);
291 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
293 idx = GPOINTER_TO_UINT (oldval);
295 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
296 mono_image_add_stream_data (&assembly->blob, b2, s2);
297 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
303 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
304 * dest may be misaligned.
307 swap_with_size (char *dest, const char* val, int len, int nelem) {
308 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
311 for (elem = 0; elem < nelem; ++elem) {
337 g_assert_not_reached ();
343 memcpy (dest, val, len * nelem);
348 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
352 guint32 idx = 0, len;
354 len = str->length * 2;
355 mono_metadata_encode_value (len, b, &b);
356 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
358 char *swapped = g_malloc (2 * mono_string_length (str));
359 const char *p = (const char*)mono_string_chars (str);
361 swap_with_size (swapped, p, 2, mono_string_length (str));
362 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
366 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
371 /* modified version needed to handle building corlib */
373 my_mono_class_from_mono_type (MonoType *type) {
374 switch (type->type) {
375 case MONO_TYPE_ARRAY:
377 case MONO_TYPE_SZARRAY:
378 case MONO_TYPE_GENERICINST:
379 return mono_class_from_mono_type (type);
382 g_assert (type->data.generic_param->pklass);
383 return type->data.generic_param->pklass;
385 /* should be always valid when we reach this case... */
386 return type->data.klass;
391 default_class_from_mono_type (MonoType *type)
393 switch (type->type) {
394 case MONO_TYPE_OBJECT:
395 return mono_defaults.object_class;
397 return mono_defaults.void_class;
398 case MONO_TYPE_BOOLEAN:
399 return mono_defaults.boolean_class;
401 return mono_defaults.char_class;
403 return mono_defaults.sbyte_class;
405 return mono_defaults.byte_class;
407 return mono_defaults.int16_class;
409 return mono_defaults.uint16_class;
411 return mono_defaults.int32_class;
413 return mono_defaults.uint32_class;
415 return mono_defaults.int_class;
417 return mono_defaults.uint_class;
419 return mono_defaults.int64_class;
421 return mono_defaults.uint64_class;
423 return mono_defaults.single_class;
425 return mono_defaults.double_class;
426 case MONO_TYPE_STRING:
427 return mono_defaults.string_class;
429 g_warning ("implement me 0x%02x\n", type->type);
430 g_assert_not_reached ();
437 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
442 g_assert_not_reached ();
446 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
447 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
448 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
449 for (i = 0; i < gclass->inst->type_argc; ++i)
450 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
456 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
459 g_assert_not_reached ();
464 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
468 case MONO_TYPE_BOOLEAN:
482 case MONO_TYPE_STRING:
483 case MONO_TYPE_OBJECT:
484 case MONO_TYPE_TYPEDBYREF:
485 mono_metadata_encode_value (type->type, p, &p);
488 mono_metadata_encode_value (type->type, p, &p);
489 encode_type (assembly, type->data.type, p, &p);
491 case MONO_TYPE_SZARRAY:
492 mono_metadata_encode_value (type->type, p, &p);
493 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
495 case MONO_TYPE_VALUETYPE:
496 case MONO_TYPE_CLASS: {
497 MonoClass *k = mono_class_from_mono_type (type);
499 * Make sure we use the correct type.
501 mono_metadata_encode_value (k->byval_arg.type, p, &p);
503 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
504 * otherwise two typerefs could point to the same type, leading to
505 * verification errors.
507 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
510 case MONO_TYPE_ARRAY:
511 mono_metadata_encode_value (type->type, p, &p);
512 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
513 mono_metadata_encode_value (type->data.array->rank, p, &p);
514 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
515 mono_metadata_encode_value (0, p, &p);
517 case MONO_TYPE_GENERICINST:
518 encode_generic_class (assembly, type->data.generic_class, p, &p);
522 mono_metadata_encode_value (type->type, p, &p);
523 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
526 g_error ("need to encode type %x", type->type);
532 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
535 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
539 encode_type (assembly, type->type, p, endbuf);
543 g_assert_not_reached ();
548 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
553 for (i = 0; i < mono_array_length (modreq); ++i) {
554 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
555 *p = MONO_TYPE_CMOD_REQD;
557 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
561 for (i = 0; i < mono_array_length (modopt); ++i) {
562 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
563 *p = MONO_TYPE_CMOD_OPT;
565 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
572 generic_class_get_signature_size (MonoGenericClass *gclass)
578 g_assert_not_reached ();
581 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
583 for (i = 0; i < gclass->inst->type_argc; ++i)
584 size += type_get_signature_size (gclass->inst->type_argv [i]);
590 type_get_signature_size (MonoType *type)
595 g_assert_not_reached ();
603 case MONO_TYPE_BOOLEAN:
617 case MONO_TYPE_STRING:
618 case MONO_TYPE_OBJECT:
619 case MONO_TYPE_TYPEDBYREF:
622 return size + 1 + type_get_signature_size (type->data.type);
623 case MONO_TYPE_SZARRAY:
624 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
625 case MONO_TYPE_VALUETYPE:
626 case MONO_TYPE_CLASS:
628 case MONO_TYPE_ARRAY:
629 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
630 case MONO_TYPE_GENERICINST:
631 return size + generic_class_get_signature_size (type->data.generic_class);
636 g_error ("need to encode type %x", type->type);
642 method_get_signature_size (MonoMethodSignature *sig)
647 size = type_get_signature_size (sig->ret);
648 for (i = 0; i < sig->param_count; i++)
649 size += type_get_signature_size (sig->params [i]);
651 if (sig->generic_param_count)
653 if (sig->sentinelpos >= 0)
660 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
665 guint32 nparams = sig->param_count;
666 guint32 size = 11 + method_get_signature_size (sig);
674 p = buf = g_malloc (size);
676 * FIXME: vararg, explicit_this, differenc call_conv values...
678 *p = sig->call_convention;
680 *p |= 0x20; /* hasthis */
681 if (sig->generic_param_count)
682 *p |= 0x10; /* generic */
684 if (sig->generic_param_count)
685 mono_metadata_encode_value (sig->generic_param_count, p, &p);
686 mono_metadata_encode_value (nparams, p, &p);
687 encode_type (assembly, sig->ret, p, &p);
688 for (i = 0; i < nparams; ++i) {
689 if (i == sig->sentinelpos)
690 *p++ = MONO_TYPE_SENTINEL;
691 encode_type (assembly, sig->params [i], p, &p);
694 g_assert (p - buf < size);
695 mono_metadata_encode_value (p-buf, b, &b);
696 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
702 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
705 * FIXME: reuse code from method_encode_signature().
710 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
711 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
712 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
713 guint32 size = 41 + nparams * 40 + notypes * 40;
718 p = buf = g_malloc (size);
719 /* LAMESPEC: all the call conv spec is foobared */
720 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
721 if (mb->call_conv & 2)
722 *p |= 0x5; /* vararg */
723 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
724 *p |= 0x20; /* hasthis */
726 *p |= 0x10; /* generic */
729 mono_metadata_encode_value (ngparams, p, &p);
730 mono_metadata_encode_value (nparams + notypes, p, &p);
731 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
732 encode_reflection_type (assembly, mb->rtype, p, &p);
733 for (i = 0; i < nparams; ++i) {
734 MonoArray *modreq = NULL;
735 MonoArray *modopt = NULL;
736 MonoReflectionType *pt;
738 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
739 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
740 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
741 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
742 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
743 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
744 encode_reflection_type (assembly, pt, p, &p);
747 *p++ = MONO_TYPE_SENTINEL;
748 for (i = 0; i < notypes; ++i) {
749 MonoReflectionType *pt;
751 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
752 encode_reflection_type (assembly, pt, p, &p);
756 g_assert (p - buf < size);
757 mono_metadata_encode_value (p-buf, b, &b);
758 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
764 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
766 MonoDynamicTable *table;
769 guint32 idx, sig_idx, size;
770 guint nl = mono_array_length (ilgen->locals);
777 p = buf = g_malloc (size);
778 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
779 idx = table->next_idx ++;
781 alloc_table (table, table->rows);
782 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
784 mono_metadata_encode_value (0x07, p, &p);
785 mono_metadata_encode_value (nl, p, &p);
786 for (i = 0; i < nl; ++i) {
787 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
790 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
792 encode_reflection_type (assembly, lb->type, p, &p);
794 g_assert (p - buf < size);
795 mono_metadata_encode_value (p-buf, b, &b);
796 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
799 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
805 method_count_clauses (MonoReflectionILGen *ilgen)
807 guint32 num_clauses = 0;
810 MonoILExceptionInfo *ex_info;
811 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
812 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
813 if (ex_info->handlers)
814 num_clauses += mono_array_length (ex_info->handlers);
822 static MonoExceptionClause*
823 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
825 MonoExceptionClause *clauses;
826 MonoExceptionClause *clause;
827 MonoILExceptionInfo *ex_info;
828 MonoILExceptionBlock *ex_block;
829 guint32 finally_start;
830 int i, j, clause_index;;
832 clauses = g_new0 (MonoExceptionClause, num_clauses);
835 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 finally_start = ex_info->start + ex_info->len;
838 g_assert (ex_info->handlers);
839 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
840 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
841 clause = &(clauses [clause_index]);
843 clause->flags = ex_block->type;
844 clause->try_offset = ex_info->start;
846 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
847 clause->try_len = finally_start - ex_info->start;
849 clause->try_len = ex_info->len;
850 clause->handler_offset = ex_block->start;
851 clause->handler_len = ex_block->len;
852 if (ex_block->extype) {
853 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
855 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
856 clause->data.filter_offset = ex_block->filter_offset;
858 clause->data.filter_offset = 0;
860 finally_start = ex_block->start + ex_block->len;
870 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
876 gint32 num_locals = 0;
877 gint32 num_exception = 0;
880 char fat_header [12];
883 guint32 local_sig = 0;
884 guint32 header_size = 12;
887 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
888 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
892 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
894 code = mb->ilgen->code;
895 code_size = mb->ilgen->code_len;
896 max_stack = mb->ilgen->max_stack;
897 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
898 if (mb->ilgen->ex_handlers)
899 num_exception = method_count_clauses (mb->ilgen);
903 char *name = mono_string_to_utf8 (mb->name);
904 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
905 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
908 mono_raise_exception (exception);
911 code_size = mono_array_length (code);
912 max_stack = 8; /* we probably need to run a verifier on the code... */
915 stream_data_align (&assembly->code);
917 /* check for exceptions, maxstack, locals */
918 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
920 if (code_size < 64 && !(code_size & 1)) {
921 flags = (code_size << 2) | 0x2;
922 } else if (code_size < 32 && (code_size & 1)) {
923 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
927 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
928 /* add to the fixup todo list */
929 if (mb->ilgen && mb->ilgen->num_token_fixups)
930 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
931 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
932 return assembly->text_rva + idx;
936 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
938 * FIXME: need to set also the header size in fat_flags.
939 * (and more sects and init locals flags)
943 fat_flags |= METHOD_HEADER_MORE_SECTS;
945 fat_flags |= METHOD_HEADER_INIT_LOCALS;
946 fat_header [0] = fat_flags;
947 fat_header [1] = (header_size / 4 ) << 4;
948 shortp = (guint16*)(fat_header + 2);
949 *shortp = GUINT16_TO_LE (max_stack);
950 intp = (guint32*)(fat_header + 4);
951 *intp = GUINT32_TO_LE (code_size);
952 intp = (guint32*)(fat_header + 8);
953 *intp = GUINT32_TO_LE (local_sig);
954 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
955 /* add to the fixup todo list */
956 if (mb->ilgen && mb->ilgen->num_token_fixups)
957 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
959 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
961 unsigned char sheader [4];
962 MonoILExceptionInfo * ex_info;
963 MonoILExceptionBlock * ex_block;
966 stream_data_align (&assembly->code);
967 /* always use fat format for now */
968 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
969 num_exception *= 6 * sizeof (guint32);
970 num_exception += 4; /* include the size of the header */
971 sheader [1] = num_exception & 0xff;
972 sheader [2] = (num_exception >> 8) & 0xff;
973 sheader [3] = (num_exception >> 16) & 0xff;
974 mono_image_add_stream_data (&assembly->code, sheader, 4);
975 /* fat header, so we are already aligned */
977 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
978 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
979 if (ex_info->handlers) {
980 int finally_start = ex_info->start + ex_info->len;
981 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
983 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
985 val = GUINT32_TO_LE (ex_block->type);
986 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
988 val = GUINT32_TO_LE (ex_info->start);
989 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
990 /* need fault, too, probably */
991 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
992 val = GUINT32_TO_LE (finally_start - ex_info->start);
994 val = GUINT32_TO_LE (ex_info->len);
995 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
997 val = GUINT32_TO_LE (ex_block->start);
998 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1000 val = GUINT32_TO_LE (ex_block->len);
1001 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1002 finally_start = ex_block->start + ex_block->len;
1003 if (ex_block->extype) {
1004 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1006 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1007 val = ex_block->filter_offset;
1011 val = GUINT32_TO_LE (val);
1012 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1013 /*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",
1014 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);*/
1017 g_error ("No clauses for ex info block %d", i);
1021 return assembly->text_rva + idx;
1025 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1028 MonoDynamicTable *table;
1031 table = &assembly->tables [table_idx];
1033 g_assert (col < table->columns);
1035 values = table->values + table->columns;
1036 for (i = 1; i <= table->rows; ++i) {
1037 if (values [col] == token)
1039 values += table->columns;
1044 static GHashTable *dynamic_custom_attrs = NULL;
1046 static MonoCustomAttrInfo*
1047 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1050 MonoCustomAttrInfo *ainfo;
1051 MonoReflectionCustomAttr *cattr;
1055 /* FIXME: check in assembly the Run flag is set */
1057 count = mono_array_length (cattrs);
1059 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1061 ainfo->image = image;
1062 ainfo->num_attrs = count;
1063 for (i = 0; i < count; ++i) {
1064 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1065 ainfo->attrs [i].ctor = cattr->ctor->method;
1066 /* FIXME: might want to memdup the data here */
1067 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1068 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1075 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1077 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1082 if (!dynamic_custom_attrs)
1083 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1085 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1086 ainfo->cached = TRUE;
1090 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1092 /* they are cached, so we don't free them */
1093 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1099 * idx is the table index of the object
1100 * type is one of MONO_CUSTOM_ATTR_*
1103 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1105 MonoDynamicTable *table;
1106 MonoReflectionCustomAttr *cattr;
1108 guint32 count, i, token;
1110 char *p = blob_size;
1112 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1115 count = mono_array_length (cattrs);
1116 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1117 table->rows += count;
1118 alloc_table (table, table->rows);
1119 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1120 idx <<= MONO_CUSTOM_ATTR_BITS;
1122 for (i = 0; i < count; ++i) {
1123 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1124 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1125 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1126 type = mono_metadata_token_index (token);
1127 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1128 switch (mono_metadata_token_table (token)) {
1129 case MONO_TABLE_METHOD:
1130 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1132 case MONO_TABLE_MEMBERREF:
1133 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1136 g_warning ("got wrong token in custom attr");
1139 values [MONO_CUSTOM_ATTR_TYPE] = type;
1141 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1142 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1143 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1144 values += MONO_CUSTOM_ATTR_SIZE;
1150 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1152 MonoDynamicTable *table;
1154 guint32 count, i, idx;
1155 MonoReflectionPermissionSet *perm;
1160 count = mono_array_length (permissions);
1161 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1162 table->rows += count;
1163 alloc_table (table, table->rows);
1165 for (i = 0; i < mono_array_length (permissions); ++i) {
1166 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1168 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1170 idx = mono_metadata_token_index (parent_token);
1171 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1172 switch (mono_metadata_token_table (parent_token)) {
1173 case MONO_TABLE_TYPEDEF:
1174 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1176 case MONO_TABLE_METHOD:
1177 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1179 case MONO_TABLE_ASSEMBLY:
1180 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1183 g_assert_not_reached ();
1186 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1187 values [MONO_DECL_SECURITY_PARENT] = idx;
1188 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1195 * Fill in the MethodDef and ParamDef tables for a method.
1196 * This is used for both normal methods and constructors.
1199 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1201 MonoDynamicTable *table;
1206 /* room in this table is already allocated */
1207 table = &assembly->tables [MONO_TABLE_METHOD];
1208 *mb->table_idx = table->next_idx ++;
1209 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1210 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1211 name = mono_string_to_utf8 (mb->name);
1212 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1214 values [MONO_METHOD_FLAGS] = mb->attrs;
1215 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1216 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1217 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1219 table = &assembly->tables [MONO_TABLE_PARAM];
1220 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1222 mono_image_add_decl_security (assembly,
1223 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1226 MonoDynamicTable *mtable;
1229 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1230 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1233 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1234 if (mono_array_get (mb->pinfo, gpointer, i))
1237 table->rows += count;
1238 alloc_table (table, table->rows);
1239 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1240 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1241 MonoReflectionParamBuilder *pb;
1242 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1243 values [MONO_PARAM_FLAGS] = pb->attrs;
1244 values [MONO_PARAM_SEQUENCE] = i;
1245 if (pb->name != NULL) {
1246 name = mono_string_to_utf8 (pb->name);
1247 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1250 values [MONO_PARAM_NAME] = 0;
1252 values += MONO_PARAM_SIZE;
1253 if (pb->marshal_info) {
1255 alloc_table (mtable, mtable->rows);
1256 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1257 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1258 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1260 pb->table_idx = table->next_idx++;
1261 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1262 guint32 field_type = 0;
1263 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1265 alloc_table (mtable, mtable->rows);
1266 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1267 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1268 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1269 mvalues [MONO_CONSTANT_TYPE] = field_type;
1270 mvalues [MONO_CONSTANT_PADDING] = 0;
1278 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1280 rmb->ilgen = mb->ilgen;
1281 rmb->rtype = mb->rtype;
1282 rmb->parameters = mb->parameters;
1283 rmb->generic_params = mb->generic_params;
1284 rmb->generic_container = mb->generic_container;
1285 rmb->opt_types = NULL;
1286 rmb->pinfo = mb->pinfo;
1287 rmb->attrs = mb->attrs;
1288 rmb->iattrs = mb->iattrs;
1289 rmb->call_conv = mb->call_conv;
1290 rmb->code = mb->code;
1291 rmb->type = mb->type;
1292 rmb->name = mb->name;
1293 rmb->table_idx = &mb->table_idx;
1294 rmb->init_locals = mb->init_locals;
1295 rmb->return_modreq = mb->return_modreq;
1296 rmb->return_modopt = mb->return_modopt;
1297 rmb->param_modreq = mb->param_modreq;
1298 rmb->param_modopt = mb->param_modopt;
1299 rmb->permissions = mb->permissions;
1300 rmb->mhandle = mb->mhandle;
1305 rmb->charset = mb->charset;
1306 rmb->extra_flags = mb->extra_flags;
1307 rmb->native_cc = mb->native_cc;
1308 rmb->dllentry = mb->dllentry;
1314 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1316 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1318 rmb->ilgen = mb->ilgen;
1319 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1320 rmb->parameters = mb->parameters;
1321 rmb->generic_params = NULL;
1322 rmb->generic_container = NULL;
1323 rmb->opt_types = NULL;
1324 rmb->pinfo = mb->pinfo;
1325 rmb->attrs = mb->attrs;
1326 rmb->iattrs = mb->iattrs;
1327 rmb->call_conv = mb->call_conv;
1329 rmb->type = mb->type;
1330 rmb->name = mono_string_new (mono_domain_get (), name);
1331 rmb->table_idx = &mb->table_idx;
1332 rmb->init_locals = mb->init_locals;
1333 rmb->return_modreq = NULL;
1334 rmb->return_modopt = NULL;
1335 rmb->param_modreq = mb->param_modreq;
1336 rmb->param_modopt = mb->param_modopt;
1337 rmb->permissions = mb->permissions;
1338 rmb->mhandle = mb->mhandle;
1344 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1346 rmb->ilgen = mb->ilgen;
1347 rmb->rtype = mb->rtype;
1348 rmb->parameters = mb->parameters;
1349 rmb->generic_params = NULL;
1350 rmb->generic_container = NULL;
1351 rmb->opt_types = NULL;
1353 rmb->attrs = mb->attrs;
1355 rmb->call_conv = mb->call_conv;
1358 rmb->name = mb->name;
1359 rmb->table_idx = NULL;
1360 rmb->init_locals = mb->init_locals;
1361 rmb->return_modreq = NULL;
1362 rmb->return_modopt = NULL;
1363 rmb->param_modreq = NULL;
1364 rmb->param_modopt = NULL;
1365 rmb->permissions = NULL;
1366 rmb->mhandle = mb->mhandle;
1372 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1374 MonoDynamicTable *table;
1377 ReflectionMethodBuilder rmb;
1380 reflection_methodbuilder_from_method_builder (&rmb, mb);
1382 mono_image_basic_method (&rmb, assembly);
1383 mb->table_idx = *rmb.table_idx;
1385 if (mb->dll) { /* It's a P/Invoke method */
1387 /* map CharSet values to on-disk values */
1388 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1389 int extra_flags = mb->extra_flags;
1390 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1392 alloc_table (table, table->rows);
1393 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1395 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1396 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1398 name = mono_string_to_utf8 (mb->dllentry);
1400 name = mono_string_to_utf8 (mb->name);
1401 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1403 name = mono_string_to_utf8 (mb->dll);
1404 moduleref = string_heap_insert (&assembly->sheap, name);
1406 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1407 table = &assembly->tables [MONO_TABLE_MODULEREF];
1409 alloc_table (table, table->rows);
1410 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1411 values [MONO_IMPLMAP_SCOPE] = table->rows;
1415 if (mb->override_method) {
1416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1418 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1420 alloc_table (table, table->rows);
1421 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1422 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1423 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1425 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1426 switch (mono_metadata_token_table (tok)) {
1427 case MONO_TABLE_MEMBERREF:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1430 case MONO_TABLE_METHOD:
1431 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1434 g_assert_not_reached ();
1436 values [MONO_METHODIMPL_DECLARATION] = tok;
1439 if (mb->generic_params) {
1440 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1441 table->rows += mono_array_length (mb->generic_params);
1442 alloc_table (table, table->rows);
1443 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1444 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1446 mono_image_get_generic_param_info (
1447 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1454 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1456 ReflectionMethodBuilder rmb;
1458 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1460 mono_image_basic_method (&rmb, assembly);
1461 mb->table_idx = *rmb.table_idx;
1465 type_get_fully_qualified_name (MonoType *type)
1467 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1471 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1475 klass = my_mono_class_from_mono_type (type);
1477 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1478 ta = klass->image->assembly;
1479 if (ta->dynamic || (ta == ass))
1480 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1482 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1486 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1488 char blob_size [64];
1489 char *b = blob_size;
1494 if (!assembly->save)
1497 p = buf = g_malloc (256);
1499 mono_metadata_encode_value (0x06, p, &p);
1500 /* encode custom attributes before the type */
1501 encode_type (assembly, type, p, &p);
1502 g_assert (p-buf < 256);
1503 mono_metadata_encode_value (p-buf, b, &b);
1504 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1510 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1512 char blob_size [64];
1513 char *b = blob_size;
1518 p = buf = g_malloc (256);
1520 mono_metadata_encode_value (0x06, p, &p);
1521 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1522 /* encode custom attributes before the type */
1523 encode_reflection_type (assembly, fb->type, p, &p);
1524 g_assert (p-buf < 256);
1525 mono_metadata_encode_value (p-buf, b, &b);
1526 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1532 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1533 char blob_size [64];
1534 char *b = blob_size;
1537 guint32 idx = 0, len = 0, dummy = 0;
1539 p = buf = g_malloc (64);
1541 *ret_type = MONO_TYPE_CLASS;
1543 box_val = (char*)&dummy;
1545 box_val = ((char*)val) + sizeof (MonoObject);
1546 *ret_type = val->vtable->klass->byval_arg.type;
1549 switch (*ret_type) {
1550 case MONO_TYPE_BOOLEAN:
1555 case MONO_TYPE_CHAR:
1570 case MONO_TYPE_VALUETYPE:
1571 if (val->vtable->klass->enumtype) {
1572 *ret_type = val->vtable->klass->enum_basetype->type;
1575 g_error ("we can't encode valuetypes");
1576 case MONO_TYPE_CLASS:
1578 case MONO_TYPE_STRING: {
1579 MonoString *str = (MonoString*)val;
1580 /* there is no signature */
1581 len = str->length * 2;
1582 mono_metadata_encode_value (len, b, &b);
1583 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1585 char *swapped = g_malloc (2 * mono_string_length (str));
1586 const char *p = (const char*)mono_string_chars (str);
1588 swap_with_size (swapped, p, 2, mono_string_length (str));
1589 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1593 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1600 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1603 /* there is no signature */
1604 mono_metadata_encode_value (len, b, &b);
1605 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1606 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1607 swap_with_size (blob_size, box_val, len, 1);
1608 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1610 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1618 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1619 char blob_size [64];
1620 char *b = blob_size;
1621 char *p, *buf, *str;
1622 guint32 idx, len, bufsize = 256;
1624 p = buf = g_malloc (bufsize);
1626 mono_metadata_encode_value (minfo->type, p, &p);
1628 switch (minfo->type) {
1629 case MONO_NATIVE_BYVALTSTR:
1630 case MONO_NATIVE_BYVALARRAY:
1631 mono_metadata_encode_value (minfo->count, p, &p);
1633 case MONO_NATIVE_LPARRAY:
1634 if (minfo->eltype || minfo->has_size) {
1635 mono_metadata_encode_value (minfo->eltype, p, &p);
1636 if (minfo->has_size) {
1637 if (minfo->param_num != -1)
1638 mono_metadata_encode_value (minfo->param_num, p, &p);
1640 mono_metadata_encode_value (0, p, &p);
1641 if (minfo->count != -1)
1642 mono_metadata_encode_value (minfo->count, p, &p);
1644 mono_metadata_encode_value (0, p, &p);
1646 /* LAMESPEC: ElemMult is undocumented */
1647 if (minfo->param_num != -1)
1648 mono_metadata_encode_value (1, p, &p);
1650 mono_metadata_encode_value (0, p, &p);
1654 case MONO_NATIVE_CUSTOM:
1656 str = mono_string_to_utf8 (minfo->guid);
1658 mono_metadata_encode_value (len, p, &p);
1659 memcpy (p, str, len);
1663 mono_metadata_encode_value (0, p, &p);
1665 /* native type name */
1666 mono_metadata_encode_value (0, p, &p);
1667 /* custom marshaler type name */
1668 if (minfo->marshaltype || minfo->marshaltyperef) {
1669 if (minfo->marshaltyperef)
1670 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1672 str = mono_string_to_utf8 (minfo->marshaltype);
1674 mono_metadata_encode_value (len, p, &p);
1675 if (p + len >= buf + bufsize) {
1678 buf = g_realloc (buf, bufsize);
1681 memcpy (p, str, len);
1685 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1686 mono_metadata_encode_value (0, p, &p);
1688 if (minfo->mcookie) {
1689 str = mono_string_to_utf8 (minfo->mcookie);
1691 mono_metadata_encode_value (len, p, &p);
1692 if (p + len >= buf + bufsize) {
1695 buf = g_realloc (buf, bufsize);
1698 memcpy (p, str, len);
1702 mono_metadata_encode_value (0, p, &p);
1709 mono_metadata_encode_value (len, b, &b);
1710 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1716 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1718 MonoDynamicTable *table;
1722 /* maybe this fixup should be done in the C# code */
1723 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1724 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1725 table = &assembly->tables [MONO_TABLE_FIELD];
1726 fb->table_idx = table->next_idx ++;
1727 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1728 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1729 name = mono_string_to_utf8 (fb->name);
1730 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1732 values [MONO_FIELD_FLAGS] = fb->attrs;
1733 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1735 if (fb->offset != -1) {
1736 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1738 alloc_table (table, table->rows);
1739 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1740 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1741 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1743 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1744 guint32 field_type = 0;
1745 table = &assembly->tables [MONO_TABLE_CONSTANT];
1747 alloc_table (table, table->rows);
1748 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1749 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1750 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1751 values [MONO_CONSTANT_TYPE] = field_type;
1752 values [MONO_CONSTANT_PADDING] = 0;
1754 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1756 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1760 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1762 * We store it in the code section because it's simpler for now.
1765 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1767 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1768 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1770 if (fb->marshal_info) {
1771 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1773 alloc_table (table, table->rows);
1774 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1775 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1776 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1781 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1785 char *b = blob_size;
1786 guint32 nparams = 0;
1787 MonoReflectionMethodBuilder *mb = fb->get_method;
1788 MonoReflectionMethodBuilder *smb = fb->set_method;
1789 guint32 idx, i, size;
1791 if (mb && mb->parameters)
1792 nparams = mono_array_length (mb->parameters);
1793 if (!mb && smb && smb->parameters)
1794 nparams = mono_array_length (smb->parameters) - 1;
1795 size = 24 + nparams * 10;
1796 buf = p = g_malloc (size);
1799 mono_metadata_encode_value (nparams, p, &p);
1801 encode_reflection_type (assembly, mb->rtype, p, &p);
1802 for (i = 0; i < nparams; ++i) {
1803 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1804 encode_reflection_type (assembly, pt, p, &p);
1807 /* the property type is the last param */
1808 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1809 for (i = 0; i < nparams; ++i) {
1810 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1811 encode_reflection_type (assembly, pt, p, &p);
1815 encode_reflection_type (assembly, fb->type, p, &p);
1819 g_assert (p - buf < size);
1820 mono_metadata_encode_value (p-buf, b, &b);
1821 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1827 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1829 MonoDynamicTable *table;
1832 guint num_methods = 0;
1836 * we need to set things in the following tables:
1837 * PROPERTYMAP (info already filled in _get_type_info ())
1838 * PROPERTY (rows already preallocated in _get_type_info ())
1839 * METHOD (method info already done with the generic method code)
1842 table = &assembly->tables [MONO_TABLE_PROPERTY];
1843 pb->table_idx = table->next_idx ++;
1844 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1845 name = mono_string_to_utf8 (pb->name);
1846 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1848 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1849 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1851 /* FIXME: we still don't handle 'other' methods */
1852 if (pb->get_method) num_methods ++;
1853 if (pb->set_method) num_methods ++;
1855 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1856 table->rows += num_methods;
1857 alloc_table (table, table->rows);
1859 if (pb->get_method) {
1860 semaidx = table->next_idx ++;
1861 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1862 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1863 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1864 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1866 if (pb->set_method) {
1867 semaidx = table->next_idx ++;
1868 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1869 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1870 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1871 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1876 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1878 MonoDynamicTable *table;
1881 guint num_methods = 0;
1885 * we need to set things in the following tables:
1886 * EVENTMAP (info already filled in _get_type_info ())
1887 * EVENT (rows already preallocated in _get_type_info ())
1888 * METHOD (method info already done with the generic method code)
1891 table = &assembly->tables [MONO_TABLE_EVENT];
1892 eb->table_idx = table->next_idx ++;
1893 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1894 name = mono_string_to_utf8 (eb->name);
1895 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1897 values [MONO_EVENT_FLAGS] = eb->attrs;
1898 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1901 * FIXME: we still don't handle 'other' methods
1903 if (eb->add_method) num_methods ++;
1904 if (eb->remove_method) num_methods ++;
1905 if (eb->raise_method) num_methods ++;
1907 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1908 table->rows += num_methods;
1909 alloc_table (table, table->rows);
1911 if (eb->add_method) {
1912 semaidx = table->next_idx ++;
1913 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1914 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1915 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1916 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1918 if (eb->remove_method) {
1919 semaidx = table->next_idx ++;
1920 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1921 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1922 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1923 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1925 if (eb->raise_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1935 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1937 static MonoClass *NewConstraintAttr;
1938 static MonoMethod *NewConstraintAttr_ctor;
1939 MonoDynamicTable *table;
1941 guint32 token, type;
1942 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1945 if (!NewConstraintAttr)
1946 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1947 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1948 g_assert (NewConstraintAttr);
1950 if (!NewConstraintAttr_ctor) {
1951 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1952 g_assert (NewConstraintAttr_ctor);
1955 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1957 alloc_table (table, table->rows);
1959 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1960 owner <<= MONO_CUSTOM_ATTR_BITS;
1961 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1962 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1964 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1966 type = mono_metadata_token_index (token);
1967 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1968 switch (mono_metadata_token_table (token)) {
1969 case MONO_TABLE_METHOD:
1970 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1972 case MONO_TABLE_MEMBERREF:
1973 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1976 g_warning ("got wrong token in custom attr");
1979 values [MONO_CUSTOM_ATTR_TYPE] = type;
1981 buf = p = g_malloc (1);
1982 mono_metadata_encode_value (4, p, &p);
1983 g_assert (p-buf == 1);
1985 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1987 values += MONO_CUSTOM_ATTR_SIZE;
1992 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1994 MonoDynamicTable *table;
1995 guint32 num_constraints, i;
1999 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2000 num_constraints = gparam->iface_constraints ?
2001 mono_array_length (gparam->iface_constraints) : 0;
2002 table->rows += num_constraints;
2003 if (gparam->base_type)
2005 alloc_table (table, table->rows);
2007 if (gparam->base_type) {
2008 table_idx = table->next_idx ++;
2009 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2011 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2012 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2013 assembly, gparam->base_type->type);
2016 for (i = 0; i < num_constraints; i++) {
2017 MonoReflectionType *constraint = mono_array_get (
2018 gparam->iface_constraints, gpointer, i);
2020 table_idx = table->next_idx ++;
2021 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2023 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2024 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2025 assembly, constraint->type);
2028 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2029 encode_new_constraint (assembly, owner);
2033 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2035 GenericParamTableEntry *entry;
2038 * The GenericParam table must be sorted according to the `owner' field.
2039 * We need to do this sorting prior to writing the GenericParamConstraint
2040 * table, since we have to use the final GenericParam table indices there
2041 * and they must also be sorted.
2044 entry = g_new0 (GenericParamTableEntry, 1);
2045 entry->owner = owner;
2046 entry->gparam = gparam;
2048 g_ptr_array_add (assembly->gen_params, entry);
2052 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2054 MonoDynamicTable *table;
2055 MonoGenericParam *param;
2059 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2060 table_idx = table->next_idx ++;
2061 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2063 param = entry->gparam->type.type->data.generic_param;
2065 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2066 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2067 values [MONO_GENERICPARAM_NUMBER] = param->num;
2068 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2070 encode_constraints (entry->gparam, table_idx, assembly);
2074 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2076 MonoDynamicTable *table;
2079 guint32 cols [MONO_ASSEMBLY_SIZE];
2083 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2086 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2087 table = &assembly->tables [MONO_TABLE_MODULEREF];
2088 token = table->next_idx ++;
2090 alloc_table (table, table->rows);
2091 values = table->values + token * MONO_MODULEREF_SIZE;
2092 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2094 token <<= MONO_RESOLTION_SCOPE_BITS;
2095 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2096 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2101 if (image->assembly->dynamic)
2103 memset (cols, 0, sizeof (cols));
2105 /* image->assembly->image is the manifest module */
2106 image = image->assembly->image;
2107 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2110 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2111 token = table->next_idx ++;
2113 alloc_table (table, table->rows);
2114 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2115 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2116 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2117 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2118 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2119 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2120 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2121 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2122 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2124 if (strcmp ("", image->assembly->aname.culture)) {
2125 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2126 image->assembly->aname.culture);
2129 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2130 guchar pubtoken [9];
2132 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2133 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2135 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2137 token <<= MONO_RESOLTION_SCOPE_BITS;
2138 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2139 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2144 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2146 MonoDynamicTable *table;
2152 char *b = blob_size;
2154 switch (type->type) {
2155 case MONO_TYPE_FNPTR:
2157 case MONO_TYPE_SZARRAY:
2158 case MONO_TYPE_ARRAY:
2160 case MONO_TYPE_MVAR:
2161 case MONO_TYPE_GENERICINST:
2162 encode_type (assembly, type, p, &p);
2164 case MONO_TYPE_CLASS:
2165 case MONO_TYPE_VALUETYPE: {
2166 MonoClass *k = mono_class_from_mono_type (type);
2167 if (!k || !k->generic_class)
2169 encode_generic_class (assembly, k->generic_class, p, &p);
2176 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2177 if (assembly->save) {
2178 g_assert (p-sig < 128);
2179 mono_metadata_encode_value (p-sig, b, &b);
2180 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2181 alloc_table (table, table->rows + 1);
2182 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2183 values [MONO_TYPESPEC_SIGNATURE] = token;
2186 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2187 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2193 * Despite the name, we handle also TypeSpec (with the above helper).
2196 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2198 MonoDynamicTable *table;
2200 guint32 token, scope, enclosing;
2203 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2206 token = create_typespec (assembly, type);
2209 klass = my_mono_class_from_mono_type (type);
2211 klass = mono_class_from_mono_type (type);
2214 * If it's in the same module and not a generic type parameter:
2216 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2217 (type->type != MONO_TYPE_MVAR)) {
2218 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2219 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2220 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2224 if (klass->nested_in) {
2225 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2226 /* get the typeref idx of the enclosing type */
2227 enclosing >>= MONO_TYPEDEFORREF_BITS;
2228 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2230 scope = resolution_scope_from_image (assembly, klass->image);
2232 table = &assembly->tables [MONO_TABLE_TYPEREF];
2233 if (assembly->save) {
2234 alloc_table (table, table->rows + 1);
2235 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2236 values [MONO_TYPEREF_SCOPE] = scope;
2237 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2238 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2240 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2241 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2243 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2248 * Insert a memberef row into the metadata: the token that point to the memberref
2249 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2250 * mono_image_get_fieldref_token()).
2251 * The sig param is an index to an already built signature.
2254 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2256 MonoDynamicTable *table;
2258 guint32 token, pclass;
2261 parent = mono_image_typedef_or_ref (assembly, type);
2262 switch (parent & MONO_TYPEDEFORREF_MASK) {
2263 case MONO_TYPEDEFORREF_TYPEREF:
2264 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2266 case MONO_TYPEDEFORREF_TYPESPEC:
2267 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2269 case MONO_TYPEDEFORREF_TYPEDEF:
2270 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2273 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2276 /* extract the index */
2277 parent >>= MONO_TYPEDEFORREF_BITS;
2279 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2281 if (assembly->save) {
2282 alloc_table (table, table->rows + 1);
2283 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2284 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2285 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2286 values [MONO_MEMBERREF_SIGNATURE] = sig;
2289 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2296 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2299 MonoMethodSignature *sig;
2301 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2306 * A methodref signature can't contain an unmanaged calling convention.
2308 sig = mono_metadata_signature_dup (mono_method_signature (method));
2309 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2310 sig->call_convention = MONO_CALL_DEFAULT;
2311 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2312 method->name, method_encode_signature (assembly, sig));
2314 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2319 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2320 const gchar *name, guint32 sig)
2322 MonoDynamicTable *table;
2326 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2328 if (assembly->save) {
2329 alloc_table (table, table->rows + 1);
2330 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2331 values [MONO_MEMBERREF_CLASS] = original;
2332 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2333 values [MONO_MEMBERREF_SIGNATURE] = sig;
2336 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2343 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2346 ReflectionMethodBuilder rmb;
2348 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2352 reflection_methodbuilder_from_method_builder (&rmb, mb);
2354 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2355 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2356 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2361 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2364 ReflectionMethodBuilder rmb;
2366 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2370 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2372 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2373 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2374 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2379 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2384 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2387 g_assert (f->field->parent);
2388 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2389 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2390 f->field->name, fieldref_encode_signature (assembly, type));
2391 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2396 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2401 guint32 nparams = gmethod->inst->type_argc;
2402 guint32 size = 10 + nparams * 30;
2405 char *b = blob_size;
2407 if (!assembly->save)
2410 p = buf = g_malloc (size);
2412 * FIXME: vararg, explicit_this, differenc call_conv values...
2414 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2415 mono_metadata_encode_value (nparams, p, &p);
2417 for (i = 0; i < nparams; i++)
2418 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2421 g_assert (p - buf < size);
2422 mono_metadata_encode_value (p-buf, b, &b);
2423 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2429 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2431 MonoDynamicTable *table;
2433 guint32 token, mtoken = 0, sig;
2434 MonoMethodInflated *imethod;
2435 MonoMethod *declaring;
2437 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2439 g_assert (method->is_inflated);
2440 method = mono_get_inflated_method (method);
2441 imethod = (MonoMethodInflated *) method;
2442 declaring = imethod->declaring;
2444 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2445 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2447 if (!mono_method_signature (declaring)->generic_param_count)
2450 switch (mono_metadata_token_table (mtoken)) {
2451 case MONO_TABLE_MEMBERREF:
2452 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2454 case MONO_TABLE_METHOD:
2455 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2458 g_assert_not_reached ();
2461 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2463 if (assembly->save) {
2464 alloc_table (table, table->rows + 1);
2465 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2466 values [MONO_METHODSPEC_METHOD] = mtoken;
2467 values [MONO_METHODSPEC_SIGNATURE] = sig;
2470 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2477 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2479 MonoMethodInflated *imethod;
2482 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2486 g_assert (m->is_inflated);
2487 m = mono_get_inflated_method (m);
2488 imethod = (MonoMethodInflated *) m;
2490 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2491 token = method_encode_methodspec (assembly, m);
2493 guint32 sig = method_encode_signature (
2494 assembly, mono_method_signature (imethod->declaring));
2495 token = mono_image_get_memberref_token (
2496 assembly, &m->klass->byval_arg, m->name, sig);
2499 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2504 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2506 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2509 m = mono_get_inflated_method (m);
2511 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2512 token = mono_image_get_memberref_token (
2513 assembly, &m->klass->byval_arg, m->name, sig);
2519 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2521 MonoDynamicTable *table;
2528 char *b = blob_size;
2532 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2533 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2534 * Because of this, we must not insert it into the `typeref' hash table.
2537 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2541 g_assert (tb->generic_params);
2542 klass = mono_class_from_mono_type (tb->type.type);
2544 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2545 encode_type (assembly, &klass->byval_arg, p, &p);
2547 count = mono_array_length (tb->generic_params);
2548 mono_metadata_encode_value (count, p, &p);
2549 for (i = 0; i < count; i++) {
2550 MonoReflectionGenericParam *gparam;
2552 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2554 encode_type (assembly, gparam->type.type, p, &p);
2557 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2558 g_assert (p-sig < 128);
2560 if (assembly->save) {
2561 mono_metadata_encode_value (p-sig, b, &b);
2562 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2563 alloc_table (table, table->rows + 1);
2564 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2565 values [MONO_TYPESPEC_SIGNATURE] = token;
2568 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2569 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2575 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2577 MonoDynamicTable *table;
2580 guint32 token, pclass, parent, sig;
2583 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2587 klass = mono_class_from_mono_type (fb->typeb->type);
2588 name = mono_string_to_utf8 (fb->name);
2590 sig = fieldref_encode_signature (assembly, fb->type->type);
2592 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2593 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2595 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2596 parent >>= MONO_TYPEDEFORREF_BITS;
2598 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2600 if (assembly->save) {
2601 alloc_table (table, table->rows + 1);
2602 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2603 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2604 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2605 values [MONO_MEMBERREF_SIGNATURE] = sig;
2608 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2610 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2615 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2623 char *b = blob_size;
2625 if (!assembly->save)
2629 g_assert (helper->type == 2);
2631 if (helper->arguments)
2632 nargs = mono_array_length (helper->arguments);
2636 size = 10 + (nargs * 10);
2638 p = buf = g_malloc (size);
2640 /* Encode calling convention */
2641 /* Change Any to Standard */
2642 if ((helper->call_conv & 0x03) == 0x03)
2643 helper->call_conv = 0x01;
2644 /* explicit_this implies has_this */
2645 if (helper->call_conv & 0x40)
2646 helper->call_conv &= 0x20;
2648 if (helper->call_conv == 0) { /* Unmanaged */
2649 *p = helper->unmanaged_call_conv - 1;
2652 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2653 if (helper->call_conv & 0x02) /* varargs */
2658 mono_metadata_encode_value (nargs, p, &p);
2659 encode_reflection_type (assembly, helper->return_type, p, &p);
2660 for (i = 0; i < nargs; ++i) {
2661 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2662 encode_reflection_type (assembly, pt, p, &p);
2665 g_assert (p - buf < size);
2666 mono_metadata_encode_value (p-buf, b, &b);
2667 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2674 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2677 MonoDynamicTable *table;
2680 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2681 idx = table->next_idx ++;
2683 alloc_table (table, table->rows);
2684 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2686 values [MONO_STAND_ALONE_SIGNATURE] =
2687 mono_reflection_encode_sighelper (assembly, helper);
2693 reflection_cc_to_file (int call_conv) {
2694 switch (call_conv & 0x3) {
2696 case 1: return MONO_CALL_DEFAULT;
2697 case 2: return MONO_CALL_VARARG;
2699 g_assert_not_reached ();
2706 MonoMethodSignature *sig;
2712 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2717 MonoMethodSignature *sig;
2720 name = mono_string_to_utf8 (m->name);
2721 nparams = mono_array_length (m->parameters);
2722 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2724 sig->sentinelpos = -1;
2725 sig->call_convention = reflection_cc_to_file (m->call_conv);
2726 sig->param_count = nparams;
2727 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2728 for (i = 0; i < nparams; ++i) {
2729 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2730 sig->params [i] = t->type;
2733 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2735 if (strcmp (name, am->name) == 0 &&
2736 mono_metadata_type_equal (am->parent, m->parent->type) &&
2737 mono_metadata_signature_equal (am->sig, sig)) {
2740 m->table_idx = am->token & 0xffffff;
2744 am = g_new0 (ArrayMethod, 1);
2747 am->parent = m->parent->type;
2748 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2749 method_encode_signature (assembly, sig));
2750 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2751 m->table_idx = am->token & 0xffffff;
2756 * Insert into the metadata tables all the info about the TypeBuilder tb.
2757 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2760 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2762 MonoDynamicTable *table;
2764 int i, is_object = 0, is_system = 0;
2767 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2768 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2769 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2770 n = mono_string_to_utf8 (tb->name);
2771 if (strcmp (n, "Object") == 0)
2773 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2775 n = mono_string_to_utf8 (tb->nspace);
2776 if (strcmp (n, "System") == 0)
2778 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2780 if (tb->parent && !(is_system && is_object) &&
2781 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2782 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2784 values [MONO_TYPEDEF_EXTENDS] = 0;
2786 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2787 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2790 * if we have explicitlayout or sequentiallayouts, output data in the
2791 * ClassLayout table.
2793 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2794 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2795 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2797 alloc_table (table, table->rows);
2798 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2799 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2800 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2801 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2804 /* handle interfaces */
2805 if (tb->interfaces) {
2806 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2808 table->rows += mono_array_length (tb->interfaces);
2809 alloc_table (table, table->rows);
2810 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2811 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2812 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2813 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2814 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2815 values += MONO_INTERFACEIMPL_SIZE;
2821 table = &assembly->tables [MONO_TABLE_FIELD];
2822 table->rows += tb->num_fields;
2823 alloc_table (table, table->rows);
2824 for (i = 0; i < tb->num_fields; ++i)
2825 mono_image_get_field_info (
2826 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2829 /* handle constructors */
2831 table = &assembly->tables [MONO_TABLE_METHOD];
2832 table->rows += mono_array_length (tb->ctors);
2833 alloc_table (table, table->rows);
2834 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2835 mono_image_get_ctor_info (domain,
2836 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2839 /* handle methods */
2841 table = &assembly->tables [MONO_TABLE_METHOD];
2842 table->rows += tb->num_methods;
2843 alloc_table (table, table->rows);
2844 for (i = 0; i < tb->num_methods; ++i)
2845 mono_image_get_method_info (
2846 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2849 /* Do the same with properties etc.. */
2850 if (tb->events && mono_array_length (tb->events)) {
2851 table = &assembly->tables [MONO_TABLE_EVENT];
2852 table->rows += mono_array_length (tb->events);
2853 alloc_table (table, table->rows);
2854 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2856 alloc_table (table, table->rows);
2857 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2858 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2859 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2860 for (i = 0; i < mono_array_length (tb->events); ++i)
2861 mono_image_get_event_info (
2862 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2864 if (tb->properties && mono_array_length (tb->properties)) {
2865 table = &assembly->tables [MONO_TABLE_PROPERTY];
2866 table->rows += mono_array_length (tb->properties);
2867 alloc_table (table, table->rows);
2868 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2870 alloc_table (table, table->rows);
2871 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2872 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2873 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2874 for (i = 0; i < mono_array_length (tb->properties); ++i)
2875 mono_image_get_property_info (
2876 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2879 /* handle generic parameters */
2880 if (tb->generic_params) {
2881 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2882 table->rows += mono_array_length (tb->generic_params);
2883 alloc_table (table, table->rows);
2884 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2885 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2887 mono_image_get_generic_param_info (
2888 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2892 mono_image_add_decl_security (assembly,
2893 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2896 MonoDynamicTable *ntable;
2898 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2899 ntable->rows += mono_array_length (tb->subtypes);
2900 alloc_table (ntable, ntable->rows);
2901 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2903 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2904 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2906 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2907 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2908 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2909 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2910 mono_string_to_utf8 (tb->name), tb->table_idx,
2911 ntable->next_idx, ntable->rows);*/
2912 values += MONO_NESTED_CLASS_SIZE;
2919 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2923 g_ptr_array_add (types, type);
2925 if (!type->subtypes)
2928 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2929 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2930 collect_types (types, subtype);
2935 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2937 if ((*type1)->table_idx < (*type2)->table_idx)
2940 if ((*type1)->table_idx > (*type2)->table_idx)
2947 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2952 for (i = 0; i < mono_array_length (pinfo); ++i) {
2953 MonoReflectionParamBuilder *pb;
2954 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2957 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2962 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2965 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2967 for (i = 0; i < tb->num_fields; ++i) {
2968 MonoReflectionFieldBuilder* fb;
2969 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2970 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2974 for (i = 0; i < mono_array_length (tb->events); ++i) {
2975 MonoReflectionEventBuilder* eb;
2976 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2977 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2980 if (tb->properties) {
2981 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2982 MonoReflectionPropertyBuilder* pb;
2983 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2984 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2988 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2989 MonoReflectionCtorBuilder* cb;
2990 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2991 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2992 params_add_cattrs (assembly, cb->pinfo);
2997 for (i = 0; i < tb->num_methods; ++i) {
2998 MonoReflectionMethodBuilder* mb;
2999 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3000 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3001 params_add_cattrs (assembly, mb->pinfo);
3006 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3007 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3012 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3015 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3017 /* no types in the module */
3021 for (i = 0; i < mb->num_types; ++i)
3022 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3026 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3028 MonoDynamicTable *table;
3032 char *b = blob_size;
3035 table = &assembly->tables [MONO_TABLE_FILE];
3037 alloc_table (table, table->rows);
3038 values = table->values + table->next_idx * MONO_FILE_SIZE;
3039 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3040 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3041 if (module->image->dynamic) {
3042 /* This depends on the fact that the main module is emitted last */
3043 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3044 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3047 path = g_strdup (module->image->name);
3049 mono_sha1_get_digest_from_file (path, hash);
3052 mono_metadata_encode_value (20, b, &b);
3053 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3054 mono_image_add_stream_data (&assembly->blob, hash, 20);
3059 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3061 MonoDynamicTable *table;
3065 table = &assembly->tables [MONO_TABLE_MODULE];
3066 mb->table_idx = table->next_idx ++;
3067 name = mono_string_to_utf8 (mb->module.name);
3068 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3070 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3073 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3074 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3075 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3076 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3080 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3081 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3083 MonoDynamicTable *table;
3087 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3088 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3091 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3093 alloc_table (table, table->rows);
3094 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3096 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3097 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3098 if (klass->nested_in)
3099 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3101 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3102 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3103 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3105 res = table->next_idx;
3109 /* Emit nested types */
3110 if (klass->nested_classes) {
3113 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3114 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3121 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3122 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3127 klass = mono_class_from_mono_type (tb->type.type);
3129 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3131 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3132 parent_index, assembly);
3136 * We need to do this ourselves since klass->nested_classes is not set up.
3139 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3140 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3145 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3146 guint32 module_index, MonoDynamicImage *assembly)
3148 MonoImage *image = module->image;
3152 t = &image->tables [MONO_TABLE_TYPEDEF];
3154 for (i = 0; i < t->rows; ++i) {
3155 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3157 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3158 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3162 #define align_pointer(base,p)\
3164 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3166 (p) += 4 - (__diff & 3);\
3170 compare_constants (const void *a, const void *b)
3172 const guint32 *a_values = a;
3173 const guint32 *b_values = b;
3174 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3178 compare_semantics (const void *a, const void *b)
3180 const guint32 *a_values = a;
3181 const guint32 *b_values = b;
3182 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3185 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3189 compare_custom_attrs (const void *a, const void *b)
3191 const guint32 *a_values = a;
3192 const guint32 *b_values = b;
3194 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3198 compare_field_marshal (const void *a, const void *b)
3200 const guint32 *a_values = a;
3201 const guint32 *b_values = b;
3203 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3207 compare_nested (const void *a, const void *b)
3209 const guint32 *a_values = a;
3210 const guint32 *b_values = b;
3212 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3216 compare_genericparam (const void *a, const void *b)
3218 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3219 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3221 if ((*b_entry)->owner == (*a_entry)->owner)
3223 (*a_entry)->gparam->type.type->data.generic_param->num -
3224 (*b_entry)->gparam->type.type->data.generic_param->num;
3226 return (*a_entry)->owner - (*b_entry)->owner;
3230 compare_declsecurity_attrs (const void *a, const void *b)
3232 const guint32 *a_values = a;
3233 const guint32 *b_values = b;
3235 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3239 pad_heap (MonoDynamicStream *sh)
3241 if (sh->index & 3) {
3242 int sz = 4 - (sh->index & 3);
3243 memset (sh->data + sh->index, 0, sz);
3250 MonoDynamicStream *stream;
3254 * build_compressed_metadata() fills in the blob of data that represents the
3255 * raw metadata as it will be saved in the PE file. The five streams are output
3256 * and the metadata tables are comnpressed from the guint32 array representation,
3257 * to the compressed on-disk format.
3260 build_compressed_metadata (MonoDynamicImage *assembly)
3262 MonoDynamicTable *table;
3264 guint64 valid_mask = 0;
3265 guint64 sorted_mask;
3266 guint32 heapt_size = 0;
3267 guint32 meta_size = 256; /* allow for header and other stuff */
3268 guint32 table_offset;
3269 guint32 ntables = 0;
3275 struct StreamDesc stream_desc [5];
3277 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3278 for (i = 0; i < assembly->gen_params->len; i++){
3279 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3280 write_generic_param_entry (assembly, entry);
3283 stream_desc [0].name = "#~";
3284 stream_desc [0].stream = &assembly->tstream;
3285 stream_desc [1].name = "#Strings";
3286 stream_desc [1].stream = &assembly->sheap;
3287 stream_desc [2].name = "#US";
3288 stream_desc [2].stream = &assembly->us;
3289 stream_desc [3].name = "#Blob";
3290 stream_desc [3].stream = &assembly->blob;
3291 stream_desc [4].name = "#GUID";
3292 stream_desc [4].stream = &assembly->guid;
3294 /* tables that are sorted */
3295 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3296 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3297 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3298 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3299 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3300 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3302 /* Compute table sizes */
3303 /* the MonoImage has already been created in mono_image_basic_init() */
3304 meta = &assembly->image;
3306 /* sizes should be multiple of 4 */
3307 pad_heap (&assembly->blob);
3308 pad_heap (&assembly->guid);
3309 pad_heap (&assembly->sheap);
3310 pad_heap (&assembly->us);
3312 /* Setup the info used by compute_sizes () */
3313 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3314 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3315 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3317 meta_size += assembly->blob.index;
3318 meta_size += assembly->guid.index;
3319 meta_size += assembly->sheap.index;
3320 meta_size += assembly->us.index;
3322 for (i=0; i < MONO_TABLE_NUM; ++i)
3323 meta->tables [i].rows = assembly->tables [i].rows;
3325 for (i = 0; i < MONO_TABLE_NUM; i++){
3326 if (meta->tables [i].rows == 0)
3328 valid_mask |= (guint64)1 << i;
3330 meta->tables [i].row_size = mono_metadata_compute_size (
3331 meta, i, &meta->tables [i].size_bitfield);
3332 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3334 heapt_size += 24; /* #~ header size */
3335 heapt_size += ntables * 4;
3336 /* make multiple of 4 */
3339 meta_size += heapt_size;
3340 meta->raw_metadata = g_malloc0 (meta_size);
3341 p = meta->raw_metadata;
3342 /* the metadata signature */
3343 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3344 /* version numbers and 4 bytes reserved */
3345 int16val = (guint16*)p;
3346 *int16val++ = GUINT16_TO_LE (1);
3347 *int16val = GUINT16_TO_LE (1);
3349 /* version string */
3350 int32val = (guint32*)p;
3351 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3353 memcpy (p, meta->version, strlen (meta->version));
3354 p += GUINT32_FROM_LE (*int32val);
3355 align_pointer (meta->raw_metadata, p);
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3358 *int16val = GUINT16_TO_LE (5); /* number of streams */
3362 * write the stream info.
3364 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3365 table_offset += 3; table_offset &= ~3;
3367 assembly->tstream.index = heapt_size;
3368 for (i = 0; i < 5; ++i) {
3369 int32val = (guint32*)p;
3370 stream_desc [i].stream->offset = table_offset;
3371 *int32val++ = GUINT32_TO_LE (table_offset);
3372 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3373 table_offset += GUINT32_FROM_LE (*int32val);
3374 table_offset += 3; table_offset &= ~3;
3376 strcpy (p, stream_desc [i].name);
3377 p += strlen (stream_desc [i].name) + 1;
3378 align_pointer (meta->raw_metadata, p);
3381 * now copy the data, the table stream header and contents goes first.
3383 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3384 p = meta->raw_metadata + assembly->tstream.offset;
3385 int32val = (guint32*)p;
3386 *int32val = GUINT32_TO_LE (0); /* reserved */
3389 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3390 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3391 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3392 *p++ = 2; /* version */
3395 *p++ = 1; /* version */
3399 if (meta->idx_string_wide)
3401 if (meta->idx_guid_wide)
3403 if (meta->idx_blob_wide)
3406 *p++ = 1; /* reserved */
3407 int64val = (guint64*)p;
3408 *int64val++ = GUINT64_TO_LE (valid_mask);
3409 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3411 int32val = (guint32*)p;
3412 for (i = 0; i < MONO_TABLE_NUM; i++){
3413 if (meta->tables [i].rows == 0)
3415 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3417 p = (unsigned char*)int32val;
3419 /* sort the tables that still need sorting */
3420 table = &assembly->tables [MONO_TABLE_CONSTANT];
3422 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3423 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3425 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3426 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3428 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3429 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3431 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3432 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3434 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3435 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3436 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3438 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3440 /* compress the tables */
3441 for (i = 0; i < MONO_TABLE_NUM; i++){
3444 guint32 bitfield = meta->tables [i].size_bitfield;
3445 if (!meta->tables [i].rows)
3447 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3448 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3449 meta->tables [i].base = p;
3450 for (row = 1; row <= meta->tables [i].rows; ++row) {
3451 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3452 for (col = 0; col < assembly->tables [i].columns; ++col) {
3453 switch (mono_metadata_table_size (bitfield, col)) {
3455 *p++ = values [col];
3458 *p++ = values [col] & 0xff;
3459 *p++ = (values [col] >> 8) & 0xff;
3462 *p++ = values [col] & 0xff;
3463 *p++ = (values [col] >> 8) & 0xff;
3464 *p++ = (values [col] >> 16) & 0xff;
3465 *p++ = (values [col] >> 24) & 0xff;
3468 g_assert_not_reached ();
3472 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3475 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3476 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3477 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3478 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3479 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3481 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3485 * Some tables in metadata need to be sorted according to some criteria, but
3486 * when methods and fields are first created with reflection, they may be assigned a token
3487 * that doesn't correspond to the final token they will get assigned after the sorting.
3488 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3489 * with the reflection objects that represent them. Once all the tables are set up, the
3490 * reflection objects will contains the correct table index. fixup_method() will fixup the
3491 * tokens for the method with ILGenerator @ilgen.
3494 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3495 guint32 code_idx = GPOINTER_TO_UINT (value);
3496 MonoReflectionILTokenInfo *iltoken;
3497 MonoReflectionFieldBuilder *field;
3498 MonoReflectionCtorBuilder *ctor;
3499 MonoReflectionMethodBuilder *method;
3500 MonoReflectionTypeBuilder *tb;
3501 MonoReflectionArrayMethod *am;
3503 unsigned char *target;
3505 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3506 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3507 target = assembly->code.data + code_idx + iltoken->code_pos;
3508 switch (target [3]) {
3509 case MONO_TABLE_FIELD:
3510 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3511 field = (MonoReflectionFieldBuilder *)iltoken->member;
3512 idx = field->table_idx;
3513 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3514 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3515 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3517 g_assert_not_reached ();
3520 case MONO_TABLE_METHOD:
3521 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3522 method = (MonoReflectionMethodBuilder *)iltoken->member;
3523 idx = method->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3525 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3526 idx = ctor->table_idx;
3527 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3528 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3529 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3530 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3532 g_assert_not_reached ();
3535 case MONO_TABLE_TYPEDEF:
3536 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3537 g_assert_not_reached ();
3538 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3539 idx = tb->table_idx;
3541 case MONO_TABLE_MEMBERREF:
3542 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3543 am = (MonoReflectionArrayMethod*)iltoken->member;
3544 idx = am->table_idx;
3545 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3546 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3547 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3548 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3549 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3550 g_assert (m->klass->generic_class || m->klass->generic_container);
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3555 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3556 g_assert (f->generic_info);
3558 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3561 g_assert_not_reached ();
3564 case MONO_TABLE_METHODSPEC:
3565 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3566 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3567 g_assert (mono_method_signature (m)->generic_param_count);
3570 g_assert_not_reached ();
3574 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3576 target [0] = idx & 0xff;
3577 target [1] = (idx >> 8) & 0xff;
3578 target [2] = (idx >> 16) & 0xff;
3585 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3586 * value is not known when the table is emitted.
3589 fixup_cattrs (MonoDynamicImage *assembly)
3591 MonoDynamicTable *table;
3593 guint32 type, i, idx, token;
3596 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3598 for (i = 0; i < table->rows; ++i) {
3599 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3601 type = values [MONO_CUSTOM_ATTR_TYPE];
3602 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3603 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3604 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3605 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3608 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3609 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3610 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3611 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3620 * The METHODIMPL table might contain METHODDEF tokens whose final
3621 * value is not known when the table is emitted.
3624 fixup_methodimpl (MonoDynamicImage *assembly)
3626 MonoDynamicTable *table;
3628 guint32 decl, i, idx, token;
3631 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3633 for (i = 0; i < table->rows; ++i) {
3634 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3635 decl = values [MONO_METHODIMPL_DECLARATION];
3637 idx = decl >> MONO_METHODDEFORREF_BITS;
3638 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3641 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3642 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3645 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3646 token = mono_image_create_token (assembly, method, FALSE);
3647 idx = mono_metadata_token_index (token);
3648 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3654 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3656 MonoDynamicTable *table;
3660 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3662 alloc_table (table, table->rows);
3663 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3664 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3665 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3666 name = mono_string_to_utf8 (rsrc->name);
3667 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3669 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3674 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3676 MonoDynamicTable *table;
3680 char *b = blob_size;
3682 guint32 idx, offset;
3684 if (rsrc->filename) {
3685 name = mono_string_to_utf8 (rsrc->filename);
3686 sname = g_path_get_basename (name);
3688 table = &assembly->tables [MONO_TABLE_FILE];
3690 alloc_table (table, table->rows);
3691 values = table->values + table->next_idx * MONO_FILE_SIZE;
3692 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3693 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3696 mono_sha1_get_digest_from_file (name, hash);
3697 mono_metadata_encode_value (20, b, &b);
3698 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3699 mono_image_add_stream_data (&assembly->blob, hash, 20);
3701 idx = table->next_idx++;
3703 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3706 offset = mono_array_length (rsrc->data);
3707 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3708 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3709 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3710 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3714 * The entry should be emitted into the MANIFESTRESOURCE table of
3715 * the main module, but that needs to reference the FILE table
3716 * which isn't emitted yet.
3723 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3727 set_version_from_string (MonoString *version, guint32 *values)
3729 gchar *ver, *p, *str;
3732 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3733 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3734 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3735 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3738 ver = str = mono_string_to_utf8 (version);
3739 for (i = 0; i < 4; ++i) {
3740 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3746 /* handle Revision and Build */
3756 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3760 char *b = blob_size;
3765 len = mono_array_length (pkey);
3766 mono_metadata_encode_value (len, b, &b);
3767 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3768 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3770 /* need to get the actual value from the key type... */
3771 assembly->strong_name_size = 128;
3772 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3778 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3780 MonoDynamicTable *table;
3781 MonoDynamicImage *assembly;
3782 MonoReflectionAssemblyBuilder *assemblyb;
3787 guint32 module_index;
3789 assemblyb = moduleb->assemblyb;
3790 assembly = moduleb->dynamic_image;
3791 domain = mono_object_domain (assemblyb);
3793 /* Emit ASSEMBLY table */
3794 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3795 alloc_table (table, 1);
3796 values = table->values + MONO_ASSEMBLY_SIZE;
3797 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3798 name = mono_string_to_utf8 (assemblyb->name);
3799 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3801 if (assemblyb->culture) {
3802 name = mono_string_to_utf8 (assemblyb->culture);
3803 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3806 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3808 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3809 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3810 set_version_from_string (assemblyb->version, values);
3812 /* Emit FILE + EXPORTED_TYPE table */
3814 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3816 MonoReflectionModuleBuilder *file_module =
3817 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3818 if (file_module != moduleb) {
3819 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3821 if (file_module->types) {
3822 for (j = 0; j < file_module->num_types; ++j) {
3823 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3824 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3829 if (assemblyb->loaded_modules) {
3830 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3831 MonoReflectionModule *file_module =
3832 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3833 mono_image_fill_file_table (domain, file_module, assembly);
3835 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3839 /* Emit MANIFESTRESOURCE table */
3841 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3843 MonoReflectionModuleBuilder *file_module =
3844 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3845 /* The table for the main module is emitted later */
3846 if (file_module != moduleb) {
3848 if (file_module->resources) {
3849 int len = mono_array_length (file_module->resources);
3850 for (j = 0; j < len; ++j) {
3851 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3852 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3860 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3861 * for the modulebuilder @moduleb.
3862 * At the end of the process, method and field tokens are fixed up and the
3863 * on-disk compressed metadata representation is created.
3866 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3868 MonoDynamicTable *table;
3869 MonoDynamicImage *assembly;
3870 MonoReflectionAssemblyBuilder *assemblyb;
3875 assemblyb = moduleb->assemblyb;
3876 assembly = moduleb->dynamic_image;
3877 domain = mono_object_domain (assemblyb);
3879 if (assembly->text_rva)
3882 assembly->text_rva = START_TEXT_RVA;
3884 if (moduleb->is_main) {
3885 mono_image_emit_manifest (moduleb);
3888 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3889 table->rows = 1; /* .<Module> */
3891 alloc_table (table, table->rows);
3893 * Set the first entry.
3895 values = table->values + table->columns;
3896 values [MONO_TYPEDEF_FLAGS] = 0;
3897 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3898 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3899 values [MONO_TYPEDEF_EXTENDS] = 0;
3900 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3901 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3904 * handle global methods
3905 * FIXME: test what to do when global methods are defined in multiple modules.
3907 if (moduleb->global_methods) {
3908 table = &assembly->tables [MONO_TABLE_METHOD];
3909 table->rows += mono_array_length (moduleb->global_methods);
3910 alloc_table (table, table->rows);
3911 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3912 mono_image_get_method_info (
3913 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3915 if (moduleb->global_fields) {
3916 table = &assembly->tables [MONO_TABLE_FIELD];
3917 table->rows += mono_array_length (moduleb->global_fields);
3918 alloc_table (table, table->rows);
3919 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3920 mono_image_get_field_info (
3921 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3924 table = &assembly->tables [MONO_TABLE_MODULE];
3925 alloc_table (table, 1);
3926 mono_image_fill_module_table (domain, moduleb, assembly);
3930 /* Collect all types into a list sorted by their table_idx */
3931 GPtrArray *types = g_ptr_array_new ();
3934 for (i = 0; i < moduleb->num_types; ++i) {
3935 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3936 collect_types (types, type);
3939 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3940 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3941 table->rows += types->len;
3942 alloc_table (table, table->rows);
3945 * Emit type names + namespaces at one place inside the string heap,
3946 * so load_class_names () needs to touch fewer pages.
3948 for (i = 0; i < types->len; ++i) {
3949 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3952 n = mono_string_to_utf8 (tb->nspace);
3953 string_heap_insert (&assembly->sheap, n);
3956 for (i = 0; i < types->len; ++i) {
3957 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
3960 n = mono_string_to_utf8 (tb->name);
3961 string_heap_insert (&assembly->sheap, n);
3965 for (i = 0; i < types->len; ++i) {
3966 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3967 mono_image_get_type_info (domain, type, assembly);
3969 g_ptr_array_free (types, TRUE);
3973 * table->rows is already set above and in mono_image_fill_module_table.
3975 /* add all the custom attributes at the end, once all the indexes are stable */
3976 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3978 /* CAS assembly permissions */
3979 if (assemblyb->permissions_minimum)
3980 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3981 if (assemblyb->permissions_optional)
3982 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3983 if (assemblyb->permissions_refused)
3984 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3986 module_add_cattrs (assembly, moduleb);
3989 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3990 fixup_cattrs (assembly);
3991 fixup_methodimpl (assembly);
3995 * mono_image_insert_string:
3996 * @module: module builder object
3999 * Insert @str into the user string stream of @module.
4002 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4004 MonoDynamicImage *assembly;
4009 MONO_ARCH_SAVE_REGS;
4011 if (!module->dynamic_image)
4012 mono_image_module_basic_init (module);
4014 assembly = module->dynamic_image;
4016 if (assembly->save) {
4017 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4018 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4019 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4021 char *swapped = g_malloc (2 * mono_string_length (str));
4022 const char *p = (const char*)mono_string_chars (str);
4024 swap_with_size (swapped, p, 2, mono_string_length (str));
4025 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4029 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4031 mono_image_add_stream_data (&assembly->us, "", 1);
4033 idx = assembly->us.index ++;
4036 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4038 return MONO_TOKEN_STRING | idx;
4042 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4047 klass = obj->vtable->klass;
4048 if (strcmp (klass->name, "MonoMethod") == 0) {
4049 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4050 MonoMethodSignature *sig, *old;
4051 guint32 sig_token, parent;
4054 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4056 nargs = mono_array_length (opt_param_types);
4057 old = mono_method_signature (method);
4058 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4060 sig->hasthis = old->hasthis;
4061 sig->explicit_this = old->explicit_this;
4062 sig->call_convention = old->call_convention;
4063 sig->generic_param_count = old->generic_param_count;
4064 sig->param_count = old->param_count + nargs;
4065 sig->sentinelpos = old->param_count;
4066 sig->ret = old->ret;
4068 for (i = 0; i < old->param_count; i++)
4069 sig->params [i] = old->params [i];
4071 for (i = 0; i < nargs; i++) {
4072 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4073 sig->params [old->param_count + i] = rt->type;
4076 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4077 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4078 parent >>= MONO_TYPEDEFORREF_BITS;
4080 parent <<= MONO_MEMBERREF_PARENT_BITS;
4081 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4083 sig_token = method_encode_signature (assembly, sig);
4084 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4085 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4086 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4087 ReflectionMethodBuilder rmb;
4088 guint32 parent, sig;
4090 reflection_methodbuilder_from_method_builder (&rmb, mb);
4091 rmb.opt_types = opt_param_types;
4093 sig = method_builder_encode_signature (assembly, &rmb);
4095 parent = mono_image_create_token (assembly, obj, TRUE);
4096 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4098 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4099 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4101 token = mono_image_get_varargs_method_token (
4102 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4104 g_error ("requested method token for %s\n", klass->name);
4111 * mono_image_create_token:
4112 * @assembly: a dynamic assembly
4115 * Get a token to insert in the IL code stream for the given MemberInfo.
4116 * @obj can be one of:
4117 * ConstructorBuilder
4127 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4132 klass = obj->vtable->klass;
4133 if (strcmp (klass->name, "MethodBuilder") == 0) {
4134 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4136 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4137 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4139 token = mono_image_get_methodbuilder_token (assembly, mb);
4140 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4141 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4142 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4144 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4145 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4147 token = mono_image_get_ctorbuilder_token (assembly, mb);
4148 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4149 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4150 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4151 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4152 if (tb->generic_params) {
4153 token = mono_image_get_generic_field_token (assembly, fb);
4155 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4157 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4158 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4159 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4160 } else if (strcmp (klass->name, "MonoType") == 0 ||
4161 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4162 MonoReflectionType *tb = (MonoReflectionType *)obj;
4163 token = mono_metadata_token_from_dor (
4164 mono_image_typedef_or_ref (assembly, tb->type));
4165 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4166 MonoReflectionType *tb = (MonoReflectionType *)obj;
4167 token = mono_metadata_token_from_dor (
4168 mono_image_typedef_or_ref (assembly, tb->type));
4169 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4170 strcmp (klass->name, "MonoMethod") == 0 ||
4171 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4172 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4173 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4174 if (m->method->is_inflated) {
4175 if (create_methodspec)
4176 token = mono_image_get_methodspec_token (assembly, m->method);
4178 token = mono_image_get_inflated_method_token (assembly, m->method);
4179 } else if ((m->method->klass->image == &assembly->image) &&
4180 !m->method->klass->generic_class) {
4181 static guint32 method_table_idx = 0xffffff;
4182 if (m->method->klass->wastypebuilder) {
4183 /* we use the same token as the one that was assigned
4184 * to the Methodbuilder.
4185 * FIXME: do the equivalent for Fields.
4187 token = m->method->token;
4190 * Each token should have a unique index, but the indexes are
4191 * assigned by managed code, so we don't know about them. An
4192 * easy solution is to count backwards...
4194 method_table_idx --;
4195 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4198 token = mono_image_get_methodref_token (assembly, m->method);
4200 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4201 } else if (strcmp (klass->name, "MonoField") == 0) {
4202 MonoReflectionField *f = (MonoReflectionField *)obj;
4203 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4204 static guint32 field_table_idx = 0xffffff;
4206 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4208 token = mono_image_get_fieldref_token (assembly, f);
4210 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4211 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4212 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4213 token = mono_image_get_array_token (assembly, m);
4214 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4215 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4216 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4218 g_error ("requested token for %s\n", klass->name);
4221 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4227 guint32 import_lookup_table;
4231 guint32 import_address_table_rva;
4239 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4241 static MonoDynamicImage*
4242 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4244 static const guchar entrycode [16] = {0xff, 0x25, 0};
4245 MonoDynamicImage *image;
4248 const char *version = mono_get_runtime_info ()->runtime_version;
4251 image = GC_MALLOC (sizeof (MonoDynamicImage));
4253 image = g_new0 (MonoDynamicImage, 1);
4256 /*g_print ("created image %p\n", image);*/
4257 /* keep in sync with image.c */
4258 image->image.name = assembly_name;
4259 image->image.assembly_name = image->image.name; /* they may be different */
4260 image->image.module_name = module_name;
4261 image->image.version = version;
4262 image->image.dynamic = TRUE;
4263 image->image.ref_count = 1;
4265 image->image.references = g_new0 (MonoAssembly*, 1);
4266 image->image.references [0] = NULL;
4268 mono_image_init (&image->image);
4270 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4271 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4272 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4273 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4274 image->handleref = g_hash_table_new (NULL, NULL);
4275 image->tokens = mono_g_hash_table_new (NULL, NULL);
4276 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4277 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4278 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4279 image->gen_params = g_ptr_array_new ();
4281 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4282 string_heap_init (&image->sheap);
4283 mono_image_add_stream_data (&image->us, "", 1);
4284 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4285 /* import tables... */
4286 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4287 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4288 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4289 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4290 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4291 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4292 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4293 stream_data_align (&image->code);
4295 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4297 for (i=0; i < MONO_TABLE_NUM; ++i) {
4298 image->tables [i].next_idx = 1;
4299 image->tables [i].columns = table_sizes [i];
4302 image->image.assembly = (MonoAssembly*)assembly;
4303 image->run = assembly->run;
4304 image->save = assembly->save;
4305 image->pe_kind = 0x1; /* ILOnly */
4306 image->machine = 0x14c; /* I386 */
4312 * mono_image_basic_init:
4313 * @assembly: an assembly builder object
4315 * Create the MonoImage that represents the assembly builder and setup some
4316 * of the helper hash table and the basic metadata streams.
4319 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4321 MonoDynamicAssembly *assembly;
4322 MonoDynamicImage *image;
4323 MonoDomain *domain = mono_object_domain (assemblyb);
4325 MONO_ARCH_SAVE_REGS;
4327 if (assemblyb->dynamic_assembly)
4331 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4333 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4336 assembly->assembly.ref_count = 1;
4337 assembly->assembly.dynamic = TRUE;
4338 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4339 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4340 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4341 if (assemblyb->culture)
4342 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4344 assembly->assembly.aname.culture = g_strdup ("");
4346 if (assemblyb->version) {
4347 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4348 char **parts = version;
4349 assembly->assembly.aname.major = atoi (*parts++);
4350 assembly->assembly.aname.minor = atoi (*parts++);
4351 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4352 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4354 g_strfreev (version);
4356 assembly->assembly.aname.major = 0;
4357 assembly->assembly.aname.minor = 0;
4358 assembly->assembly.aname.build = 0;
4359 assembly->assembly.aname.revision = 0;
4362 assembly->run = assemblyb->access != 2;
4363 assembly->save = assemblyb->access != 1;
4365 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4366 image->initial_image = TRUE;
4367 assembly->assembly.aname.name = image->image.name;
4368 assembly->assembly.image = &image->image;
4370 mono_domain_assemblies_lock (domain);
4371 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4372 mono_domain_assemblies_unlock (domain);
4374 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4375 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4379 calc_section_size (MonoDynamicImage *assembly)
4383 /* alignment constraints */
4384 assembly->code.index += 3;
4385 assembly->code.index &= ~3;
4386 assembly->meta_size += 3;
4387 assembly->meta_size &= ~3;
4388 assembly->resources.index += 3;
4389 assembly->resources.index &= ~3;
4391 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4392 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4395 if (assembly->win32_res) {
4396 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4398 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4399 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4403 assembly->sections [MONO_SECTION_RELOC].size = 12;
4404 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4414 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4418 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4420 ResTreeNode *t1 = (ResTreeNode*)a;
4421 ResTreeNode *t2 = (ResTreeNode*)b;
4423 return t1->id - t2->id;
4427 * resource_tree_create:
4429 * Organize the resources into a resource tree.
4431 static ResTreeNode *
4432 resource_tree_create (MonoArray *win32_resources)
4434 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4438 tree = g_new0 (ResTreeNode, 1);
4440 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4441 MonoReflectionWin32Resource *win32_res =
4442 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4446 lang_node = g_new0 (ResTreeNode, 1);
4447 lang_node->id = win32_res->lang_id;
4448 lang_node->win32_res = win32_res;
4450 /* Create type node if neccesary */
4452 for (l = tree->children; l; l = l->next)
4453 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4454 type_node = (ResTreeNode*)l->data;
4459 type_node = g_new0 (ResTreeNode, 1);
4460 type_node->id = win32_res->res_type;
4463 * The resource types have to be sorted otherwise
4464 * Windows Explorer can't display the version information.
4466 tree->children = g_slist_insert_sorted (tree->children,
4467 type_node, resource_tree_compare_by_id);
4470 /* Create res node if neccesary */
4472 for (l = type_node->children; l; l = l->next)
4473 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4474 res_node = (ResTreeNode*)l->data;
4479 res_node = g_new0 (ResTreeNode, 1);
4480 res_node->id = win32_res->res_id;
4481 type_node->children = g_slist_append (type_node->children, res_node);
4484 res_node->children = g_slist_append (res_node->children, lang_node);
4491 * resource_tree_encode:
4493 * Encode the resource tree into the format used in the PE file.
4496 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4499 MonoPEResourceDir dir;
4500 MonoPEResourceDirEntry dir_entry;
4501 MonoPEResourceDataEntry data_entry;
4505 * For the format of the resource directory, see the article
4506 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4510 memset (&dir, 0, sizeof (dir));
4511 memset (&dir_entry, 0, sizeof (dir_entry));
4512 memset (&data_entry, 0, sizeof (data_entry));
4514 g_assert (sizeof (dir) == 16);
4515 g_assert (sizeof (dir_entry) == 8);
4516 g_assert (sizeof (data_entry) == 16);
4518 node->offset = p - begin;
4520 /* IMAGE_RESOURCE_DIRECTORY */
4521 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4523 memcpy (p, &dir, sizeof (dir));
4526 /* Reserve space for entries */
4528 p += sizeof (dir_entry) * dir.res_id_entries;
4530 /* Write children */
4531 for (l = node->children; l; l = l->next) {
4532 ResTreeNode *child = (ResTreeNode*)l->data;
4534 if (child->win32_res) {
4536 child->offset = p - begin;
4538 /* IMAGE_RESOURCE_DATA_ENTRY */
4539 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4540 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4542 memcpy (p, &data_entry, sizeof (data_entry));
4543 p += sizeof (data_entry);
4545 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4546 p += data_entry.rde_size;
4548 resource_tree_encode (child, begin, p, &p);
4552 /* IMAGE_RESOURCE_ENTRY */
4553 for (l = node->children; l; l = l->next) {
4554 ResTreeNode *child = (ResTreeNode*)l->data;
4555 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4557 dir_entry.is_dir = child->win32_res ? 0 : 1;
4558 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4560 memcpy (entries, &dir_entry, sizeof (dir_entry));
4561 entries += sizeof (dir_entry);
4568 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4573 MonoReflectionWin32Resource *win32_res;
4576 if (!assemblyb->win32_resources)
4580 * Resources are stored in a three level tree inside the PE file.
4581 * - level one contains a node for each type of resource
4582 * - level two contains a node for each resource
4583 * - level three contains a node for each instance of a resource for a
4584 * specific language.
4587 tree = resource_tree_create (assemblyb->win32_resources);
4589 /* Estimate the size of the encoded tree */
4591 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4592 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4593 size += mono_array_length (win32_res->res_data);
4595 /* Directory structure */
4596 size += mono_array_length (assemblyb->win32_resources) * 256;
4597 p = buf = g_malloc (size);
4599 resource_tree_encode (tree, p, p, &p);
4601 g_assert (p - buf < size);
4603 assembly->win32_res = g_malloc (p - buf);
4604 assembly->win32_res_size = p - buf;
4605 memcpy (assembly->win32_res, buf, p - buf);
4611 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4613 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4616 p += sizeof (MonoPEResourceDir);
4617 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4618 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4619 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4620 if (dir_entry->is_dir) {
4621 fixup_resource_directory (res_section, child, rva);
4623 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4624 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4627 p += sizeof (MonoPEResourceDirEntry);
4632 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4635 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4636 g_error ("WriteFile returned %d\n", GetLastError ());
4640 * mono_image_create_pefile:
4641 * @mb: a module builder object
4643 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4644 * assembly->pefile where it can be easily retrieved later in chunks.
4647 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4648 MonoMSDOSHeader *msdos;
4649 MonoDotNetHeader *header;
4650 MonoSectionTable *section;
4651 MonoCLIHeader *cli_header;
4652 guint32 size, image_size, virtual_base, text_offset;
4653 guint32 header_start, section_start, file_offset, virtual_offset;
4654 MonoDynamicImage *assembly;
4655 MonoReflectionAssemblyBuilder *assemblyb;
4656 MonoDynamicStream pefile_stream = {0};
4657 MonoDynamicStream *pefile = &pefile_stream;
4659 guint32 *rva, value;
4661 static const unsigned char msheader[] = {
4662 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4663 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4666 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4667 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4668 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4669 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4672 assemblyb = mb->assemblyb;
4674 mono_image_basic_init (assemblyb);
4675 assembly = mb->dynamic_image;
4677 assembly->pe_kind = assemblyb->pe_kind;
4678 assembly->machine = assemblyb->machine;
4679 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4680 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4682 mono_image_build_metadata (mb);
4684 if (mb->is_main && assemblyb->resources) {
4685 int len = mono_array_length (assemblyb->resources);
4686 for (i = 0; i < len; ++i)
4687 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4690 if (mb->resources) {
4691 int len = mono_array_length (mb->resources);
4692 for (i = 0; i < len; ++i)
4693 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4696 build_compressed_metadata (assembly);
4699 assembly_add_win32_resources (assembly, assemblyb);
4701 nsections = calc_section_size (assembly);
4703 /* The DOS header and stub */
4704 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4705 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4707 /* the dotnet header */
4708 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4710 /* the section tables */
4711 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4713 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4714 virtual_offset = VIRT_ALIGN;
4717 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4718 if (!assembly->sections [i].size)
4721 file_offset += FILE_ALIGN - 1;
4722 file_offset &= ~(FILE_ALIGN - 1);
4723 virtual_offset += VIRT_ALIGN - 1;
4724 virtual_offset &= ~(VIRT_ALIGN - 1);
4726 assembly->sections [i].offset = file_offset;
4727 assembly->sections [i].rva = virtual_offset;
4729 file_offset += assembly->sections [i].size;
4730 virtual_offset += assembly->sections [i].size;
4731 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4734 file_offset += FILE_ALIGN - 1;
4735 file_offset &= ~(FILE_ALIGN - 1);
4737 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4739 /* back-patch info */
4740 msdos = (MonoMSDOSHeader*)pefile->data;
4741 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4743 header = (MonoDotNetHeader*)(pefile->data + header_start);
4744 header->pesig [0] = 'P';
4745 header->pesig [1] = 'E';
4747 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4748 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4749 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4750 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4751 if (assemblyb->pekind == 1) {
4753 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4756 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4759 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4761 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4762 header->pe.pe_major = 6;
4763 header->pe.pe_minor = 0;
4764 size = assembly->sections [MONO_SECTION_TEXT].size;
4765 size += FILE_ALIGN - 1;
4766 size &= ~(FILE_ALIGN - 1);
4767 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4768 size = assembly->sections [MONO_SECTION_RSRC].size;
4769 size += FILE_ALIGN - 1;
4770 size &= ~(FILE_ALIGN - 1);
4771 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4772 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4773 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4774 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4775 /* pe_rva_entry_point always at the beginning of the text section */
4776 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4778 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4779 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4780 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4781 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4782 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4783 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4784 size = section_start;
4785 size += FILE_ALIGN - 1;
4786 size &= ~(FILE_ALIGN - 1);
4787 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4789 size += VIRT_ALIGN - 1;
4790 size &= ~(VIRT_ALIGN - 1);
4791 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4794 // Translate the PEFileKind value to the value expected by the Windows loader
4800 // PEFileKinds.Dll == 1
4801 // PEFileKinds.ConsoleApplication == 2
4802 // PEFileKinds.WindowApplication == 3
4805 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4806 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4808 if (assemblyb->pekind == 3)
4813 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4815 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4816 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4817 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4818 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4819 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4820 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4822 /* fill data directory entries */
4824 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4825 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4827 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4828 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4830 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4831 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4832 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4833 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4834 /* patch entrypoint name */
4835 if (assemblyb->pekind == 1)
4836 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4838 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4839 /* patch imported function RVA name */
4840 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4841 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4843 /* the import table */
4844 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4845 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4846 /* patch imported dll RVA name and other entries in the dir */
4847 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4848 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4849 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4850 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4851 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4852 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4854 p = (assembly->code.data + assembly->ilt_offset);
4855 value = (assembly->text_rva + assembly->imp_names_offset);
4856 *p++ = (value) & 0xff;
4857 *p++ = (value >> 8) & (0xff);
4858 *p++ = (value >> 16) & (0xff);
4859 *p++ = (value >> 24) & (0xff);
4861 /* the CLI header info */
4862 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4863 cli_header->ch_size = GUINT32_FROM_LE (72);
4864 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4865 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4866 if (assemblyb->entry_point) {
4867 guint32 table_idx = 0;
4868 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4869 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4870 table_idx = methodb->table_idx;
4872 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4874 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4876 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4878 /* The embedded managed resources */
4879 text_offset = assembly->text_rva + assembly->code.index;
4880 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4881 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4882 text_offset += assembly->resources.index;
4883 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4884 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4885 text_offset += assembly->meta_size;
4886 if (assembly->strong_name_size) {
4887 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4888 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4889 text_offset += assembly->strong_name_size;
4892 /* write the section tables and section content */
4893 section = (MonoSectionTable*)(pefile->data + section_start);
4894 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4895 static const char *section_names [] = {
4896 ".text", ".rsrc", ".reloc"
4898 if (!assembly->sections [i].size)
4900 strcpy (section->st_name, section_names [i]);
4901 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4902 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4903 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4904 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4905 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4906 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4907 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4911 checked_write_file (file, pefile->data, pefile->index);
4913 mono_dynamic_stream_reset (pefile);
4915 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4916 if (!assembly->sections [i].size)
4919 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4920 g_error ("SetFilePointer returned %d\n", GetLastError ());
4923 case MONO_SECTION_TEXT:
4924 /* patch entry point */
4925 p = (assembly->code.data + 2);
4926 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4927 *p++ = (value) & 0xff;
4928 *p++ = (value >> 8) & 0xff;
4929 *p++ = (value >> 16) & 0xff;
4930 *p++ = (value >> 24) & 0xff;
4932 checked_write_file (file, assembly->code.data, assembly->code.index);
4933 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4934 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4935 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4938 g_free (assembly->image.raw_metadata);
4940 case MONO_SECTION_RELOC: {
4944 guint16 type_and_offset;
4948 g_assert (sizeof (reloc) == 12);
4950 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4951 reloc.block_size = GUINT32_FROM_LE (12);
4954 * the entrypoint is always at the start of the text section
4955 * 3 is IMAGE_REL_BASED_HIGHLOW
4956 * 2 is patch_size_rva - text_rva
4958 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4961 checked_write_file (file, &reloc, sizeof (reloc));
4965 case MONO_SECTION_RSRC:
4966 if (assembly->win32_res) {
4968 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4969 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4970 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4974 g_assert_not_reached ();
4978 /* check that the file is properly padded */
4979 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4980 g_error ("SetFilePointer returned %d\n", GetLastError ());
4981 if (! SetEndOfFile (file))
4982 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4984 mono_dynamic_stream_reset (&assembly->code);
4985 mono_dynamic_stream_reset (&assembly->us);
4986 mono_dynamic_stream_reset (&assembly->blob);
4987 mono_dynamic_stream_reset (&assembly->guid);
4988 mono_dynamic_stream_reset (&assembly->sheap);
4990 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4991 g_hash_table_destroy (assembly->blob_cache);
4992 assembly->blob_cache = NULL;
4995 MonoReflectionModule *
4996 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5000 MonoImageOpenStatus status;
5001 MonoDynamicAssembly *assembly;
5002 guint32 module_count;
5003 MonoImage **new_modules;
5005 name = mono_string_to_utf8 (fileName);
5007 image = mono_image_open (name, &status);
5010 if (status == MONO_IMAGE_ERROR_ERRNO)
5011 exc = mono_get_exception_file_not_found (fileName);
5013 exc = mono_get_exception_bad_image_format (name);
5015 mono_raise_exception (exc);
5020 assembly = ab->dynamic_assembly;
5021 image->assembly = (MonoAssembly*)assembly;
5023 module_count = image->assembly->image->module_count;
5024 new_modules = g_new0 (MonoImage *, module_count + 1);
5026 if (image->assembly->image->modules)
5027 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5028 new_modules [module_count] = image;
5030 g_free (image->assembly->image->modules);
5031 image->assembly->image->modules = new_modules;
5032 image->assembly->image->module_count ++;
5034 mono_assembly_load_references (image, &status);
5036 mono_image_close (image);
5037 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5040 return mono_module_get_object (mono_domain_get (), image);
5044 * We need to return always the same object for MethodInfo, FieldInfo etc..
5045 * but we need to consider the reflected type.
5046 * type uses a different hash, since it uses custom hash/equal functions.
5051 MonoClass *refclass;
5055 reflected_equal (gconstpointer a, gconstpointer b) {
5056 const ReflectedEntry *ea = a;
5057 const ReflectedEntry *eb = b;
5059 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5063 reflected_hash (gconstpointer a) {
5064 const ReflectedEntry *ea = a;
5065 return GPOINTER_TO_UINT (ea->item);
5068 #define CHECK_OBJECT(t,p,k) \
5074 mono_domain_lock (domain); \
5075 if (!domain->refobject_hash) \
5076 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5077 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5078 mono_domain_unlock (domain); \
5081 mono_domain_unlock (domain); \
5085 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5087 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5090 #define CACHE_OBJECT(t,p,o,k) \
5093 ReflectedEntry pe; \
5095 pe.refclass = (k); \
5096 mono_domain_lock (domain); \
5097 if (!domain->refobject_hash) \
5098 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5099 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5101 ReflectedEntry *e = ALLOC_REFENTRY; \
5103 e->refclass = (k); \
5104 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5107 mono_domain_unlock (domain); \
5112 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5114 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5118 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5120 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5124 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5126 MonoDynamicImage *image = moduleb->dynamic_image;
5127 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5130 MonoImage **new_modules;
5133 * FIXME: we already created an image in mono_image_basic_init (), but
5134 * we don't know which module it belongs to, since that is only
5135 * determined at assembly save time.
5137 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5138 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5140 moduleb->module.image = &image->image;
5141 moduleb->dynamic_image = image;
5142 register_module (mono_object_domain (moduleb), moduleb, image);
5144 /* register the module with the assembly */
5145 ass = ab->dynamic_assembly->assembly.image;
5146 module_count = ass->module_count;
5147 new_modules = g_new0 (MonoImage *, module_count + 1);
5150 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5151 new_modules [module_count] = &image->image;
5153 g_free (ass->modules);
5154 ass->modules = new_modules;
5155 ass->module_count ++;
5160 * mono_assembly_get_object:
5161 * @domain: an app domain
5162 * @assembly: an assembly
5164 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5166 MonoReflectionAssembly*
5167 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5169 static MonoClass *System_Reflection_Assembly;
5170 MonoReflectionAssembly *res;
5172 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5173 if (!System_Reflection_Assembly)
5174 System_Reflection_Assembly = mono_class_from_name (
5175 mono_defaults.corlib, "System.Reflection", "Assembly");
5176 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5177 res->assembly = assembly;
5179 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5184 MonoReflectionModule*
5185 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5187 static MonoClass *System_Reflection_Module;
5188 MonoReflectionModule *res;
5191 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5192 if (!System_Reflection_Module)
5193 System_Reflection_Module = mono_class_from_name (
5194 mono_defaults.corlib, "System.Reflection", "Module");
5195 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5198 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5200 res->fqname = mono_string_new (domain, image->name);
5201 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5202 res->scopename = mono_string_new (domain, image->module_name);
5206 if (image->assembly->image == image) {
5207 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5210 g_assert (image->assembly->image->modules);
5212 for (i = 0; i < image->assembly->image->module_count; i++) {
5213 if (image->assembly->image->modules [i] == image)
5214 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5216 g_assert (res->token);
5219 mono_image_addref (image);
5221 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5224 MonoReflectionModule*
5225 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5227 static MonoClass *System_Reflection_Module;
5228 MonoReflectionModule *res;
5229 MonoTableInfo *table;
5230 guint32 cols [MONO_FILE_SIZE];
5232 guint32 i, name_idx;
5235 if (!System_Reflection_Module)
5236 System_Reflection_Module = mono_class_from_name (
5237 mono_defaults.corlib, "System.Reflection", "Module");
5238 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5240 table = &image->tables [MONO_TABLE_FILE];
5241 g_assert (table_index < table->rows);
5242 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5245 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5246 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5248 /* Check whenever the row has a corresponding row in the moduleref table */
5249 table = &image->tables [MONO_TABLE_MODULEREF];
5250 for (i = 0; i < table->rows; ++i) {
5251 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5252 val = mono_metadata_string_heap (image, name_idx);
5253 if (strcmp (val, name) == 0)
5254 res->image = image->modules [i];
5257 res->fqname = mono_string_new (domain, name);
5258 res->name = mono_string_new (domain, name);
5259 res->scopename = mono_string_new (domain, name);
5260 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5261 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5267 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5269 if ((t1->type != t2->type) ||
5270 (t1->byref != t2->byref))
5274 case MONO_TYPE_VOID:
5275 case MONO_TYPE_BOOLEAN:
5276 case MONO_TYPE_CHAR:
5287 case MONO_TYPE_STRING:
5290 case MONO_TYPE_OBJECT:
5291 case MONO_TYPE_TYPEDBYREF:
5293 case MONO_TYPE_VALUETYPE:
5294 case MONO_TYPE_CLASS:
5295 case MONO_TYPE_SZARRAY:
5296 return t1->data.klass == t2->data.klass;
5298 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5299 case MONO_TYPE_ARRAY:
5300 if (t1->data.array->rank != t2->data.array->rank)
5302 return t1->data.array->eklass == t2->data.array->eklass;
5303 case MONO_TYPE_GENERICINST: {
5305 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5307 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5308 &t2->data.generic_class->container_class->byval_arg))
5310 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5311 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5317 case MONO_TYPE_MVAR:
5318 return t1->data.generic_param == t2->data.generic_param;
5320 g_error ("implement type compare for %0x!", t1->type);
5328 mymono_metadata_type_hash (MonoType *t1)
5334 hash |= t1->byref << 6; /* do not collide with t1->type values */
5336 case MONO_TYPE_VALUETYPE:
5337 case MONO_TYPE_CLASS:
5338 case MONO_TYPE_SZARRAY:
5339 /* check if the distribution is good enough */
5340 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5342 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5343 case MONO_TYPE_GENERICINST: {
5345 MonoGenericInst *inst = t1->data.generic_class->inst;
5346 hash += g_str_hash (t1->data.generic_class->container_class->name);
5348 for (i = 0; i < inst->type_argc; ++i) {
5349 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5358 static MonoReflectionGenericClass*
5359 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5361 static MonoClass *System_Reflection_MonoGenericClass;
5362 MonoReflectionGenericClass *res;
5363 MonoInflatedGenericClass *gclass;
5366 if (!System_Reflection_MonoGenericClass) {
5367 System_Reflection_MonoGenericClass = mono_class_from_name (
5368 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5369 g_assert (System_Reflection_MonoGenericClass);
5372 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5373 gklass = gclass->generic_class.container_class;
5375 mono_class_init (gclass->klass);
5377 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5379 res->type.type = geninst;
5380 if (gklass->wastypebuilder && gklass->reflection_info)
5381 res->generic_type = gklass->reflection_info;
5383 res->generic_type = mono_type_get_object (
5384 domain, &gclass->generic_class.container_class->byval_arg);
5390 * mono_type_get_object:
5391 * @domain: an app domain
5394 * Return an System.MonoType object representing the type @type.
5397 mono_type_get_object (MonoDomain *domain, MonoType *type)
5399 MonoReflectionType *res;
5400 MonoClass *klass = mono_class_from_mono_type (type);
5402 mono_domain_lock (domain);
5403 if (!domain->type_hash)
5404 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5405 (GCompareFunc)mymono_metadata_type_equal);
5406 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5407 mono_domain_unlock (domain);
5410 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5411 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5412 mono_g_hash_table_insert (domain->type_hash, type, res);
5413 mono_domain_unlock (domain);
5416 if (klass->reflection_info && !klass->wastypebuilder) {
5417 /* g_assert_not_reached (); */
5418 /* should this be considered an error condition? */
5420 mono_domain_unlock (domain);
5421 return klass->reflection_info;
5424 mono_class_init (klass);
5425 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5427 mono_g_hash_table_insert (domain->type_hash, type, res);
5428 mono_domain_unlock (domain);
5433 * mono_method_get_object:
5434 * @domain: an app domain
5436 * @refclass: the reflected type (can be NULL)
5438 * Return an System.Reflection.MonoMethod object representing the method @method.
5440 MonoReflectionMethod*
5441 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5444 * We use the same C representation for methods and constructors, but the type
5445 * name in C# is different.
5449 MonoReflectionMethod *ret;
5451 if (method->is_inflated) {
5452 MonoReflectionGenericMethod *gret;
5454 refclass = method->klass;
5455 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5456 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5457 cname = "MonoGenericCMethod";
5459 cname = "MonoGenericMethod";
5460 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5462 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5463 gret->method.method = method;
5464 gret->method.name = mono_string_new (domain, method->name);
5465 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5466 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5470 refclass = method->klass;
5472 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5473 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5474 cname = "MonoCMethod";
5476 cname = "MonoMethod";
5477 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5479 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5480 ret->method = method;
5481 ret->name = mono_string_new (domain, method->name);
5482 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5483 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5487 * mono_field_get_object:
5488 * @domain: an app domain
5492 * Return an System.Reflection.MonoField object representing the field @field
5495 MonoReflectionField*
5496 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5498 MonoReflectionField *res;
5501 CHECK_OBJECT (MonoReflectionField *, field, klass);
5502 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5503 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5506 res->name = mono_string_new (domain, field->name);
5507 if (field->generic_info)
5508 res->attrs = field->generic_info->generic_type->attrs;
5510 res->attrs = field->type->attrs;
5511 res->type = mono_type_get_object (domain, field->type);
5512 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5516 * mono_property_get_object:
5517 * @domain: an app domain
5519 * @property: a property
5521 * Return an System.Reflection.MonoProperty object representing the property @property
5524 MonoReflectionProperty*
5525 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5527 MonoReflectionProperty *res;
5530 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5531 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5532 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5534 res->property = property;
5535 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5539 * mono_event_get_object:
5540 * @domain: an app domain
5544 * Return an System.Reflection.MonoEvent object representing the event @event
5547 MonoReflectionEvent*
5548 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5550 MonoReflectionEvent *res;
5553 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5554 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5555 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5558 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5562 * mono_param_get_objects:
5563 * @domain: an app domain
5566 * Return an System.Reflection.ParameterInfo array object representing the parameters
5567 * in the method @method.
5570 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5572 static MonoClass *System_Reflection_ParameterInfo;
5573 MonoArray *res = NULL;
5574 MonoReflectionMethod *member = NULL;
5575 MonoReflectionParameter *param = NULL;
5576 char **names, **blobs = NULL;
5577 guint32 *types = NULL;
5578 MonoType *type = NULL;
5579 MonoObject *dbnull = mono_get_dbnull_object (domain);
5580 MonoMarshalSpec **mspecs;
5583 if (!System_Reflection_ParameterInfo)
5584 System_Reflection_ParameterInfo = mono_class_from_name (
5585 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5587 if (!mono_method_signature (method)->param_count)
5588 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5590 /* Note: the cache is based on the address of the signature into the method
5591 * since we already cache MethodInfos with the method as keys.
5593 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5595 member = mono_method_get_object (domain, method, NULL);
5596 names = g_new (char *, mono_method_signature (method)->param_count);
5597 mono_method_get_param_names (method, (const char **) names);
5599 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5600 mono_method_get_marshal_info (method, mspecs);
5602 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5603 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5604 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5605 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5606 param->MemberImpl = (MonoObject*)member;
5607 param->NameImpl = mono_string_new (domain, names [i]);
5608 param->PositionImpl = i;
5609 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5611 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5612 param->DefaultValueImpl = dbnull;
5616 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5617 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5618 get_default_param_value_blobs (method, blobs, types);
5621 /* Build MonoType for the type from the Constant Table */
5623 type = g_new0 (MonoType, 1);
5624 type->type = types [i];
5625 type->data.klass = NULL;
5626 if (types [i] == MONO_TYPE_CLASS)
5627 type->data.klass = mono_defaults.object_class;
5629 type->data.klass = mono_class_from_mono_type (type);
5631 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5633 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5634 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5635 param->DefaultValueImpl = dbnull;
5640 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5642 mono_array_set (res, gpointer, i, param);
5649 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5651 mono_metadata_free_marshal_spec (mspecs [i]);
5654 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5658 * mono_method_body_get_object:
5659 * @domain: an app domain
5662 * Return an System.Reflection.MethodBody object representing the method @method.
5664 MonoReflectionMethodBody*
5665 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5667 static MonoClass *System_Reflection_MethodBody = NULL;
5668 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5669 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5670 MonoReflectionMethodBody *ret;
5671 MonoMethodNormal *mn;
5672 MonoMethodHeader *header;
5673 guint32 method_rva, local_var_sig_token;
5675 unsigned char format, flags;
5678 if (!System_Reflection_MethodBody)
5679 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5680 if (!System_Reflection_LocalVariableInfo)
5681 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5682 if (!System_Reflection_ExceptionHandlingClause)
5683 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5685 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5687 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5688 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5689 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5690 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5692 mn = (MonoMethodNormal *)method;
5693 header = mono_method_get_header (method);
5695 /* Obtain local vars signature token */
5696 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5697 ptr = mono_image_rva_map (method->klass->image, method_rva);
5698 flags = *(const unsigned char *) ptr;
5699 format = flags & METHOD_HEADER_FORMAT_MASK;
5701 case METHOD_HEADER_TINY_FORMAT:
5702 case METHOD_HEADER_TINY_FORMAT1:
5703 local_var_sig_token = 0;
5705 case METHOD_HEADER_FAT_FORMAT:
5709 local_var_sig_token = read32 (ptr);
5712 g_assert_not_reached ();
5715 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5717 ret->init_locals = header->init_locals;
5718 ret->max_stack = header->max_stack;
5719 ret->local_var_sig_token = local_var_sig_token;
5720 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5721 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5724 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5725 for (i = 0; i < header->num_locals; ++i) {
5726 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5727 info->local_type = mono_type_get_object (domain, header->locals [i]);
5728 info->is_pinned = header->locals [i]->pinned;
5729 info->local_index = i;
5730 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5734 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5735 for (i = 0; i < header->num_clauses; ++i) {
5736 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5737 MonoExceptionClause *clause = &header->clauses [i];
5739 info->flags = clause->flags;
5740 info->try_offset = clause->try_offset;
5741 info->try_length = clause->try_len;
5742 info->handler_offset = clause->handler_offset;
5743 info->handler_length = clause->handler_len;
5744 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5745 info->filter_offset = clause->data.filter_offset;
5746 else if (clause->data.catch_class)
5747 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5749 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5752 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5757 mono_get_dbnull_object (MonoDomain *domain)
5761 static MonoClassField *dbnull_value_field = NULL;
5763 if (!dbnull_value_field) {
5764 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5765 mono_class_init (klass);
5766 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5767 g_assert (dbnull_value_field);
5769 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5776 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5778 guint32 param_index, i, lastp, crow = 0;
5779 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5782 MonoClass *klass = method->klass;
5783 MonoImage *image = klass->image;
5784 MonoMethodSignature *methodsig = mono_method_signature (method);
5786 MonoTableInfo *constt;
5787 MonoTableInfo *methodt;
5788 MonoTableInfo *paramt;
5790 if (!methodsig->param_count)
5793 mono_class_init (klass);
5795 if (klass->image->dynamic) {
5796 MonoReflectionMethodAux *aux;
5797 if (method->is_inflated)
5798 method = ((MonoMethodInflated*)method)->declaring;
5799 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5800 if (aux && aux->param_defaults) {
5801 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5802 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5807 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5808 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5809 constt = &image->tables [MONO_TABLE_CONSTANT];
5811 idx = mono_method_get_index (method) - 1;
5812 g_assert (idx != -1);
5814 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5815 if (idx + 1 < methodt->rows)
5816 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5818 lastp = paramt->rows + 1;
5820 for (i = param_index; i < lastp; ++i) {
5823 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5824 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5826 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5829 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5834 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5835 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5836 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5843 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5848 MonoType *basetype = type;
5853 klass = mono_class_from_mono_type (type);
5854 if (klass->valuetype) {
5855 object = mono_object_new (domain, klass);
5856 retval = ((gchar *) object + sizeof (MonoObject));
5857 if (klass->enumtype)
5858 basetype = klass->enum_basetype;
5863 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5870 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5874 memset (assembly, 0, sizeof (MonoAssemblyName));
5876 assembly->culture = "";
5877 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5879 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5882 while (g_ascii_isspace (*p) || *p == ',') {
5891 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5893 assembly->major = strtoul (p, &s, 10);
5894 if (s == p || *s != '.')
5897 assembly->minor = strtoul (p, &s, 10);
5898 if (s == p || *s != '.')
5901 assembly->build = strtoul (p, &s, 10);
5902 if (s == p || *s != '.')
5905 assembly->revision = strtoul (p, &s, 10);
5909 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5911 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5912 assembly->culture = "";
5915 assembly->culture = p;
5916 while (*p && *p != ',') {
5920 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5922 if (strncmp (p, "null", 4) == 0) {
5927 while (*p && *p != ',') {
5930 len = (p - start + 1);
5931 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5932 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5933 g_strlcpy (assembly->public_key_token, start, len);
5936 while (*p && *p != ',')
5940 while (g_ascii_isspace (*p) || *p == ',') {
5954 * mono_reflection_parse_type:
5957 * Parse a type name as accepted by the GetType () method and output the info
5958 * extracted in the info structure.
5959 * the name param will be mangled, so, make a copy before passing it to this function.
5960 * The fields in info will be valid until the memory pointed to by name is valid.
5962 * See also mono_type_get_name () below.
5964 * Returns: 0 on parse error.
5967 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5968 MonoTypeNameParse *info)
5970 char *start, *p, *w, *temp, *last_point, *startn;
5971 int in_modifiers = 0;
5972 int isbyref = 0, rank, arity = 0, i;
5974 start = p = w = name;
5976 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5977 info->name = info->name_space = NULL;
5978 info->nested = NULL;
5979 info->modifiers = NULL;
5980 info->type_arguments = NULL;
5982 /* last_point separates the namespace from the name */
5988 *p = 0; /* NULL terminate the name */
5990 info->nested = g_list_append (info->nested, startn);
5991 /* we have parsed the nesting namespace + name */
5995 info->name_space = start;
5997 info->name = last_point + 1;
5999 info->name_space = (char *)"";
6018 i = strtol (p, &temp, 10);
6035 info->name_space = start;
6037 info->name = last_point + 1;
6039 info->name_space = (char *)"";
6046 if (isbyref) /* only one level allowed by the spec */
6049 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6053 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6059 info->type_arguments = g_ptr_array_new ();
6060 for (i = 0; i < arity; i++) {
6061 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6062 gboolean fqname = FALSE;
6064 g_ptr_array_add (info->type_arguments, subinfo);
6071 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6082 while (*p && (*p != ']'))
6090 if (g_ascii_isspace (*aname)) {
6097 !assembly_name_to_aname (&subinfo->assembly, aname))
6101 if (i + 1 < arity) {
6121 else if (*p != '*') /* '*' means unknown lower bound */
6127 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6138 if (g_ascii_isspace (*p)) {
6145 return 0; /* missing assembly name */
6146 if (!assembly_name_to_aname (&info->assembly, p))
6152 if (info->assembly.name)
6155 // *w = 0; /* terminate class name */
6157 if (!info->name || !*info->name)
6161 /* add other consistency checks */
6166 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6168 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6172 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6174 gboolean type_resolve = FALSE;
6177 if (info->assembly.name) {
6178 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6180 /* then we must load the assembly ourselve - see #60439 */
6181 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6185 image = assembly->image;
6186 } else if (!image) {
6187 image = mono_defaults.corlib;
6190 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6191 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6192 image = mono_defaults.corlib;
6193 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6200 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6207 image = mono_defaults.corlib;
6210 klass = mono_class_from_name_case (image, info->name_space, info->name);
6212 klass = mono_class_from_name (image, info->name_space, info->name);
6215 for (mod = info->nested; mod; mod = mod->next) {
6218 mono_class_init (klass);
6219 nested = klass->nested_classes;
6222 klass = nested->data;
6224 if (g_strcasecmp (klass->name, mod->data) == 0)
6227 if (strcmp (klass->name, mod->data) == 0)
6231 nested = nested->next;
6238 mono_class_init (klass);
6240 if (info->type_arguments) {
6241 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6242 MonoReflectionType *the_type;
6246 for (i = 0; i < info->type_arguments->len; i++) {
6247 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6249 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6250 if (!type_args [i]) {
6256 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6258 instance = mono_reflection_bind_generic_parameters (
6259 the_type, info->type_arguments->len, type_args);
6266 klass = mono_class_from_mono_type (instance);
6269 for (mod = info->modifiers; mod; mod = mod->next) {
6270 modval = GPOINTER_TO_UINT (mod->data);
6271 if (!modval) { /* byref: must be last modifier */
6272 return &klass->this_arg;
6273 } else if (modval == -1) {
6274 klass = mono_ptr_class_get (&klass->byval_arg);
6275 } else { /* array rank */
6276 klass = mono_array_class_get (klass, modval);
6278 mono_class_init (klass);
6281 return &klass->byval_arg;
6285 * mono_reflection_get_type:
6286 * @image: a metadata context
6287 * @info: type description structure
6288 * @ignorecase: flag for case-insensitive string compares
6289 * @type_resolve: whenever type resolve was already tried
6291 * Build a MonoType from the type description in @info.
6296 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6299 MonoReflectionAssembly *assembly;
6303 type = mono_reflection_get_type_internal (image, info, ignorecase);
6306 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6313 *type_resolve = TRUE;
6316 /* Reconstruct the type name */
6317 fullName = g_string_new ("");
6318 if (info->name_space && (info->name_space [0] != '\0'))
6319 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6321 g_string_printf (fullName, info->name);
6322 for (mod = info->nested; mod; mod = mod->next)
6323 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6325 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6327 if (assembly->assembly->dynamic) {
6328 /* Enumerate all modules */
6329 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6333 if (abuilder->modules) {
6334 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6335 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6336 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6342 if (!type && abuilder->loaded_modules) {
6343 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6344 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6345 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6352 type = mono_reflection_get_type_internal (assembly->assembly->image,
6355 g_string_free (fullName, TRUE);
6360 free_type_info (MonoTypeNameParse *info)
6362 g_list_free (info->modifiers);
6363 g_list_free (info->nested);
6365 if (info->type_arguments) {
6368 for (i = 0; i < info->type_arguments->len; i++) {
6369 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6371 free_type_info (subinfo);
6374 g_ptr_array_free (info->type_arguments, TRUE);
6379 * mono_reflection_type_from_name:
6381 * @image: a metadata context (can be NULL).
6383 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6384 * it defaults to get the type from @image or, if @image is NULL or loading
6385 * from it fails, uses corlib.
6389 mono_reflection_type_from_name (char *name, MonoImage *image)
6391 MonoType *type = NULL;
6392 MonoTypeNameParse info;
6395 /* Make a copy since parse_type modifies its argument */
6396 tmp = g_strdup (name);
6398 /*g_print ("requested type %s\n", str);*/
6399 if (mono_reflection_parse_type (tmp, &info)) {
6400 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6404 free_type_info (&info);
6409 * mono_reflection_get_token:
6411 * Return the metadata token of OBJ which should be an object
6412 * representing a metadata element.
6415 mono_reflection_get_token (MonoObject *obj)
6420 klass = obj->vtable->klass;
6422 if (strcmp (klass->name, "MethodBuilder") == 0) {
6423 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6425 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6426 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6427 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6429 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6430 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6431 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6432 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6433 if (tb->generic_params) {
6434 g_assert_not_reached ();
6436 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6438 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6439 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6440 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6441 } else if (strcmp (klass->name, "MonoType") == 0) {
6442 MonoReflectionType *tb = (MonoReflectionType *)obj;
6443 token = mono_class_from_mono_type (tb->type)->type_token;
6444 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6445 strcmp (klass->name, "MonoMethod") == 0) {
6446 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6447 if (m->method->is_inflated) {
6448 g_assert_not_reached ();
6449 } else if (mono_method_signature (m->method)->generic_param_count) {
6450 g_assert_not_reached ();
6451 } else if (m->method->klass->generic_class) {
6452 g_assert_not_reached ();
6454 token = m->method->token;
6456 } else if (strcmp (klass->name, "MonoField") == 0) {
6457 MonoReflectionField *f = (MonoReflectionField*)obj;
6459 token = mono_class_get_field_token (f->field);
6460 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6461 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6463 token = mono_class_get_property_token (p->property);
6464 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6465 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6467 token = mono_class_get_event_token (p->event);
6468 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6469 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6471 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6472 } else if (strcmp (klass->name, "Module") == 0) {
6473 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6476 } else if (strcmp (klass->name, "Assembly") == 0) {
6477 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6479 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6480 MonoException *ex = mono_get_exception_not_implemented (msg);
6482 mono_raise_exception (ex);
6489 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6491 int slen, type = t->type;
6496 case MONO_TYPE_BOOLEAN: {
6497 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6502 case MONO_TYPE_CHAR:
6504 case MONO_TYPE_I2: {
6505 guint16 *val = g_malloc (sizeof (guint16));
6510 #if SIZEOF_VOID_P == 4
6516 case MONO_TYPE_I4: {
6517 guint32 *val = g_malloc (sizeof (guint32));
6522 #if SIZEOF_VOID_P == 8
6523 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6528 case MONO_TYPE_I8: {
6529 guint64 *val = g_malloc (sizeof (guint64));
6534 case MONO_TYPE_VALUETYPE:
6535 if (t->data.klass->enumtype) {
6536 type = t->data.klass->enum_basetype->type;
6539 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6542 case MONO_TYPE_STRING:
6543 if (*p == (char)0xFF) {
6547 slen = mono_metadata_decode_value (p, &p);
6549 return mono_string_new_len (mono_domain_get (), p, slen);
6550 case MONO_TYPE_CLASS: {
6553 if (*p == (char)0xFF) {
6558 slen = mono_metadata_decode_value (p, &p);
6559 n = g_memdup (p, slen + 1);
6561 t = mono_reflection_type_from_name (n, image);
6563 g_warning ("Cannot load type '%s'", n);
6567 return mono_type_get_object (mono_domain_get (), t);
6571 case MONO_TYPE_OBJECT: {
6574 MonoClass *subc = NULL;
6579 } else if (subt == 0x0E) {
6580 type = MONO_TYPE_STRING;
6582 } else if (subt == 0x55) {
6585 slen = mono_metadata_decode_value (p, &p);
6586 n = g_memdup (p, slen + 1);
6588 t = mono_reflection_type_from_name (n, image);
6590 g_warning ("Cannot load type '%s'", n);
6593 subc = mono_class_from_mono_type (t);
6594 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6595 MonoType simple_type = {{0}};
6596 simple_type.type = subt;
6597 subc = mono_class_from_mono_type (&simple_type);
6599 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6601 val = load_cattr_value (image, &subc->byval_arg, p, end);
6602 obj = mono_object_new (mono_domain_get (), subc);
6603 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6607 case MONO_TYPE_SZARRAY: {
6609 guint32 i, alen, basetype;
6612 if (alen == 0xffffffff) {
6616 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6617 basetype = t->data.klass->byval_arg.type;
6622 case MONO_TYPE_BOOLEAN:
6623 for (i = 0; i < alen; i++) {
6624 MonoBoolean val = *p++;
6625 mono_array_set (arr, MonoBoolean, i, val);
6628 case MONO_TYPE_CHAR:
6631 for (i = 0; i < alen; i++) {
6632 guint16 val = read16 (p);
6633 mono_array_set (arr, guint16, i, val);
6640 for (i = 0; i < alen; i++) {
6641 guint32 val = read32 (p);
6642 mono_array_set (arr, guint32, i, val);
6649 for (i = 0; i < alen; i++) {
6650 guint64 val = read64 (p);
6651 mono_array_set (arr, guint64, i, val);
6655 case MONO_TYPE_CLASS:
6656 case MONO_TYPE_OBJECT:
6657 case MONO_TYPE_STRING:
6658 for (i = 0; i < alen; i++) {
6659 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6660 mono_array_set (arr, gpointer, i, item);
6664 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6670 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6676 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6678 static MonoClass *klass;
6679 static MonoMethod *ctor;
6681 void *params [2], *unboxed;
6684 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6686 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6688 params [0] = mono_type_get_object (mono_domain_get (), t);
6690 retval = mono_object_new (mono_domain_get (), klass);
6691 unboxed = mono_object_unbox (retval);
6692 mono_runtime_invoke (ctor, unboxed, params, NULL);
6698 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6700 static MonoClass *klass;
6701 static MonoMethod *ctor;
6703 void *unboxed, *params [2];
6706 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6708 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6711 params [1] = typedarg;
6712 retval = mono_object_new (mono_domain_get (), klass);
6713 unboxed = mono_object_unbox (retval);
6714 mono_runtime_invoke (ctor, unboxed, params, NULL);
6720 type_is_reference (MonoType *type)
6722 switch (type->type) {
6723 case MONO_TYPE_BOOLEAN:
6724 case MONO_TYPE_CHAR:
6737 case MONO_TYPE_VALUETYPE:
6745 free_param_data (MonoMethodSignature *sig, void **params) {
6747 for (i = 0; i < sig->param_count; ++i) {
6748 if (!type_is_reference (sig->params [i]))
6749 g_free (params [i]);
6754 * Find the field index in the metadata FieldDef table.
6757 find_field_index (MonoClass *klass, MonoClassField *field) {
6760 for (i = 0; i < klass->field.count; ++i) {
6761 if (field == &klass->fields [i])
6762 return klass->field.first + 1 + i;
6768 * Find the property index in the metadata Property table.
6771 find_property_index (MonoClass *klass, MonoProperty *property) {
6774 for (i = 0; i < klass->property.count; ++i) {
6775 if (property == &klass->properties [i])
6776 return klass->property.first + 1 + i;
6782 * Find the event index in the metadata Event table.
6785 find_event_index (MonoClass *klass, MonoEvent *event) {
6788 for (i = 0; i < klass->event.count; ++i) {
6789 if (event == &klass->events [i])
6790 return klass->event.first + 1 + i;
6796 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6798 const char *p = data;
6800 guint32 i, j, num_named;
6804 mono_class_init (method->klass);
6807 attr = mono_object_new (mono_domain_get (), method->klass);
6808 mono_runtime_invoke (method, attr, NULL, NULL);
6812 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6815 /*g_print ("got attr %s\n", method->klass->name);*/
6817 /* Allocate using alloca so it gets GC tracking */
6818 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6822 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6823 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6827 attr = mono_object_new (mono_domain_get (), method->klass);
6828 mono_runtime_invoke (method, attr, params, NULL);
6829 free_param_data (method->signature, params);
6830 num_named = read16 (named);
6832 for (j = 0; j < num_named; j++) {
6834 gboolean is_boxed = FALSE;
6835 char *name, named_type, data_type;
6836 named_type = *named++;
6837 data_type = *named++; /* type of data */
6838 if (data_type == 0x51)
6841 if (data_type == 0x55) {
6844 type_len = mono_metadata_decode_blob_size (named, &named);
6845 type_name = g_malloc (type_len + 1);
6846 memcpy (type_name, named, type_len);
6847 type_name [type_len] = 0;
6849 /* FIXME: lookup the type and check type consistency */
6851 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6852 /* this seems to be the type of the element of the array */
6853 /* g_print ("skipping 0x%02x after prop\n", *named); */
6856 name_len = mono_metadata_decode_blob_size (named, &named);
6857 name = g_malloc (name_len + 1);
6858 memcpy (name, named, name_len);
6859 name [name_len] = 0;
6861 if (named_type == 0x53) {
6862 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6863 void *val = load_cattr_value (image, field->type, named, &named);
6864 mono_field_set_value (attr, field, val);
6865 if (!type_is_reference (field->type))
6867 } else if (named_type == 0x54) {
6870 MonoType *prop_type;
6872 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6873 /* can we have more that 1 arg in a custom attr named property? */
6874 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6875 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6876 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6877 mono_property_set_value (prop, attr, pparams, NULL);
6878 if (!type_is_reference (prop_type))
6879 g_free (pparams [0]);
6888 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6890 MonoArray *typedargs, *namedargs;
6891 MonoClass *attrklass;
6892 static MonoClass *klass;
6893 static MonoMethod *ctor;
6896 const char *p = data;
6898 guint32 i, j, num_named;
6901 mono_class_init (method->klass);
6904 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6906 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6908 domain = mono_domain_get ();
6910 /* This is for Attributes with no parameters */
6911 attr = mono_object_new (domain, klass);
6912 params [0] = mono_method_get_object (domain, method, NULL);
6913 params [1] = params [2] = NULL;
6914 mono_runtime_invoke (method, attr, params, NULL);
6918 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6921 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6925 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6926 MonoObject *obj, *typedarg;
6929 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6930 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6931 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6932 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6933 mono_array_set (typedargs, void*, i, typedarg);
6935 if (!type_is_reference (mono_method_signature (method)->params [i]))
6940 num_named = read16 (named);
6941 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6943 attrklass = method->klass;
6944 for (j = 0; j < num_named; j++) {
6946 char *name, named_type, data_type;
6947 named_type = *named++;
6948 data_type = *named++; /* type of data */
6949 if (data_type == 0x55) {
6952 type_len = mono_metadata_decode_blob_size (named, &named);
6953 type_name = g_malloc (type_len + 1);
6954 memcpy (type_name, named, type_len);
6955 type_name [type_len] = 0;
6957 /* FIXME: lookup the type and check type consistency */
6959 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6960 /* this seems to be the type of the element of the array */
6961 /* g_print ("skipping 0x%02x after prop\n", *named); */
6964 name_len = mono_metadata_decode_blob_size (named, &named);
6965 name = g_malloc (name_len + 1);
6966 memcpy (name, named, name_len);
6967 name [name_len] = 0;
6969 if (named_type == 0x53) {
6970 MonoObject *obj, *typedarg, *namedarg;
6971 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6972 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6974 minfo = mono_field_get_object (domain, NULL, field);
6975 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6976 typedarg = create_cattr_typed_arg (field->type, obj);
6977 namedarg = create_cattr_named_arg (minfo, typedarg);
6978 mono_array_set (namedargs, void*, j, namedarg);
6979 if (!type_is_reference (field->type))
6981 } else if (named_type == 0x54) {
6982 MonoObject *obj, *typedarg, *namedarg;
6983 MonoType *prop_type;
6985 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6987 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6988 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6989 minfo = mono_property_get_object (domain, NULL, prop);
6990 val = load_cattr_value (image, prop_type, named, &named);
6991 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6992 typedarg = create_cattr_typed_arg (prop_type, obj);
6993 namedarg = create_cattr_named_arg (minfo, typedarg);
6994 mono_array_set (namedargs, void*, j, namedarg);
6995 if (!type_is_reference (prop_type))
7000 attr = mono_object_new (domain, klass);
7001 params [0] = mono_method_get_object (domain, method, NULL);
7002 params [1] = typedargs;
7003 params [2] = namedargs;
7004 mono_runtime_invoke (ctor, attr, params, NULL);
7009 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
7016 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7017 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7018 for (i = 0; i < cinfo->num_attrs; ++i) {
7019 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7020 mono_array_set (result, gpointer, i, attr);
7026 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
7034 for (i = 0; i < cinfo->num_attrs; ++i) {
7035 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
7039 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7040 result = mono_array_new (mono_domain_get (), klass, n);
7042 for (i = 0; i < cinfo->num_attrs; ++i) {
7043 if (mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass)) {
7044 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7045 mono_array_set (result, gpointer, n, attr);
7053 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7056 static MonoClass *klass;
7061 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7063 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7064 for (i = 0; i < cinfo->num_attrs; ++i) {
7065 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7066 mono_array_set (result, gpointer, i, attr);
7072 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7074 guint32 mtoken, i, len;
7075 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7077 MonoCustomAttrInfo *ainfo;
7078 GList *tmp, *list = NULL;
7081 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7083 i = mono_metadata_custom_attrs_from_index (image, idx);
7087 while (i < ca->rows) {
7088 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7090 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7093 len = g_list_length (list);
7096 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7097 ainfo->num_attrs = len;
7098 ainfo->image = image;
7099 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7100 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7101 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7102 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7103 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7104 mtoken |= MONO_TOKEN_METHOD_DEF;
7106 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7107 mtoken |= MONO_TOKEN_MEMBER_REF;
7110 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7113 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7114 if (!ainfo->attrs [i].ctor)
7115 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7116 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7117 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7118 ainfo->attrs [i].data = data;
7126 mono_custom_attrs_from_method (MonoMethod *method)
7128 MonoCustomAttrInfo *cinfo;
7131 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7133 idx = mono_method_get_index (method);
7134 idx <<= MONO_CUSTOM_ATTR_BITS;
7135 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7136 return mono_custom_attrs_from_index (method->klass->image, idx);
7140 mono_custom_attrs_from_class (MonoClass *klass)
7142 MonoCustomAttrInfo *cinfo;
7145 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7147 idx = mono_metadata_token_index (klass->type_token);
7148 idx <<= MONO_CUSTOM_ATTR_BITS;
7149 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7150 return mono_custom_attrs_from_index (klass->image, idx);
7154 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7156 MonoCustomAttrInfo *cinfo;
7159 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7161 idx = 1; /* there is only one assembly */
7162 idx <<= MONO_CUSTOM_ATTR_BITS;
7163 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7164 return mono_custom_attrs_from_index (assembly->image, idx);
7167 static MonoCustomAttrInfo*
7168 mono_custom_attrs_from_module (MonoImage *image)
7170 MonoCustomAttrInfo *cinfo;
7173 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7175 idx = 1; /* there is only one module */
7176 idx <<= MONO_CUSTOM_ATTR_BITS;
7177 idx |= MONO_CUSTOM_ATTR_MODULE;
7178 return mono_custom_attrs_from_index (image, idx);
7182 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7184 MonoCustomAttrInfo *cinfo;
7187 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7189 idx = find_property_index (klass, property);
7190 idx <<= MONO_CUSTOM_ATTR_BITS;
7191 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7192 return mono_custom_attrs_from_index (klass->image, idx);
7196 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7198 MonoCustomAttrInfo *cinfo;
7201 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7203 idx = find_event_index (klass, event);
7204 idx <<= MONO_CUSTOM_ATTR_BITS;
7205 idx |= MONO_CUSTOM_ATTR_EVENT;
7206 return mono_custom_attrs_from_index (klass->image, idx);
7210 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7212 MonoCustomAttrInfo *cinfo;
7215 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7217 idx = find_field_index (klass, field);
7218 idx <<= MONO_CUSTOM_ATTR_BITS;
7219 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7220 return mono_custom_attrs_from_index (klass->image, idx);
7224 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7227 guint32 i, idx, method_index;
7228 guint32 param_list, param_last, param_pos, found;
7230 MonoReflectionMethodAux *aux;
7232 if (method->klass->image->dynamic) {
7233 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7234 if (!aux || !aux->param_cattr)
7236 return aux->param_cattr [param];
7239 image = method->klass->image;
7240 method_index = mono_method_get_index (method);
7241 ca = &image->tables [MONO_TABLE_METHOD];
7243 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7244 /* FIXME FIXME FIXME */
7248 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7249 if (method_index == ca->rows) {
7250 ca = &image->tables [MONO_TABLE_PARAM];
7251 param_last = ca->rows + 1;
7253 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7254 ca = &image->tables [MONO_TABLE_PARAM];
7257 for (i = param_list; i < param_last; ++i) {
7258 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7259 if (param_pos == param) {
7267 idx <<= MONO_CUSTOM_ATTR_BITS;
7268 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7269 return mono_custom_attrs_from_index (image, idx);
7273 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7277 for (i = 0; i < ainfo->num_attrs; ++i) {
7278 klass = ainfo->attrs [i].ctor->klass;
7279 if (mono_class_has_parent (klass, attr_klass))
7286 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7293 for (i = 0; i < ainfo->num_attrs; ++i) {
7294 klass = ainfo->attrs [i].ctor->klass;
7295 if (mono_class_has_parent (klass, attr_klass)) {
7300 if (attr_index == -1)
7303 attrs = mono_custom_attrs_construct (ainfo);
7305 return mono_array_get (attrs, MonoObject*, attr_index);
7311 * mono_reflection_get_custom_attrs_info:
7312 * @obj: a reflection object handle
7314 * Return the custom attribute info for attributes defined for the
7315 * reflection handle @obj. The objects.
7318 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7321 MonoCustomAttrInfo *cinfo = NULL;
7323 klass = obj->vtable->klass;
7324 if (klass == mono_defaults.monotype_class) {
7325 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7326 klass = mono_class_from_mono_type (rtype->type);
7327 cinfo = mono_custom_attrs_from_class (klass);
7328 } else if (strcmp ("Assembly", klass->name) == 0) {
7329 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7330 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7331 } else if (strcmp ("Module", klass->name) == 0) {
7332 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7333 cinfo = mono_custom_attrs_from_module (module->image);
7334 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7335 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7336 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7337 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7338 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7339 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7340 } else if (strcmp ("MonoField", klass->name) == 0) {
7341 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7342 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7343 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7344 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7345 cinfo = mono_custom_attrs_from_method (rmethod->method);
7346 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7347 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7348 cinfo = mono_custom_attrs_from_method (method);
7349 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7350 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7351 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7352 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7353 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7354 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7355 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7356 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7357 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7358 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7359 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7360 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7361 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7362 } else { /* handle other types here... */
7363 g_error ("get custom attrs not yet supported for %s", klass->name);
7370 * mono_reflection_get_custom_attrs_by_type:
7371 * @obj: a reflection object handle
7373 * Return an array with all the custom attributes defined of the
7374 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
7375 * of that type are returned. The objects are fully build.
7378 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
7381 MonoCustomAttrInfo *cinfo;
7383 cinfo = mono_reflection_get_custom_attrs_info (obj);
7386 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
7388 result = mono_custom_attrs_construct (cinfo);
7390 mono_custom_attrs_free (cinfo);
7393 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7394 result = mono_array_new (mono_domain_get (), klass, 0);
7401 * mono_reflection_get_custom_attrs:
7402 * @obj: a reflection object handle
7404 * Return an array with all the custom attributes defined of the
7405 * reflection handle @obj. The objects are fully build.
7408 mono_reflection_get_custom_attrs (MonoObject *obj)
7410 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
7414 * mono_reflection_get_custom_attrs_data:
7415 * @obj: a reflection obj handle
7417 * Returns an array of System.Reflection.CustomAttributeData,
7418 * which include information about attributes reflected on
7419 * types loaded using the Reflection Only methods
7422 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7425 MonoCustomAttrInfo *cinfo;
7427 cinfo = mono_reflection_get_custom_attrs_info (obj);
7429 result = mono_custom_attrs_data_construct (cinfo);
7431 mono_custom_attrs_free (cinfo);
7434 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7435 result = mono_array_new (mono_domain_get (), klass, 0);
7441 static MonoMethodSignature*
7442 parameters_to_signature (MonoArray *parameters) {
7443 MonoMethodSignature *sig;
7446 count = parameters? mono_array_length (parameters): 0;
7448 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7449 sig->param_count = count;
7450 sig->sentinelpos = -1; /* FIXME */
7451 for (i = 0; i < count; ++i) {
7452 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7453 sig->params [i] = pt->type;
7458 static MonoMethodSignature*
7459 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7460 MonoMethodSignature *sig;
7462 sig = parameters_to_signature (ctor->parameters);
7463 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7464 sig->ret = &mono_defaults.void_class->byval_arg;
7468 static MonoMethodSignature*
7469 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7470 MonoMethodSignature *sig;
7472 sig = parameters_to_signature (method->parameters);
7473 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7474 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7475 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7479 static MonoMethodSignature*
7480 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7481 MonoMethodSignature *sig;
7483 sig = parameters_to_signature (method->parameters);
7484 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7485 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7486 sig->generic_param_count = 0;
7491 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7493 MonoClass *klass = mono_object_class (prop);
7494 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7495 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7496 *name = mono_string_to_utf8 (pb->name);
7497 *type = pb->type->type;
7499 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7500 *name = g_strdup (p->property->name);
7501 if (p->property->get)
7502 *type = mono_method_signature (p->property->get)->ret;
7504 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7509 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7511 MonoClass *klass = mono_object_class (field);
7512 if (strcmp (klass->name, "FieldBuilder") == 0) {
7513 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7514 *name = mono_string_to_utf8 (fb->name);
7515 *type = fb->type->type;
7517 MonoReflectionField *f = (MonoReflectionField *)field;
7518 *name = g_strdup (f->field->name);
7519 *type = f->field->type;
7524 * Encode a value in a custom attribute stream of bytes.
7525 * The value to encode is either supplied as an object in argument val
7526 * (valuetypes are boxed), or as a pointer to the data in the
7528 * @type represents the type of the value
7529 * @buffer is the start of the buffer
7530 * @p the current position in the buffer
7531 * @buflen contains the size of the buffer and is used to return the new buffer size
7532 * if this needs to be realloced.
7533 * @retbuffer and @retp return the start and the position of the buffer
7536 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7538 MonoTypeEnum simple_type;
7540 if ((p-buffer) + 10 >= *buflen) {
7543 newbuf = g_realloc (buffer, *buflen);
7544 p = newbuf + (p-buffer);
7548 argval = ((char*)arg + sizeof (MonoObject));
7549 simple_type = type->type;
7551 switch (simple_type) {
7552 case MONO_TYPE_BOOLEAN:
7557 case MONO_TYPE_CHAR:
7560 swap_with_size (p, argval, 2, 1);
7566 swap_with_size (p, argval, 4, 1);
7572 swap_with_size (p, argval, 8, 1);
7575 case MONO_TYPE_VALUETYPE:
7576 if (type->data.klass->enumtype) {
7577 simple_type = type->data.klass->enum_basetype->type;
7580 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7583 case MONO_TYPE_STRING: {
7590 str = mono_string_to_utf8 ((MonoString*)arg);
7591 slen = strlen (str);
7592 if ((p-buffer) + 10 + slen >= *buflen) {
7596 newbuf = g_realloc (buffer, *buflen);
7597 p = newbuf + (p-buffer);
7600 mono_metadata_encode_value (slen, p, &p);
7601 memcpy (p, str, slen);
7606 case MONO_TYPE_CLASS: {
7614 k = mono_object_class (arg);
7615 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7616 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7617 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7619 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7620 slen = strlen (str);
7621 if ((p-buffer) + 10 + slen >= *buflen) {
7625 newbuf = g_realloc (buffer, *buflen);
7626 p = newbuf + (p-buffer);
7629 mono_metadata_encode_value (slen, p, &p);
7630 memcpy (p, str, slen);
7635 case MONO_TYPE_SZARRAY: {
7637 MonoClass *eclass, *arg_eclass;
7640 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7643 len = mono_array_length ((MonoArray*)arg);
7645 *p++ = (len >> 8) & 0xff;
7646 *p++ = (len >> 16) & 0xff;
7647 *p++ = (len >> 24) & 0xff;
7649 *retbuffer = buffer;
7650 eclass = type->data.klass;
7651 arg_eclass = mono_object_class (arg)->element_class;
7652 if (eclass->valuetype && arg_eclass->valuetype) {
7653 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7654 int elsize = mono_class_array_element_size (eclass);
7655 for (i = 0; i < len; ++i) {
7656 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7660 for (i = 0; i < len; ++i) {
7661 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7666 /* it may be a boxed value or a Type */
7667 case MONO_TYPE_OBJECT: {
7673 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7678 klass = mono_object_class (arg);
7680 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7683 } else if (klass->enumtype) {
7685 } else if (klass == mono_defaults.string_class) {
7686 simple_type = MONO_TYPE_STRING;
7689 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7690 *p++ = simple_type = klass->byval_arg.type;
7693 g_error ("unhandled type in custom attr");
7695 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7696 slen = strlen (str);
7697 if ((p-buffer) + 10 + slen >= *buflen) {
7701 newbuf = g_realloc (buffer, *buflen);
7702 p = newbuf + (p-buffer);
7705 mono_metadata_encode_value (slen, p, &p);
7706 memcpy (p, str, slen);
7709 simple_type = klass->enum_basetype->type;
7713 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7716 *retbuffer = buffer;
7720 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7723 /* Preallocate a large enough buffer */
7724 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7725 char *str = type_get_qualified_name (type, NULL);
7731 len += strlen (name);
7733 if ((p-buffer) + 20 + len >= *buflen) {
7737 newbuf = g_realloc (buffer, *buflen);
7738 p = newbuf + (p-buffer);
7742 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7743 char *str = type_get_qualified_name (type, NULL);
7744 int slen = strlen (str);
7748 * This seems to be optional...
7751 mono_metadata_encode_value (slen, p, &p);
7752 memcpy (p, str, slen);
7755 } else if (type->type == MONO_TYPE_OBJECT) {
7757 } else if (type->type == MONO_TYPE_CLASS) {
7758 /* it should be a type: encode_cattr_value () has the check */
7761 mono_metadata_encode_value (type->type, p, &p);
7762 if (type->type == MONO_TYPE_SZARRAY)
7763 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7765 len = strlen (name);
7766 mono_metadata_encode_value (len, p, &p);
7767 memcpy (p, name, len);
7769 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7771 *retbuffer = buffer;
7775 * mono_reflection_get_custom_attrs_blob:
7776 * @ctor: custom attribute constructor
7777 * @ctorArgs: arguments o the constructor
7783 * Creates the blob of data that needs to be saved in the metadata and that represents
7784 * the custom attributed described by @ctor, @ctorArgs etc.
7785 * Returns: a Byte array representing the blob of data.
7788 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7791 MonoMethodSignature *sig;
7796 MONO_ARCH_SAVE_REGS;
7798 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7799 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7801 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7803 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7805 p = buffer = g_malloc (buflen);
7806 /* write the prolog */
7809 for (i = 0; i < sig->param_count; ++i) {
7810 arg = mono_array_get (ctorArgs, MonoObject*, i);
7811 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7815 i += mono_array_length (properties);
7817 i += mono_array_length (fields);
7819 *p++ = (i >> 8) & 0xff;
7822 for (i = 0; i < mono_array_length (properties); ++i) {
7826 prop = mono_array_get (properties, gpointer, i);
7827 get_prop_name_and_type (prop, &pname, &ptype);
7828 *p++ = 0x54; /* PROPERTY signature */
7829 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7836 for (i = 0; i < mono_array_length (fields); ++i) {
7840 field = mono_array_get (fields, gpointer, i);
7841 get_field_name_and_type (field, &fname, &ftype);
7842 *p++ = 0x53; /* FIELD signature */
7843 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7848 g_assert (p - buffer <= buflen);
7849 buflen = p - buffer;
7850 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7851 p = mono_array_addr (result, char, 0);
7852 memcpy (p, buffer, buflen);
7854 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7860 * mono_reflection_setup_internal_class:
7861 * @tb: a TypeBuilder object
7863 * Creates a MonoClass that represents the TypeBuilder.
7864 * This is a trick that lets us simplify a lot of reflection code
7865 * (and will allow us to support Build and Run assemblies easier).
7868 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7870 MonoClass *klass, *parent;
7872 MONO_ARCH_SAVE_REGS;
7874 mono_loader_lock ();
7877 /* check so we can compile corlib correctly */
7878 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7879 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7880 parent = tb->parent->type->data.klass;
7882 parent = my_mono_class_from_mono_type (tb->parent->type);
7888 /* the type has already being created: it means we just have to change the parent */
7889 if (tb->type.type) {
7890 klass = mono_class_from_mono_type (tb->type.type);
7891 klass->parent = NULL;
7892 /* fool mono_class_setup_parent */
7893 g_free (klass->supertypes);
7894 klass->supertypes = NULL;
7895 mono_class_setup_parent (klass, parent);
7896 mono_class_setup_mono_type (klass);
7897 mono_loader_unlock ();
7901 klass = g_new0 (MonoClass, 1);
7903 klass->image = &tb->module->dynamic_image->image;
7905 klass->inited = 1; /* we lie to the runtime */
7906 klass->name = mono_string_to_utf8 (tb->name);
7907 klass->name_space = mono_string_to_utf8 (tb->nspace);
7908 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7909 klass->flags = tb->attrs;
7911 klass->element_class = klass;
7912 klass->reflection_info = tb; /* need to pin. */
7914 /* Put into cache so mono_class_get () will find it */
7915 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7917 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7918 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7920 if (parent != NULL) {
7921 mono_class_setup_parent (klass, parent);
7922 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7923 const char *old_n = klass->name;
7924 /* trick to get relative numbering right when compiling corlib */
7925 klass->name = "BuildingObject";
7926 mono_class_setup_parent (klass, mono_defaults.object_class);
7927 klass->name = old_n;
7930 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7931 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7932 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7933 klass->instance_size = sizeof (MonoObject);
7934 klass->size_inited = 1;
7935 mono_class_setup_vtable_general (klass, NULL, 0);
7938 mono_class_setup_mono_type (klass);
7940 mono_class_setup_supertypes (klass);
7943 * FIXME: handle interfaces.
7946 tb->type.type = &klass->byval_arg;
7948 if (tb->nesting_type) {
7949 g_assert (tb->nesting_type->type);
7950 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7953 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7955 mono_loader_unlock ();
7959 * mono_reflection_setup_generic_class:
7960 * @tb: a TypeBuilder object
7962 * Setup the generic class before adding the first generic parameter.
7965 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7969 MONO_ARCH_SAVE_REGS;
7971 klass = my_mono_class_from_mono_type (tb->type.type);
7972 if (tb->generic_container)
7975 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7976 tb->generic_container->klass = klass;
7978 tb->generic_container->context.container = tb->generic_container;
7982 * mono_reflection_create_generic_class:
7983 * @tb: a TypeBuilder object
7985 * Creates the generic class after all generic parameters have been added.
7988 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7993 MONO_ARCH_SAVE_REGS;
7995 klass = my_mono_class_from_mono_type (tb->type.type);
7997 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7999 if (klass->generic_container || (count == 0))
8002 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
8004 klass->generic_container = tb->generic_container;
8006 klass->generic_container->type_argc = count;
8007 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
8009 for (i = 0; i < count; i++) {
8010 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
8011 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
8012 g_assert (klass->generic_container->type_params [i].owner);
8015 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
8019 * mono_reflection_create_internal_class:
8020 * @tb: a TypeBuilder object
8022 * Actually create the MonoClass that is associated with the TypeBuilder.
8025 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
8029 MONO_ARCH_SAVE_REGS;
8031 klass = my_mono_class_from_mono_type (tb->type.type);
8033 mono_loader_lock ();
8034 if (klass->enumtype && klass->enum_basetype == NULL) {
8035 MonoReflectionFieldBuilder *fb;
8038 g_assert (tb->fields != NULL);
8039 g_assert (mono_array_length (tb->fields) >= 1);
8041 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
8043 klass->enum_basetype = fb->type->type;
8044 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
8045 if (!klass->element_class)
8046 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
8049 * get the element_class from the current corlib.
8051 ec = default_class_from_mono_type (klass->enum_basetype);
8052 klass->instance_size = ec->instance_size;
8053 klass->size_inited = 1;
8055 * this is almost safe to do with enums and it's needed to be able
8056 * to create objects of the enum type (for use in SetConstant).
8058 /* FIXME: Does this mean enums can't have method overrides ? */
8059 mono_class_setup_vtable_general (klass, NULL, 0);
8061 mono_loader_unlock ();
8064 static MonoMarshalSpec*
8065 mono_marshal_spec_from_builder (MonoAssembly *assembly,
8066 MonoReflectionMarshal *minfo)
8068 MonoMarshalSpec *res;
8070 res = g_new0 (MonoMarshalSpec, 1);
8071 res->native = minfo->type;
8073 switch (minfo->type) {
8074 case MONO_NATIVE_LPARRAY:
8075 res->data.array_data.elem_type = minfo->eltype;
8076 if (minfo->has_size) {
8077 res->data.array_data.param_num = minfo->param_num;
8078 res->data.array_data.num_elem = minfo->count;
8079 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8082 res->data.array_data.param_num = -1;
8083 res->data.array_data.num_elem = -1;
8084 res->data.array_data.elem_mult = -1;
8088 case MONO_NATIVE_BYVALTSTR:
8089 case MONO_NATIVE_BYVALARRAY:
8090 res->data.array_data.num_elem = minfo->count;
8093 case MONO_NATIVE_CUSTOM:
8094 if (minfo->marshaltyperef)
8095 res->data.custom_data.custom_name =
8096 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8098 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8108 MonoReflectionMarshal*
8109 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8110 MonoMarshalSpec *spec)
8112 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8113 MonoReflectionMarshal *minfo;
8116 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8117 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8118 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8119 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8122 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8123 minfo->type = spec->native;
8125 switch (minfo->type) {
8126 case MONO_NATIVE_LPARRAY:
8127 minfo->eltype = spec->data.array_data.elem_type;
8128 minfo->count = spec->data.array_data.num_elem;
8129 minfo->param_num = spec->data.array_data.param_num;
8132 case MONO_NATIVE_BYVALTSTR:
8133 case MONO_NATIVE_BYVALARRAY:
8134 minfo->count = spec->data.array_data.num_elem;
8137 case MONO_NATIVE_CUSTOM:
8138 if (spec->data.custom_data.custom_name) {
8139 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8141 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8143 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8145 if (spec->data.custom_data.cookie)
8146 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8157 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8158 ReflectionMethodBuilder *rmb,
8159 MonoMethodSignature *sig)
8162 MonoMethodNormal *pm;
8163 MonoMarshalSpec **specs;
8164 MonoReflectionMethodAux *method_aux;
8167 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8168 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8169 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8171 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8173 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8175 pm = (MonoMethodNormal*)m;
8178 m->flags = rmb->attrs;
8179 m->iflags = rmb->iattrs;
8180 m->name = mono_string_to_utf8 (rmb->name);
8184 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8186 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8187 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8190 m->signature->pinvoke = 1;
8191 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8192 m->signature->pinvoke = 1;
8194 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8196 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8197 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8199 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8201 if (klass->image->dynamic)
8202 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8205 } else if (!m->klass->dummy &&
8206 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8207 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8208 MonoMethodHeader *header;
8210 gint32 max_stack, i;
8211 gint32 num_locals = 0;
8212 gint32 num_clauses = 0;
8216 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8217 code_size = rmb->ilgen->code_len;
8218 max_stack = rmb->ilgen->max_stack;
8219 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8220 if (rmb->ilgen->ex_handlers)
8221 num_clauses = method_count_clauses (rmb->ilgen);
8224 code = mono_array_addr (rmb->code, guint8, 0);
8225 code_size = mono_array_length (rmb->code);
8226 /* we probably need to run a verifier on the code... */
8236 header = g_malloc0 (sizeof (MonoMethodHeader) +
8237 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8238 header->code_size = code_size;
8239 header->code = g_malloc (code_size);
8240 memcpy ((char*)header->code, code, code_size);
8241 header->max_stack = max_stack;
8242 header->init_locals = rmb->init_locals;
8243 header->num_locals = num_locals;
8245 for (i = 0; i < num_locals; ++i) {
8246 MonoReflectionLocalBuilder *lb =
8247 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8249 header->locals [i] = g_new0 (MonoType, 1);
8250 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8253 header->num_clauses = num_clauses;
8255 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8256 rmb->ilgen, num_clauses);
8259 pm->header = header;
8262 if (rmb->generic_params) {
8263 int count = mono_array_length (rmb->generic_params);
8264 MonoGenericContainer *container;
8266 pm->generic_container = container = rmb->generic_container;
8267 container->type_argc = count;
8268 container->type_params = g_new0 (MonoGenericParam, count);
8270 for (i = 0; i < count; i++) {
8271 MonoReflectionGenericParam *gp =
8272 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8274 container->type_params [i] = *gp->type.type->data.generic_param;
8279 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8283 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8285 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8286 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8287 for (i = 0; i < rmb->nrefs; ++i)
8288 data [i + 1] = rmb->refs [i];
8293 /* Parameter info */
8296 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8297 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8298 for (i = 0; i <= m->signature->param_count; ++i) {
8299 MonoReflectionParamBuilder *pb;
8300 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8301 if ((i > 0) && (pb->attrs)) {
8302 /* Make a copy since it might point to a shared type structure */
8303 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)));
8304 m->signature->params [i - 1]->attrs = pb->attrs;
8307 if (pb->def_value) {
8308 MonoDynamicImage *assembly;
8309 guint32 idx, def_type, len;
8313 if (!method_aux->param_defaults) {
8314 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8315 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8317 assembly = (MonoDynamicImage*)klass->image;
8318 idx = encode_constant (assembly, pb->def_value, &def_type);
8319 /* Copy the data from the blob since it might get realloc-ed */
8320 p = assembly->blob.data + idx;
8321 len = mono_metadata_decode_blob_size (p, &p2);
8323 method_aux->param_defaults [i] = g_malloc (len);
8324 method_aux->param_default_types [i] = def_type;
8325 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8329 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8331 if (!method_aux->param_cattr)
8332 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8333 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8339 /* Parameter marshalling */
8342 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8343 MonoReflectionParamBuilder *pb;
8344 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8345 if (pb->marshal_info) {
8347 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8348 specs [pb->position] =
8349 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8353 if (specs != NULL) {
8355 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8356 method_aux->param_marshall = specs;
8359 if (klass->image->dynamic && method_aux)
8360 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8366 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8368 ReflectionMethodBuilder rmb;
8369 MonoMethodSignature *sig;
8371 sig = ctor_builder_to_signature (mb);
8373 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8375 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8376 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8378 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8379 /* ilgen is no longer needed */
8387 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8389 ReflectionMethodBuilder rmb;
8390 MonoMethodSignature *sig;
8392 sig = method_builder_to_signature (mb);
8394 reflection_methodbuilder_from_method_builder (&rmb, mb);
8396 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8397 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8399 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8400 /* ilgen is no longer needed */
8406 static MonoClassField*
8407 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8409 MonoClassField *field;
8416 field = g_new0 (MonoClassField, 1);
8418 field->name = mono_string_to_utf8 (fb->name);
8420 /* FIXME: handle type modifiers */
8421 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8422 field->type->attrs = fb->attrs;
8424 field->type = fb->type->type;
8426 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8427 field->data = mono_array_addr (fb->rva_data, char, 0);
8428 if (fb->offset != -1)
8429 field->offset = fb->offset;
8430 field->parent = klass;
8432 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8434 if (fb->def_value) {
8435 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8436 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8437 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8438 /* Copy the data from the blob since it might get realloc-ed */
8439 p = assembly->blob.data + idx;
8440 len = mono_metadata_decode_blob_size (p, &p2);
8442 field->data = g_malloc (len);
8443 memcpy ((gpointer)field->data, p, len);
8450 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8454 MonoReflectionTypeBuilder *tb = NULL;
8455 MonoGenericClass *gclass, *cached;
8456 MonoInflatedGenericClass *igclass;
8457 MonoDynamicGenericClass *dgclass = NULL;
8458 gboolean is_dynamic = FALSE;
8463 klass = mono_class_from_mono_type (type->type);
8464 if (!klass->generic_container && !klass->generic_class &&
8465 !(klass->nested_in && klass->nested_in->generic_container))
8468 mono_loader_lock ();
8470 domain = mono_object_domain (type);
8472 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8473 tb = (MonoReflectionTypeBuilder *) type;
8475 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8477 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8478 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8479 MonoReflectionType *rgt = rgi->generic_type;
8481 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8482 tb = (MonoReflectionTypeBuilder *) rgt;
8484 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8486 } else if (klass->wastypebuilder) {
8487 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8489 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8492 icount = klass->interface_count;
8496 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8497 igclass = &dgclass->generic_class;
8498 gclass = &igclass->generic_class;
8499 gclass->is_dynamic = TRUE;
8500 gclass->is_inflated = TRUE;
8502 igclass = g_new0 (MonoInflatedGenericClass, 1);
8503 gclass = &igclass->generic_class;
8504 gclass->is_inflated = TRUE;
8507 gclass->inst = g_new0 (MonoGenericInst, 1);
8509 gclass->inst->type_argc = type_argc;
8510 gclass->inst->type_argv = types;
8511 gclass->inst->is_reference = 1;
8513 for (i = 0; i < gclass->inst->type_argc; ++i) {
8514 if (!gclass->inst->is_open)
8515 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8516 if (gclass->inst->is_reference)
8517 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8520 gclass->container_class = klass;
8522 if (klass->generic_class) {
8523 MonoGenericClass *kgclass = klass->generic_class;
8524 MonoGenericClass *ogclass = gclass;
8526 ogclass->context = g_new0 (MonoGenericContext, 1);
8527 ogclass->context->container = gclass->container_class->generic_container;
8528 ogclass->context->gclass = gclass;
8531 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8532 igclass = &dgclass->generic_class;
8533 gclass = &igclass->generic_class;
8534 gclass->is_dynamic = TRUE;
8535 gclass->is_inflated = TRUE;
8537 igclass = g_new0 (MonoInflatedGenericClass, 1);
8538 gclass = &igclass->generic_class;
8539 gclass->is_inflated = TRUE;
8542 gclass->inst = g_new0 (MonoGenericInst, 1);
8544 gclass->inst->type_argc = kgclass->inst->type_argc;
8545 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8546 gclass->inst->is_reference = 1;
8548 for (i = 0; i < gclass->inst->type_argc; i++) {
8549 MonoType *t = kgclass->inst->type_argv [i];
8551 t = mono_class_inflate_generic_type (t, ogclass->context);
8553 if (!gclass->inst->is_open)
8554 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8555 if (gclass->inst->is_reference)
8556 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8558 gclass->inst->type_argv [i] = t;
8561 gclass->container_class = kgclass->container_class;
8564 geninst = g_new0 (MonoType, 1);
8565 geninst->type = MONO_TYPE_GENERICINST;
8567 cached = mono_metadata_lookup_generic_class (gclass);
8570 mono_loader_unlock ();
8571 geninst->data.generic_class = cached;
8575 geninst->data.generic_class = gclass;
8577 gclass->context = g_new0 (MonoGenericContext, 1);
8578 gclass->context->container = gclass->container_class->generic_container;
8579 gclass->context->gclass = gclass;
8582 dgclass->parent = parent;
8583 dgclass->ifaces = g_new0 (MonoType *, icount);
8584 dgclass->count_ifaces = icount;
8586 for (i = 0; i < icount; i++) {
8587 MonoReflectionType *itype;
8590 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8592 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8593 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8594 if (!dgclass->ifaces [i])
8595 dgclass->ifaces [i] = itype->type;
8599 mono_loader_unlock ();
8605 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8607 MonoClass *klass, *pklass = NULL;
8608 MonoReflectionType *parent = NULL;
8609 MonoType *the_parent = NULL, *geninst;
8610 MonoReflectionTypeBuilder *tb = NULL;
8611 MonoGenericClass *gclass;
8614 domain = mono_object_domain (type);
8615 klass = mono_class_from_mono_type (type->type);
8617 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8618 tb = (MonoReflectionTypeBuilder *) type;
8621 parent = tb->parent;
8622 pklass = mono_class_from_mono_type (parent->type);
8624 } else if (klass->wastypebuilder) {
8625 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8627 parent = tb->parent;
8628 pklass = mono_class_from_mono_type (parent->type);
8631 pklass = klass->parent;
8633 parent = mono_type_get_object (domain, &pklass->byval_arg);
8634 else if (klass->generic_class && klass->generic_class->is_dynamic) {
8635 MonoDynamicGenericClass *dgclass;
8637 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8638 if (dgclass->parent) {
8639 parent = mono_type_get_object (domain, dgclass->parent);
8640 pklass = mono_class_from_mono_type (dgclass->parent);
8645 if (pklass && pklass->generic_class)
8646 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8648 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8652 gclass = geninst->data.generic_class;
8658 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8661 MonoGenericClass *gclass, *cached;
8662 MonoInflatedGenericClass *igclass;
8666 klass = mono_class_from_mono_type (type);
8667 if (!klass->generic_container && !klass->generic_class &&
8668 !(klass->nested_in && klass->nested_in->generic_container))
8671 mono_loader_lock ();
8673 icount = klass->interface_count;
8675 igclass = g_new0 (MonoInflatedGenericClass, 1);
8676 gclass = &igclass->generic_class;
8677 gclass->is_inflated = TRUE;
8679 gclass->inst = g_new0 (MonoGenericInst, 1);
8680 gclass->inst->type_argc = type_argc;
8681 gclass->inst->type_argv = types;
8682 gclass->inst->is_reference = 1;
8684 for (i = 0; i < gclass->inst->type_argc; ++i) {
8685 if (!gclass->inst->is_open)
8686 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8687 if (gclass->inst->is_reference)
8688 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8691 gclass->container_class = klass;
8693 if (klass->generic_class) {
8694 MonoGenericClass *kgclass = klass->generic_class;
8695 MonoGenericClass *ogclass = gclass;
8697 gclass->context = g_new0 (MonoGenericContext, 1);
8698 gclass->context->container = gclass->container_class->generic_container;
8699 gclass->context->gclass = gclass;
8701 igclass = g_new0 (MonoInflatedGenericClass, 1);
8702 gclass = &igclass->generic_class;
8703 gclass->is_inflated = TRUE;
8705 gclass->inst = g_new0 (MonoGenericInst, 1);
8706 gclass->inst->type_argc = kgclass->inst->type_argc;
8707 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8708 gclass->inst->is_reference = 1;
8710 for (i = 0; i < gclass->inst->type_argc; i++) {
8711 MonoType *t = kgclass->inst->type_argv [i];
8713 t = mono_class_inflate_generic_type (t, ogclass->context);
8715 if (!gclass->inst->is_open)
8716 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8717 if (gclass->inst->is_reference)
8718 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8720 gclass->inst->type_argv [i] = t;
8723 gclass->container_class = kgclass->container_class;
8726 geninst = g_new0 (MonoType, 1);
8727 geninst->type = MONO_TYPE_GENERICINST;
8729 cached = mono_metadata_lookup_generic_class (gclass);
8732 mono_loader_unlock ();
8733 geninst->data.generic_class = cached;
8737 geninst->data.generic_class = gclass;
8739 gclass->context = g_new0 (MonoGenericContext, 1);
8740 gclass->context->container = gclass->container_class->generic_container;
8741 gclass->context->gclass = gclass;
8743 mono_loader_unlock ();
8748 static inline MonoType*
8749 dup_type (const MonoType *original)
8751 MonoType *r = g_new0 (MonoType, 1);
8753 r->attrs = original->attrs;
8754 r->byref = original->byref;
8755 if (original->type == MONO_TYPE_PTR)
8756 r->data.type = dup_type (original->data.type);
8757 else if (original->type == MONO_TYPE_ARRAY)
8758 r->data.array = mono_dup_array_type (original->data.array);
8759 else if (original->type == MONO_TYPE_FNPTR)
8760 r->data.method = mono_metadata_signature_deep_dup (original->data.method);
8761 mono_stats.generics_metadata_size += sizeof (MonoType);
8765 MonoReflectionMethod*
8766 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8768 MonoMethod *method, *inflated;
8769 MonoReflectionMethodBuilder *mb = NULL;
8770 MonoGenericContainer *container;
8771 MonoGenericMethod *gmethod;
8772 MonoGenericContext *context;
8773 MonoGenericInst *ginst;
8776 MONO_ARCH_SAVE_REGS;
8777 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8778 MonoReflectionTypeBuilder *tb;
8781 mb = (MonoReflectionMethodBuilder *) rmethod;
8782 tb = (MonoReflectionTypeBuilder *) mb->type;
8783 klass = mono_class_from_mono_type (tb->type.type);
8785 method = methodbuilder_to_mono_method (klass, mb);
8787 method = rmethod->method;
8790 method = mono_get_inflated_method (method);
8792 count = mono_method_signature (method)->generic_param_count;
8793 if (count != mono_array_length (types))
8796 container = ((MonoMethodNormal*) method)->generic_container;
8797 g_assert (container);
8799 if (!container->method_hash)
8800 container->method_hash = g_hash_table_new (
8801 (GHashFunc) mono_metadata_generic_method_hash,
8802 (GCompareFunc) mono_metadata_generic_method_equal);
8804 ginst = g_new0 (MonoGenericInst,1 );
8805 ginst->type_argc = count;
8806 ginst->type_argv = g_new0 (MonoType *, count);
8807 ginst->is_reference = 1;
8808 for (i = 0; i < count; i++) {
8809 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8810 ginst->type_argv [i] = dup_type (garg->type);
8812 if (!ginst->is_open)
8813 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8814 if (ginst->is_reference)
8815 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8817 ginst = mono_metadata_lookup_generic_inst (ginst);
8819 gmethod = g_new0 (MonoGenericMethod, 1);
8820 gmethod->generic_class = method->klass->generic_class;
8821 gmethod->container = container;
8822 gmethod->inst = ginst;
8824 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8828 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8831 gmethod->reflection_info = rmethod;
8833 context = g_new0 (MonoGenericContext, 1);
8834 context->container = container;
8835 context->gclass = method->klass->generic_class;
8836 context->gmethod = gmethod;
8838 if (method->is_inflated)
8839 method = ((MonoMethodInflated *) method)->declaring;
8841 inflated = mono_class_inflate_generic_method (method, context);
8842 g_hash_table_insert (container->method_hash, gmethod, inflated);
8844 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8848 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8850 MonoGenericMethod *gmethod;
8851 MonoInflatedGenericClass *gclass;
8852 MonoGenericContext *context;
8855 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8857 gmethod = g_new0 (MonoGenericMethod, 1);
8858 gmethod->generic_class = &gclass->generic_class;
8859 gmethod->inst = g_new0 (MonoGenericInst, 1);
8860 gmethod->reflection_info = obj;
8862 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8863 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8865 for (i = 0; i < gmethod->inst->type_argc; i++) {
8866 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8867 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8869 g_assert (gparam->pklass);
8870 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8873 context = g_new0 (MonoGenericContext, 1);
8874 context->container = gclass->generic_class.container_class->generic_container;
8875 context->gclass = &gclass->generic_class;
8876 context->gmethod = gmethod;
8878 return mono_class_inflate_generic_method (method, context);
8882 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8887 klass = mono_class_from_mono_type (type->type.type);
8889 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8890 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8891 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8892 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8893 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8894 method = ((MonoReflectionMethod *) obj)->method;
8896 method = NULL; /* prevent compiler warning */
8897 g_assert_not_reached ();
8900 return inflate_mono_method (type, method, obj);
8904 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8905 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8908 MonoGenericClass *gclass;
8909 MonoDynamicGenericClass *dgclass;
8910 MonoClass *klass, *gklass, *pklass;
8913 MONO_ARCH_SAVE_REGS;
8915 klass = mono_class_from_mono_type (type->type.type);
8916 gclass = type->type.type->data.generic_class;
8918 g_assert (gclass->is_dynamic);
8919 dgclass = (MonoDynamicGenericClass *) gclass;
8921 if (dgclass->initialized)
8924 gklass = gclass->container_class;
8925 mono_class_init (gklass);
8927 if (dgclass->parent)
8928 pklass = mono_class_from_mono_type (dgclass->parent);
8930 pklass = gklass->parent;
8932 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8933 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8934 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8935 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8936 dgclass->count_events = events ? mono_array_length (events) : 0;
8938 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8939 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8940 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8941 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8942 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8944 for (i = 0; i < dgclass->count_methods; i++) {
8945 MonoObject *obj = mono_array_get (methods, gpointer, i);
8947 dgclass->methods [i] = inflate_method (type, obj);
8950 for (i = 0; i < dgclass->count_ctors; i++) {
8951 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8953 dgclass->ctors [i] = inflate_method (type, obj);
8956 for (i = 0; i < dgclass->count_fields; i++) {
8957 MonoObject *obj = mono_array_get (fields, gpointer, i);
8958 MonoClassField *field;
8959 MonoInflatedField *ifield;
8961 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8962 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8963 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8964 field = ((MonoReflectionField *) obj)->field;
8966 field = NULL; /* prevent compiler warning */
8967 g_assert_not_reached ();
8970 ifield = g_new0 (MonoInflatedField, 1);
8971 ifield->generic_type = field->type;
8972 ifield->reflection_info = obj;
8974 dgclass->fields [i] = *field;
8975 dgclass->fields [i].parent = klass;
8976 dgclass->fields [i].generic_info = ifield;
8977 dgclass->fields [i].type = mono_class_inflate_generic_type (
8978 field->type, dgclass->generic_class.generic_class.context);
8981 for (i = 0; i < dgclass->count_properties; i++) {
8982 MonoObject *obj = mono_array_get (properties, gpointer, i);
8983 MonoProperty *property = &dgclass->properties [i];
8985 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8986 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8988 property->parent = klass;
8989 property->attrs = pb->attrs;
8990 property->name = mono_string_to_utf8 (pb->name);
8992 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8994 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8995 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8996 *property = *((MonoReflectionProperty *) obj)->property;
8999 property->get = inflate_mono_method (type, property->get, NULL);
9001 property->set = inflate_mono_method (type, property->set, NULL);
9003 g_assert_not_reached ();
9006 for (i = 0; i < dgclass->count_events; i++) {
9007 MonoObject *obj = mono_array_get (events, gpointer, i);
9008 MonoEvent *event = &dgclass->events [i];
9010 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
9011 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
9013 event->parent = klass;
9014 event->attrs = eb->attrs;
9015 event->name = mono_string_to_utf8 (eb->name);
9017 event->add = inflate_method (type, (MonoObject *) eb->add_method);
9018 if (eb->remove_method)
9019 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
9020 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
9021 *event = *((MonoReflectionEvent *) obj)->event;
9024 event->add = inflate_mono_method (type, event->add, NULL);
9026 event->remove = inflate_mono_method (type, event->remove, NULL);
9028 g_assert_not_reached ();
9031 dgclass->initialized = TRUE;
9035 ensure_runtime_vtable (MonoClass *klass)
9037 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9038 int i, num, j, onum;
9039 MonoMethod **overrides;
9041 if (!tb || klass->wastypebuilder)
9044 ensure_runtime_vtable (klass->parent);
9046 num = tb->ctors? mono_array_length (tb->ctors): 0;
9047 num += tb->num_methods;
9048 klass->method.count = num;
9049 klass->methods = g_new (MonoMethod*, num);
9050 num = tb->ctors? mono_array_length (tb->ctors): 0;
9051 for (i = 0; i < num; ++i)
9052 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9053 num = tb->num_methods;
9055 for (i = 0; i < num; ++i)
9056 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9058 if (tb->interfaces) {
9059 klass->interface_count = mono_array_length (tb->interfaces);
9060 klass->interfaces = g_new (MonoClass*, klass->interface_count);
9061 for (i = 0; i < klass->interface_count; ++i) {
9062 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9063 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9067 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9068 for (i = 0; i < klass->method.count; ++i)
9069 klass->methods [i]->slot = i;
9071 if (!((MonoDynamicImage*)klass->image)->run)
9072 /* No need to create a generic vtable */
9078 for (i = 0; i < tb->num_methods; ++i) {
9079 MonoReflectionMethodBuilder *mb =
9080 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9081 if (mb->override_method)
9086 overrides = g_new0 (MonoMethod*, onum * 2);
9090 for (i = 0; i < tb->num_methods; ++i) {
9091 MonoReflectionMethodBuilder *mb =
9092 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9093 if (mb->override_method) {
9094 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9095 overrides [onum * 2] =
9096 mb->override_method->method;
9097 overrides [onum * 2 + 1] =
9100 g_assert (mb->mhandle);
9107 mono_class_setup_vtable_general (klass, overrides, onum);
9112 typebuilder_setup_fields (MonoClass *klass)
9114 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9115 MonoReflectionFieldBuilder *fb;
9116 MonoClassField *field;
9121 klass->field.count = tb->num_fields;
9122 klass->field.first = 0;
9124 if (!klass->field.count)
9127 klass->fields = g_new0 (MonoClassField, klass->field.count);
9129 for (i = 0; i < klass->field.count; ++i) {
9130 fb = mono_array_get (tb->fields, gpointer, i);
9131 field = &klass->fields [i];
9132 field->name = mono_string_to_utf8 (fb->name);
9134 /* FIXME: handle type modifiers */
9135 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9136 field->type->attrs = fb->attrs;
9138 field->type = fb->type->type;
9140 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9141 field->data = mono_array_addr (fb->rva_data, char, 0);
9142 if (fb->offset != -1)
9143 field->offset = fb->offset;
9144 field->parent = klass;
9146 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9148 if (fb->def_value) {
9149 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9150 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9151 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9152 /* Copy the data from the blob since it might get realloc-ed */
9153 p = assembly->blob.data + idx;
9154 len = mono_metadata_decode_blob_size (p, &p2);
9156 field->data = g_malloc (len);
9157 memcpy ((gpointer)field->data, p, len);
9160 mono_class_layout_fields (klass);
9164 typebuilder_setup_properties (MonoClass *klass)
9166 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9167 MonoReflectionPropertyBuilder *pb;
9170 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9171 klass->property.first = 0;
9173 klass->properties = g_new0 (MonoProperty, klass->property.count);
9174 for (i = 0; i < klass->property.count; ++i) {
9175 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9176 klass->properties [i].parent = klass;
9177 klass->properties [i].attrs = pb->attrs;
9178 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9180 klass->properties [i].get = pb->get_method->mhandle;
9182 klass->properties [i].set = pb->set_method->mhandle;
9186 MonoReflectionEvent *
9187 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9189 MonoEvent *event = g_new0 (MonoEvent, 1);
9193 klass = my_mono_class_from_mono_type (tb->type.type);
9195 event->parent = klass;
9196 event->attrs = eb->attrs;
9197 event->name = mono_string_to_utf8 (eb->name);
9199 event->add = eb->add_method->mhandle;
9200 if (eb->remove_method)
9201 event->remove = eb->remove_method->mhandle;
9202 if (eb->raise_method)
9203 event->raise = eb->raise_method->mhandle;
9205 if (eb->other_methods) {
9206 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9207 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9208 MonoReflectionMethodBuilder *mb =
9209 mono_array_get (eb->other_methods,
9210 MonoReflectionMethodBuilder*, j);
9211 event->other [j] = mb->mhandle;
9215 return mono_event_get_object (mono_object_domain (tb), klass, event);
9219 typebuilder_setup_events (MonoClass *klass)
9221 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9222 MonoReflectionEventBuilder *eb;
9225 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9226 klass->event.first = 0;
9228 klass->events = g_new0 (MonoEvent, klass->event.count);
9229 for (i = 0; i < klass->event.count; ++i) {
9230 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9231 klass->events [i].parent = klass;
9232 klass->events [i].attrs = eb->attrs;
9233 klass->events [i].name = mono_string_to_utf8 (eb->name);
9235 klass->events [i].add = eb->add_method->mhandle;
9236 if (eb->remove_method)
9237 klass->events [i].remove = eb->remove_method->mhandle;
9238 if (eb->raise_method)
9239 klass->events [i].raise = eb->raise_method->mhandle;
9241 if (eb->other_methods) {
9242 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9243 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9244 MonoReflectionMethodBuilder *mb =
9245 mono_array_get (eb->other_methods,
9246 MonoReflectionMethodBuilder*, j);
9247 klass->events [i].other [j] = mb->mhandle;
9254 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9258 MonoReflectionType* res;
9261 MONO_ARCH_SAVE_REGS;
9263 domain = mono_object_domain (tb);
9264 klass = my_mono_class_from_mono_type (tb->type.type);
9266 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9269 * we need to lock the domain because the lock will be taken inside
9270 * So, we need to keep the locking order correct.
9272 mono_domain_lock (domain);
9273 mono_loader_lock ();
9274 if (klass->wastypebuilder) {
9275 mono_loader_unlock ();
9276 mono_domain_unlock (domain);
9277 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9280 * Fields to set in klass:
9281 * the various flags: delegate/unicode/contextbound etc.
9283 klass->flags = tb->attrs;
9284 klass->has_cctor = 1;
9285 klass->has_finalize = 1;
9288 if (!((MonoDynamicImage*)klass->image)->run) {
9289 if (klass->generic_container) {
9290 /* FIXME: The code below can't handle generic classes */
9291 klass->wastypebuilder = TRUE;
9292 mono_loader_unlock ();
9293 mono_domain_unlock (domain);
9294 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9299 /* enums are done right away */
9300 if (!klass->enumtype)
9301 ensure_runtime_vtable (klass);
9304 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9305 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9306 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9310 /* fields and object layout */
9311 if (klass->parent) {
9312 if (!klass->parent->size_inited)
9313 mono_class_init (klass->parent);
9314 klass->instance_size += klass->parent->instance_size;
9315 klass->class_size += klass->parent->class_size;
9316 klass->min_align = klass->parent->min_align;
9317 /* if the type has no fields we won't call the field_setup
9318 * routine which sets up klass->has_references.
9320 klass->has_references |= klass->parent->has_references;
9322 klass->instance_size = sizeof (MonoObject);
9323 klass->min_align = 1;
9326 /* FIXME: handle packing_size and instance_size */
9327 typebuilder_setup_fields (klass);
9329 typebuilder_setup_properties (klass);
9331 typebuilder_setup_events (klass);
9333 klass->wastypebuilder = TRUE;
9334 mono_loader_unlock ();
9335 mono_domain_unlock (domain);
9337 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9338 g_assert (res != (MonoReflectionType*)tb);
9343 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9345 MonoGenericParam *param;
9348 MONO_ARCH_SAVE_REGS;
9350 param = g_new0 (MonoGenericParam, 1);
9352 if (gparam->mbuilder) {
9353 if (!gparam->mbuilder->generic_container)
9354 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9355 param->owner = gparam->mbuilder->generic_container;
9356 } else if (gparam->tbuilder) {
9357 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9358 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9363 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9364 if (gparam->index >= count)
9367 container = nesting->generic_container;
9368 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9371 g_assert (container);
9372 param->owner = container;
9375 param->method = NULL;
9376 param->name = mono_string_to_utf8 (gparam->name);
9377 param->num = gparam->index;
9379 image = &gparam->tbuilder->module->dynamic_image->image;
9380 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9382 param->pklass->reflection_info = gparam;
9384 gparam->type.type = g_new0 (MonoType, 1);
9385 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9386 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9387 gparam->type.type->data.generic_param = param;
9391 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9393 MonoDynamicImage *assembly = sig->module->dynamic_image;
9394 guint32 na = mono_array_length (sig->arguments);
9395 guint32 buflen, i, size;
9399 MONO_ARCH_SAVE_REGS;
9401 p = buf = g_malloc (size = 50 + na * 50);
9403 mono_metadata_encode_value (0x07, p, &p);
9404 mono_metadata_encode_value (na, p, &p);
9405 for (i = 0; i < na; ++i) {
9406 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9407 encode_reflection_type (assembly, type, p, &p);
9411 g_assert (buflen < size);
9412 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9413 p = mono_array_addr (result, char, 0);
9414 memcpy (p, buf, buflen);
9421 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9423 MonoDynamicImage *assembly = sig->module->dynamic_image;
9424 guint32 na = mono_array_length (sig->arguments);
9425 guint32 buflen, i, size;
9429 MONO_ARCH_SAVE_REGS;
9431 p = buf = g_malloc (size = 10 + na * 10);
9433 mono_metadata_encode_value (0x06, p, &p);
9434 for (i = 0; i < na; ++i) {
9435 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9436 encode_reflection_type (assembly, type, p, &p);
9440 g_assert (buflen < size);
9441 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9442 p = mono_array_addr (result, char, 0);
9443 memcpy (p, buf, buflen);
9450 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9452 ReflectionMethodBuilder rmb;
9453 MonoMethodSignature *sig;
9456 sig = dynamic_method_to_signature (mb);
9458 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9461 * Resolve references.
9464 * Every second entry in the refs array is reserved for storing handle_class,
9465 * which is needed by the ldtoken implementation in the JIT.
9467 rmb.nrefs = mb->nrefs;
9468 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9469 for (i = 0; i < mb->nrefs; i += 2) {
9470 MonoClass *handle_class;
9471 gpointer ref = resolve_object (mb->module->image,
9472 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9475 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
9479 rmb.refs [i + 1] = handle_class;
9483 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9487 /* ilgen is no longer needed */
9492 * mono_reflection_lookup_dynamic_token:
9494 * Finish the Builder object pointed to by TOKEN and return the corresponding
9495 * runtime structure. HANDLE_CLASS is set to the class required by
9499 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9501 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9504 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9507 return resolve_object (image, obj, handle_class);
9511 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9513 gpointer result = NULL;
9515 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9516 result = mono_string_intern ((MonoString*)obj);
9517 *handle_class = NULL;
9519 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9520 MonoReflectionType *tb = (MonoReflectionType*)obj;
9521 result = mono_class_from_mono_type (tb->type);
9522 *handle_class = mono_defaults.typehandle_class;
9524 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9525 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9526 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9527 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9528 result = ((MonoReflectionMethod*)obj)->method;
9529 *handle_class = mono_defaults.methodhandle_class;
9531 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9532 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9533 result = mb->mhandle;
9535 /* Type is not yet created */
9536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9538 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9541 * Hopefully this has been filled in by calling CreateType() on the
9545 * TODO: This won't work if the application finishes another
9546 * TypeBuilder instance instead of this one.
9548 result = mb->mhandle;
9550 *handle_class = mono_defaults.methodhandle_class;
9551 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9552 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9554 result = cb->mhandle;
9556 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9558 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9559 result = cb->mhandle;
9561 *handle_class = mono_defaults.methodhandle_class;
9562 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9563 result = ((MonoReflectionField*)obj)->field;
9564 *handle_class = mono_defaults.fieldhandle_class;
9566 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9567 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9568 result = fb->handle;
9571 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9573 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9574 result = fb->handle;
9576 *handle_class = mono_defaults.fieldhandle_class;
9577 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9578 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9581 klass = tb->type.type->data.klass;
9582 if (klass->wastypebuilder) {
9583 /* Already created */
9587 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9588 result = tb->type.type->data.klass;
9591 *handle_class = mono_defaults.typehandle_class;
9592 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9593 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9594 MonoMethodSignature *sig;
9597 if (helper->arguments)
9598 nargs = mono_array_length (helper->arguments);
9602 sig = mono_metadata_signature_alloc (image, nargs);
9603 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9604 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9606 if (helper->call_conv == 0) /* unmanaged */
9607 sig->call_convention = helper->unmanaged_call_conv - 1;
9609 if (helper->call_conv & 0x02)
9610 sig->call_convention = MONO_CALL_VARARG;
9612 sig->call_convention = MONO_CALL_DEFAULT;
9614 sig->param_count = nargs;
9615 /* TODO: Copy type ? */
9616 sig->ret = helper->return_type->type;
9617 for (i = 0; i < nargs; ++i) {
9618 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9619 sig->params [i] = rt->type;
9623 *handle_class = NULL;
9625 g_print (obj->vtable->klass->name);
9626 g_assert_not_reached ();
9632 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9633 const static guint32 declsec_flags_map[] = {
9634 0x00000000, /* empty */
9635 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9636 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9637 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9638 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9639 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9640 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9641 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9642 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9643 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9644 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9645 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9646 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9647 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9648 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9649 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9650 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9651 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9652 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9656 * Returns flags that includes all available security action associated to the handle.
9657 * @token: metadata token (either for a class or a method)
9658 * @image: image where resides the metadata.
9661 mono_declsec_get_flags (MonoImage *image, guint32 token)
9663 guint32 index = mono_metadata_declsec_from_index (image, token);
9664 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9669 for (i = index; i < t->rows; i++) {
9670 guint32 cols [MONO_DECL_SECURITY_SIZE];
9672 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9673 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9676 action = cols [MONO_DECL_SECURITY_ACTION];
9677 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9678 result |= declsec_flags_map [action];
9680 g_assert_not_reached ();
9687 * Get the security actions (in the form of flags) associated with the specified method.
9689 * @method: The method for which we want the declarative security flags.
9690 * Return the declarative security flags for the method (only).
9692 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9693 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9696 mono_declsec_flags_from_method (MonoMethod *method)
9698 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9699 /* FIXME: No cache (for the moment) */
9700 guint32 idx = mono_method_get_index (method);
9701 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9702 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9703 return mono_declsec_get_flags (method->klass->image, idx);
9709 * Get the security actions (in the form of flags) associated with the specified class.
9711 * @klass: The class for which we want the declarative security flags.
9712 * Return the declarative security flags for the class.
9714 * Note: We cache the flags inside the MonoClass structure as this will get
9715 * called very often (at least for each method).
9718 mono_declsec_flags_from_class (MonoClass *klass)
9720 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9721 if (!klass->declsec_flags) {
9722 guint32 idx = mono_metadata_token_index (klass->type_token);
9723 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9724 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9725 /* we cache the flags on classes */
9726 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9728 return klass->declsec_flags;
9734 * Get the security actions (in the form of flags) associated with the specified assembly.
9736 * @assembly: The assembly for which we want the declarative security flags.
9737 * Return the declarative security flags for the assembly.
9740 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9742 guint32 idx = 1; /* there is only one assembly */
9743 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9744 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9745 return mono_declsec_get_flags (assembly->image, idx);
9750 * Fill actions for the specific index (which may either be an encoded class token or
9751 * an encoded method token) from the metadata image.
9752 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9755 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9756 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9758 MonoBoolean result = FALSE;
9760 guint32 cols [MONO_DECL_SECURITY_SIZE];
9761 int index = mono_metadata_declsec_from_index (image, token);
9764 t = &image->tables [MONO_TABLE_DECLSECURITY];
9765 for (i = index; i < t->rows; i++) {
9766 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9768 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9771 /* if present only replace (class) permissions with method permissions */
9772 /* if empty accept either class or method permissions */
9773 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9774 if (!actions->demand.blob) {
9775 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9776 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9777 actions->demand.blob = (char*) (blob + 2);
9778 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9781 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9782 if (!actions->noncasdemand.blob) {
9783 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9784 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9785 actions->noncasdemand.blob = (char*) (blob + 2);
9786 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9789 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9790 if (!actions->demandchoice.blob) {
9791 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9792 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9793 actions->demandchoice.blob = (char*) (blob + 2);
9794 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9804 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9805 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9807 guint32 idx = mono_metadata_token_index (klass->type_token);
9808 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9809 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9810 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9814 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9815 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9817 guint32 idx = mono_method_get_index (method);
9818 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9819 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9820 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9824 * Collect all actions (that requires to generate code in mini) assigned for
9825 * the specified method.
9826 * Note: Don't use the content of actions if the function return FALSE.
9829 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9831 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9832 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9833 MonoBoolean result = FALSE;
9836 /* quick exit if no declarative security is present in the metadata */
9837 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9840 /* we want the original as the wrapper is "free" of the security informations */
9841 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9842 method = mono_marshal_method_from_wrapper (method);
9847 /* First we look for method-level attributes */
9848 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9849 mono_class_init (method->klass);
9850 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9852 result = mono_declsec_get_method_demands_params (method, demands,
9853 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9856 /* Here we use (or create) the class declarative cache to look for demands */
9857 flags = mono_declsec_flags_from_class (method->klass);
9860 mono_class_init (method->klass);
9861 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9863 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9864 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9867 /* The boolean return value is used as a shortcut in case nothing needs to
9868 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9874 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9876 * Note: Don't use the content of actions if the function return FALSE.
9879 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9881 MonoBoolean result = FALSE;
9884 /* quick exit if no declarative security is present in the metadata */
9885 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9888 /* we want the original as the wrapper is "free" of the security informations */
9889 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9890 method = mono_marshal_method_from_wrapper (method);
9895 /* results are independant - zeroize both */
9896 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9897 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9899 /* First we look for method-level attributes */
9900 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9901 mono_class_init (method->klass);
9903 result = mono_declsec_get_method_demands_params (method, cmethod,
9904 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9907 /* Here we use (or create) the class declarative cache to look for demands */
9908 flags = mono_declsec_flags_from_class (method->klass);
9909 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9910 mono_class_init (method->klass);
9912 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9913 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9920 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9922 * @klass The inherited class - this is the class that provides the security check (attributes)
9924 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9926 * Note: Don't use the content of actions if the function return FALSE.
9929 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9931 MonoBoolean result = FALSE;
9934 /* quick exit if no declarative security is present in the metadata */
9935 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9938 /* Here we use (or create) the class declarative cache to look for demands */
9939 flags = mono_declsec_flags_from_class (klass);
9940 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9941 mono_class_init (klass);
9942 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9944 result |= mono_declsec_get_class_demands_params (klass, demands,
9945 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9952 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9954 * Note: Don't use the content of actions if the function return FALSE.
9957 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9959 /* quick exit if no declarative security is present in the metadata */
9960 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9963 /* we want the original as the wrapper is "free" of the security informations */
9964 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9965 method = mono_marshal_method_from_wrapper (method);
9970 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9971 mono_class_init (method->klass);
9972 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9974 return mono_declsec_get_method_demands_params (method, demands,
9975 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9982 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9984 guint32 cols [MONO_DECL_SECURITY_SIZE];
9988 int index = mono_metadata_declsec_from_index (image, token);
9992 t = &image->tables [MONO_TABLE_DECLSECURITY];
9993 for (i = index; i < t->rows; i++) {
9994 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9996 /* shortcut - index are ordered */
9997 if (token != cols [MONO_DECL_SECURITY_PARENT])
10000 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
10001 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
10002 entry->blob = (char*) (metadata + 2);
10003 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
10012 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
10014 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
10015 guint32 idx = mono_method_get_index (method);
10016 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10017 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
10018 return get_declsec_action (method->klass->image, idx, action, entry);
10024 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
10027 guint32 flags = mono_declsec_flags_from_class (klass);
10028 if (declsec_flags_map [action] & flags) {
10029 guint32 idx = mono_metadata_token_index (klass->type_token);
10030 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10031 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
10032 return get_declsec_action (klass->image, idx, action, entry);
10038 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
10040 guint32 idx = 1; /* there is only one assembly */
10041 idx <<= MONO_HAS_DECL_SECURITY_BITS;
10042 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
10044 return get_declsec_action (assembly->image, idx, action, entry);
10048 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
10050 MonoObject *res, *exc;
10052 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
10053 static MonoMethod *method = NULL;
10055 if (!System_Reflection_Emit_TypeBuilder) {
10056 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10057 g_assert (System_Reflection_Emit_TypeBuilder);
10059 if (method == NULL) {
10060 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10065 * The result of mono_type_get_object () might be a System.MonoType but we
10066 * need a TypeBuilder so use klass->reflection_info.
10068 g_assert (klass->reflection_info);
10069 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10071 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10073 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10077 return *(MonoBoolean*)mono_object_unbox (res);