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);
498 mono_metadata_encode_value (type->type, p, &p);
500 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
501 * otherwise two typerefs could point to the same type, leading to
502 * verification errors.
504 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
507 case MONO_TYPE_ARRAY:
508 mono_metadata_encode_value (type->type, p, &p);
509 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
510 mono_metadata_encode_value (type->data.array->rank, p, &p);
511 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
512 mono_metadata_encode_value (0, p, &p);
514 case MONO_TYPE_GENERICINST:
515 encode_generic_class (assembly, type->data.generic_class, p, &p);
519 mono_metadata_encode_value (type->type, p, &p);
520 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
523 g_error ("need to encode type %x", type->type);
529 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
532 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
536 encode_type (assembly, type->type, p, endbuf);
540 g_assert_not_reached ();
545 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
550 for (i = 0; i < mono_array_length (modreq); ++i) {
551 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
552 *p = MONO_TYPE_CMOD_REQD;
554 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
558 for (i = 0; i < mono_array_length (modopt); ++i) {
559 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
560 *p = MONO_TYPE_CMOD_OPT;
562 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
569 generic_class_get_signature_size (MonoGenericClass *gclass)
575 g_assert_not_reached ();
578 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
580 for (i = 0; i < gclass->inst->type_argc; ++i)
581 size += type_get_signature_size (gclass->inst->type_argv [i]);
587 type_get_signature_size (MonoType *type)
592 g_assert_not_reached ();
600 case MONO_TYPE_BOOLEAN:
614 case MONO_TYPE_STRING:
615 case MONO_TYPE_OBJECT:
616 case MONO_TYPE_TYPEDBYREF:
619 return size + 1 + type_get_signature_size (type->data.type);
620 case MONO_TYPE_SZARRAY:
621 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
622 case MONO_TYPE_VALUETYPE:
623 case MONO_TYPE_CLASS:
625 case MONO_TYPE_ARRAY:
626 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
627 case MONO_TYPE_GENERICINST:
628 return size + generic_class_get_signature_size (type->data.generic_class);
633 g_error ("need to encode type %x", type->type);
639 method_get_signature_size (MonoMethodSignature *sig)
644 size = type_get_signature_size (sig->ret);
645 for (i = 0; i < sig->param_count; i++)
646 size += type_get_signature_size (sig->params [i]);
648 if (sig->generic_param_count)
650 if (sig->sentinelpos >= 0)
657 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
662 guint32 nparams = sig->param_count;
663 guint32 size = 11 + method_get_signature_size (sig);
671 p = buf = g_malloc (size);
673 * FIXME: vararg, explicit_this, differenc call_conv values...
675 *p = sig->call_convention;
677 *p |= 0x20; /* hasthis */
678 if (sig->generic_param_count)
679 *p |= 0x10; /* generic */
681 if (sig->generic_param_count)
682 mono_metadata_encode_value (sig->generic_param_count, p, &p);
683 mono_metadata_encode_value (nparams, p, &p);
684 encode_type (assembly, sig->ret, p, &p);
685 for (i = 0; i < nparams; ++i) {
686 if (i == sig->sentinelpos)
687 *p++ = MONO_TYPE_SENTINEL;
688 encode_type (assembly, sig->params [i], p, &p);
691 g_assert (p - buf < size);
692 mono_metadata_encode_value (p-buf, b, &b);
693 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
699 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
702 * FIXME: reuse code from method_encode_signature().
707 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
708 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
709 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
710 guint32 size = 41 + nparams * 40 + notypes * 40;
715 p = buf = g_malloc (size);
716 /* LAMESPEC: all the call conv spec is foobared */
717 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
718 if (mb->call_conv & 2)
719 *p |= 0x5; /* vararg */
720 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
721 *p |= 0x20; /* hasthis */
723 *p |= 0x10; /* generic */
726 mono_metadata_encode_value (ngparams, p, &p);
727 mono_metadata_encode_value (nparams + notypes, p, &p);
728 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
729 encode_reflection_type (assembly, mb->rtype, p, &p);
730 for (i = 0; i < nparams; ++i) {
731 MonoArray *modreq = NULL;
732 MonoArray *modopt = NULL;
733 MonoReflectionType *pt;
735 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
736 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
737 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
738 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
739 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
740 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
741 encode_reflection_type (assembly, pt, p, &p);
744 *p++ = MONO_TYPE_SENTINEL;
745 for (i = 0; i < notypes; ++i) {
746 MonoReflectionType *pt;
748 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
749 encode_reflection_type (assembly, pt, p, &p);
753 g_assert (p - buf < size);
754 mono_metadata_encode_value (p-buf, b, &b);
755 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
761 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
763 MonoDynamicTable *table;
766 guint32 idx, sig_idx, size;
767 guint nl = mono_array_length (ilgen->locals);
774 p = buf = g_malloc (size);
775 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
776 idx = table->next_idx ++;
778 alloc_table (table, table->rows);
779 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
781 mono_metadata_encode_value (0x07, p, &p);
782 mono_metadata_encode_value (nl, p, &p);
783 for (i = 0; i < nl; ++i) {
784 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
787 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
789 encode_reflection_type (assembly, lb->type, p, &p);
791 g_assert (p - buf < size);
792 mono_metadata_encode_value (p-buf, b, &b);
793 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
796 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
802 method_count_clauses (MonoReflectionILGen *ilgen)
804 guint32 num_clauses = 0;
807 MonoILExceptionInfo *ex_info;
808 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
809 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
810 if (ex_info->handlers)
811 num_clauses += mono_array_length (ex_info->handlers);
819 static MonoExceptionClause*
820 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
822 MonoExceptionClause *clauses;
823 MonoExceptionClause *clause;
824 MonoILExceptionInfo *ex_info;
825 MonoILExceptionBlock *ex_block;
826 guint32 finally_start;
827 int i, j, clause_index;;
829 clauses = g_new0 (MonoExceptionClause, num_clauses);
832 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
833 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
834 finally_start = ex_info->start + ex_info->len;
835 g_assert (ex_info->handlers);
836 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
837 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
838 clause = &(clauses [clause_index]);
840 clause->flags = ex_block->type;
841 clause->try_offset = ex_info->start;
843 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
844 clause->try_len = finally_start - ex_info->start;
846 clause->try_len = ex_info->len;
847 clause->handler_offset = ex_block->start;
848 clause->handler_len = ex_block->len;
849 if (ex_block->extype) {
850 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
852 /* FIXME: handle filters */
853 clause->data.filter_offset = 0;
855 finally_start = ex_block->start + ex_block->len;
865 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
871 gint32 num_locals = 0;
872 gint32 num_exception = 0;
875 char fat_header [12];
878 guint32 local_sig = 0;
879 guint32 header_size = 12;
882 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
883 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
887 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
889 code = mb->ilgen->code;
890 code_size = mb->ilgen->code_len;
891 max_stack = mb->ilgen->max_stack;
892 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
893 if (mb->ilgen->ex_handlers)
894 num_exception = method_count_clauses (mb->ilgen);
898 char *name = mono_string_to_utf8 (mb->name);
899 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
900 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
903 mono_raise_exception (exception);
906 code_size = mono_array_length (code);
907 max_stack = 8; /* we probably need to run a verifier on the code... */
910 stream_data_align (&assembly->code);
912 /* check for exceptions, maxstack, locals */
913 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
915 if (code_size < 64 && !(code_size & 1)) {
916 flags = (code_size << 2) | 0x2;
917 } else if (code_size < 32 && (code_size & 1)) {
918 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
922 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
923 /* add to the fixup todo list */
924 if (mb->ilgen && mb->ilgen->num_token_fixups)
925 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
926 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
927 return assembly->text_rva + idx;
931 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
933 * FIXME: need to set also the header size in fat_flags.
934 * (and more sects and init locals flags)
938 fat_flags |= METHOD_HEADER_MORE_SECTS;
940 fat_flags |= METHOD_HEADER_INIT_LOCALS;
941 fat_header [0] = fat_flags;
942 fat_header [1] = (header_size / 4 ) << 4;
943 shortp = (guint16*)(fat_header + 2);
944 *shortp = GUINT16_TO_LE (max_stack);
945 intp = (guint32*)(fat_header + 4);
946 *intp = GUINT32_TO_LE (code_size);
947 intp = (guint32*)(fat_header + 8);
948 *intp = GUINT32_TO_LE (local_sig);
949 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
954 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
956 unsigned char sheader [4];
957 MonoILExceptionInfo * ex_info;
958 MonoILExceptionBlock * ex_block;
961 stream_data_align (&assembly->code);
962 /* always use fat format for now */
963 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
964 num_exception *= 6 * sizeof (guint32);
965 num_exception += 4; /* include the size of the header */
966 sheader [1] = num_exception & 0xff;
967 sheader [2] = (num_exception >> 8) & 0xff;
968 sheader [3] = (num_exception >> 16) & 0xff;
969 mono_image_add_stream_data (&assembly->code, sheader, 4);
970 /* fat header, so we are already aligned */
972 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
973 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
974 if (ex_info->handlers) {
975 int finally_start = ex_info->start + ex_info->len;
976 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
978 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
980 val = GUINT32_TO_LE (ex_block->type);
981 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
983 val = GUINT32_TO_LE (ex_info->start);
984 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
985 /* need fault, too, probably */
986 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
987 val = GUINT32_TO_LE (finally_start - ex_info->start);
989 val = GUINT32_TO_LE (ex_info->len);
990 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
992 val = GUINT32_TO_LE (ex_block->start);
993 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
995 val = GUINT32_TO_LE (ex_block->len);
996 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
997 finally_start = ex_block->start + ex_block->len;
998 if (ex_block->extype) {
999 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1001 /* FIXME: handle filters */
1004 val = GUINT32_TO_LE (val);
1005 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1006 /*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",
1007 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);*/
1010 g_error ("No clauses for ex info block %d", i);
1014 return assembly->text_rva + idx;
1018 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1021 MonoDynamicTable *table;
1024 table = &assembly->tables [table_idx];
1026 g_assert (col < table->columns);
1028 values = table->values + table->columns;
1029 for (i = 1; i <= table->rows; ++i) {
1030 if (values [col] == token)
1032 values += table->columns;
1037 static GHashTable *dynamic_custom_attrs = NULL;
1039 static MonoCustomAttrInfo*
1040 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1043 MonoCustomAttrInfo *ainfo;
1044 MonoReflectionCustomAttr *cattr;
1048 /* FIXME: check in assembly the Run flag is set */
1050 count = mono_array_length (cattrs);
1052 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1054 ainfo->image = image;
1055 ainfo->num_attrs = count;
1056 for (i = 0; i < count; ++i) {
1057 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1058 ainfo->attrs [i].ctor = cattr->ctor->method;
1059 /* FIXME: might want to memdup the data here */
1060 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1061 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1068 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1070 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1075 if (!dynamic_custom_attrs)
1076 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1078 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1079 ainfo->cached = TRUE;
1083 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1085 /* they are cached, so we don't free them */
1086 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1092 * idx is the table index of the object
1093 * type is one of MONO_CUSTOM_ATTR_*
1096 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1098 MonoDynamicTable *table;
1099 MonoReflectionCustomAttr *cattr;
1101 guint32 count, i, token;
1103 char *p = blob_size;
1105 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1108 count = mono_array_length (cattrs);
1109 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1110 table->rows += count;
1111 alloc_table (table, table->rows);
1112 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1113 idx <<= MONO_CUSTOM_ATTR_BITS;
1115 for (i = 0; i < count; ++i) {
1116 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1117 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1118 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1119 type = mono_metadata_token_index (token);
1120 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1121 switch (mono_metadata_token_table (token)) {
1122 case MONO_TABLE_METHOD:
1123 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1125 case MONO_TABLE_MEMBERREF:
1126 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1129 g_warning ("got wrong token in custom attr");
1132 values [MONO_CUSTOM_ATTR_TYPE] = type;
1134 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1135 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1136 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1137 values += MONO_CUSTOM_ATTR_SIZE;
1143 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1145 MonoDynamicTable *table;
1147 guint32 count, i, idx;
1148 MonoReflectionPermissionSet *perm;
1153 count = mono_array_length (permissions);
1154 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1155 table->rows += count;
1156 alloc_table (table, table->rows);
1158 for (i = 0; i < mono_array_length (permissions); ++i) {
1159 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1161 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1163 idx = mono_metadata_token_index (parent_token);
1164 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1165 switch (mono_metadata_token_table (parent_token)) {
1166 case MONO_TABLE_TYPEDEF:
1167 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1169 case MONO_TABLE_METHOD:
1170 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1172 case MONO_TABLE_ASSEMBLY:
1173 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1176 g_assert_not_reached ();
1179 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1180 values [MONO_DECL_SECURITY_PARENT] = idx;
1181 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1188 * Fill in the MethodDef and ParamDef tables for a method.
1189 * This is used for both normal methods and constructors.
1192 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1194 MonoDynamicTable *table;
1199 /* room in this table is already allocated */
1200 table = &assembly->tables [MONO_TABLE_METHOD];
1201 *mb->table_idx = table->next_idx ++;
1202 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1203 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1204 name = mono_string_to_utf8 (mb->name);
1205 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1207 values [MONO_METHOD_FLAGS] = mb->attrs;
1208 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1209 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1210 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1212 table = &assembly->tables [MONO_TABLE_PARAM];
1213 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1215 mono_image_add_decl_security (assembly,
1216 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1219 MonoDynamicTable *mtable;
1222 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1223 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1226 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1227 if (mono_array_get (mb->pinfo, gpointer, i))
1230 table->rows += count;
1231 alloc_table (table, table->rows);
1232 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1233 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1234 MonoReflectionParamBuilder *pb;
1235 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1236 values [MONO_PARAM_FLAGS] = pb->attrs;
1237 values [MONO_PARAM_SEQUENCE] = i;
1238 if (pb->name != NULL) {
1239 name = mono_string_to_utf8 (pb->name);
1240 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1243 values [MONO_PARAM_NAME] = 0;
1245 values += MONO_PARAM_SIZE;
1246 if (pb->marshal_info) {
1248 alloc_table (mtable, mtable->rows);
1249 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1250 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1251 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1253 pb->table_idx = table->next_idx++;
1254 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1255 guint32 field_type = 0;
1256 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1258 alloc_table (mtable, mtable->rows);
1259 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1260 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1261 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1262 mvalues [MONO_CONSTANT_TYPE] = field_type;
1263 mvalues [MONO_CONSTANT_PADDING] = 0;
1271 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1273 rmb->ilgen = mb->ilgen;
1274 rmb->rtype = mb->rtype;
1275 rmb->parameters = mb->parameters;
1276 rmb->generic_params = mb->generic_params;
1277 rmb->generic_container = mb->generic_container;
1278 rmb->opt_types = NULL;
1279 rmb->pinfo = mb->pinfo;
1280 rmb->attrs = mb->attrs;
1281 rmb->iattrs = mb->iattrs;
1282 rmb->call_conv = mb->call_conv;
1283 rmb->code = mb->code;
1284 rmb->type = mb->type;
1285 rmb->name = mb->name;
1286 rmb->table_idx = &mb->table_idx;
1287 rmb->init_locals = mb->init_locals;
1288 rmb->return_modreq = mb->return_modreq;
1289 rmb->return_modopt = mb->return_modopt;
1290 rmb->param_modreq = mb->param_modreq;
1291 rmb->param_modopt = mb->param_modopt;
1292 rmb->permissions = mb->permissions;
1293 rmb->mhandle = mb->mhandle;
1298 rmb->charset = mb->charset;
1299 rmb->extra_flags = mb->extra_flags;
1300 rmb->native_cc = mb->native_cc;
1301 rmb->dllentry = mb->dllentry;
1307 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1309 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1311 rmb->ilgen = mb->ilgen;
1312 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1313 rmb->parameters = mb->parameters;
1314 rmb->generic_params = NULL;
1315 rmb->generic_container = NULL;
1316 rmb->opt_types = NULL;
1317 rmb->pinfo = mb->pinfo;
1318 rmb->attrs = mb->attrs;
1319 rmb->iattrs = mb->iattrs;
1320 rmb->call_conv = mb->call_conv;
1322 rmb->type = mb->type;
1323 rmb->name = mono_string_new (mono_domain_get (), name);
1324 rmb->table_idx = &mb->table_idx;
1325 rmb->init_locals = mb->init_locals;
1326 rmb->return_modreq = NULL;
1327 rmb->return_modopt = NULL;
1328 rmb->param_modreq = mb->param_modreq;
1329 rmb->param_modopt = mb->param_modopt;
1330 rmb->permissions = mb->permissions;
1331 rmb->mhandle = mb->mhandle;
1337 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1339 rmb->ilgen = mb->ilgen;
1340 rmb->rtype = mb->rtype;
1341 rmb->parameters = mb->parameters;
1342 rmb->generic_params = NULL;
1343 rmb->generic_container = NULL;
1344 rmb->opt_types = NULL;
1346 rmb->attrs = mb->attrs;
1348 rmb->call_conv = mb->call_conv;
1351 rmb->name = mb->name;
1352 rmb->table_idx = NULL;
1353 rmb->init_locals = mb->init_locals;
1354 rmb->return_modreq = NULL;
1355 rmb->return_modopt = NULL;
1356 rmb->param_modreq = NULL;
1357 rmb->param_modopt = NULL;
1358 rmb->permissions = NULL;
1359 rmb->mhandle = mb->mhandle;
1365 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1367 MonoDynamicTable *table;
1370 ReflectionMethodBuilder rmb;
1373 reflection_methodbuilder_from_method_builder (&rmb, mb);
1375 mono_image_basic_method (&rmb, assembly);
1376 mb->table_idx = *rmb.table_idx;
1378 if (mb->dll) { /* It's a P/Invoke method */
1380 /* map CharSet values to on-disk values */
1381 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1382 int extra_flags = mb->extra_flags;
1383 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1385 alloc_table (table, table->rows);
1386 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1388 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1389 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1391 name = mono_string_to_utf8 (mb->dllentry);
1393 name = mono_string_to_utf8 (mb->name);
1394 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1396 name = mono_string_to_utf8 (mb->dll);
1397 moduleref = string_heap_insert (&assembly->sheap, name);
1399 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1400 table = &assembly->tables [MONO_TABLE_MODULEREF];
1402 alloc_table (table, table->rows);
1403 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1404 values [MONO_IMPLMAP_SCOPE] = table->rows;
1408 if (mb->override_method) {
1409 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1411 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1413 alloc_table (table, table->rows);
1414 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1415 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1416 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1418 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1419 switch (mono_metadata_token_table (tok)) {
1420 case MONO_TABLE_MEMBERREF:
1421 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1423 case MONO_TABLE_METHOD:
1424 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1427 g_assert_not_reached ();
1429 values [MONO_METHODIMPL_DECLARATION] = tok;
1432 if (mb->generic_params) {
1433 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1434 table->rows += mono_array_length (mb->generic_params);
1435 alloc_table (table, table->rows);
1436 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1437 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1439 mono_image_get_generic_param_info (
1440 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1447 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1449 ReflectionMethodBuilder rmb;
1451 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1453 mono_image_basic_method (&rmb, assembly);
1454 mb->table_idx = *rmb.table_idx;
1458 type_get_fully_qualified_name (MonoType *type)
1460 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1464 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1468 klass = my_mono_class_from_mono_type (type);
1470 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1471 ta = klass->image->assembly;
1472 if (ta->dynamic || (ta == ass))
1473 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1475 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1479 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1481 char blob_size [64];
1482 char *b = blob_size;
1487 if (!assembly->save)
1490 p = buf = g_malloc (64);
1492 mono_metadata_encode_value (0x06, p, &p);
1493 /* encode custom attributes before the type */
1494 encode_type (assembly, type, p, &p);
1495 g_assert (p-buf < 64);
1496 mono_metadata_encode_value (p-buf, b, &b);
1497 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1503 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1505 char blob_size [64];
1506 char *b = blob_size;
1511 p = buf = g_malloc (256);
1513 mono_metadata_encode_value (0x06, p, &p);
1514 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1515 /* encode custom attributes before the type */
1516 encode_reflection_type (assembly, fb->type, p, &p);
1517 g_assert (p-buf < 256);
1518 mono_metadata_encode_value (p-buf, b, &b);
1519 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1525 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1526 char blob_size [64];
1527 char *b = blob_size;
1530 guint32 idx = 0, len = 0, dummy = 0;
1532 p = buf = g_malloc (64);
1534 *ret_type = MONO_TYPE_CLASS;
1536 box_val = (char*)&dummy;
1538 box_val = ((char*)val) + sizeof (MonoObject);
1539 *ret_type = val->vtable->klass->byval_arg.type;
1542 switch (*ret_type) {
1543 case MONO_TYPE_BOOLEAN:
1548 case MONO_TYPE_CHAR:
1563 case MONO_TYPE_VALUETYPE:
1564 if (val->vtable->klass->enumtype) {
1565 *ret_type = val->vtable->klass->enum_basetype->type;
1568 g_error ("we can't encode valuetypes");
1569 case MONO_TYPE_CLASS:
1571 case MONO_TYPE_STRING: {
1572 MonoString *str = (MonoString*)val;
1573 /* there is no signature */
1574 len = str->length * 2;
1575 mono_metadata_encode_value (len, b, &b);
1576 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1578 char *swapped = g_malloc (2 * mono_string_length (str));
1579 const char *p = (const char*)mono_string_chars (str);
1581 swap_with_size (swapped, p, 2, mono_string_length (str));
1582 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1586 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1593 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1596 /* there is no signature */
1597 mono_metadata_encode_value (len, b, &b);
1598 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1599 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1600 swap_with_size (blob_size, box_val, len, 1);
1601 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1603 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1611 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1612 char blob_size [64];
1613 char *b = blob_size;
1614 char *p, *buf, *str;
1615 guint32 idx, len, bufsize = 256;
1617 p = buf = g_malloc (bufsize);
1619 mono_metadata_encode_value (minfo->type, p, &p);
1621 switch (minfo->type) {
1622 case MONO_NATIVE_BYVALTSTR:
1623 case MONO_NATIVE_BYVALARRAY:
1624 mono_metadata_encode_value (minfo->count, p, &p);
1626 case MONO_NATIVE_LPARRAY:
1627 if (minfo->eltype || minfo->has_size) {
1628 mono_metadata_encode_value (minfo->eltype, p, &p);
1629 if (minfo->has_size) {
1630 if (minfo->param_num != -1)
1631 mono_metadata_encode_value (minfo->param_num, p, &p);
1633 mono_metadata_encode_value (0, p, &p);
1634 if (minfo->count != -1)
1635 mono_metadata_encode_value (minfo->count, p, &p);
1637 mono_metadata_encode_value (0, p, &p);
1639 /* LAMESPEC: ElemMult is undocumented */
1640 if (minfo->param_num != -1)
1641 mono_metadata_encode_value (1, p, &p);
1643 mono_metadata_encode_value (0, p, &p);
1647 case MONO_NATIVE_CUSTOM:
1649 str = mono_string_to_utf8 (minfo->guid);
1651 mono_metadata_encode_value (len, p, &p);
1652 memcpy (p, str, len);
1656 mono_metadata_encode_value (0, p, &p);
1658 if (minfo->marshaltype) {
1659 str = mono_string_to_utf8 (minfo->marshaltype);
1661 mono_metadata_encode_value (len, p, &p);
1662 if (p + len >= buf + bufsize) {
1665 buf = g_realloc (buf, bufsize);
1668 memcpy (p, str, len);
1672 mono_metadata_encode_value (0, p, &p);
1674 if (minfo->marshaltyperef) {
1675 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1677 mono_metadata_encode_value (len, p, &p);
1678 if (p + len >= buf + bufsize) {
1681 buf = g_realloc (buf, bufsize);
1684 memcpy (p, str, len);
1688 mono_metadata_encode_value (0, p, &p);
1690 if (minfo->mcookie) {
1691 str = mono_string_to_utf8 (minfo->mcookie);
1693 mono_metadata_encode_value (len, p, &p);
1694 if (p + len >= buf + bufsize) {
1697 buf = g_realloc (buf, bufsize);
1700 memcpy (p, str, len);
1704 mono_metadata_encode_value (0, p, &p);
1711 mono_metadata_encode_value (len, b, &b);
1712 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1718 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1720 MonoDynamicTable *table;
1724 /* maybe this fixup should be done in the C# code */
1725 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1726 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1727 table = &assembly->tables [MONO_TABLE_FIELD];
1728 fb->table_idx = table->next_idx ++;
1729 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1730 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1731 name = mono_string_to_utf8 (fb->name);
1732 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1734 values [MONO_FIELD_FLAGS] = fb->attrs;
1735 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1737 if (fb->offset != -1) {
1738 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1740 alloc_table (table, table->rows);
1741 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1742 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1743 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1745 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1746 guint32 field_type = 0;
1747 table = &assembly->tables [MONO_TABLE_CONSTANT];
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1751 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1752 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1753 values [MONO_CONSTANT_TYPE] = field_type;
1754 values [MONO_CONSTANT_PADDING] = 0;
1756 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1758 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1760 alloc_table (table, table->rows);
1761 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1762 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1764 * We store it in the code section because it's simpler for now.
1767 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1769 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1770 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1772 if (fb->marshal_info) {
1773 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1775 alloc_table (table, table->rows);
1776 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1777 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1778 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1783 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1787 char *b = blob_size;
1788 guint32 nparams = 0;
1789 MonoReflectionMethodBuilder *mb = fb->get_method;
1790 MonoReflectionMethodBuilder *smb = fb->set_method;
1791 guint32 idx, i, size;
1793 if (mb && mb->parameters)
1794 nparams = mono_array_length (mb->parameters);
1795 if (!mb && smb && smb->parameters)
1796 nparams = mono_array_length (smb->parameters) - 1;
1797 size = 24 + nparams * 10;
1798 buf = p = g_malloc (size);
1801 mono_metadata_encode_value (nparams, p, &p);
1803 encode_reflection_type (assembly, mb->rtype, p, &p);
1804 for (i = 0; i < nparams; ++i) {
1805 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1806 encode_reflection_type (assembly, pt, p, &p);
1809 /* the property type is the last param */
1810 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1811 for (i = 0; i < nparams; ++i) {
1812 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1813 encode_reflection_type (assembly, pt, p, &p);
1817 encode_reflection_type (assembly, fb->type, p, &p);
1821 g_assert (p - buf < size);
1822 mono_metadata_encode_value (p-buf, b, &b);
1823 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1829 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1831 MonoDynamicTable *table;
1834 guint num_methods = 0;
1838 * we need to set things in the following tables:
1839 * PROPERTYMAP (info already filled in _get_type_info ())
1840 * PROPERTY (rows already preallocated in _get_type_info ())
1841 * METHOD (method info already done with the generic method code)
1844 table = &assembly->tables [MONO_TABLE_PROPERTY];
1845 pb->table_idx = table->next_idx ++;
1846 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1847 name = mono_string_to_utf8 (pb->name);
1848 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1850 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1851 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1853 /* FIXME: we still don't handle 'other' methods */
1854 if (pb->get_method) num_methods ++;
1855 if (pb->set_method) num_methods ++;
1857 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1858 table->rows += num_methods;
1859 alloc_table (table, table->rows);
1861 if (pb->get_method) {
1862 semaidx = table->next_idx ++;
1863 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1864 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1865 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1866 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1868 if (pb->set_method) {
1869 semaidx = table->next_idx ++;
1870 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1871 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1872 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1873 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1878 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1880 MonoDynamicTable *table;
1883 guint num_methods = 0;
1887 * we need to set things in the following tables:
1888 * EVENTMAP (info already filled in _get_type_info ())
1889 * EVENT (rows already preallocated in _get_type_info ())
1890 * METHOD (method info already done with the generic method code)
1893 table = &assembly->tables [MONO_TABLE_EVENT];
1894 eb->table_idx = table->next_idx ++;
1895 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1896 name = mono_string_to_utf8 (eb->name);
1897 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1899 values [MONO_EVENT_FLAGS] = eb->attrs;
1900 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1903 * FIXME: we still don't handle 'other' methods
1905 if (eb->add_method) num_methods ++;
1906 if (eb->remove_method) num_methods ++;
1907 if (eb->raise_method) num_methods ++;
1909 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1910 table->rows += num_methods;
1911 alloc_table (table, table->rows);
1913 if (eb->add_method) {
1914 semaidx = table->next_idx ++;
1915 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1916 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1917 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1918 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1920 if (eb->remove_method) {
1921 semaidx = table->next_idx ++;
1922 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1923 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1924 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1925 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1927 if (eb->raise_method) {
1928 semaidx = table->next_idx ++;
1929 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1930 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1931 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1932 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1937 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1939 static MonoClass *NewConstraintAttr;
1940 static MonoMethod *NewConstraintAttr_ctor;
1941 MonoDynamicTable *table;
1943 guint32 token, type;
1944 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1947 if (!NewConstraintAttr)
1948 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1949 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1950 g_assert (NewConstraintAttr);
1952 if (!NewConstraintAttr_ctor) {
1953 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1954 g_assert (NewConstraintAttr_ctor);
1957 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1959 alloc_table (table, table->rows);
1961 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1962 owner <<= MONO_CUSTOM_ATTR_BITS;
1963 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1964 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1966 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1968 type = mono_metadata_token_index (token);
1969 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1970 switch (mono_metadata_token_table (token)) {
1971 case MONO_TABLE_METHOD:
1972 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1974 case MONO_TABLE_MEMBERREF:
1975 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1978 g_warning ("got wrong token in custom attr");
1981 values [MONO_CUSTOM_ATTR_TYPE] = type;
1983 buf = p = g_malloc (1);
1984 mono_metadata_encode_value (4, p, &p);
1985 g_assert (p-buf == 1);
1987 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1989 values += MONO_CUSTOM_ATTR_SIZE;
1994 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1996 MonoDynamicTable *table;
1997 guint32 num_constraints, i;
2001 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2002 num_constraints = gparam->iface_constraints ?
2003 mono_array_length (gparam->iface_constraints) : 0;
2004 table->rows += num_constraints;
2005 if (gparam->base_type)
2007 alloc_table (table, table->rows);
2009 if (gparam->base_type) {
2010 table_idx = table->next_idx ++;
2011 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2013 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2014 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2015 assembly, gparam->base_type->type);
2018 for (i = 0; i < num_constraints; i++) {
2019 MonoReflectionType *constraint = mono_array_get (
2020 gparam->iface_constraints, gpointer, i);
2022 table_idx = table->next_idx ++;
2023 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2025 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2026 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2027 assembly, constraint->type);
2030 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2031 encode_new_constraint (assembly, owner);
2035 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2037 GenericParamTableEntry *entry;
2040 * The GenericParam table must be sorted according to the `owner' field.
2041 * We need to do this sorting prior to writing the GenericParamConstraint
2042 * table, since we have to use the final GenericParam table indices there
2043 * and they must also be sorted.
2046 entry = g_new0 (GenericParamTableEntry, 1);
2047 entry->owner = owner;
2048 entry->gparam = gparam;
2050 g_ptr_array_add (assembly->gen_params, entry);
2054 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2056 MonoDynamicTable *table;
2057 MonoGenericParam *param;
2061 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2062 table_idx = table->next_idx ++;
2063 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2065 param = entry->gparam->type.type->data.generic_param;
2067 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2068 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2069 values [MONO_GENERICPARAM_NUMBER] = param->num;
2070 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2072 encode_constraints (entry->gparam, table_idx, assembly);
2076 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2078 MonoDynamicTable *table;
2081 guint32 cols [MONO_ASSEMBLY_SIZE];
2085 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2088 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2089 table = &assembly->tables [MONO_TABLE_MODULEREF];
2090 token = table->next_idx ++;
2092 alloc_table (table, table->rows);
2093 values = table->values + token * MONO_MODULEREF_SIZE;
2094 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2096 token <<= MONO_RESOLTION_SCOPE_BITS;
2097 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2098 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2103 if (image->assembly->dynamic)
2105 memset (cols, 0, sizeof (cols));
2107 /* image->assembly->image is the manifest module */
2108 image = image->assembly->image;
2109 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2112 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2113 token = table->next_idx ++;
2115 alloc_table (table, table->rows);
2116 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2117 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2118 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2119 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2120 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2121 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2122 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2123 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2124 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2126 if (strcmp ("", image->assembly->aname.culture)) {
2127 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2128 image->assembly->aname.culture);
2131 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2132 guchar pubtoken [9];
2134 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2135 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2137 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2139 token <<= MONO_RESOLTION_SCOPE_BITS;
2140 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2141 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2146 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2148 MonoDynamicTable *table;
2154 char *b = blob_size;
2156 switch (type->type) {
2157 case MONO_TYPE_FNPTR:
2159 case MONO_TYPE_SZARRAY:
2160 case MONO_TYPE_ARRAY:
2162 case MONO_TYPE_MVAR:
2163 case MONO_TYPE_GENERICINST:
2164 encode_type (assembly, type, p, &p);
2166 case MONO_TYPE_CLASS:
2167 case MONO_TYPE_VALUETYPE: {
2168 MonoClass *k = mono_class_from_mono_type (type);
2169 if (!k || !k->generic_class)
2171 encode_generic_class (assembly, k->generic_class, p, &p);
2178 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2179 if (assembly->save) {
2180 g_assert (p-sig < 128);
2181 mono_metadata_encode_value (p-sig, b, &b);
2182 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2183 alloc_table (table, table->rows + 1);
2184 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2185 values [MONO_TYPESPEC_SIGNATURE] = token;
2188 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2189 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2195 * Despite the name, we handle also TypeSpec (with the above helper).
2198 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2200 MonoDynamicTable *table;
2202 guint32 token, scope, enclosing;
2205 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2208 token = create_typespec (assembly, type);
2211 klass = my_mono_class_from_mono_type (type);
2213 klass = mono_class_from_mono_type (type);
2216 * If it's in the same module and not a generic type parameter:
2218 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2219 (type->type != MONO_TYPE_MVAR)) {
2220 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2221 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2222 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2226 if (klass->nested_in) {
2227 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2228 /* get the typeref idx of the enclosing type */
2229 enclosing >>= MONO_TYPEDEFORREF_BITS;
2230 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2232 scope = resolution_scope_from_image (assembly, klass->image);
2234 table = &assembly->tables [MONO_TABLE_TYPEREF];
2235 if (assembly->save) {
2236 alloc_table (table, table->rows + 1);
2237 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2238 values [MONO_TYPEREF_SCOPE] = scope;
2239 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2240 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2242 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2243 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2245 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2250 * Insert a memberef row into the metadata: the token that point to the memberref
2251 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2252 * mono_image_get_fieldref_token()).
2253 * The sig param is an index to an already built signature.
2256 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2258 MonoDynamicTable *table;
2260 guint32 token, pclass;
2263 parent = mono_image_typedef_or_ref (assembly, type);
2264 switch (parent & MONO_TYPEDEFORREF_MASK) {
2265 case MONO_TYPEDEFORREF_TYPEREF:
2266 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2268 case MONO_TYPEDEFORREF_TYPESPEC:
2269 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2271 case MONO_TYPEDEFORREF_TYPEDEF:
2272 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2275 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2278 /* extract the index */
2279 parent >>= MONO_TYPEDEFORREF_BITS;
2281 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2283 if (assembly->save) {
2284 alloc_table (table, table->rows + 1);
2285 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2286 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2287 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2288 values [MONO_MEMBERREF_SIGNATURE] = sig;
2291 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2298 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2301 MonoMethodSignature *sig;
2303 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2308 * A methodref signature can't contain an unmanaged calling convention.
2310 sig = mono_metadata_signature_dup (mono_method_signature (method));
2311 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2312 sig->call_convention = MONO_CALL_DEFAULT;
2313 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2314 method->name, method_encode_signature (assembly, sig));
2316 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2321 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2322 const gchar *name, guint32 sig)
2324 MonoDynamicTable *table;
2328 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2330 if (assembly->save) {
2331 alloc_table (table, table->rows + 1);
2332 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2333 values [MONO_MEMBERREF_CLASS] = original;
2334 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2335 values [MONO_MEMBERREF_SIGNATURE] = sig;
2338 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2345 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2348 ReflectionMethodBuilder rmb;
2350 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2354 reflection_methodbuilder_from_method_builder (&rmb, mb);
2356 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2357 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2358 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2363 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2366 ReflectionMethodBuilder rmb;
2368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2372 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2374 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2375 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2376 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2381 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2386 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2389 g_assert (f->field->parent);
2390 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2391 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2392 f->field->name, fieldref_encode_signature (assembly, type));
2393 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2398 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2403 guint32 nparams = gmethod->inst->type_argc;
2404 guint32 size = 10 + nparams * 30;
2407 char *b = blob_size;
2409 if (!assembly->save)
2412 p = buf = g_malloc (size);
2414 * FIXME: vararg, explicit_this, differenc call_conv values...
2416 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2417 mono_metadata_encode_value (nparams, p, &p);
2419 for (i = 0; i < nparams; i++)
2420 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2423 g_assert (p - buf < size);
2424 mono_metadata_encode_value (p-buf, b, &b);
2425 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2431 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2433 MonoDynamicTable *table;
2435 guint32 token, mtoken = 0, sig;
2436 MonoMethodInflated *imethod;
2437 MonoMethod *declaring;
2439 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2441 g_assert (method->is_inflated);
2442 method = mono_get_inflated_method (method);
2443 imethod = (MonoMethodInflated *) method;
2444 declaring = imethod->declaring;
2446 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2447 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2449 if (!mono_method_signature (declaring)->generic_param_count)
2452 switch (mono_metadata_token_table (mtoken)) {
2453 case MONO_TABLE_MEMBERREF:
2454 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2456 case MONO_TABLE_METHOD:
2457 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2460 g_assert_not_reached ();
2463 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2465 if (assembly->save) {
2466 alloc_table (table, table->rows + 1);
2467 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2468 values [MONO_METHODSPEC_METHOD] = mtoken;
2469 values [MONO_METHODSPEC_SIGNATURE] = sig;
2472 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2479 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2481 MonoMethodInflated *imethod;
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2488 g_assert (m->is_inflated);
2489 m = mono_get_inflated_method (m);
2490 imethod = (MonoMethodInflated *) m;
2492 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2493 token = method_encode_methodspec (assembly, m);
2495 guint32 sig = method_encode_signature (
2496 assembly, mono_method_signature (imethod->declaring));
2497 token = mono_image_get_memberref_token (
2498 assembly, &m->klass->byval_arg, m->name, sig);
2501 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2506 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2508 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2511 m = mono_get_inflated_method (m);
2513 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2514 token = mono_image_get_memberref_token (
2515 assembly, &m->klass->byval_arg, m->name, sig);
2521 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2523 MonoDynamicTable *table;
2530 char *b = blob_size;
2534 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2535 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2536 * Because of this, we must not insert it into the `typeref' hash table.
2539 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2543 g_assert (tb->generic_params);
2544 klass = mono_class_from_mono_type (tb->type.type);
2546 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2547 encode_type (assembly, &klass->byval_arg, p, &p);
2549 count = mono_array_length (tb->generic_params);
2550 mono_metadata_encode_value (count, p, &p);
2551 for (i = 0; i < count; i++) {
2552 MonoReflectionGenericParam *gparam;
2554 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2556 encode_type (assembly, gparam->type.type, p, &p);
2559 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2560 g_assert (p-sig < 128);
2562 if (assembly->save) {
2563 mono_metadata_encode_value (p-sig, b, &b);
2564 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2567 values [MONO_TYPESPEC_SIGNATURE] = token;
2570 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2571 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2577 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2579 MonoDynamicTable *table;
2582 guint32 token, pclass, parent, sig;
2585 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2589 klass = mono_class_from_mono_type (fb->typeb->type);
2590 name = mono_string_to_utf8 (fb->name);
2592 sig = fieldref_encode_signature (assembly, fb->type->type);
2594 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2595 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2597 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2598 parent >>= MONO_TYPEDEFORREF_BITS;
2600 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2602 if (assembly->save) {
2603 alloc_table (table, table->rows + 1);
2604 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2605 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2606 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2607 values [MONO_MEMBERREF_SIGNATURE] = sig;
2610 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2612 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2617 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2625 char *b = blob_size;
2627 if (!assembly->save)
2631 g_assert (helper->type == 2);
2633 if (helper->arguments)
2634 nargs = mono_array_length (helper->arguments);
2638 size = 10 + (nargs * 10);
2640 p = buf = g_malloc (size);
2642 /* Encode calling convention */
2643 /* Change Any to Standard */
2644 if ((helper->call_conv & 0x03) == 0x03)
2645 helper->call_conv = 0x01;
2646 /* explicit_this implies has_this */
2647 if (helper->call_conv & 0x40)
2648 helper->call_conv &= 0x20;
2650 if (helper->call_conv == 0) { /* Unmanaged */
2651 *p = helper->unmanaged_call_conv - 1;
2654 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2655 if (helper->call_conv & 0x02) /* varargs */
2660 mono_metadata_encode_value (nargs, p, &p);
2661 encode_reflection_type (assembly, helper->return_type, p, &p);
2662 for (i = 0; i < nargs; ++i) {
2663 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2664 encode_reflection_type (assembly, pt, p, &p);
2667 g_assert (p - buf < size);
2668 mono_metadata_encode_value (p-buf, b, &b);
2669 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2676 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2679 MonoDynamicTable *table;
2682 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2683 idx = table->next_idx ++;
2685 alloc_table (table, table->rows);
2686 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2688 values [MONO_STAND_ALONE_SIGNATURE] =
2689 mono_reflection_encode_sighelper (assembly, helper);
2695 reflection_cc_to_file (int call_conv) {
2696 switch (call_conv & 0x3) {
2698 case 1: return MONO_CALL_DEFAULT;
2699 case 2: return MONO_CALL_VARARG;
2701 g_assert_not_reached ();
2708 MonoMethodSignature *sig;
2714 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2719 MonoMethodSignature *sig;
2722 name = mono_string_to_utf8 (m->name);
2723 nparams = mono_array_length (m->parameters);
2724 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2726 sig->sentinelpos = -1;
2727 sig->call_convention = reflection_cc_to_file (m->call_conv);
2728 sig->param_count = nparams;
2729 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2730 for (i = 0; i < nparams; ++i) {
2731 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2732 sig->params [i] = t->type;
2735 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2737 if (strcmp (name, am->name) == 0 &&
2738 mono_metadata_type_equal (am->parent, m->parent->type) &&
2739 mono_metadata_signature_equal (am->sig, sig)) {
2742 m->table_idx = am->token & 0xffffff;
2746 am = g_new0 (ArrayMethod, 1);
2749 am->parent = m->parent->type;
2750 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2751 method_encode_signature (assembly, sig));
2752 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2753 m->table_idx = am->token & 0xffffff;
2758 * Insert into the metadata tables all the info about the TypeBuilder tb.
2759 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2762 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2764 MonoDynamicTable *table;
2766 int i, is_object = 0, is_system = 0;
2769 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2770 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2771 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2772 n = mono_string_to_utf8 (tb->name);
2773 if (strcmp (n, "Object") == 0)
2775 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2777 n = mono_string_to_utf8 (tb->nspace);
2778 if (strcmp (n, "System") == 0)
2780 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2782 if (tb->parent && !(is_system && is_object) &&
2783 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2784 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2786 values [MONO_TYPEDEF_EXTENDS] = 0;
2788 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2789 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2792 * if we have explicitlayout or sequentiallayouts, output data in the
2793 * ClassLayout table.
2795 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2796 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2797 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2799 alloc_table (table, table->rows);
2800 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2801 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2802 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2803 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2806 /* handle interfaces */
2807 if (tb->interfaces) {
2808 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2810 table->rows += mono_array_length (tb->interfaces);
2811 alloc_table (table, table->rows);
2812 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2813 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2814 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2815 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2816 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2817 values += MONO_INTERFACEIMPL_SIZE;
2823 table = &assembly->tables [MONO_TABLE_FIELD];
2824 table->rows += tb->num_fields;
2825 alloc_table (table, table->rows);
2826 for (i = 0; i < tb->num_fields; ++i)
2827 mono_image_get_field_info (
2828 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2831 /* handle constructors */
2833 table = &assembly->tables [MONO_TABLE_METHOD];
2834 table->rows += mono_array_length (tb->ctors);
2835 alloc_table (table, table->rows);
2836 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2837 mono_image_get_ctor_info (domain,
2838 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2841 /* handle methods */
2843 table = &assembly->tables [MONO_TABLE_METHOD];
2844 table->rows += tb->num_methods;
2845 alloc_table (table, table->rows);
2846 for (i = 0; i < tb->num_methods; ++i)
2847 mono_image_get_method_info (
2848 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2851 /* Do the same with properties etc.. */
2852 if (tb->events && mono_array_length (tb->events)) {
2853 table = &assembly->tables [MONO_TABLE_EVENT];
2854 table->rows += mono_array_length (tb->events);
2855 alloc_table (table, table->rows);
2856 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2858 alloc_table (table, table->rows);
2859 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2860 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2861 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2862 for (i = 0; i < mono_array_length (tb->events); ++i)
2863 mono_image_get_event_info (
2864 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2866 if (tb->properties && mono_array_length (tb->properties)) {
2867 table = &assembly->tables [MONO_TABLE_PROPERTY];
2868 table->rows += mono_array_length (tb->properties);
2869 alloc_table (table, table->rows);
2870 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2872 alloc_table (table, table->rows);
2873 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2874 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2875 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2876 for (i = 0; i < mono_array_length (tb->properties); ++i)
2877 mono_image_get_property_info (
2878 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2881 /* handle generic parameters */
2882 if (tb->generic_params) {
2883 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2884 table->rows += mono_array_length (tb->generic_params);
2885 alloc_table (table, table->rows);
2886 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2887 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2889 mono_image_get_generic_param_info (
2890 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2894 mono_image_add_decl_security (assembly,
2895 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2898 MonoDynamicTable *ntable;
2900 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2901 ntable->rows += mono_array_length (tb->subtypes);
2902 alloc_table (ntable, ntable->rows);
2903 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2905 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2906 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2908 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2909 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2910 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2911 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2912 mono_string_to_utf8 (tb->name), tb->table_idx,
2913 ntable->next_idx, ntable->rows);*/
2914 values += MONO_NESTED_CLASS_SIZE;
2921 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2925 g_ptr_array_add (types, type);
2927 if (!type->subtypes)
2930 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2932 collect_types (types, subtype);
2937 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2939 if ((*type1)->table_idx < (*type2)->table_idx)
2942 if ((*type1)->table_idx > (*type2)->table_idx)
2949 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2954 for (i = 0; i < mono_array_length (pinfo); ++i) {
2955 MonoReflectionParamBuilder *pb;
2956 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2959 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2964 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2967 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2969 for (i = 0; i < tb->num_fields; ++i) {
2970 MonoReflectionFieldBuilder* fb;
2971 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2972 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2976 for (i = 0; i < mono_array_length (tb->events); ++i) {
2977 MonoReflectionEventBuilder* eb;
2978 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2979 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2982 if (tb->properties) {
2983 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2984 MonoReflectionPropertyBuilder* pb;
2985 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2986 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2990 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2991 MonoReflectionCtorBuilder* cb;
2992 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2993 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2994 params_add_cattrs (assembly, cb->pinfo);
2999 for (i = 0; i < tb->num_methods; ++i) {
3000 MonoReflectionMethodBuilder* mb;
3001 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3002 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3003 params_add_cattrs (assembly, mb->pinfo);
3008 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3009 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3014 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3017 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3019 /* no types in the module */
3023 for (i = 0; i < mb->num_types; ++i)
3024 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3028 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3030 MonoDynamicTable *table;
3034 char *b = blob_size;
3037 table = &assembly->tables [MONO_TABLE_FILE];
3039 alloc_table (table, table->rows);
3040 values = table->values + table->next_idx * MONO_FILE_SIZE;
3041 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3042 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3043 if (module->image->dynamic) {
3044 /* This depends on the fact that the main module is emitted last */
3045 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3046 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3049 path = g_strdup (module->image->name);
3051 mono_sha1_get_digest_from_file (path, hash);
3054 mono_metadata_encode_value (20, b, &b);
3055 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3056 mono_image_add_stream_data (&assembly->blob, hash, 20);
3061 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3063 MonoDynamicTable *table;
3067 table = &assembly->tables [MONO_TABLE_MODULE];
3068 mb->table_idx = table->next_idx ++;
3069 name = mono_string_to_utf8 (mb->module.name);
3070 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3072 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3075 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3076 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3077 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3082 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3083 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3085 MonoDynamicTable *table;
3089 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3090 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3093 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3095 alloc_table (table, table->rows);
3096 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3098 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3099 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3100 if (klass->nested_in)
3101 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3103 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3104 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3105 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3107 res = table->next_idx;
3111 /* Emit nested types */
3112 if (klass->nested_classes) {
3115 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3116 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3123 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3124 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3129 klass = mono_class_from_mono_type (tb->type.type);
3131 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3133 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3134 parent_index, assembly);
3138 * We need to do this ourselves since klass->nested_classes is not set up.
3141 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3142 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3147 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3148 guint32 module_index, MonoDynamicImage *assembly)
3150 MonoImage *image = module->image;
3154 t = &image->tables [MONO_TABLE_TYPEDEF];
3156 for (i = 0; i < t->rows; ++i) {
3157 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3159 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3160 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3164 #define align_pointer(base,p)\
3166 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3168 (p) += 4 - (__diff & 3);\
3172 compare_constants (const void *a, const void *b)
3174 const guint32 *a_values = a;
3175 const guint32 *b_values = b;
3176 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3180 compare_semantics (const void *a, const void *b)
3182 const guint32 *a_values = a;
3183 const guint32 *b_values = b;
3184 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3187 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3191 compare_custom_attrs (const void *a, const void *b)
3193 const guint32 *a_values = a;
3194 const guint32 *b_values = b;
3196 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3200 compare_field_marshal (const void *a, const void *b)
3202 const guint32 *a_values = a;
3203 const guint32 *b_values = b;
3205 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3209 compare_nested (const void *a, const void *b)
3211 const guint32 *a_values = a;
3212 const guint32 *b_values = b;
3214 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3218 compare_genericparam (const void *a, const void *b)
3220 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3221 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3223 if ((*b_entry)->owner == (*a_entry)->owner)
3225 (*a_entry)->gparam->type.type->data.generic_param->num -
3226 (*b_entry)->gparam->type.type->data.generic_param->num;
3228 return (*a_entry)->owner - (*b_entry)->owner;
3232 compare_declsecurity_attrs (const void *a, const void *b)
3234 const guint32 *a_values = a;
3235 const guint32 *b_values = b;
3237 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3241 pad_heap (MonoDynamicStream *sh)
3243 if (sh->index & 3) {
3244 int sz = 4 - (sh->index & 3);
3245 memset (sh->data + sh->index, 0, sz);
3252 MonoDynamicStream *stream;
3256 * build_compressed_metadata() fills in the blob of data that represents the
3257 * raw metadata as it will be saved in the PE file. The five streams are output
3258 * and the metadata tables are comnpressed from the guint32 array representation,
3259 * to the compressed on-disk format.
3262 build_compressed_metadata (MonoDynamicImage *assembly)
3264 MonoDynamicTable *table;
3266 guint64 valid_mask = 0;
3267 guint64 sorted_mask;
3268 guint32 heapt_size = 0;
3269 guint32 meta_size = 256; /* allow for header and other stuff */
3270 guint32 table_offset;
3271 guint32 ntables = 0;
3277 struct StreamDesc stream_desc [5];
3279 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3280 for (i = 0; i < assembly->gen_params->len; i++){
3281 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3282 write_generic_param_entry (assembly, entry);
3285 stream_desc [0].name = "#~";
3286 stream_desc [0].stream = &assembly->tstream;
3287 stream_desc [1].name = "#Strings";
3288 stream_desc [1].stream = &assembly->sheap;
3289 stream_desc [2].name = "#US";
3290 stream_desc [2].stream = &assembly->us;
3291 stream_desc [3].name = "#Blob";
3292 stream_desc [3].stream = &assembly->blob;
3293 stream_desc [4].name = "#GUID";
3294 stream_desc [4].stream = &assembly->guid;
3296 /* tables that are sorted */
3297 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3298 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3299 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3300 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3301 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3302 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3304 /* Compute table sizes */
3305 /* the MonoImage has already been created in mono_image_basic_init() */
3306 meta = &assembly->image;
3308 /* sizes should be multiple of 4 */
3309 pad_heap (&assembly->blob);
3310 pad_heap (&assembly->guid);
3311 pad_heap (&assembly->sheap);
3312 pad_heap (&assembly->us);
3314 /* Setup the info used by compute_sizes () */
3315 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3316 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3317 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3319 meta_size += assembly->blob.index;
3320 meta_size += assembly->guid.index;
3321 meta_size += assembly->sheap.index;
3322 meta_size += assembly->us.index;
3324 for (i=0; i < MONO_TABLE_NUM; ++i)
3325 meta->tables [i].rows = assembly->tables [i].rows;
3327 for (i = 0; i < MONO_TABLE_NUM; i++){
3328 if (meta->tables [i].rows == 0)
3330 valid_mask |= (guint64)1 << i;
3332 meta->tables [i].row_size = mono_metadata_compute_size (
3333 meta, i, &meta->tables [i].size_bitfield);
3334 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3336 heapt_size += 24; /* #~ header size */
3337 heapt_size += ntables * 4;
3338 /* make multiple of 4 */
3341 meta_size += heapt_size;
3342 meta->raw_metadata = g_malloc0 (meta_size);
3343 p = meta->raw_metadata;
3344 /* the metadata signature */
3345 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3346 /* version numbers and 4 bytes reserved */
3347 int16val = (guint16*)p;
3348 *int16val++ = GUINT16_TO_LE (1);
3349 *int16val = GUINT16_TO_LE (1);
3351 /* version string */
3352 int32val = (guint32*)p;
3353 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3355 memcpy (p, meta->version, strlen (meta->version));
3356 p += GUINT32_FROM_LE (*int32val);
3357 align_pointer (meta->raw_metadata, p);
3358 int16val = (guint16*)p;
3359 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3360 *int16val = GUINT16_TO_LE (5); /* number of streams */
3364 * write the stream info.
3366 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3367 table_offset += 3; table_offset &= ~3;
3369 assembly->tstream.index = heapt_size;
3370 for (i = 0; i < 5; ++i) {
3371 int32val = (guint32*)p;
3372 stream_desc [i].stream->offset = table_offset;
3373 *int32val++ = GUINT32_TO_LE (table_offset);
3374 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3375 table_offset += GUINT32_FROM_LE (*int32val);
3376 table_offset += 3; table_offset &= ~3;
3378 strcpy (p, stream_desc [i].name);
3379 p += strlen (stream_desc [i].name) + 1;
3380 align_pointer (meta->raw_metadata, p);
3383 * now copy the data, the table stream header and contents goes first.
3385 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3386 p = meta->raw_metadata + assembly->tstream.offset;
3387 int32val = (guint32*)p;
3388 *int32val = GUINT32_TO_LE (0); /* reserved */
3391 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3392 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3393 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3394 *p++ = 2; /* version */
3397 *p++ = 1; /* version */
3401 if (meta->idx_string_wide)
3403 if (meta->idx_guid_wide)
3405 if (meta->idx_blob_wide)
3408 *p++ = 1; /* reserved */
3409 int64val = (guint64*)p;
3410 *int64val++ = GUINT64_TO_LE (valid_mask);
3411 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3413 int32val = (guint32*)p;
3414 for (i = 0; i < MONO_TABLE_NUM; i++){
3415 if (meta->tables [i].rows == 0)
3417 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3419 p = (unsigned char*)int32val;
3421 /* sort the tables that still need sorting */
3422 table = &assembly->tables [MONO_TABLE_CONSTANT];
3424 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3425 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3427 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3428 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3430 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3431 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3433 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3434 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3436 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3437 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3438 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3440 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3442 /* compress the tables */
3443 for (i = 0; i < MONO_TABLE_NUM; i++){
3446 guint32 bitfield = meta->tables [i].size_bitfield;
3447 if (!meta->tables [i].rows)
3449 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3450 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3451 meta->tables [i].base = p;
3452 for (row = 1; row <= meta->tables [i].rows; ++row) {
3453 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3454 for (col = 0; col < assembly->tables [i].columns; ++col) {
3455 switch (mono_metadata_table_size (bitfield, col)) {
3457 *p++ = values [col];
3460 *p++ = values [col] & 0xff;
3461 *p++ = (values [col] >> 8) & 0xff;
3464 *p++ = values [col] & 0xff;
3465 *p++ = (values [col] >> 8) & 0xff;
3466 *p++ = (values [col] >> 16) & 0xff;
3467 *p++ = (values [col] >> 24) & 0xff;
3470 g_assert_not_reached ();
3474 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3477 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3478 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3479 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3480 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3481 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3483 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3487 * Some tables in metadata need to be sorted according to some criteria, but
3488 * when methods and fields are first created with reflection, they may be assigned a token
3489 * that doesn't correspond to the final token they will get assigned after the sorting.
3490 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3491 * with the reflection objects that represent them. Once all the tables are set up, the
3492 * reflection objects will contains the correct table index. fixup_method() will fixup the
3493 * tokens for the method with ILGenerator @ilgen.
3496 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3497 guint32 code_idx = GPOINTER_TO_UINT (value);
3498 MonoReflectionILTokenInfo *iltoken;
3499 MonoReflectionFieldBuilder *field;
3500 MonoReflectionCtorBuilder *ctor;
3501 MonoReflectionMethodBuilder *method;
3502 MonoReflectionTypeBuilder *tb;
3503 MonoReflectionArrayMethod *am;
3505 unsigned char *target;
3507 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3508 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3509 target = assembly->code.data + code_idx + iltoken->code_pos;
3510 switch (target [3]) {
3511 case MONO_TABLE_FIELD:
3512 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3513 field = (MonoReflectionFieldBuilder *)iltoken->member;
3514 idx = field->table_idx;
3515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3516 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3517 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3519 g_assert_not_reached ();
3522 case MONO_TABLE_METHOD:
3523 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3524 method = (MonoReflectionMethodBuilder *)iltoken->member;
3525 idx = method->table_idx;
3526 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3527 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3528 idx = ctor->table_idx;
3529 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3530 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3531 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3532 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3534 g_assert_not_reached ();
3537 case MONO_TABLE_TYPEDEF:
3538 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3539 g_assert_not_reached ();
3540 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3541 idx = tb->table_idx;
3543 case MONO_TABLE_MEMBERREF:
3544 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3545 am = (MonoReflectionArrayMethod*)iltoken->member;
3546 idx = am->table_idx;
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3548 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3549 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3550 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3551 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3552 g_assert (m->klass->generic_class || m->klass->generic_container);
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3556 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3557 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3558 g_assert (f->generic_info);
3560 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3563 g_assert_not_reached ();
3566 case MONO_TABLE_METHODSPEC:
3567 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3568 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3569 g_assert (mono_method_signature (m)->generic_param_count);
3572 g_assert_not_reached ();
3576 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3578 target [0] = idx & 0xff;
3579 target [1] = (idx >> 8) & 0xff;
3580 target [2] = (idx >> 16) & 0xff;
3587 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3588 * value is not known when the table is emitted.
3591 fixup_cattrs (MonoDynamicImage *assembly)
3593 MonoDynamicTable *table;
3595 guint32 type, i, idx, token;
3598 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3600 for (i = 0; i < table->rows; ++i) {
3601 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3603 type = values [MONO_CUSTOM_ATTR_TYPE];
3604 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3605 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3606 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3607 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3610 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3611 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3612 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3613 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3622 * The METHODIMPL table might contain METHODDEF tokens whose final
3623 * value is not known when the table is emitted.
3626 fixup_methodimpl (MonoDynamicImage *assembly)
3628 MonoDynamicTable *table;
3630 guint32 decl, i, idx, token;
3633 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3635 for (i = 0; i < table->rows; ++i) {
3636 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3637 decl = values [MONO_METHODIMPL_DECLARATION];
3639 idx = decl >> MONO_METHODDEFORREF_BITS;
3640 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3643 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3644 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3647 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3648 token = mono_image_create_token (assembly, method, FALSE);
3649 idx = mono_metadata_token_index (token);
3650 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3656 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3658 MonoDynamicTable *table;
3662 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3664 alloc_table (table, table->rows);
3665 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3666 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3667 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3668 name = mono_string_to_utf8 (rsrc->name);
3669 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3671 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3676 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3678 MonoDynamicTable *table;
3682 char *b = blob_size;
3684 guint32 idx, offset;
3686 if (rsrc->filename) {
3687 name = mono_string_to_utf8 (rsrc->filename);
3688 sname = g_path_get_basename (name);
3690 table = &assembly->tables [MONO_TABLE_FILE];
3692 alloc_table (table, table->rows);
3693 values = table->values + table->next_idx * MONO_FILE_SIZE;
3694 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3695 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3698 mono_sha1_get_digest_from_file (name, hash);
3699 mono_metadata_encode_value (20, b, &b);
3700 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3701 mono_image_add_stream_data (&assembly->blob, hash, 20);
3703 idx = table->next_idx++;
3705 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3708 offset = mono_array_length (rsrc->data);
3709 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3710 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3711 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3712 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3716 * The entry should be emitted into the MANIFESTRESOURCE table of
3717 * the main module, but that needs to reference the FILE table
3718 * which isn't emitted yet.
3725 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3729 set_version_from_string (MonoString *version, guint32 *values)
3731 gchar *ver, *p, *str;
3734 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3735 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3736 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3737 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3740 ver = str = mono_string_to_utf8 (version);
3741 for (i = 0; i < 4; ++i) {
3742 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3748 /* handle Revision and Build */
3758 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3762 char *b = blob_size;
3767 len = mono_array_length (pkey);
3768 mono_metadata_encode_value (len, b, &b);
3769 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3770 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3772 /* need to get the actual value from the key type... */
3773 assembly->strong_name_size = 128;
3774 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3780 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3782 MonoDynamicTable *table;
3783 MonoDynamicImage *assembly;
3784 MonoReflectionAssemblyBuilder *assemblyb;
3789 guint32 module_index;
3791 assemblyb = moduleb->assemblyb;
3792 assembly = moduleb->dynamic_image;
3793 domain = mono_object_domain (assemblyb);
3795 /* Emit ASSEMBLY table */
3796 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3797 alloc_table (table, 1);
3798 values = table->values + MONO_ASSEMBLY_SIZE;
3799 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3800 name = mono_string_to_utf8 (assemblyb->name);
3801 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3803 if (assemblyb->culture) {
3804 name = mono_string_to_utf8 (assemblyb->culture);
3805 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3808 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3810 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3811 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3812 set_version_from_string (assemblyb->version, values);
3814 /* Emit FILE + EXPORTED_TYPE table */
3816 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3818 MonoReflectionModuleBuilder *file_module =
3819 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3820 if (file_module != moduleb) {
3821 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3823 if (file_module->types) {
3824 for (j = 0; j < file_module->num_types; ++j) {
3825 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3826 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3831 if (assemblyb->loaded_modules) {
3832 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3833 MonoReflectionModule *file_module =
3834 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3835 mono_image_fill_file_table (domain, file_module, assembly);
3837 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3841 /* Emit MANIFESTRESOURCE table */
3843 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3845 MonoReflectionModuleBuilder *file_module =
3846 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3847 /* The table for the main module is emitted later */
3848 if (file_module != moduleb) {
3850 if (file_module->resources) {
3851 int len = mono_array_length (file_module->resources);
3852 for (j = 0; j < len; ++j) {
3853 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3854 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3862 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3863 * for the modulebuilder @moduleb.
3864 * At the end of the process, method and field tokens are fixed up and the
3865 * on-disk compressed metadata representation is created.
3868 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3870 MonoDynamicTable *table;
3871 MonoDynamicImage *assembly;
3872 MonoReflectionAssemblyBuilder *assemblyb;
3877 assemblyb = moduleb->assemblyb;
3878 assembly = moduleb->dynamic_image;
3879 domain = mono_object_domain (assemblyb);
3881 if (assembly->text_rva)
3884 assembly->text_rva = START_TEXT_RVA;
3886 if (moduleb->is_main) {
3887 mono_image_emit_manifest (moduleb);
3890 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3891 table->rows = 1; /* .<Module> */
3893 alloc_table (table, table->rows);
3895 * Set the first entry.
3897 values = table->values + table->columns;
3898 values [MONO_TYPEDEF_FLAGS] = 0;
3899 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3900 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3901 values [MONO_TYPEDEF_EXTENDS] = 0;
3902 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3903 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3906 * handle global methods
3907 * FIXME: test what to do when global methods are defined in multiple modules.
3909 if (moduleb->global_methods) {
3910 table = &assembly->tables [MONO_TABLE_METHOD];
3911 table->rows += mono_array_length (moduleb->global_methods);
3912 alloc_table (table, table->rows);
3913 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3914 mono_image_get_method_info (
3915 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3917 if (moduleb->global_fields) {
3918 table = &assembly->tables [MONO_TABLE_FIELD];
3919 table->rows += mono_array_length (moduleb->global_fields);
3920 alloc_table (table, table->rows);
3921 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3922 mono_image_get_field_info (
3923 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3926 table = &assembly->tables [MONO_TABLE_MODULE];
3927 alloc_table (table, 1);
3928 mono_image_fill_module_table (domain, moduleb, assembly);
3932 /* Collect all types into a list sorted by their table_idx */
3933 GPtrArray *types = g_ptr_array_new ();
3936 for (i = 0; i < moduleb->num_types; ++i) {
3937 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3938 collect_types (types, type);
3941 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3942 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3943 table->rows += types->len;
3944 alloc_table (table, table->rows);
3946 for (i = 0; i < types->len; ++i) {
3947 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3948 mono_image_get_type_info (domain, type, assembly);
3950 g_ptr_array_free (types, TRUE);
3954 * table->rows is already set above and in mono_image_fill_module_table.
3956 /* add all the custom attributes at the end, once all the indexes are stable */
3957 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3959 /* CAS assembly permissions */
3960 if (assemblyb->permissions_minimum)
3961 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3962 if (assemblyb->permissions_optional)
3963 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3964 if (assemblyb->permissions_refused)
3965 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3967 module_add_cattrs (assembly, moduleb);
3970 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3971 fixup_cattrs (assembly);
3972 fixup_methodimpl (assembly);
3976 * mono_image_insert_string:
3977 * @module: module builder object
3980 * Insert @str into the user string stream of @module.
3983 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3985 MonoDynamicImage *assembly;
3990 MONO_ARCH_SAVE_REGS;
3992 if (!module->dynamic_image)
3993 mono_image_module_basic_init (module);
3995 assembly = module->dynamic_image;
3997 if (assembly->save) {
3998 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3999 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4000 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4002 char *swapped = g_malloc (2 * mono_string_length (str));
4003 const char *p = (const char*)mono_string_chars (str);
4005 swap_with_size (swapped, p, 2, mono_string_length (str));
4006 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4010 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4012 mono_image_add_stream_data (&assembly->us, "", 1);
4014 idx = assembly->us.index ++;
4017 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4019 return MONO_TOKEN_STRING | idx;
4023 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4028 klass = obj->vtable->klass;
4029 if (strcmp (klass->name, "MonoMethod") == 0) {
4030 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4031 MonoMethodSignature *sig, *old;
4032 guint32 sig_token, parent;
4035 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4037 nargs = mono_array_length (opt_param_types);
4038 old = mono_method_signature (method);
4039 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4041 sig->hasthis = old->hasthis;
4042 sig->explicit_this = old->explicit_this;
4043 sig->call_convention = old->call_convention;
4044 sig->generic_param_count = old->generic_param_count;
4045 sig->param_count = old->param_count + nargs;
4046 sig->sentinelpos = old->param_count;
4047 sig->ret = old->ret;
4049 for (i = 0; i < old->param_count; i++)
4050 sig->params [i] = old->params [i];
4052 for (i = 0; i < nargs; i++) {
4053 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4054 sig->params [old->param_count + i] = rt->type;
4057 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4058 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4059 parent >>= MONO_TYPEDEFORREF_BITS;
4061 parent <<= MONO_MEMBERREF_PARENT_BITS;
4062 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4064 sig_token = method_encode_signature (assembly, sig);
4065 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4066 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4067 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4068 ReflectionMethodBuilder rmb;
4069 guint32 parent, sig;
4071 reflection_methodbuilder_from_method_builder (&rmb, mb);
4072 rmb.opt_types = opt_param_types;
4074 sig = method_builder_encode_signature (assembly, &rmb);
4076 parent = mono_image_create_token (assembly, obj, TRUE);
4077 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4079 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4080 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4082 token = mono_image_get_varargs_method_token (
4083 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4085 g_error ("requested method token for %s\n", klass->name);
4092 * mono_image_create_token:
4093 * @assembly: a dynamic assembly
4096 * Get a token to insert in the IL code stream for the given MemberInfo.
4097 * @obj can be one of:
4098 * ConstructorBuilder
4108 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4113 klass = obj->vtable->klass;
4114 if (strcmp (klass->name, "MethodBuilder") == 0) {
4115 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4117 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4118 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4120 token = mono_image_get_methodbuilder_token (assembly, mb);
4121 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4122 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4123 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4125 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4126 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4128 token = mono_image_get_ctorbuilder_token (assembly, mb);
4129 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4130 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4131 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4132 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4133 if (tb->generic_params) {
4134 token = mono_image_get_generic_field_token (assembly, fb);
4136 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4138 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4139 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4140 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4141 } else if (strcmp (klass->name, "MonoType") == 0 ||
4142 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4143 MonoReflectionType *tb = (MonoReflectionType *)obj;
4144 token = mono_metadata_token_from_dor (
4145 mono_image_typedef_or_ref (assembly, tb->type));
4146 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4147 MonoReflectionType *tb = (MonoReflectionType *)obj;
4148 token = mono_metadata_token_from_dor (
4149 mono_image_typedef_or_ref (assembly, tb->type));
4150 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4151 strcmp (klass->name, "MonoMethod") == 0 ||
4152 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4153 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4154 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4155 if (m->method->is_inflated) {
4156 if (create_methodspec)
4157 token = mono_image_get_methodspec_token (assembly, m->method);
4159 token = mono_image_get_inflated_method_token (assembly, m->method);
4160 } else if ((m->method->klass->image == &assembly->image) &&
4161 !m->method->klass->generic_class) {
4162 static guint32 method_table_idx = 0xffffff;
4163 if (m->method->klass->wastypebuilder) {
4164 /* we use the same token as the one that was assigned
4165 * to the Methodbuilder.
4166 * FIXME: do the equivalent for Fields.
4168 token = m->method->token;
4171 * Each token should have a unique index, but the indexes are
4172 * assigned by managed code, so we don't know about them. An
4173 * easy solution is to count backwards...
4175 method_table_idx --;
4176 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4179 token = mono_image_get_methodref_token (assembly, m->method);
4181 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4182 } else if (strcmp (klass->name, "MonoField") == 0) {
4183 MonoReflectionField *f = (MonoReflectionField *)obj;
4184 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4185 static guint32 field_table_idx = 0xffffff;
4187 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4189 token = mono_image_get_fieldref_token (assembly, f);
4191 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4192 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4193 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4194 token = mono_image_get_array_token (assembly, m);
4195 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4196 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4197 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4199 g_error ("requested token for %s\n", klass->name);
4202 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4208 guint32 import_lookup_table;
4212 guint32 import_address_table_rva;
4220 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4222 static MonoDynamicImage*
4223 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4225 static const guchar entrycode [16] = {0xff, 0x25, 0};
4226 MonoDynamicImage *image;
4229 const char *version = mono_get_runtime_info ()->runtime_version;
4232 image = GC_MALLOC (sizeof (MonoDynamicImage));
4234 image = g_new0 (MonoDynamicImage, 1);
4237 /*g_print ("created image %p\n", image);*/
4238 /* keep in sync with image.c */
4239 image->image.name = assembly_name;
4240 image->image.assembly_name = image->image.name; /* they may be different */
4241 image->image.module_name = module_name;
4242 image->image.version = version;
4243 image->image.dynamic = TRUE;
4244 image->image.ref_count = 1;
4246 image->image.references = g_new0 (MonoAssembly*, 1);
4247 image->image.references [0] = NULL;
4249 mono_image_init (&image->image);
4251 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4252 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4253 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4254 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4255 image->handleref = g_hash_table_new (NULL, NULL);
4256 image->tokens = mono_g_hash_table_new (NULL, NULL);
4257 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4258 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4259 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4260 image->gen_params = g_ptr_array_new ();
4262 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4263 string_heap_init (&image->sheap);
4264 mono_image_add_stream_data (&image->us, "", 1);
4265 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4266 /* import tables... */
4267 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4268 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4269 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4270 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4271 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4272 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4273 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4274 stream_data_align (&image->code);
4276 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4278 for (i=0; i < MONO_TABLE_NUM; ++i) {
4279 image->tables [i].next_idx = 1;
4280 image->tables [i].columns = table_sizes [i];
4283 image->image.assembly = (MonoAssembly*)assembly;
4284 image->run = assembly->run;
4285 image->save = assembly->save;
4286 image->pe_kind = 0x1; /* ILOnly */
4287 image->machine = 0x14c; /* I386 */
4293 * mono_image_basic_init:
4294 * @assembly: an assembly builder object
4296 * Create the MonoImage that represents the assembly builder and setup some
4297 * of the helper hash table and the basic metadata streams.
4300 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4302 MonoDynamicAssembly *assembly;
4303 MonoDynamicImage *image;
4304 MonoDomain *domain = mono_object_domain (assemblyb);
4306 MONO_ARCH_SAVE_REGS;
4308 if (assemblyb->dynamic_assembly)
4312 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4314 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4317 assembly->assembly.ref_count = 1;
4318 assembly->assembly.dynamic = TRUE;
4319 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4320 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4321 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4322 if (assemblyb->culture)
4323 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4325 assembly->assembly.aname.culture = g_strdup ("");
4327 if (assemblyb->version) {
4328 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4329 char **parts = version;
4330 assembly->assembly.aname.major = atoi (*parts++);
4331 assembly->assembly.aname.minor = atoi (*parts++);
4332 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4333 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4335 g_strfreev (version);
4337 assembly->assembly.aname.major = 0;
4338 assembly->assembly.aname.minor = 0;
4339 assembly->assembly.aname.build = 0;
4340 assembly->assembly.aname.revision = 0;
4343 assembly->run = assemblyb->access != 2;
4344 assembly->save = assemblyb->access != 1;
4346 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4347 image->initial_image = TRUE;
4348 assembly->assembly.aname.name = image->image.name;
4349 assembly->assembly.image = &image->image;
4351 mono_domain_assemblies_lock (domain);
4352 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4353 mono_domain_assemblies_unlock (domain);
4355 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4356 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4360 calc_section_size (MonoDynamicImage *assembly)
4364 /* alignment constraints */
4365 assembly->code.index += 3;
4366 assembly->code.index &= ~3;
4367 assembly->meta_size += 3;
4368 assembly->meta_size &= ~3;
4369 assembly->resources.index += 3;
4370 assembly->resources.index &= ~3;
4372 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4373 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4376 if (assembly->win32_res) {
4377 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4379 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4380 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4384 assembly->sections [MONO_SECTION_RELOC].size = 12;
4385 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4395 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4399 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4401 ResTreeNode *t1 = (ResTreeNode*)a;
4402 ResTreeNode *t2 = (ResTreeNode*)b;
4404 return t1->id - t2->id;
4408 * resource_tree_create:
4410 * Organize the resources into a resource tree.
4412 static ResTreeNode *
4413 resource_tree_create (MonoArray *win32_resources)
4415 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4419 tree = g_new0 (ResTreeNode, 1);
4421 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4422 MonoReflectionWin32Resource *win32_res =
4423 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4427 lang_node = g_new0 (ResTreeNode, 1);
4428 lang_node->id = win32_res->lang_id;
4429 lang_node->win32_res = win32_res;
4431 /* Create type node if neccesary */
4433 for (l = tree->children; l; l = l->next)
4434 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4435 type_node = (ResTreeNode*)l->data;
4440 type_node = g_new0 (ResTreeNode, 1);
4441 type_node->id = win32_res->res_type;
4444 * The resource types have to be sorted otherwise
4445 * Windows Explorer can't display the version information.
4447 tree->children = g_slist_insert_sorted (tree->children,
4448 type_node, resource_tree_compare_by_id);
4451 /* Create res node if neccesary */
4453 for (l = type_node->children; l; l = l->next)
4454 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4455 res_node = (ResTreeNode*)l->data;
4460 res_node = g_new0 (ResTreeNode, 1);
4461 res_node->id = win32_res->res_id;
4462 type_node->children = g_slist_append (type_node->children, res_node);
4465 res_node->children = g_slist_append (res_node->children, lang_node);
4472 * resource_tree_encode:
4474 * Encode the resource tree into the format used in the PE file.
4477 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4480 MonoPEResourceDir dir;
4481 MonoPEResourceDirEntry dir_entry;
4482 MonoPEResourceDataEntry data_entry;
4486 * For the format of the resource directory, see the article
4487 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4491 memset (&dir, 0, sizeof (dir));
4492 memset (&dir_entry, 0, sizeof (dir_entry));
4493 memset (&data_entry, 0, sizeof (data_entry));
4495 g_assert (sizeof (dir) == 16);
4496 g_assert (sizeof (dir_entry) == 8);
4497 g_assert (sizeof (data_entry) == 16);
4499 node->offset = p - begin;
4501 /* IMAGE_RESOURCE_DIRECTORY */
4502 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4504 memcpy (p, &dir, sizeof (dir));
4507 /* Reserve space for entries */
4509 p += sizeof (dir_entry) * dir.res_id_entries;
4511 /* Write children */
4512 for (l = node->children; l; l = l->next) {
4513 ResTreeNode *child = (ResTreeNode*)l->data;
4515 if (child->win32_res) {
4517 child->offset = p - begin;
4519 /* IMAGE_RESOURCE_DATA_ENTRY */
4520 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4521 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4523 memcpy (p, &data_entry, sizeof (data_entry));
4524 p += sizeof (data_entry);
4526 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4527 p += data_entry.rde_size;
4529 resource_tree_encode (child, begin, p, &p);
4533 /* IMAGE_RESOURCE_ENTRY */
4534 for (l = node->children; l; l = l->next) {
4535 ResTreeNode *child = (ResTreeNode*)l->data;
4536 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4538 dir_entry.is_dir = child->win32_res ? 0 : 1;
4539 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4541 memcpy (entries, &dir_entry, sizeof (dir_entry));
4542 entries += sizeof (dir_entry);
4549 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4554 MonoReflectionWin32Resource *win32_res;
4557 if (!assemblyb->win32_resources)
4561 * Resources are stored in a three level tree inside the PE file.
4562 * - level one contains a node for each type of resource
4563 * - level two contains a node for each resource
4564 * - level three contains a node for each instance of a resource for a
4565 * specific language.
4568 tree = resource_tree_create (assemblyb->win32_resources);
4570 /* Estimate the size of the encoded tree */
4572 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4573 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4574 size += mono_array_length (win32_res->res_data);
4576 /* Directory structure */
4577 size += mono_array_length (assemblyb->win32_resources) * 256;
4578 p = buf = g_malloc (size);
4580 resource_tree_encode (tree, p, p, &p);
4582 g_assert (p - buf < size);
4584 assembly->win32_res = g_malloc (p - buf);
4585 assembly->win32_res_size = p - buf;
4586 memcpy (assembly->win32_res, buf, p - buf);
4592 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4594 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4597 p += sizeof (MonoPEResourceDir);
4598 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4599 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4600 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4601 if (dir_entry->is_dir) {
4602 fixup_resource_directory (res_section, child, rva);
4604 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4605 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4608 p += sizeof (MonoPEResourceDirEntry);
4613 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4616 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4617 g_error ("WriteFile returned %d\n", GetLastError ());
4621 * mono_image_create_pefile:
4622 * @mb: a module builder object
4624 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4625 * assembly->pefile where it can be easily retrieved later in chunks.
4628 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4629 MonoMSDOSHeader *msdos;
4630 MonoDotNetHeader *header;
4631 MonoSectionTable *section;
4632 MonoCLIHeader *cli_header;
4633 guint32 size, image_size, virtual_base, text_offset;
4634 guint32 header_start, section_start, file_offset, virtual_offset;
4635 MonoDynamicImage *assembly;
4636 MonoReflectionAssemblyBuilder *assemblyb;
4637 MonoDynamicStream pefile_stream = {0};
4638 MonoDynamicStream *pefile = &pefile_stream;
4640 guint32 *rva, value;
4642 static const unsigned char msheader[] = {
4643 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4644 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4647 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4648 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4649 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4650 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4653 assemblyb = mb->assemblyb;
4655 mono_image_basic_init (assemblyb);
4656 assembly = mb->dynamic_image;
4658 assembly->pe_kind = assemblyb->pe_kind;
4659 assembly->machine = assemblyb->machine;
4660 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4661 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4663 mono_image_build_metadata (mb);
4665 if (mb->is_main && assemblyb->resources) {
4666 int len = mono_array_length (assemblyb->resources);
4667 for (i = 0; i < len; ++i)
4668 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4671 if (mb->resources) {
4672 int len = mono_array_length (mb->resources);
4673 for (i = 0; i < len; ++i)
4674 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4677 build_compressed_metadata (assembly);
4680 assembly_add_win32_resources (assembly, assemblyb);
4682 nsections = calc_section_size (assembly);
4684 /* The DOS header and stub */
4685 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4686 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4688 /* the dotnet header */
4689 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4691 /* the section tables */
4692 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4694 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4695 virtual_offset = VIRT_ALIGN;
4698 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4699 if (!assembly->sections [i].size)
4702 file_offset += FILE_ALIGN - 1;
4703 file_offset &= ~(FILE_ALIGN - 1);
4704 virtual_offset += VIRT_ALIGN - 1;
4705 virtual_offset &= ~(VIRT_ALIGN - 1);
4707 assembly->sections [i].offset = file_offset;
4708 assembly->sections [i].rva = virtual_offset;
4710 file_offset += assembly->sections [i].size;
4711 virtual_offset += assembly->sections [i].size;
4712 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4715 file_offset += FILE_ALIGN - 1;
4716 file_offset &= ~(FILE_ALIGN - 1);
4718 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4720 /* back-patch info */
4721 msdos = (MonoMSDOSHeader*)pefile->data;
4722 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4724 header = (MonoDotNetHeader*)(pefile->data + header_start);
4725 header->pesig [0] = 'P';
4726 header->pesig [1] = 'E';
4728 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4729 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4730 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4731 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4732 if (assemblyb->pekind == 1) {
4734 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4737 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4740 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4742 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4743 header->pe.pe_major = 6;
4744 header->pe.pe_minor = 0;
4745 size = assembly->sections [MONO_SECTION_TEXT].size;
4746 size += FILE_ALIGN - 1;
4747 size &= ~(FILE_ALIGN - 1);
4748 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4749 size = assembly->sections [MONO_SECTION_RSRC].size;
4750 size += FILE_ALIGN - 1;
4751 size &= ~(FILE_ALIGN - 1);
4752 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4753 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4754 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4755 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4756 /* pe_rva_entry_point always at the beginning of the text section */
4757 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4759 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4760 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4761 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4762 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4763 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4764 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4765 size = section_start;
4766 size += FILE_ALIGN - 1;
4767 size &= ~(FILE_ALIGN - 1);
4768 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4770 size += VIRT_ALIGN - 1;
4771 size &= ~(VIRT_ALIGN - 1);
4772 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4775 // Translate the PEFileKind value to the value expected by the Windows loader
4781 // PEFileKinds.Dll == 1
4782 // PEFileKinds.ConsoleApplication == 2
4783 // PEFileKinds.WindowApplication == 3
4786 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4787 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4789 if (assemblyb->pekind == 3)
4794 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4796 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4797 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4798 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4799 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4800 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4801 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4803 /* fill data directory entries */
4805 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4806 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4808 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4809 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4811 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4812 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4813 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4814 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4815 /* patch entrypoint name */
4816 if (assemblyb->pekind == 1)
4817 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4819 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4820 /* patch imported function RVA name */
4821 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4822 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4824 /* the import table */
4825 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4826 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4827 /* patch imported dll RVA name and other entries in the dir */
4828 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4829 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4830 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4831 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4832 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4833 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4835 p = (assembly->code.data + assembly->ilt_offset);
4836 value = (assembly->text_rva + assembly->imp_names_offset);
4837 *p++ = (value) & 0xff;
4838 *p++ = (value >> 8) & (0xff);
4839 *p++ = (value >> 16) & (0xff);
4840 *p++ = (value >> 24) & (0xff);
4842 /* the CLI header info */
4843 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4844 cli_header->ch_size = GUINT32_FROM_LE (72);
4845 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4846 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4847 if (assemblyb->entry_point) {
4848 guint32 table_idx = 0;
4849 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4850 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4851 table_idx = methodb->table_idx;
4853 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4855 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4857 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4859 /* The embedded managed resources */
4860 text_offset = assembly->text_rva + assembly->code.index;
4861 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4862 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4863 text_offset += assembly->resources.index;
4864 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4865 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4866 text_offset += assembly->meta_size;
4867 if (assembly->strong_name_size) {
4868 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4869 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4870 text_offset += assembly->strong_name_size;
4873 /* write the section tables and section content */
4874 section = (MonoSectionTable*)(pefile->data + section_start);
4875 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4876 static const char *section_names [] = {
4877 ".text", ".rsrc", ".reloc"
4879 if (!assembly->sections [i].size)
4881 strcpy (section->st_name, section_names [i]);
4882 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4883 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4884 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4885 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4886 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4887 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4888 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4892 checked_write_file (file, pefile->data, pefile->index);
4894 mono_dynamic_stream_reset (pefile);
4896 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4897 if (!assembly->sections [i].size)
4900 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4901 g_error ("SetFilePointer returned %d\n", GetLastError ());
4904 case MONO_SECTION_TEXT:
4905 /* patch entry point */
4906 p = (assembly->code.data + 2);
4907 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4908 *p++ = (value) & 0xff;
4909 *p++ = (value >> 8) & 0xff;
4910 *p++ = (value >> 16) & 0xff;
4911 *p++ = (value >> 24) & 0xff;
4913 checked_write_file (file, assembly->code.data, assembly->code.index);
4914 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4915 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4916 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4919 g_free (assembly->image.raw_metadata);
4921 case MONO_SECTION_RELOC: {
4925 guint16 type_and_offset;
4929 g_assert (sizeof (reloc) == 12);
4931 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4932 reloc.block_size = GUINT32_FROM_LE (12);
4935 * the entrypoint is always at the start of the text section
4936 * 3 is IMAGE_REL_BASED_HIGHLOW
4937 * 2 is patch_size_rva - text_rva
4939 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4942 checked_write_file (file, &reloc, sizeof (reloc));
4946 case MONO_SECTION_RSRC:
4947 if (assembly->win32_res) {
4949 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4950 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4951 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4955 g_assert_not_reached ();
4959 /* check that the file is properly padded */
4960 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4961 g_error ("SetFilePointer returned %d\n", GetLastError ());
4962 if (! SetEndOfFile (file))
4963 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4965 mono_dynamic_stream_reset (&assembly->code);
4966 mono_dynamic_stream_reset (&assembly->us);
4967 mono_dynamic_stream_reset (&assembly->blob);
4968 mono_dynamic_stream_reset (&assembly->guid);
4969 mono_dynamic_stream_reset (&assembly->sheap);
4971 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4972 g_hash_table_destroy (assembly->blob_cache);
4973 assembly->blob_cache = NULL;
4976 MonoReflectionModule *
4977 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4981 MonoImageOpenStatus status;
4982 MonoDynamicAssembly *assembly;
4983 guint32 module_count;
4984 MonoImage **new_modules;
4986 name = mono_string_to_utf8 (fileName);
4988 image = mono_image_open (name, &status);
4991 if (status == MONO_IMAGE_ERROR_ERRNO)
4992 exc = mono_get_exception_file_not_found (fileName);
4994 exc = mono_get_exception_bad_image_format (name);
4996 mono_raise_exception (exc);
5001 assembly = ab->dynamic_assembly;
5002 image->assembly = (MonoAssembly*)assembly;
5004 module_count = image->assembly->image->module_count;
5005 new_modules = g_new0 (MonoImage *, module_count + 1);
5007 if (image->assembly->image->modules)
5008 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5009 new_modules [module_count] = image;
5011 g_free (image->assembly->image->modules);
5012 image->assembly->image->modules = new_modules;
5013 image->assembly->image->module_count ++;
5015 mono_assembly_load_references (image, &status);
5017 mono_image_close (image);
5018 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5021 return mono_module_get_object (mono_domain_get (), image);
5025 * We need to return always the same object for MethodInfo, FieldInfo etc..
5026 * but we need to consider the reflected type.
5027 * type uses a different hash, since it uses custom hash/equal functions.
5032 MonoClass *refclass;
5036 reflected_equal (gconstpointer a, gconstpointer b) {
5037 const ReflectedEntry *ea = a;
5038 const ReflectedEntry *eb = b;
5040 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5044 reflected_hash (gconstpointer a) {
5045 const ReflectedEntry *ea = a;
5046 return GPOINTER_TO_UINT (ea->item);
5049 #define CHECK_OBJECT(t,p,k) \
5055 mono_domain_lock (domain); \
5056 if (!domain->refobject_hash) \
5057 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5058 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5059 mono_domain_unlock (domain); \
5062 mono_domain_unlock (domain); \
5066 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5068 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5071 #define CACHE_OBJECT(t,p,o,k) \
5074 ReflectedEntry pe; \
5076 pe.refclass = (k); \
5077 mono_domain_lock (domain); \
5078 if (!domain->refobject_hash) \
5079 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5080 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5082 ReflectedEntry *e = ALLOC_REFENTRY; \
5084 e->refclass = (k); \
5085 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5088 mono_domain_unlock (domain); \
5093 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5095 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5099 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5101 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5105 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5107 MonoDynamicImage *image = moduleb->dynamic_image;
5108 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5111 MonoImage **new_modules;
5114 * FIXME: we already created an image in mono_image_basic_init (), but
5115 * we don't know which module it belongs to, since that is only
5116 * determined at assembly save time.
5118 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5119 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5121 moduleb->module.image = &image->image;
5122 moduleb->dynamic_image = image;
5123 register_module (mono_object_domain (moduleb), moduleb, image);
5125 /* register the module with the assembly */
5126 ass = ab->dynamic_assembly->assembly.image;
5127 module_count = ass->module_count;
5128 new_modules = g_new0 (MonoImage *, module_count + 1);
5131 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5132 new_modules [module_count] = &image->image;
5134 g_free (ass->modules);
5135 ass->modules = new_modules;
5136 ass->module_count ++;
5141 * mono_assembly_get_object:
5142 * @domain: an app domain
5143 * @assembly: an assembly
5145 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5147 MonoReflectionAssembly*
5148 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5150 static MonoClass *System_Reflection_Assembly;
5151 MonoReflectionAssembly *res;
5153 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5154 if (!System_Reflection_Assembly)
5155 System_Reflection_Assembly = mono_class_from_name (
5156 mono_defaults.corlib, "System.Reflection", "Assembly");
5157 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5158 res->assembly = assembly;
5160 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5165 MonoReflectionModule*
5166 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5168 static MonoClass *System_Reflection_Module;
5169 MonoReflectionModule *res;
5172 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5173 if (!System_Reflection_Module)
5174 System_Reflection_Module = mono_class_from_name (
5175 mono_defaults.corlib, "System.Reflection", "Module");
5176 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5179 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5181 res->fqname = mono_string_new (domain, image->name);
5182 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5183 res->scopename = mono_string_new (domain, image->module_name);
5187 if (image->assembly->image == image) {
5188 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5191 g_assert (image->assembly->image->modules);
5193 for (i = 0; i < image->assembly->image->module_count; i++) {
5194 if (image->assembly->image->modules [i] == image)
5195 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5197 g_assert (res->token);
5200 mono_image_addref (image);
5202 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5205 MonoReflectionModule*
5206 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5208 static MonoClass *System_Reflection_Module;
5209 MonoReflectionModule *res;
5210 MonoTableInfo *table;
5211 guint32 cols [MONO_FILE_SIZE];
5213 guint32 i, name_idx;
5216 if (!System_Reflection_Module)
5217 System_Reflection_Module = mono_class_from_name (
5218 mono_defaults.corlib, "System.Reflection", "Module");
5219 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5221 table = &image->tables [MONO_TABLE_FILE];
5222 g_assert (table_index < table->rows);
5223 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5226 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5227 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5229 /* Check whenever the row has a corresponding row in the moduleref table */
5230 table = &image->tables [MONO_TABLE_MODULEREF];
5231 for (i = 0; i < table->rows; ++i) {
5232 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5233 val = mono_metadata_string_heap (image, name_idx);
5234 if (strcmp (val, name) == 0)
5235 res->image = image->modules [i];
5238 res->fqname = mono_string_new (domain, name);
5239 res->name = mono_string_new (domain, name);
5240 res->scopename = mono_string_new (domain, name);
5241 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5242 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5248 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5250 if ((t1->type != t2->type) ||
5251 (t1->byref != t2->byref))
5255 case MONO_TYPE_VOID:
5256 case MONO_TYPE_BOOLEAN:
5257 case MONO_TYPE_CHAR:
5268 case MONO_TYPE_STRING:
5271 case MONO_TYPE_OBJECT:
5272 case MONO_TYPE_TYPEDBYREF:
5274 case MONO_TYPE_VALUETYPE:
5275 case MONO_TYPE_CLASS:
5276 case MONO_TYPE_SZARRAY:
5277 return t1->data.klass == t2->data.klass;
5279 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5280 case MONO_TYPE_ARRAY:
5281 if (t1->data.array->rank != t2->data.array->rank)
5283 return t1->data.array->eklass == t2->data.array->eklass;
5284 case MONO_TYPE_GENERICINST: {
5286 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5288 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5289 &t2->data.generic_class->container_class->byval_arg))
5291 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5292 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5298 case MONO_TYPE_MVAR:
5299 return t1->data.generic_param == t2->data.generic_param;
5301 g_error ("implement type compare for %0x!", t1->type);
5309 mymono_metadata_type_hash (MonoType *t1)
5315 hash |= t1->byref << 6; /* do not collide with t1->type values */
5317 case MONO_TYPE_VALUETYPE:
5318 case MONO_TYPE_CLASS:
5319 case MONO_TYPE_SZARRAY:
5320 /* check if the distribution is good enough */
5321 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5323 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5328 static MonoReflectionGenericClass*
5329 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5331 static MonoClass *System_Reflection_MonoGenericClass;
5332 MonoReflectionGenericClass *res;
5333 MonoInflatedGenericClass *gclass;
5336 if (!System_Reflection_MonoGenericClass) {
5337 System_Reflection_MonoGenericClass = mono_class_from_name (
5338 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5339 g_assert (System_Reflection_MonoGenericClass);
5342 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5343 gklass = gclass->generic_class.container_class;
5345 mono_class_init (gclass->klass);
5347 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5349 res->type.type = geninst;
5350 if (gklass->wastypebuilder && gklass->reflection_info)
5351 res->generic_type = gklass->reflection_info;
5353 res->generic_type = mono_type_get_object (
5354 domain, &gclass->generic_class.container_class->byval_arg);
5360 * mono_type_get_object:
5361 * @domain: an app domain
5364 * Return an System.MonoType object representing the type @type.
5367 mono_type_get_object (MonoDomain *domain, MonoType *type)
5369 MonoReflectionType *res;
5370 MonoClass *klass = mono_class_from_mono_type (type);
5372 mono_domain_lock (domain);
5373 if (!domain->type_hash)
5374 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5375 (GCompareFunc)mymono_metadata_type_equal);
5376 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5377 mono_domain_unlock (domain);
5380 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5381 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5382 mono_g_hash_table_insert (domain->type_hash, type, res);
5383 mono_domain_unlock (domain);
5386 if (klass->reflection_info && !klass->wastypebuilder) {
5387 /* g_assert_not_reached (); */
5388 /* should this be considered an error condition? */
5390 mono_domain_unlock (domain);
5391 return klass->reflection_info;
5394 mono_class_init (klass);
5395 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5397 mono_g_hash_table_insert (domain->type_hash, type, res);
5398 mono_domain_unlock (domain);
5403 * mono_method_get_object:
5404 * @domain: an app domain
5406 * @refclass: the reflected type (can be NULL)
5408 * Return an System.Reflection.MonoMethod object representing the method @method.
5410 MonoReflectionMethod*
5411 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5414 * We use the same C representation for methods and constructors, but the type
5415 * name in C# is different.
5419 MonoReflectionMethod *ret;
5421 if (method->is_inflated) {
5422 MonoReflectionGenericMethod *gret;
5424 refclass = method->klass;
5425 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5426 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5427 cname = "MonoGenericCMethod";
5429 cname = "MonoGenericMethod";
5430 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5432 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5433 gret->method.method = method;
5434 gret->method.name = mono_string_new (domain, method->name);
5435 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5436 CACHE_OBJECT (MonoReflectionMethod *, method, gret, refclass);
5440 refclass = method->klass;
5442 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5443 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5444 cname = "MonoCMethod";
5446 cname = "MonoMethod";
5447 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5449 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5450 ret->method = method;
5451 ret->name = mono_string_new (domain, method->name);
5452 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5453 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5457 * mono_field_get_object:
5458 * @domain: an app domain
5462 * Return an System.Reflection.MonoField object representing the field @field
5465 MonoReflectionField*
5466 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5468 MonoReflectionField *res;
5471 CHECK_OBJECT (MonoReflectionField *, field, klass);
5472 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5473 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5476 res->name = mono_string_new (domain, field->name);
5477 if (field->generic_info)
5478 res->attrs = field->generic_info->generic_type->attrs;
5480 res->attrs = field->type->attrs;
5481 res->type = mono_type_get_object (domain, field->type);
5482 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5486 * mono_property_get_object:
5487 * @domain: an app domain
5489 * @property: a property
5491 * Return an System.Reflection.MonoProperty object representing the property @property
5494 MonoReflectionProperty*
5495 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5497 MonoReflectionProperty *res;
5500 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5501 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5502 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5504 res->property = property;
5505 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5509 * mono_event_get_object:
5510 * @domain: an app domain
5514 * Return an System.Reflection.MonoEvent object representing the event @event
5517 MonoReflectionEvent*
5518 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5520 MonoReflectionEvent *res;
5523 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5524 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5525 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5528 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5532 * mono_param_get_objects:
5533 * @domain: an app domain
5536 * Return an System.Reflection.ParameterInfo array object representing the parameters
5537 * in the method @method.
5540 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5542 static MonoClass *System_Reflection_ParameterInfo;
5543 MonoArray *res = NULL;
5544 MonoReflectionMethod *member = NULL;
5545 MonoReflectionParameter *param = NULL;
5546 char **names, **blobs = NULL;
5547 guint32 *types = NULL;
5548 MonoType *type = NULL;
5549 MonoObject *dbnull = mono_get_dbnull_object (domain);
5550 MonoMarshalSpec **mspecs;
5553 if (!System_Reflection_ParameterInfo)
5554 System_Reflection_ParameterInfo = mono_class_from_name (
5555 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5557 if (!mono_method_signature (method)->param_count)
5558 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5560 /* Note: the cache is based on the address of the signature into the method
5561 * since we already cache MethodInfos with the method as keys.
5563 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5565 member = mono_method_get_object (domain, method, NULL);
5566 names = g_new (char *, mono_method_signature (method)->param_count);
5567 mono_method_get_param_names (method, (const char **) names);
5569 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5570 mono_method_get_marshal_info (method, mspecs);
5572 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5573 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5574 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5575 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5576 param->MemberImpl = (MonoObject*)member;
5577 param->NameImpl = mono_string_new (domain, names [i]);
5578 param->PositionImpl = i;
5579 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5581 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5582 param->DefaultValueImpl = dbnull;
5586 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5587 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5588 get_default_param_value_blobs (method, blobs, types);
5591 /* Build MonoType for the type from the Constant Table */
5593 type = g_new0 (MonoType, 1);
5594 type->type = types [i];
5595 type->data.klass = NULL;
5596 if (types [i] == MONO_TYPE_CLASS)
5597 type->data.klass = mono_defaults.object_class;
5599 type->data.klass = mono_class_from_mono_type (type);
5601 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5603 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5604 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5605 param->DefaultValueImpl = dbnull;
5610 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5612 mono_array_set (res, gpointer, i, param);
5619 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5621 mono_metadata_free_marshal_spec (mspecs [i]);
5624 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5628 * mono_method_body_get_object:
5629 * @domain: an app domain
5632 * Return an System.Reflection.MethodBody object representing the method @method.
5634 MonoReflectionMethodBody*
5635 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5637 static MonoClass *System_Reflection_MethodBody = NULL;
5638 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5639 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5640 MonoReflectionMethodBody *ret;
5641 MonoMethodNormal *mn;
5642 MonoMethodHeader *header;
5643 guint32 method_rva, local_var_sig_token;
5645 unsigned char format, flags;
5648 if (!System_Reflection_MethodBody)
5649 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5650 if (!System_Reflection_LocalVariableInfo)
5651 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5652 if (!System_Reflection_ExceptionHandlingClause)
5653 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5655 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5657 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5658 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5659 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5660 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5662 mn = (MonoMethodNormal *)method;
5663 header = mono_method_get_header (method);
5665 /* Obtain local vars signature token */
5666 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5667 ptr = mono_image_rva_map (method->klass->image, method_rva);
5668 flags = *(const unsigned char *) ptr;
5669 format = flags & METHOD_HEADER_FORMAT_MASK;
5671 case METHOD_HEADER_TINY_FORMAT:
5672 case METHOD_HEADER_TINY_FORMAT1:
5673 local_var_sig_token = 0;
5675 case METHOD_HEADER_FAT_FORMAT:
5679 local_var_sig_token = read32 (ptr);
5682 g_assert_not_reached ();
5685 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5687 ret->init_locals = header->init_locals;
5688 ret->max_stack = header->max_stack;
5689 ret->local_var_sig_token = local_var_sig_token;
5690 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5691 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5694 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5695 for (i = 0; i < header->num_locals; ++i) {
5696 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5697 info->local_type = mono_type_get_object (domain, header->locals [i]);
5698 info->is_pinned = header->locals [i]->pinned;
5699 info->local_index = i;
5700 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5704 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5705 for (i = 0; i < header->num_clauses; ++i) {
5706 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5707 MonoExceptionClause *clause = &header->clauses [i];
5709 info->flags = clause->flags;
5710 info->try_offset = clause->try_offset;
5711 info->try_length = clause->try_len;
5712 info->handler_offset = clause->handler_offset;
5713 info->handler_length = clause->handler_len;
5714 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5715 info->filter_offset = clause->data.filter_offset;
5716 else if (clause->data.catch_class)
5717 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5719 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5722 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5727 mono_get_dbnull_object (MonoDomain *domain)
5731 static MonoClassField *dbnull_value_field = NULL;
5733 if (!dbnull_value_field) {
5734 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5735 mono_class_init (klass);
5736 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5737 g_assert (dbnull_value_field);
5739 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5746 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5748 guint32 param_index, i, lastp, crow = 0;
5749 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5752 MonoClass *klass = method->klass;
5753 MonoImage *image = klass->image;
5754 MonoMethodSignature *methodsig = mono_method_signature (method);
5756 MonoTableInfo *constt;
5757 MonoTableInfo *methodt;
5758 MonoTableInfo *paramt;
5760 if (!methodsig->param_count)
5763 if (klass->generic_class) {
5764 return; /* FIXME - ??? */
5767 mono_class_init (klass);
5769 if (klass->image->dynamic) {
5770 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5771 if (aux && aux->param_defaults) {
5772 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5773 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5778 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5779 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5780 constt = &image->tables [MONO_TABLE_CONSTANT];
5782 idx = mono_method_get_index (method) - 1;
5783 g_assert (idx != -1);
5785 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5786 if (idx + 1 < methodt->rows)
5787 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5789 lastp = paramt->rows + 1;
5791 for (i = param_index; i < lastp; ++i) {
5794 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5795 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5797 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5800 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5805 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5806 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5807 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5814 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5819 MonoType *basetype = type;
5824 klass = mono_class_from_mono_type (type);
5825 if (klass->valuetype) {
5826 object = mono_object_new (domain, klass);
5827 retval = ((gchar *) object + sizeof (MonoObject));
5828 if (klass->enumtype)
5829 basetype = klass->enum_basetype;
5834 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5841 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5845 memset (assembly, 0, sizeof (MonoAssemblyName));
5847 assembly->culture = "";
5848 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5850 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5853 while (g_ascii_isspace (*p) || *p == ',') {
5862 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5864 assembly->major = strtoul (p, &s, 10);
5865 if (s == p || *s != '.')
5868 assembly->minor = strtoul (p, &s, 10);
5869 if (s == p || *s != '.')
5872 assembly->build = strtoul (p, &s, 10);
5873 if (s == p || *s != '.')
5876 assembly->revision = strtoul (p, &s, 10);
5880 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5882 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5883 assembly->culture = "";
5886 assembly->culture = p;
5887 while (*p && *p != ',') {
5891 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5893 if (strncmp (p, "null", 4) == 0) {
5898 while (*p && *p != ',') {
5901 len = (p - start + 1);
5902 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5903 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5904 g_strlcpy (assembly->public_key_token, start, len);
5907 while (*p && *p != ',')
5911 while (g_ascii_isspace (*p) || *p == ',') {
5925 * mono_reflection_parse_type:
5928 * Parse a type name as accepted by the GetType () method and output the info
5929 * extracted in the info structure.
5930 * the name param will be mangled, so, make a copy before passing it to this function.
5931 * The fields in info will be valid until the memory pointed to by name is valid.
5933 * See also mono_type_get_name () below.
5935 * Returns: 0 on parse error.
5938 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5939 MonoTypeNameParse *info)
5941 char *start, *p, *w, *temp, *last_point, *startn;
5942 int in_modifiers = 0;
5943 int isbyref = 0, rank, arity = 0, i;
5945 start = p = w = name;
5947 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5948 info->name = info->name_space = NULL;
5949 info->nested = NULL;
5950 info->modifiers = NULL;
5951 info->type_arguments = NULL;
5953 /* last_point separates the namespace from the name */
5959 *p = 0; /* NULL terminate the name */
5961 info->nested = g_list_append (info->nested, startn);
5962 /* we have parsed the nesting namespace + name */
5966 info->name_space = start;
5968 info->name = last_point + 1;
5970 info->name_space = (char *)"";
5989 i = strtol (p, &temp, 10);
6006 info->name_space = start;
6008 info->name = last_point + 1;
6010 info->name_space = (char *)"";
6017 if (isbyref) /* only one level allowed by the spec */
6020 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6024 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6030 info->type_arguments = g_ptr_array_new ();
6031 for (i = 0; i < arity; i++) {
6032 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6033 gboolean fqname = FALSE;
6035 g_ptr_array_add (info->type_arguments, subinfo);
6042 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6053 while (*p && (*p != ']'))
6061 if (g_ascii_isspace (*aname)) {
6068 !assembly_name_to_aname (&subinfo->assembly, aname))
6072 if (i + 1 < arity) {
6092 else if (*p != '*') /* '*' means unknown lower bound */
6098 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6109 if (g_ascii_isspace (*p)) {
6116 return 0; /* missing assembly name */
6117 if (!assembly_name_to_aname (&info->assembly, p))
6123 if (info->assembly.name)
6126 // *w = 0; /* terminate class name */
6128 if (!info->name || !*info->name)
6132 /* add other consistency checks */
6137 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6139 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6143 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6145 gboolean type_resolve = FALSE;
6148 if (info->assembly.name) {
6149 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6151 /* then we must load the assembly ourselve - see #60439 */
6152 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6156 image = assembly->image;
6157 } else if (!image) {
6158 image = mono_defaults.corlib;
6161 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6162 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6163 image = mono_defaults.corlib;
6164 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6171 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6178 image = mono_defaults.corlib;
6181 klass = mono_class_from_name_case (image, info->name_space, info->name);
6183 klass = mono_class_from_name (image, info->name_space, info->name);
6186 for (mod = info->nested; mod; mod = mod->next) {
6189 mono_class_init (klass);
6190 nested = klass->nested_classes;
6193 klass = nested->data;
6195 if (g_strcasecmp (klass->name, mod->data) == 0)
6198 if (strcmp (klass->name, mod->data) == 0)
6202 nested = nested->next;
6209 mono_class_init (klass);
6211 if (info->type_arguments) {
6212 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6213 MonoReflectionType *the_type;
6217 for (i = 0; i < info->type_arguments->len; i++) {
6218 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6220 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6221 if (!type_args [i]) {
6227 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6229 instance = mono_reflection_bind_generic_parameters (
6230 the_type, info->type_arguments->len, type_args);
6237 klass = mono_class_from_mono_type (instance);
6240 for (mod = info->modifiers; mod; mod = mod->next) {
6241 modval = GPOINTER_TO_UINT (mod->data);
6242 if (!modval) { /* byref: must be last modifier */
6243 return &klass->this_arg;
6244 } else if (modval == -1) {
6245 klass = mono_ptr_class_get (&klass->byval_arg);
6246 } else { /* array rank */
6247 klass = mono_array_class_get (klass, modval);
6249 mono_class_init (klass);
6252 return &klass->byval_arg;
6256 * mono_reflection_get_type:
6257 * @image: a metadata context
6258 * @info: type description structure
6259 * @ignorecase: flag for case-insensitive string compares
6260 * @type_resolve: whenever type resolve was already tried
6262 * Build a MonoType from the type description in @info.
6267 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6270 MonoReflectionAssembly *assembly;
6274 type = mono_reflection_get_type_internal (image, info, ignorecase);
6277 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6284 *type_resolve = TRUE;
6287 /* Reconstruct the type name */
6288 fullName = g_string_new ("");
6289 if (info->name_space && (info->name_space [0] != '\0'))
6290 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6292 g_string_printf (fullName, info->name);
6293 for (mod = info->nested; mod; mod = mod->next)
6294 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6296 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6298 if (assembly->assembly->dynamic) {
6299 /* Enumerate all modules */
6300 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6304 if (abuilder->modules) {
6305 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6306 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6307 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6313 if (!type && abuilder->loaded_modules) {
6314 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6315 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6316 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6323 type = mono_reflection_get_type_internal (assembly->assembly->image,
6326 g_string_free (fullName, TRUE);
6331 free_type_info (MonoTypeNameParse *info)
6333 g_list_free (info->modifiers);
6334 g_list_free (info->nested);
6336 if (info->type_arguments) {
6339 for (i = 0; i < info->type_arguments->len; i++) {
6340 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6342 free_type_info (subinfo);
6345 g_ptr_array_free (info->type_arguments, TRUE);
6350 * mono_reflection_type_from_name:
6352 * @image: a metadata context (can be NULL).
6354 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6355 * it defaults to get the type from @image or, if @image is NULL or loading
6356 * from it fails, uses corlib.
6360 mono_reflection_type_from_name (char *name, MonoImage *image)
6362 MonoType *type = NULL;
6363 MonoTypeNameParse info;
6366 /* Make a copy since parse_type modifies its argument */
6367 tmp = g_strdup (name);
6369 /*g_print ("requested type %s\n", str);*/
6370 if (mono_reflection_parse_type (tmp, &info)) {
6371 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6375 free_type_info (&info);
6380 * mono_reflection_get_token:
6382 * Return the metadata token of OBJ which should be an object
6383 * representing a metadata element.
6386 mono_reflection_get_token (MonoObject *obj)
6391 klass = obj->vtable->klass;
6393 if (strcmp (klass->name, "MethodBuilder") == 0) {
6394 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6396 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6397 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6398 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6400 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6401 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6402 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6403 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6404 if (tb->generic_params) {
6405 g_assert_not_reached ();
6407 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6409 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6410 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6411 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6412 } else if (strcmp (klass->name, "MonoType") == 0) {
6413 MonoReflectionType *tb = (MonoReflectionType *)obj;
6414 token = mono_class_from_mono_type (tb->type)->type_token;
6415 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6416 strcmp (klass->name, "MonoMethod") == 0) {
6417 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6418 if (m->method->is_inflated) {
6419 g_assert_not_reached ();
6420 } else if (mono_method_signature (m->method)->generic_param_count) {
6421 g_assert_not_reached ();
6422 } else if (m->method->klass->generic_class) {
6423 g_assert_not_reached ();
6425 token = m->method->token;
6427 } else if (strcmp (klass->name, "MonoField") == 0) {
6428 MonoReflectionField *f = (MonoReflectionField*)obj;
6430 token = mono_class_get_field_token (f->field);
6431 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6432 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6434 token = mono_class_get_property_token (p->property);
6435 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6436 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6438 token = mono_class_get_event_token (p->event);
6439 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6440 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6442 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6443 } else if (strcmp (klass->name, "Module") == 0) {
6444 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6447 } else if (strcmp (klass->name, "Assembly") == 0) {
6448 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6450 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6451 MonoException *ex = mono_get_exception_not_implemented (msg);
6453 mono_raise_exception (ex);
6460 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6462 int slen, type = t->type;
6467 case MONO_TYPE_BOOLEAN: {
6468 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6473 case MONO_TYPE_CHAR:
6475 case MONO_TYPE_I2: {
6476 guint16 *val = g_malloc (sizeof (guint16));
6481 #if SIZEOF_VOID_P == 4
6487 case MONO_TYPE_I4: {
6488 guint32 *val = g_malloc (sizeof (guint32));
6493 #if SIZEOF_VOID_P == 8
6494 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6499 case MONO_TYPE_I8: {
6500 guint64 *val = g_malloc (sizeof (guint64));
6505 case MONO_TYPE_VALUETYPE:
6506 if (t->data.klass->enumtype) {
6507 type = t->data.klass->enum_basetype->type;
6510 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6513 case MONO_TYPE_STRING:
6514 if (*p == (char)0xFF) {
6518 slen = mono_metadata_decode_value (p, &p);
6520 return mono_string_new_len (mono_domain_get (), p, slen);
6521 case MONO_TYPE_CLASS: {
6524 if (*p == (char)0xFF) {
6529 slen = mono_metadata_decode_value (p, &p);
6530 n = g_memdup (p, slen + 1);
6532 t = mono_reflection_type_from_name (n, image);
6534 g_warning ("Cannot load type '%s'", n);
6538 return mono_type_get_object (mono_domain_get (), t);
6542 case MONO_TYPE_OBJECT: {
6545 MonoClass *subc = NULL;
6550 } else if (subt == 0x0E) {
6551 type = MONO_TYPE_STRING;
6553 } else if (subt == 0x55) {
6556 slen = mono_metadata_decode_value (p, &p);
6557 n = g_memdup (p, slen + 1);
6559 t = mono_reflection_type_from_name (n, image);
6561 g_warning ("Cannot load type '%s'", n);
6564 subc = mono_class_from_mono_type (t);
6565 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6566 MonoType simple_type = {{0}};
6567 simple_type.type = subt;
6568 subc = mono_class_from_mono_type (&simple_type);
6570 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6572 val = load_cattr_value (image, &subc->byval_arg, p, end);
6573 obj = mono_object_new (mono_domain_get (), subc);
6574 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6578 case MONO_TYPE_SZARRAY: {
6580 guint32 i, alen, basetype;
6583 if (alen == 0xffffffff) {
6587 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6588 basetype = t->data.klass->byval_arg.type;
6593 case MONO_TYPE_BOOLEAN:
6594 for (i = 0; i < alen; i++) {
6595 MonoBoolean val = *p++;
6596 mono_array_set (arr, MonoBoolean, i, val);
6599 case MONO_TYPE_CHAR:
6602 for (i = 0; i < alen; i++) {
6603 guint16 val = read16 (p);
6604 mono_array_set (arr, guint16, i, val);
6611 for (i = 0; i < alen; i++) {
6612 guint32 val = read32 (p);
6613 mono_array_set (arr, guint32, i, val);
6620 for (i = 0; i < alen; i++) {
6621 guint64 val = read64 (p);
6622 mono_array_set (arr, guint64, i, val);
6626 case MONO_TYPE_CLASS:
6627 case MONO_TYPE_OBJECT:
6628 case MONO_TYPE_STRING:
6629 for (i = 0; i < alen; i++) {
6630 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6631 mono_array_set (arr, gpointer, i, item);
6635 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6641 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6647 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6649 static MonoClass *klass;
6650 static MonoMethod *ctor;
6652 void *params [2], *unboxed;
6655 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6657 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6659 params [0] = mono_type_get_object (mono_domain_get (), t);
6661 retval = mono_object_new (mono_domain_get (), klass);
6662 unboxed = mono_object_unbox (retval);
6663 mono_runtime_invoke (ctor, unboxed, params, NULL);
6669 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6671 static MonoClass *klass;
6672 static MonoMethod *ctor;
6674 void *unboxed, *params [2];
6677 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6679 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6682 params [1] = typedarg;
6683 retval = mono_object_new (mono_domain_get (), klass);
6684 unboxed = mono_object_unbox (retval);
6685 mono_runtime_invoke (ctor, unboxed, params, NULL);
6691 type_is_reference (MonoType *type)
6693 switch (type->type) {
6694 case MONO_TYPE_BOOLEAN:
6695 case MONO_TYPE_CHAR:
6708 case MONO_TYPE_VALUETYPE:
6716 free_param_data (MonoMethodSignature *sig, void **params) {
6718 for (i = 0; i < sig->param_count; ++i) {
6719 if (!type_is_reference (sig->params [i]))
6720 g_free (params [i]);
6725 * Find the field index in the metadata FieldDef table.
6728 find_field_index (MonoClass *klass, MonoClassField *field) {
6731 for (i = 0; i < klass->field.count; ++i) {
6732 if (field == &klass->fields [i])
6733 return klass->field.first + 1 + i;
6739 * Find the property index in the metadata Property table.
6742 find_property_index (MonoClass *klass, MonoProperty *property) {
6745 for (i = 0; i < klass->property.count; ++i) {
6746 if (property == &klass->properties [i])
6747 return klass->property.first + 1 + i;
6753 * Find the event index in the metadata Event table.
6756 find_event_index (MonoClass *klass, MonoEvent *event) {
6759 for (i = 0; i < klass->event.count; ++i) {
6760 if (event == &klass->events [i])
6761 return klass->event.first + 1 + i;
6767 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6769 const char *p = data;
6771 guint32 i, j, num_named;
6775 mono_class_init (method->klass);
6778 attr = mono_object_new (mono_domain_get (), method->klass);
6779 mono_runtime_invoke (method, attr, NULL, NULL);
6783 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6786 /*g_print ("got attr %s\n", method->klass->name);*/
6788 /* Allocate using alloca so it gets GC tracking */
6789 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6793 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6794 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6798 attr = mono_object_new (mono_domain_get (), method->klass);
6799 mono_runtime_invoke (method, attr, params, NULL);
6800 free_param_data (method->signature, params);
6801 num_named = read16 (named);
6803 for (j = 0; j < num_named; j++) {
6805 gboolean is_boxed = FALSE;
6806 char *name, named_type, data_type;
6807 named_type = *named++;
6808 data_type = *named++; /* type of data */
6809 if (data_type == 0x51)
6812 if (data_type == 0x55) {
6815 type_len = mono_metadata_decode_blob_size (named, &named);
6816 type_name = g_malloc (type_len + 1);
6817 memcpy (type_name, named, type_len);
6818 type_name [type_len] = 0;
6820 /* FIXME: lookup the type and check type consistency */
6821 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6822 /* this seems to be the type of the element of the array */
6823 /* g_print ("skipping 0x%02x after prop\n", *named); */
6826 name_len = mono_metadata_decode_blob_size (named, &named);
6827 name = g_malloc (name_len + 1);
6828 memcpy (name, named, name_len);
6829 name [name_len] = 0;
6831 if (named_type == 0x53) {
6832 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6833 void *val = load_cattr_value (image, field->type, named, &named);
6834 mono_field_set_value (attr, field, val);
6835 if (!type_is_reference (field->type))
6837 } else if (named_type == 0x54) {
6840 MonoType *prop_type;
6842 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6843 /* can we have more that 1 arg in a custom attr named property? */
6844 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6845 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6846 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6847 mono_property_set_value (prop, attr, pparams, NULL);
6848 if (!type_is_reference (prop_type))
6849 g_free (pparams [0]);
6858 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6860 MonoArray *typedargs, *namedargs;
6861 MonoClass *attrklass;
6862 static MonoClass *klass;
6863 static MonoMethod *ctor;
6866 const char *p = data;
6868 guint32 i, j, num_named;
6871 mono_class_init (method->klass);
6874 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6876 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6878 domain = mono_domain_get ();
6880 /* This is for Attributes with no parameters */
6881 attr = mono_object_new (domain, klass);
6882 params [0] = mono_method_get_object (domain, method, NULL);
6883 params [1] = params [2] = NULL;
6884 mono_runtime_invoke (method, attr, params, NULL);
6888 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6891 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6895 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6896 MonoObject *obj, *typedarg;
6899 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6900 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6901 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6902 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6903 mono_array_set (typedargs, void*, i, typedarg);
6905 if (!type_is_reference (mono_method_signature (method)->params [i]))
6910 num_named = read16 (named);
6911 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6913 attrklass = method->klass;
6914 for (j = 0; j < num_named; j++) {
6916 char *name, named_type, data_type;
6917 named_type = *named++;
6918 data_type = *named++; /* type of data */
6919 if (data_type == 0x55) {
6922 type_len = mono_metadata_decode_blob_size (named, &named);
6923 type_name = g_malloc (type_len + 1);
6924 memcpy (type_name, named, type_len);
6925 type_name [type_len] = 0;
6927 /* FIXME: lookup the type and check type consistency */
6928 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6929 /* this seems to be the type of the element of the array */
6930 /* g_print ("skipping 0x%02x after prop\n", *named); */
6933 name_len = mono_metadata_decode_blob_size (named, &named);
6934 name = g_malloc (name_len + 1);
6935 memcpy (name, named, name_len);
6936 name [name_len] = 0;
6938 if (named_type == 0x53) {
6939 MonoObject *obj, *typedarg, *namedarg;
6940 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6941 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6943 minfo = mono_field_get_object (domain, NULL, field);
6944 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6945 typedarg = create_cattr_typed_arg (field->type, obj);
6946 namedarg = create_cattr_named_arg (minfo, typedarg);
6947 mono_array_set (namedargs, void*, j, namedarg);
6948 if (!type_is_reference (field->type))
6950 } else if (named_type == 0x54) {
6951 MonoObject *obj, *typedarg, *namedarg;
6952 MonoType *prop_type;
6954 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6956 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6957 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6958 minfo = mono_property_get_object (domain, NULL, prop);
6959 val = load_cattr_value (image, prop_type, named, &named);
6960 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6961 typedarg = create_cattr_typed_arg (prop_type, obj);
6962 namedarg = create_cattr_named_arg (minfo, typedarg);
6963 mono_array_set (namedargs, void*, j, namedarg);
6964 if (!type_is_reference (prop_type))
6969 attr = mono_object_new (domain, klass);
6970 params [0] = mono_method_get_object (domain, method, NULL);
6971 params [1] = typedargs;
6972 params [2] = namedargs;
6973 mono_runtime_invoke (ctor, attr, params, NULL);
6978 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6985 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6986 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6987 for (i = 0; i < cinfo->num_attrs; ++i) {
6988 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6989 mono_array_set (result, gpointer, i, attr);
6995 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
6998 static MonoClass *klass;
7003 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7005 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7006 for (i = 0; i < cinfo->num_attrs; ++i) {
7007 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7008 mono_array_set (result, gpointer, i, attr);
7014 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7016 guint32 mtoken, i, len;
7017 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7019 MonoCustomAttrInfo *ainfo;
7020 GList *tmp, *list = NULL;
7023 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7025 i = mono_metadata_custom_attrs_from_index (image, idx);
7029 while (i < ca->rows) {
7030 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7032 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7035 len = g_list_length (list);
7038 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7039 ainfo->num_attrs = len;
7040 ainfo->image = image;
7041 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7042 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7043 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7044 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7045 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7046 mtoken |= MONO_TOKEN_METHOD_DEF;
7048 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7049 mtoken |= MONO_TOKEN_MEMBER_REF;
7052 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7055 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7056 if (!ainfo->attrs [i].ctor)
7057 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7058 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7059 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7060 ainfo->attrs [i].data = data;
7068 mono_custom_attrs_from_method (MonoMethod *method)
7070 MonoCustomAttrInfo *cinfo;
7073 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7075 idx = mono_method_get_index (method);
7076 idx <<= MONO_CUSTOM_ATTR_BITS;
7077 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7078 return mono_custom_attrs_from_index (method->klass->image, idx);
7082 mono_custom_attrs_from_class (MonoClass *klass)
7084 MonoCustomAttrInfo *cinfo;
7087 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7089 idx = mono_metadata_token_index (klass->type_token);
7090 idx <<= MONO_CUSTOM_ATTR_BITS;
7091 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7092 return mono_custom_attrs_from_index (klass->image, idx);
7096 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7098 MonoCustomAttrInfo *cinfo;
7101 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7103 idx = 1; /* there is only one assembly */
7104 idx <<= MONO_CUSTOM_ATTR_BITS;
7105 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7106 return mono_custom_attrs_from_index (assembly->image, idx);
7109 static MonoCustomAttrInfo*
7110 mono_custom_attrs_from_module (MonoImage *image)
7112 MonoCustomAttrInfo *cinfo;
7115 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7117 idx = 1; /* there is only one module */
7118 idx <<= MONO_CUSTOM_ATTR_BITS;
7119 idx |= MONO_CUSTOM_ATTR_MODULE;
7120 return mono_custom_attrs_from_index (image, idx);
7124 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7126 MonoCustomAttrInfo *cinfo;
7129 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7131 idx = find_property_index (klass, property);
7132 idx <<= MONO_CUSTOM_ATTR_BITS;
7133 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7134 return mono_custom_attrs_from_index (klass->image, idx);
7138 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7140 MonoCustomAttrInfo *cinfo;
7143 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7145 idx = find_event_index (klass, event);
7146 idx <<= MONO_CUSTOM_ATTR_BITS;
7147 idx |= MONO_CUSTOM_ATTR_EVENT;
7148 return mono_custom_attrs_from_index (klass->image, idx);
7152 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7154 MonoCustomAttrInfo *cinfo;
7157 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7159 idx = find_field_index (klass, field);
7160 idx <<= MONO_CUSTOM_ATTR_BITS;
7161 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7162 return mono_custom_attrs_from_index (klass->image, idx);
7166 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7169 guint32 i, idx, method_index;
7170 guint32 param_list, param_last, param_pos, found;
7172 MonoReflectionMethodAux *aux;
7174 if (method->klass->image->dynamic) {
7175 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7176 if (!aux || !aux->param_cattr)
7178 return aux->param_cattr [param];
7181 image = method->klass->image;
7182 method_index = mono_method_get_index (method);
7183 ca = &image->tables [MONO_TABLE_METHOD];
7185 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7186 /* FIXME FIXME FIXME */
7190 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7191 if (method_index == ca->rows) {
7192 ca = &image->tables [MONO_TABLE_PARAM];
7193 param_last = ca->rows + 1;
7195 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7196 ca = &image->tables [MONO_TABLE_PARAM];
7199 for (i = param_list; i < param_last; ++i) {
7200 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7201 if (param_pos == param) {
7209 idx <<= MONO_CUSTOM_ATTR_BITS;
7210 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7211 return mono_custom_attrs_from_index (image, idx);
7215 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7219 for (i = 0; i < ainfo->num_attrs; ++i) {
7220 klass = ainfo->attrs [i].ctor->klass;
7221 if (mono_class_has_parent (klass, attr_klass))
7228 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7235 for (i = 0; i < ainfo->num_attrs; ++i) {
7236 klass = ainfo->attrs [i].ctor->klass;
7237 if (mono_class_has_parent (klass, attr_klass)) {
7242 if (attr_index == -1)
7245 attrs = mono_custom_attrs_construct (ainfo);
7247 return mono_array_get (attrs, MonoObject*, attr_index);
7253 * mono_reflection_get_custom_attrs_info:
7254 * @obj: a reflection object handle
7256 * Return the custom attribute info for attributes defined for the
7257 * reflection handle @obj. The objects.
7260 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7263 MonoCustomAttrInfo *cinfo = NULL;
7265 klass = obj->vtable->klass;
7266 if (klass == mono_defaults.monotype_class) {
7267 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7268 klass = mono_class_from_mono_type (rtype->type);
7269 cinfo = mono_custom_attrs_from_class (klass);
7270 } else if (strcmp ("Assembly", klass->name) == 0) {
7271 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7272 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7273 } else if (strcmp ("Module", klass->name) == 0) {
7274 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7275 cinfo = mono_custom_attrs_from_module (module->image);
7276 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7277 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7278 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7279 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7280 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7281 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7282 } else if (strcmp ("MonoField", klass->name) == 0) {
7283 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7284 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7285 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7286 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7287 cinfo = mono_custom_attrs_from_method (rmethod->method);
7288 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7289 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7290 cinfo = mono_custom_attrs_from_method (method);
7291 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7292 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7293 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7294 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7295 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7296 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7297 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7298 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7299 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7300 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7301 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7302 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7303 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7304 } else { /* handle other types here... */
7305 g_error ("get custom attrs not yet supported for %s", klass->name);
7312 * mono_reflection_get_custom_attrs:
7313 * @obj: a reflection object handle
7315 * Return an array with all the custom attributes defined of the
7316 * reflection handle @obj. The objects are fully build.
7319 mono_reflection_get_custom_attrs (MonoObject *obj)
7322 MonoCustomAttrInfo *cinfo;
7324 cinfo = mono_reflection_get_custom_attrs_info (obj);
7326 result = mono_custom_attrs_construct (cinfo);
7328 mono_custom_attrs_free (cinfo);
7331 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7332 result = mono_array_new (mono_domain_get (), klass, 0);
7339 * mono_reflection_get_custom_attrs_data:
7340 * @obj: a reflection obj handle
7342 * Returns an array of System.Reflection.CustomAttributeData,
7343 * which include information about attributes reflected on
7344 * types loaded using the Reflection Only methods
7347 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7350 MonoCustomAttrInfo *cinfo;
7352 cinfo = mono_reflection_get_custom_attrs_info (obj);
7354 result = mono_custom_attrs_data_construct (cinfo);
7356 mono_custom_attrs_free (cinfo);
7359 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7360 result = mono_array_new (mono_domain_get (), klass, 0);
7366 static MonoMethodSignature*
7367 parameters_to_signature (MonoArray *parameters) {
7368 MonoMethodSignature *sig;
7371 count = parameters? mono_array_length (parameters): 0;
7373 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7374 sig->param_count = count;
7375 sig->sentinelpos = -1; /* FIXME */
7376 for (i = 0; i < count; ++i) {
7377 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7378 sig->params [i] = pt->type;
7383 static MonoMethodSignature*
7384 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7385 MonoMethodSignature *sig;
7387 sig = parameters_to_signature (ctor->parameters);
7388 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7389 sig->ret = &mono_defaults.void_class->byval_arg;
7393 static MonoMethodSignature*
7394 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7395 MonoMethodSignature *sig;
7397 sig = parameters_to_signature (method->parameters);
7398 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7399 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7400 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7404 static MonoMethodSignature*
7405 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7406 MonoMethodSignature *sig;
7408 sig = parameters_to_signature (method->parameters);
7409 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7410 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7411 sig->generic_param_count = 0;
7416 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7418 MonoClass *klass = mono_object_class (prop);
7419 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7420 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7421 *name = mono_string_to_utf8 (pb->name);
7422 *type = pb->type->type;
7424 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7425 *name = g_strdup (p->property->name);
7426 if (p->property->get)
7427 *type = mono_method_signature (p->property->get)->ret;
7429 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7434 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7436 MonoClass *klass = mono_object_class (field);
7437 if (strcmp (klass->name, "FieldBuilder") == 0) {
7438 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7439 *name = mono_string_to_utf8 (fb->name);
7440 *type = fb->type->type;
7442 MonoReflectionField *f = (MonoReflectionField *)field;
7443 *name = g_strdup (f->field->name);
7444 *type = f->field->type;
7449 * Encode a value in a custom attribute stream of bytes.
7450 * The value to encode is either supplied as an object in argument val
7451 * (valuetypes are boxed), or as a pointer to the data in the
7453 * @type represents the type of the value
7454 * @buffer is the start of the buffer
7455 * @p the current position in the buffer
7456 * @buflen contains the size of the buffer and is used to return the new buffer size
7457 * if this needs to be realloced.
7458 * @retbuffer and @retp return the start and the position of the buffer
7461 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7463 MonoTypeEnum simple_type;
7465 if ((p-buffer) + 10 >= *buflen) {
7468 newbuf = g_realloc (buffer, *buflen);
7469 p = newbuf + (p-buffer);
7473 argval = ((char*)arg + sizeof (MonoObject));
7474 simple_type = type->type;
7476 switch (simple_type) {
7477 case MONO_TYPE_BOOLEAN:
7482 case MONO_TYPE_CHAR:
7485 swap_with_size (p, argval, 2, 1);
7491 swap_with_size (p, argval, 4, 1);
7497 swap_with_size (p, argval, 8, 1);
7500 case MONO_TYPE_VALUETYPE:
7501 if (type->data.klass->enumtype) {
7502 simple_type = type->data.klass->enum_basetype->type;
7505 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7508 case MONO_TYPE_STRING: {
7515 str = mono_string_to_utf8 ((MonoString*)arg);
7516 slen = strlen (str);
7517 if ((p-buffer) + 10 + slen >= *buflen) {
7521 newbuf = g_realloc (buffer, *buflen);
7522 p = newbuf + (p-buffer);
7525 mono_metadata_encode_value (slen, p, &p);
7526 memcpy (p, str, slen);
7531 case MONO_TYPE_CLASS: {
7539 k = mono_object_class (arg);
7540 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7541 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7542 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7544 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7545 slen = strlen (str);
7546 if ((p-buffer) + 10 + slen >= *buflen) {
7550 newbuf = g_realloc (buffer, *buflen);
7551 p = newbuf + (p-buffer);
7554 mono_metadata_encode_value (slen, p, &p);
7555 memcpy (p, str, slen);
7560 case MONO_TYPE_SZARRAY: {
7562 MonoClass *eclass, *arg_eclass;
7565 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7568 len = mono_array_length ((MonoArray*)arg);
7570 *p++ = (len >> 8) & 0xff;
7571 *p++ = (len >> 16) & 0xff;
7572 *p++ = (len >> 24) & 0xff;
7574 *retbuffer = buffer;
7575 eclass = type->data.klass;
7576 arg_eclass = mono_object_class (arg)->element_class;
7577 if (eclass->valuetype && arg_eclass->valuetype) {
7578 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7579 int elsize = mono_class_array_element_size (eclass);
7580 for (i = 0; i < len; ++i) {
7581 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7585 for (i = 0; i < len; ++i) {
7586 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7591 /* it may be a boxed value or a Type */
7592 case MONO_TYPE_OBJECT: {
7598 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7603 klass = mono_object_class (arg);
7605 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7608 } else if (klass->enumtype) {
7610 } else if (klass == mono_defaults.string_class) {
7611 simple_type = MONO_TYPE_STRING;
7614 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7615 *p++ = simple_type = klass->byval_arg.type;
7618 g_error ("unhandled type in custom attr");
7620 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7621 slen = strlen (str);
7622 if ((p-buffer) + 10 + slen >= *buflen) {
7626 newbuf = g_realloc (buffer, *buflen);
7627 p = newbuf + (p-buffer);
7630 mono_metadata_encode_value (slen, p, &p);
7631 memcpy (p, str, slen);
7634 simple_type = klass->enum_basetype->type;
7638 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7641 *retbuffer = buffer;
7645 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7648 /* Preallocate a large enough buffer */
7649 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7650 char *str = type_get_qualified_name (type, NULL);
7656 len += strlen (name);
7658 if ((p-buffer) + 20 + len >= *buflen) {
7662 newbuf = g_realloc (buffer, *buflen);
7663 p = newbuf + (p-buffer);
7667 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7668 char *str = type_get_qualified_name (type, NULL);
7669 int slen = strlen (str);
7673 * This seems to be optional...
7676 mono_metadata_encode_value (slen, p, &p);
7677 memcpy (p, str, slen);
7680 } else if (type->type == MONO_TYPE_OBJECT) {
7682 } else if (type->type == MONO_TYPE_CLASS) {
7683 /* it should be a type: encode_cattr_value () has the check */
7686 mono_metadata_encode_value (type->type, p, &p);
7687 if (type->type == MONO_TYPE_SZARRAY)
7688 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7690 len = strlen (name);
7691 mono_metadata_encode_value (len, p, &p);
7692 memcpy (p, name, len);
7694 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7696 *retbuffer = buffer;
7700 * mono_reflection_get_custom_attrs_blob:
7701 * @ctor: custom attribute constructor
7702 * @ctorArgs: arguments o the constructor
7708 * Creates the blob of data that needs to be saved in the metadata and that represents
7709 * the custom attributed described by @ctor, @ctorArgs etc.
7710 * Returns: a Byte array representing the blob of data.
7713 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7716 MonoMethodSignature *sig;
7721 MONO_ARCH_SAVE_REGS;
7723 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7724 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7726 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7728 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7730 p = buffer = g_malloc (buflen);
7731 /* write the prolog */
7734 for (i = 0; i < sig->param_count; ++i) {
7735 arg = mono_array_get (ctorArgs, MonoObject*, i);
7736 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7740 i += mono_array_length (properties);
7742 i += mono_array_length (fields);
7744 *p++ = (i >> 8) & 0xff;
7747 for (i = 0; i < mono_array_length (properties); ++i) {
7751 prop = mono_array_get (properties, gpointer, i);
7752 get_prop_name_and_type (prop, &pname, &ptype);
7753 *p++ = 0x54; /* PROPERTY signature */
7754 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7761 for (i = 0; i < mono_array_length (fields); ++i) {
7765 field = mono_array_get (fields, gpointer, i);
7766 get_field_name_and_type (field, &fname, &ftype);
7767 *p++ = 0x53; /* FIELD signature */
7768 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7773 g_assert (p - buffer <= buflen);
7774 buflen = p - buffer;
7775 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7776 p = mono_array_addr (result, char, 0);
7777 memcpy (p, buffer, buflen);
7779 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7785 * mono_reflection_setup_internal_class:
7786 * @tb: a TypeBuilder object
7788 * Creates a MonoClass that represents the TypeBuilder.
7789 * This is a trick that lets us simplify a lot of reflection code
7790 * (and will allow us to support Build and Run assemblies easier).
7793 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7795 MonoClass *klass, *parent;
7797 MONO_ARCH_SAVE_REGS;
7799 mono_loader_lock ();
7802 /* check so we can compile corlib correctly */
7803 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7804 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7805 parent = tb->parent->type->data.klass;
7807 parent = my_mono_class_from_mono_type (tb->parent->type);
7813 /* the type has already being created: it means we just have to change the parent */
7814 if (tb->type.type) {
7815 klass = mono_class_from_mono_type (tb->type.type);
7816 klass->parent = NULL;
7817 /* fool mono_class_setup_parent */
7818 g_free (klass->supertypes);
7819 klass->supertypes = NULL;
7820 mono_class_setup_parent (klass, parent);
7821 mono_class_setup_mono_type (klass);
7822 mono_loader_unlock ();
7826 klass = g_new0 (MonoClass, 1);
7828 klass->image = &tb->module->dynamic_image->image;
7830 klass->inited = 1; /* we lie to the runtime */
7831 klass->name = mono_string_to_utf8 (tb->name);
7832 klass->name_space = mono_string_to_utf8 (tb->nspace);
7833 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7834 klass->flags = tb->attrs;
7836 klass->element_class = klass;
7837 klass->reflection_info = tb; /* need to pin. */
7839 /* Put into cache so mono_class_get () will find it */
7840 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7842 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7843 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7845 if (parent != NULL) {
7846 mono_class_setup_parent (klass, parent);
7847 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7848 const char *old_n = klass->name;
7849 /* trick to get relative numbering right when compiling corlib */
7850 klass->name = "BuildingObject";
7851 mono_class_setup_parent (klass, mono_defaults.object_class);
7852 klass->name = old_n;
7855 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7856 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7857 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7858 klass->instance_size = sizeof (MonoObject);
7859 klass->size_inited = 1;
7860 mono_class_setup_vtable_general (klass, NULL, 0);
7863 mono_class_setup_mono_type (klass);
7865 mono_class_setup_supertypes (klass);
7868 * FIXME: handle interfaces.
7871 tb->type.type = &klass->byval_arg;
7873 if (tb->nesting_type) {
7874 g_assert (tb->nesting_type->type);
7875 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7878 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7880 mono_loader_unlock ();
7884 * mono_reflection_setup_generic_class:
7885 * @tb: a TypeBuilder object
7887 * Setup the generic class before adding the first generic parameter.
7890 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7894 MONO_ARCH_SAVE_REGS;
7896 klass = my_mono_class_from_mono_type (tb->type.type);
7897 if (tb->generic_container)
7900 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7901 tb->generic_container->klass = klass;
7903 tb->generic_container->context.container = tb->generic_container;
7907 * mono_reflection_create_generic_class:
7908 * @tb: a TypeBuilder object
7910 * Creates the generic class after all generic parameters have been added.
7913 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7918 MONO_ARCH_SAVE_REGS;
7920 klass = my_mono_class_from_mono_type (tb->type.type);
7922 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7924 if (klass->generic_container || (count == 0))
7927 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7929 klass->generic_container = tb->generic_container;
7931 klass->generic_container->type_argc = count;
7932 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7934 for (i = 0; i < count; i++) {
7935 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7936 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7937 g_assert (klass->generic_container->type_params [i].owner);
7940 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7944 * mono_reflection_create_internal_class:
7945 * @tb: a TypeBuilder object
7947 * Actually create the MonoClass that is associated with the TypeBuilder.
7950 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7954 MONO_ARCH_SAVE_REGS;
7956 klass = my_mono_class_from_mono_type (tb->type.type);
7958 mono_loader_lock ();
7959 if (klass->enumtype && klass->enum_basetype == NULL) {
7960 MonoReflectionFieldBuilder *fb;
7963 g_assert (tb->fields != NULL);
7964 g_assert (mono_array_length (tb->fields) >= 1);
7966 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7968 klass->enum_basetype = fb->type->type;
7969 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7970 if (!klass->element_class)
7971 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7974 * get the element_class from the current corlib.
7976 ec = default_class_from_mono_type (klass->enum_basetype);
7977 klass->instance_size = ec->instance_size;
7978 klass->size_inited = 1;
7980 * this is almost safe to do with enums and it's needed to be able
7981 * to create objects of the enum type (for use in SetConstant).
7983 /* FIXME: Does this mean enums can't have method overrides ? */
7984 mono_class_setup_vtable_general (klass, NULL, 0);
7986 mono_loader_unlock ();
7989 static MonoMarshalSpec*
7990 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7991 MonoReflectionMarshal *minfo)
7993 MonoMarshalSpec *res;
7995 res = g_new0 (MonoMarshalSpec, 1);
7996 res->native = minfo->type;
7998 switch (minfo->type) {
7999 case MONO_NATIVE_LPARRAY:
8000 res->data.array_data.elem_type = minfo->eltype;
8001 if (minfo->has_size) {
8002 res->data.array_data.param_num = minfo->param_num;
8003 res->data.array_data.num_elem = minfo->count;
8004 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8007 res->data.array_data.param_num = -1;
8008 res->data.array_data.num_elem = -1;
8009 res->data.array_data.elem_mult = -1;
8013 case MONO_NATIVE_BYVALTSTR:
8014 case MONO_NATIVE_BYVALARRAY:
8015 res->data.array_data.num_elem = minfo->count;
8018 case MONO_NATIVE_CUSTOM:
8019 if (minfo->marshaltyperef)
8020 res->data.custom_data.custom_name =
8021 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8023 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8033 MonoReflectionMarshal*
8034 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8035 MonoMarshalSpec *spec)
8037 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8038 MonoReflectionMarshal *minfo;
8041 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8042 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8043 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8044 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8047 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8048 minfo->type = spec->native;
8050 switch (minfo->type) {
8051 case MONO_NATIVE_LPARRAY:
8052 minfo->eltype = spec->data.array_data.elem_type;
8053 minfo->count = spec->data.array_data.num_elem;
8054 minfo->param_num = spec->data.array_data.param_num;
8057 case MONO_NATIVE_BYVALTSTR:
8058 case MONO_NATIVE_BYVALARRAY:
8059 minfo->count = spec->data.array_data.num_elem;
8062 case MONO_NATIVE_CUSTOM:
8063 if (spec->data.custom_data.custom_name) {
8064 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8066 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8068 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8070 if (spec->data.custom_data.cookie)
8071 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8082 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8083 ReflectionMethodBuilder *rmb,
8084 MonoMethodSignature *sig)
8087 MonoMethodNormal *pm;
8088 MonoMarshalSpec **specs;
8089 MonoReflectionMethodAux *method_aux;
8092 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8093 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8094 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8096 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8098 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8100 pm = (MonoMethodNormal*)m;
8103 m->flags = rmb->attrs;
8104 m->iflags = rmb->iattrs;
8105 m->name = mono_string_to_utf8 (rmb->name);
8109 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8111 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8112 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8115 m->signature->pinvoke = 1;
8116 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8117 m->signature->pinvoke = 1;
8119 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8121 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8122 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8124 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8126 if (klass->image->dynamic)
8127 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8130 } else if (!m->klass->dummy &&
8131 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8132 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8133 MonoMethodHeader *header;
8135 gint32 max_stack, i;
8136 gint32 num_locals = 0;
8137 gint32 num_clauses = 0;
8141 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8142 code_size = rmb->ilgen->code_len;
8143 max_stack = rmb->ilgen->max_stack;
8144 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8145 if (rmb->ilgen->ex_handlers)
8146 num_clauses = method_count_clauses (rmb->ilgen);
8149 code = mono_array_addr (rmb->code, guint8, 0);
8150 code_size = mono_array_length (rmb->code);
8151 /* we probably need to run a verifier on the code... */
8161 header = g_malloc0 (sizeof (MonoMethodHeader) +
8162 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8163 header->code_size = code_size;
8164 header->code = g_malloc (code_size);
8165 memcpy ((char*)header->code, code, code_size);
8166 header->max_stack = max_stack;
8167 header->init_locals = rmb->init_locals;
8168 header->num_locals = num_locals;
8170 for (i = 0; i < num_locals; ++i) {
8171 MonoReflectionLocalBuilder *lb =
8172 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8174 header->locals [i] = g_new0 (MonoType, 1);
8175 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8178 header->num_clauses = num_clauses;
8180 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8181 rmb->ilgen, num_clauses);
8184 pm->header = header;
8187 if (rmb->generic_params) {
8188 int count = mono_array_length (rmb->generic_params);
8189 MonoGenericContainer *container;
8191 pm->generic_container = container = rmb->generic_container;
8192 container->type_argc = count;
8193 container->type_params = g_new0 (MonoGenericParam, count);
8195 for (i = 0; i < count; i++) {
8196 MonoReflectionGenericParam *gp =
8197 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8199 container->type_params [i] = *gp->type.type->data.generic_param;
8204 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8208 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8210 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8211 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8212 for (i = 0; i < rmb->nrefs; ++i)
8213 data [i + 1] = rmb->refs [i];
8218 /* Parameter info */
8221 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8222 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8223 for (i = 0; i <= m->signature->param_count; ++i) {
8224 MonoReflectionParamBuilder *pb;
8225 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8226 if ((i > 0) && (pb->attrs)) {
8227 /* Make a copy since it might point to a shared type structure */
8228 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)));
8229 m->signature->params [i - 1]->attrs = pb->attrs;
8232 if (pb->def_value) {
8233 MonoDynamicImage *assembly;
8234 guint32 idx, def_type, len;
8238 if (!method_aux->param_defaults) {
8239 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8240 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8242 assembly = (MonoDynamicImage*)klass->image;
8243 idx = encode_constant (assembly, pb->def_value, &def_type);
8244 /* Copy the data from the blob since it might get realloc-ed */
8245 p = assembly->blob.data + idx;
8246 len = mono_metadata_decode_blob_size (p, &p2);
8248 method_aux->param_defaults [i] = g_malloc (len);
8249 method_aux->param_default_types [i] = def_type;
8250 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8254 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8256 if (!method_aux->param_cattr)
8257 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8258 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8264 /* Parameter marshalling */
8267 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8268 MonoReflectionParamBuilder *pb;
8269 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8270 if (pb->marshal_info) {
8272 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8273 specs [pb->position] =
8274 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8278 if (specs != NULL) {
8280 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8281 method_aux->param_marshall = specs;
8284 if (klass->image->dynamic && method_aux)
8285 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8291 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8293 ReflectionMethodBuilder rmb;
8294 MonoMethodSignature *sig;
8296 sig = ctor_builder_to_signature (mb);
8298 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8300 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8301 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8303 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8304 /* ilgen is no longer needed */
8312 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8314 ReflectionMethodBuilder rmb;
8315 MonoMethodSignature *sig;
8317 sig = method_builder_to_signature (mb);
8319 reflection_methodbuilder_from_method_builder (&rmb, mb);
8321 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8322 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8324 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8325 /* ilgen is no longer needed */
8331 static MonoClassField*
8332 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8334 MonoClassField *field;
8341 field = g_new0 (MonoClassField, 1);
8343 field->name = mono_string_to_utf8 (fb->name);
8345 /* FIXME: handle type modifiers */
8346 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8347 field->type->attrs = fb->attrs;
8349 field->type = fb->type->type;
8351 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8352 field->data = mono_array_addr (fb->rva_data, char, 0);
8353 if (fb->offset != -1)
8354 field->offset = fb->offset;
8355 field->parent = klass;
8357 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8359 if (fb->def_value) {
8360 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8361 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8362 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8363 /* Copy the data from the blob since it might get realloc-ed */
8364 p = assembly->blob.data + idx;
8365 len = mono_metadata_decode_blob_size (p, &p2);
8367 field->data = g_malloc (len);
8368 memcpy ((gpointer)field->data, p, len);
8375 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8379 MonoReflectionTypeBuilder *tb = NULL;
8380 MonoGenericClass *gclass, *cached;
8381 MonoInflatedGenericClass *igclass;
8382 MonoDynamicGenericClass *dgclass = NULL;
8383 gboolean is_dynamic = FALSE;
8388 klass = mono_class_from_mono_type (type->type);
8389 if (!klass->generic_container && !klass->generic_class &&
8390 !(klass->nested_in && klass->nested_in->generic_container))
8393 mono_loader_lock ();
8395 domain = mono_object_domain (type);
8397 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8398 tb = (MonoReflectionTypeBuilder *) type;
8400 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8402 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8403 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8404 MonoReflectionType *rgt = rgi->generic_type;
8406 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8407 tb = (MonoReflectionTypeBuilder *) rgt;
8409 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8412 icount = klass->interface_count;
8416 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8417 igclass = &dgclass->generic_class;
8418 gclass = &igclass->generic_class;
8419 gclass->is_dynamic = TRUE;
8420 gclass->is_inflated = TRUE;
8422 igclass = g_new0 (MonoInflatedGenericClass, 1);
8423 gclass = &igclass->generic_class;
8424 gclass->is_inflated = TRUE;
8427 gclass->inst = g_new0 (MonoGenericInst, 1);
8429 gclass->inst->type_argc = type_argc;
8430 gclass->inst->type_argv = types;
8431 gclass->inst->is_reference = 1;
8433 for (i = 0; i < gclass->inst->type_argc; ++i) {
8434 if (!gclass->inst->is_open)
8435 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8436 if (gclass->inst->is_reference)
8437 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8440 gclass->container_class = klass;
8442 if (klass->generic_class) {
8443 MonoGenericClass *kgclass = klass->generic_class;
8444 MonoGenericClass *ogclass = gclass;
8446 ogclass->context = g_new0 (MonoGenericContext, 1);
8447 ogclass->context->container = gclass->container_class->generic_container;
8448 ogclass->context->gclass = gclass;
8451 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8452 igclass = &dgclass->generic_class;
8453 gclass = &igclass->generic_class;
8454 gclass->is_dynamic = TRUE;
8455 gclass->is_inflated = TRUE;
8457 igclass = g_new0 (MonoInflatedGenericClass, 1);
8458 gclass = &igclass->generic_class;
8459 gclass->is_inflated = TRUE;
8462 gclass->inst = g_new0 (MonoGenericInst, 1);
8464 gclass->inst->type_argc = kgclass->inst->type_argc;
8465 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8466 gclass->inst->is_reference = 1;
8468 for (i = 0; i < gclass->inst->type_argc; i++) {
8469 MonoType *t = kgclass->inst->type_argv [i];
8471 t = mono_class_inflate_generic_type (t, ogclass->context);
8473 if (!gclass->inst->is_open)
8474 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8475 if (gclass->inst->is_reference)
8476 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8478 gclass->inst->type_argv [i] = t;
8481 gclass->container_class = kgclass->container_class;
8484 geninst = g_new0 (MonoType, 1);
8485 geninst->type = MONO_TYPE_GENERICINST;
8487 cached = mono_metadata_lookup_generic_class (gclass);
8490 mono_loader_unlock ();
8491 geninst->data.generic_class = cached;
8495 geninst->data.generic_class = gclass;
8497 gclass->context = g_new0 (MonoGenericContext, 1);
8498 gclass->context->container = gclass->container_class->generic_container;
8499 gclass->context->gclass = gclass;
8502 dgclass->parent = parent;
8503 dgclass->ifaces = g_new0 (MonoType *, icount);
8504 dgclass->count_ifaces = icount;
8506 for (i = 0; i < icount; i++) {
8507 MonoReflectionType *itype;
8510 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8512 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8513 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8514 if (!dgclass->ifaces [i])
8515 dgclass->ifaces [i] = itype->type;
8519 mono_loader_unlock ();
8525 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8527 MonoClass *klass, *pklass = NULL;
8528 MonoReflectionType *parent = NULL;
8529 MonoType *the_parent = NULL, *geninst;
8530 MonoReflectionTypeBuilder *tb = NULL;
8531 MonoGenericClass *gclass;
8534 domain = mono_object_domain (type);
8535 klass = mono_class_from_mono_type (type->type);
8537 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8538 tb = (MonoReflectionTypeBuilder *) type;
8541 parent = tb->parent;
8542 pklass = mono_class_from_mono_type (parent->type);
8545 pklass = klass->parent;
8547 parent = mono_type_get_object (domain, &pklass->byval_arg);
8548 else if (klass->generic_class && klass->generic_class->is_dynamic) {
8549 MonoDynamicGenericClass *dgclass;
8551 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8552 if (dgclass->parent) {
8553 parent = mono_type_get_object (domain, dgclass->parent);
8554 pklass = mono_class_from_mono_type (dgclass->parent);
8559 if (pklass && pklass->generic_class)
8560 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8562 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8566 gclass = geninst->data.generic_class;
8572 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8575 MonoGenericClass *gclass, *cached;
8576 MonoInflatedGenericClass *igclass;
8580 klass = mono_class_from_mono_type (type);
8581 if (!klass->generic_container && !klass->generic_class &&
8582 !(klass->nested_in && klass->nested_in->generic_container))
8585 mono_loader_lock ();
8587 icount = klass->interface_count;
8589 igclass = g_new0 (MonoInflatedGenericClass, 1);
8590 gclass = &igclass->generic_class;
8591 gclass->is_inflated = TRUE;
8593 gclass->inst = g_new0 (MonoGenericInst, 1);
8594 gclass->inst->type_argc = type_argc;
8595 gclass->inst->type_argv = types;
8596 gclass->inst->is_reference = 1;
8598 for (i = 0; i < gclass->inst->type_argc; ++i) {
8599 if (!gclass->inst->is_open)
8600 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8601 if (gclass->inst->is_reference)
8602 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8605 gclass->container_class = klass;
8607 if (klass->generic_class) {
8608 MonoGenericClass *kgclass = klass->generic_class;
8609 MonoGenericClass *ogclass = gclass;
8611 gclass->context = g_new0 (MonoGenericContext, 1);
8612 gclass->context->container = gclass->container_class->generic_container;
8613 gclass->context->gclass = gclass;
8615 igclass = g_new0 (MonoInflatedGenericClass, 1);
8616 gclass = &igclass->generic_class;
8617 gclass->is_inflated = TRUE;
8619 gclass->inst = g_new0 (MonoGenericInst, 1);
8620 gclass->inst->type_argc = kgclass->inst->type_argc;
8621 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8622 gclass->inst->is_reference = 1;
8624 for (i = 0; i < gclass->inst->type_argc; i++) {
8625 MonoType *t = kgclass->inst->type_argv [i];
8627 t = mono_class_inflate_generic_type (t, ogclass->context);
8629 if (!gclass->inst->is_open)
8630 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8631 if (gclass->inst->is_reference)
8632 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8634 gclass->inst->type_argv [i] = t;
8637 gclass->container_class = kgclass->container_class;
8640 geninst = g_new0 (MonoType, 1);
8641 geninst->type = MONO_TYPE_GENERICINST;
8643 cached = mono_metadata_lookup_generic_class (gclass);
8646 mono_loader_unlock ();
8647 geninst->data.generic_class = cached;
8651 geninst->data.generic_class = gclass;
8653 gclass->context = g_new0 (MonoGenericContext, 1);
8654 gclass->context->container = gclass->container_class->generic_container;
8655 gclass->context->gclass = gclass;
8657 mono_loader_unlock ();
8662 static inline MonoType*
8663 dup_type (const MonoType *original)
8665 MonoType *r = g_new0 (MonoType, 1);
8667 r->attrs = original->attrs;
8668 r->byref = original->byref;
8669 if (original->type == MONO_TYPE_PTR)
8670 r->data.type = dup_type (original->data.type);
8671 mono_stats.generics_metadata_size += sizeof (MonoType);
8675 MonoReflectionMethod*
8676 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8678 MonoMethod *method, *inflated;
8679 MonoReflectionMethodBuilder *mb = NULL;
8680 MonoGenericContainer *container;
8681 MonoGenericMethod *gmethod;
8682 MonoGenericContext *context;
8683 MonoGenericInst *ginst;
8686 MONO_ARCH_SAVE_REGS;
8687 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8688 MonoReflectionTypeBuilder *tb;
8691 mb = (MonoReflectionMethodBuilder *) rmethod;
8692 tb = (MonoReflectionTypeBuilder *) mb->type;
8693 klass = mono_class_from_mono_type (tb->type.type);
8695 method = methodbuilder_to_mono_method (klass, mb);
8697 method = rmethod->method;
8700 method = mono_get_inflated_method (method);
8702 count = mono_method_signature (method)->generic_param_count;
8703 if (count != mono_array_length (types))
8706 container = ((MonoMethodNormal*) method)->generic_container;
8707 g_assert (container);
8709 if (!container->method_hash)
8710 container->method_hash = g_hash_table_new (
8711 (GHashFunc) mono_metadata_generic_method_hash,
8712 (GCompareFunc) mono_metadata_generic_method_equal);
8714 ginst = g_new0 (MonoGenericInst,1 );
8715 ginst->type_argc = count;
8716 ginst->type_argv = g_new0 (MonoType *, count);
8717 ginst->is_reference = 1;
8718 for (i = 0; i < count; i++) {
8719 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8720 ginst->type_argv [i] = dup_type (garg->type);
8722 if (!ginst->is_open)
8723 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8724 if (ginst->is_reference)
8725 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8727 ginst = mono_metadata_lookup_generic_inst (ginst);
8729 gmethod = g_new0 (MonoGenericMethod, 1);
8730 gmethod->generic_class = method->klass->generic_class;
8731 gmethod->container = container;
8732 gmethod->inst = ginst;
8734 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8738 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8741 gmethod->reflection_info = rmethod;
8743 context = g_new0 (MonoGenericContext, 1);
8744 context->container = container;
8745 context->gclass = method->klass->generic_class;
8746 context->gmethod = gmethod;
8748 if (method->is_inflated)
8749 method = ((MonoMethodInflated *) method)->declaring;
8751 inflated = mono_class_inflate_generic_method (method, context);
8752 g_hash_table_insert (container->method_hash, gmethod, inflated);
8754 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8758 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8760 MonoGenericMethod *gmethod;
8761 MonoInflatedGenericClass *gclass;
8762 MonoGenericContext *context;
8765 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8767 gmethod = g_new0 (MonoGenericMethod, 1);
8768 gmethod->generic_class = &gclass->generic_class;
8769 gmethod->inst = g_new0 (MonoGenericInst, 1);
8770 gmethod->reflection_info = obj;
8772 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8773 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8775 for (i = 0; i < gmethod->inst->type_argc; i++) {
8776 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8777 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8779 g_assert (gparam->pklass);
8780 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8783 context = g_new0 (MonoGenericContext, 1);
8784 context->container = gclass->generic_class.container_class->generic_container;
8785 context->gclass = &gclass->generic_class;
8786 context->gmethod = gmethod;
8788 return mono_class_inflate_generic_method (method, context);
8792 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8797 klass = mono_class_from_mono_type (type->type.type);
8799 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8800 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8801 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8802 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8803 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8804 method = ((MonoReflectionMethod *) obj)->method;
8806 method = NULL; /* prevent compiler warning */
8807 g_assert_not_reached ();
8810 return inflate_mono_method (type, method, obj);
8814 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8815 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8818 MonoGenericClass *gclass;
8819 MonoDynamicGenericClass *dgclass;
8820 MonoClass *klass, *gklass, *pklass;
8823 MONO_ARCH_SAVE_REGS;
8825 klass = mono_class_from_mono_type (type->type.type);
8826 gclass = type->type.type->data.generic_class;
8828 g_assert (gclass->is_dynamic);
8829 dgclass = (MonoDynamicGenericClass *) gclass;
8831 if (dgclass->initialized)
8834 gklass = gclass->container_class;
8835 mono_class_init (gklass);
8837 if (dgclass->parent)
8838 pklass = mono_class_from_mono_type (dgclass->parent);
8840 pklass = gklass->parent;
8842 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8843 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8844 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8845 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8846 dgclass->count_events = events ? mono_array_length (events) : 0;
8848 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8849 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8850 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8851 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8852 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8854 for (i = 0; i < dgclass->count_methods; i++) {
8855 MonoObject *obj = mono_array_get (methods, gpointer, i);
8857 dgclass->methods [i] = inflate_method (type, obj);
8860 for (i = 0; i < dgclass->count_ctors; i++) {
8861 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8863 dgclass->ctors [i] = inflate_method (type, obj);
8866 for (i = 0; i < dgclass->count_fields; i++) {
8867 MonoObject *obj = mono_array_get (fields, gpointer, i);
8868 MonoClassField *field;
8869 MonoInflatedField *ifield;
8871 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8872 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8873 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8874 field = ((MonoReflectionField *) obj)->field;
8876 field = NULL; /* prevent compiler warning */
8877 g_assert_not_reached ();
8880 ifield = g_new0 (MonoInflatedField, 1);
8881 ifield->generic_type = field->type;
8882 ifield->reflection_info = obj;
8884 dgclass->fields [i] = *field;
8885 dgclass->fields [i].parent = klass;
8886 dgclass->fields [i].generic_info = ifield;
8887 dgclass->fields [i].type = mono_class_inflate_generic_type (
8888 field->type, dgclass->generic_class.generic_class.context);
8891 for (i = 0; i < dgclass->count_properties; i++) {
8892 MonoObject *obj = mono_array_get (properties, gpointer, i);
8893 MonoProperty *property = &dgclass->properties [i];
8895 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8896 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8898 property->parent = klass;
8899 property->attrs = pb->attrs;
8900 property->name = mono_string_to_utf8 (pb->name);
8902 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8904 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8905 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8906 *property = *((MonoReflectionProperty *) obj)->property;
8909 property->get = inflate_mono_method (type, property->get, NULL);
8911 property->set = inflate_mono_method (type, property->set, NULL);
8913 g_assert_not_reached ();
8916 for (i = 0; i < dgclass->count_events; i++) {
8917 MonoObject *obj = mono_array_get (events, gpointer, i);
8918 MonoEvent *event = &dgclass->events [i];
8920 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8921 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8923 event->parent = klass;
8924 event->attrs = eb->attrs;
8925 event->name = mono_string_to_utf8 (eb->name);
8927 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8928 if (eb->remove_method)
8929 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8930 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8931 *event = *((MonoReflectionEvent *) obj)->event;
8934 event->add = inflate_mono_method (type, event->add, NULL);
8936 event->remove = inflate_mono_method (type, event->remove, NULL);
8938 g_assert_not_reached ();
8941 dgclass->initialized = TRUE;
8945 ensure_runtime_vtable (MonoClass *klass)
8947 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8948 int i, num, j, onum;
8949 MonoMethod **overrides;
8951 if (!tb || klass->wastypebuilder)
8954 ensure_runtime_vtable (klass->parent);
8956 num = tb->ctors? mono_array_length (tb->ctors): 0;
8957 num += tb->num_methods;
8958 klass->method.count = num;
8959 klass->methods = g_new (MonoMethod*, num);
8960 num = tb->ctors? mono_array_length (tb->ctors): 0;
8961 for (i = 0; i < num; ++i)
8962 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8963 num = tb->num_methods;
8965 for (i = 0; i < num; ++i)
8966 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8968 if (tb->interfaces) {
8969 klass->interface_count = mono_array_length (tb->interfaces);
8970 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8971 for (i = 0; i < klass->interface_count; ++i) {
8972 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8973 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8977 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8978 for (i = 0; i < klass->method.count; ++i)
8979 klass->methods [i]->slot = i;
8981 if (!((MonoDynamicImage*)klass->image)->run)
8982 /* No need to create a generic vtable */
8988 for (i = 0; i < tb->num_methods; ++i) {
8989 MonoReflectionMethodBuilder *mb =
8990 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8991 if (mb->override_method)
8996 overrides = g_new0 (MonoMethod*, onum * 2);
9000 for (i = 0; i < tb->num_methods; ++i) {
9001 MonoReflectionMethodBuilder *mb =
9002 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9003 if (mb->override_method) {
9004 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9005 overrides [onum * 2] =
9006 mb->override_method->method;
9007 overrides [onum * 2 + 1] =
9010 g_assert (mb->mhandle);
9017 mono_class_setup_vtable_general (klass, overrides, onum);
9022 typebuilder_setup_fields (MonoClass *klass)
9024 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9025 MonoReflectionFieldBuilder *fb;
9026 MonoClassField *field;
9031 klass->field.count = tb->num_fields;
9032 klass->field.first = 0;
9033 klass->field.last = klass->field.count;
9035 if (!klass->field.count)
9038 klass->fields = g_new0 (MonoClassField, klass->field.count);
9040 for (i = 0; i < klass->field.count; ++i) {
9041 fb = mono_array_get (tb->fields, gpointer, i);
9042 field = &klass->fields [i];
9043 field->name = mono_string_to_utf8 (fb->name);
9045 /* FIXME: handle type modifiers */
9046 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9047 field->type->attrs = fb->attrs;
9049 field->type = fb->type->type;
9051 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9052 field->data = mono_array_addr (fb->rva_data, char, 0);
9053 if (fb->offset != -1)
9054 field->offset = fb->offset;
9055 field->parent = klass;
9057 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9059 if (fb->def_value) {
9060 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9061 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9062 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9063 /* Copy the data from the blob since it might get realloc-ed */
9064 p = assembly->blob.data + idx;
9065 len = mono_metadata_decode_blob_size (p, &p2);
9067 field->data = g_malloc (len);
9068 memcpy ((gpointer)field->data, p, len);
9071 mono_class_layout_fields (klass);
9075 typebuilder_setup_properties (MonoClass *klass)
9077 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9078 MonoReflectionPropertyBuilder *pb;
9081 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9082 klass->property.first = 0;
9083 klass->property.last = klass->property.count;
9085 klass->properties = g_new0 (MonoProperty, klass->property.count);
9086 for (i = 0; i < klass->property.count; ++i) {
9087 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9088 klass->properties [i].parent = klass;
9089 klass->properties [i].attrs = pb->attrs;
9090 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9092 klass->properties [i].get = pb->get_method->mhandle;
9094 klass->properties [i].set = pb->set_method->mhandle;
9098 MonoReflectionEvent *
9099 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9101 MonoEvent *event = g_new0 (MonoEvent, 1);
9105 klass = my_mono_class_from_mono_type (tb->type.type);
9107 event->parent = klass;
9108 event->attrs = eb->attrs;
9109 event->name = mono_string_to_utf8 (eb->name);
9111 event->add = eb->add_method->mhandle;
9112 if (eb->remove_method)
9113 event->remove = eb->remove_method->mhandle;
9114 if (eb->raise_method)
9115 event->raise = eb->raise_method->mhandle;
9117 if (eb->other_methods) {
9118 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9119 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9120 MonoReflectionMethodBuilder *mb =
9121 mono_array_get (eb->other_methods,
9122 MonoReflectionMethodBuilder*, j);
9123 event->other [j] = mb->mhandle;
9127 return mono_event_get_object (mono_object_domain (tb), klass, event);
9131 typebuilder_setup_events (MonoClass *klass)
9133 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9134 MonoReflectionEventBuilder *eb;
9137 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9138 klass->event.first = 0;
9139 klass->event.last = klass->event.count;
9141 klass->events = g_new0 (MonoEvent, klass->event.count);
9142 for (i = 0; i < klass->event.count; ++i) {
9143 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9144 klass->events [i].parent = klass;
9145 klass->events [i].attrs = eb->attrs;
9146 klass->events [i].name = mono_string_to_utf8 (eb->name);
9148 klass->events [i].add = eb->add_method->mhandle;
9149 if (eb->remove_method)
9150 klass->events [i].remove = eb->remove_method->mhandle;
9151 if (eb->raise_method)
9152 klass->events [i].raise = eb->raise_method->mhandle;
9154 if (eb->other_methods) {
9155 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9156 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9157 MonoReflectionMethodBuilder *mb =
9158 mono_array_get (eb->other_methods,
9159 MonoReflectionMethodBuilder*, j);
9160 klass->events [i].other [j] = mb->mhandle;
9167 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9171 MonoReflectionType* res;
9174 MONO_ARCH_SAVE_REGS;
9176 domain = mono_object_domain (tb);
9177 klass = my_mono_class_from_mono_type (tb->type.type);
9179 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9182 * we need to lock the domain because the lock will be taken inside
9183 * So, we need to keep the locking order correct.
9185 mono_domain_lock (domain);
9186 mono_loader_lock ();
9187 if (klass->wastypebuilder) {
9188 mono_loader_unlock ();
9189 mono_domain_unlock (domain);
9190 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9193 * Fields to set in klass:
9194 * the various flags: delegate/unicode/contextbound etc.
9196 klass->flags = tb->attrs;
9197 klass->has_cctor = 1;
9198 klass->has_finalize = 1;
9200 if (!((MonoDynamicImage*)klass->image)->run) {
9201 if (klass->generic_container) {
9202 /* FIXME: The code below can't handle generic classes */
9203 klass->wastypebuilder = TRUE;
9204 mono_loader_unlock ();
9205 mono_domain_unlock (domain);
9206 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9210 /* enums are done right away */
9211 if (!klass->enumtype)
9212 ensure_runtime_vtable (klass);
9215 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9216 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9217 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9221 /* fields and object layout */
9222 if (klass->parent) {
9223 if (!klass->parent->size_inited)
9224 mono_class_init (klass->parent);
9225 klass->instance_size += klass->parent->instance_size;
9226 klass->class_size += klass->parent->class_size;
9227 klass->min_align = klass->parent->min_align;
9228 /* if the type has no fields we won't call the field_setup
9229 * routine which sets up klass->has_references.
9231 klass->has_references |= klass->parent->has_references;
9233 klass->instance_size = sizeof (MonoObject);
9234 klass->min_align = 1;
9237 /* FIXME: handle packing_size and instance_size */
9238 typebuilder_setup_fields (klass);
9240 typebuilder_setup_properties (klass);
9242 typebuilder_setup_events (klass);
9244 klass->wastypebuilder = TRUE;
9245 mono_loader_unlock ();
9246 mono_domain_unlock (domain);
9248 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9249 g_assert (res != (MonoReflectionType*)tb);
9254 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9256 MonoGenericParam *param;
9259 MONO_ARCH_SAVE_REGS;
9261 param = g_new0 (MonoGenericParam, 1);
9263 if (gparam->mbuilder) {
9264 if (!gparam->mbuilder->generic_container)
9265 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9266 param->owner = gparam->mbuilder->generic_container;
9267 } else if (gparam->tbuilder) {
9268 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9269 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9274 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9275 if (gparam->index >= count)
9278 container = nesting->generic_container;
9279 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9282 g_assert (container);
9283 param->owner = container;
9286 param->method = NULL;
9287 param->name = mono_string_to_utf8 (gparam->name);
9288 param->num = gparam->index;
9290 image = &gparam->tbuilder->module->dynamic_image->image;
9291 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9293 param->pklass->reflection_info = gparam;
9295 gparam->type.type = g_new0 (MonoType, 1);
9296 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9297 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9298 gparam->type.type->data.generic_param = param;
9302 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9304 MonoDynamicImage *assembly = sig->module->dynamic_image;
9305 guint32 na = mono_array_length (sig->arguments);
9306 guint32 buflen, i, size;
9310 MONO_ARCH_SAVE_REGS;
9312 p = buf = g_malloc (size = 10 + na * 10);
9314 mono_metadata_encode_value (0x07, p, &p);
9315 mono_metadata_encode_value (na, p, &p);
9316 for (i = 0; i < na; ++i) {
9317 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9318 encode_reflection_type (assembly, type, p, &p);
9322 g_assert (buflen < size);
9323 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9324 p = mono_array_addr (result, char, 0);
9325 memcpy (p, buf, buflen);
9332 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9334 MonoDynamicImage *assembly = sig->module->dynamic_image;
9335 guint32 na = mono_array_length (sig->arguments);
9336 guint32 buflen, i, size;
9340 MONO_ARCH_SAVE_REGS;
9342 p = buf = g_malloc (size = 10 + na * 10);
9344 mono_metadata_encode_value (0x06, p, &p);
9345 for (i = 0; i < na; ++i) {
9346 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9347 encode_reflection_type (assembly, type, p, &p);
9351 g_assert (buflen < size);
9352 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9353 p = mono_array_addr (result, char, 0);
9354 memcpy (p, buf, buflen);
9361 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9363 ReflectionMethodBuilder rmb;
9364 MonoMethodSignature *sig;
9367 sig = dynamic_method_to_signature (mb);
9369 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9372 * Resolve references.
9374 rmb.nrefs = mb->nrefs;
9375 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9376 for (i = 0; i < mb->nrefs; ++i) {
9377 MonoClass *handle_class;
9378 gpointer ref = resolve_object (mb->module->image,
9379 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9382 mono_raise_exception (mono_get_exception_type_load (NULL));
9389 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9393 /* ilgen is no longer needed */
9398 * mono_reflection_lookup_dynamic_token:
9400 * Finish the Builder object pointed to by TOKEN and return the corresponding
9401 * runtime structure. HANDLE_CLASS is set to the class required by
9405 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9407 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9410 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9413 return resolve_object (image, obj, handle_class);
9417 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9419 gpointer result = NULL;
9421 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9422 result = mono_string_intern ((MonoString*)obj);
9423 *handle_class = NULL;
9425 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9426 MonoReflectionType *tb = (MonoReflectionType*)obj;
9427 result = mono_class_from_mono_type (tb->type);
9428 *handle_class = mono_defaults.typehandle_class;
9430 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
9431 result = ((MonoReflectionMethod*)obj)->method;
9432 *handle_class = mono_defaults.methodhandle_class;
9434 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
9435 result = ((MonoReflectionMethod*)obj)->method;
9436 *handle_class = mono_defaults.methodhandle_class;
9438 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9439 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9440 result = mb->mhandle;
9442 /* Type is not yet created */
9443 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9445 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9448 * Hopefully this has been filled in by calling CreateType() on the
9452 * TODO: This won't work if the application finishes another
9453 * TypeBuilder instance instead of this one.
9455 result = mb->mhandle;
9457 *handle_class = mono_defaults.methodhandle_class;
9458 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9459 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9461 result = cb->mhandle;
9463 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9465 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9466 result = cb->mhandle;
9468 *handle_class = mono_defaults.methodhandle_class;
9469 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9470 result = ((MonoReflectionField*)obj)->field;
9471 *handle_class = mono_defaults.fieldhandle_class;
9473 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9474 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9475 result = fb->handle;
9478 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9480 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9481 result = fb->handle;
9483 *handle_class = mono_defaults.fieldhandle_class;
9484 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9485 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9488 klass = tb->type.type->data.klass;
9489 if (klass->wastypebuilder) {
9490 /* Already created */
9494 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9495 result = tb->type.type->data.klass;
9498 *handle_class = mono_defaults.typehandle_class;
9499 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9500 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9501 MonoMethodSignature *sig;
9504 if (helper->arguments)
9505 nargs = mono_array_length (helper->arguments);
9509 sig = mono_metadata_signature_alloc (image, nargs);
9510 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9511 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9513 if (helper->call_conv == 0) /* unmanaged */
9514 sig->call_convention = helper->unmanaged_call_conv - 1;
9516 if (helper->call_conv & 0x02)
9517 sig->call_convention = MONO_CALL_VARARG;
9519 sig->call_convention = MONO_CALL_DEFAULT;
9521 sig->param_count = nargs;
9522 /* TODO: Copy type ? */
9523 sig->ret = helper->return_type->type;
9524 for (i = 0; i < nargs; ++i) {
9525 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9526 sig->params [i] = rt->type;
9530 *handle_class = NULL;
9532 g_print (obj->vtable->klass->name);
9533 g_assert_not_reached ();
9539 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9540 const static guint32 declsec_flags_map[] = {
9541 0x00000000, /* empty */
9542 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9543 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9544 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9545 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9546 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9547 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9548 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9549 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9550 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9551 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9552 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9553 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9554 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9555 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9556 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9557 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9558 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9559 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9563 * Returns flags that includes all available security action associated to the handle.
9564 * @token: metadata token (either for a class or a method)
9565 * @image: image where resides the metadata.
9568 mono_declsec_get_flags (MonoImage *image, guint32 token)
9570 guint32 index = mono_metadata_declsec_from_index (image, token);
9571 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9576 for (i = index; i < t->rows; i++) {
9577 guint32 cols [MONO_DECL_SECURITY_SIZE];
9579 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9580 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9583 action = cols [MONO_DECL_SECURITY_ACTION];
9584 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9585 result |= declsec_flags_map [action];
9587 g_assert_not_reached ();
9594 * Get the security actions (in the form of flags) associated with the specified method.
9596 * @method: The method for which we want the declarative security flags.
9597 * Return the declarative security flags for the method (only).
9599 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9600 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9603 mono_declsec_flags_from_method (MonoMethod *method)
9605 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9606 /* FIXME: No cache (for the moment) */
9607 guint32 idx = mono_method_get_index (method);
9608 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9609 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9610 return mono_declsec_get_flags (method->klass->image, idx);
9616 * Get the security actions (in the form of flags) associated with the specified class.
9618 * @klass: The class for which we want the declarative security flags.
9619 * Return the declarative security flags for the class.
9621 * Note: We cache the flags inside the MonoClass structure as this will get
9622 * called very often (at least for each method).
9625 mono_declsec_flags_from_class (MonoClass *klass)
9627 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9628 if (!klass->declsec_flags) {
9629 guint32 idx = mono_metadata_token_index (klass->type_token);
9630 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9631 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9632 /* we cache the flags on classes */
9633 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9635 return klass->declsec_flags;
9641 * Get the security actions (in the form of flags) associated with the specified assembly.
9643 * @assembly: The assembly for which we want the declarative security flags.
9644 * Return the declarative security flags for the assembly.
9647 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9649 guint32 idx = 1; /* there is only one assembly */
9650 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9651 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9652 return mono_declsec_get_flags (assembly->image, idx);
9657 * Fill actions for the specific index (which may either be an encoded class token or
9658 * an encoded method token) from the metadata image.
9659 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9662 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9663 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9665 MonoBoolean result = FALSE;
9667 guint32 cols [MONO_DECL_SECURITY_SIZE];
9668 int index = mono_metadata_declsec_from_index (image, token);
9671 t = &image->tables [MONO_TABLE_DECLSECURITY];
9672 for (i = index; i < t->rows; i++) {
9673 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9675 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9678 /* if present only replace (class) permissions with method permissions */
9679 /* if empty accept either class or method permissions */
9680 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9681 if (!actions->demand.blob) {
9682 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9683 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9684 actions->demand.blob = (char*) (blob + 2);
9685 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9688 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9689 if (!actions->noncasdemand.blob) {
9690 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9691 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9692 actions->noncasdemand.blob = (char*) (blob + 2);
9693 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9696 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9697 if (!actions->demandchoice.blob) {
9698 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9699 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9700 actions->demandchoice.blob = (char*) (blob + 2);
9701 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9711 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9712 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9714 guint32 idx = mono_metadata_token_index (klass->type_token);
9715 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9716 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9717 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9721 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9722 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9724 guint32 idx = mono_method_get_index (method);
9725 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9726 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9727 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9731 * Collect all actions (that requires to generate code in mini) assigned for
9732 * the specified method.
9733 * Note: Don't use the content of actions if the function return FALSE.
9736 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9738 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9739 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9740 MonoBoolean result = FALSE;
9743 /* quick exit if no declarative security is present in the metadata */
9744 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9747 /* we want the original as the wrapper is "free" of the security informations */
9748 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9749 method = mono_marshal_method_from_wrapper (method);
9754 /* First we look for method-level attributes */
9755 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9756 mono_class_init (method->klass);
9757 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9759 result = mono_declsec_get_method_demands_params (method, demands,
9760 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9763 /* Here we use (or create) the class declarative cache to look for demands */
9764 flags = mono_declsec_flags_from_class (method->klass);
9767 mono_class_init (method->klass);
9768 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9770 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9771 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9774 /* The boolean return value is used as a shortcut in case nothing needs to
9775 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9781 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9783 * Note: Don't use the content of actions if the function return FALSE.
9786 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9788 MonoBoolean result = FALSE;
9791 /* quick exit if no declarative security is present in the metadata */
9792 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9795 /* we want the original as the wrapper is "free" of the security informations */
9796 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9797 method = mono_marshal_method_from_wrapper (method);
9802 /* results are independant - zeroize both */
9803 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9804 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9806 /* First we look for method-level attributes */
9807 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9808 mono_class_init (method->klass);
9810 result = mono_declsec_get_method_demands_params (method, cmethod,
9811 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9814 /* Here we use (or create) the class declarative cache to look for demands */
9815 flags = mono_declsec_flags_from_class (method->klass);
9816 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9817 mono_class_init (method->klass);
9819 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9820 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9827 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9829 * @klass The inherited class - this is the class that provides the security check (attributes)
9831 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9833 * Note: Don't use the content of actions if the function return FALSE.
9836 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9838 MonoBoolean result = FALSE;
9841 /* quick exit if no declarative security is present in the metadata */
9842 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9845 /* Here we use (or create) the class declarative cache to look for demands */
9846 flags = mono_declsec_flags_from_class (klass);
9847 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9848 mono_class_init (klass);
9849 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9851 result |= mono_declsec_get_class_demands_params (klass, demands,
9852 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9859 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9861 * Note: Don't use the content of actions if the function return FALSE.
9864 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9866 /* quick exit if no declarative security is present in the metadata */
9867 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9870 /* we want the original as the wrapper is "free" of the security informations */
9871 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9872 method = mono_marshal_method_from_wrapper (method);
9877 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9878 mono_class_init (method->klass);
9879 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9881 return mono_declsec_get_method_demands_params (method, demands,
9882 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9889 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9891 guint32 cols [MONO_DECL_SECURITY_SIZE];
9895 int index = mono_metadata_declsec_from_index (image, token);
9899 t = &image->tables [MONO_TABLE_DECLSECURITY];
9900 for (i = index; i < t->rows; i++) {
9901 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9903 /* shortcut - index are ordered */
9904 if (token != cols [MONO_DECL_SECURITY_PARENT])
9907 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9908 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9909 entry->blob = (char*) (metadata + 2);
9910 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9919 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9921 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9922 guint32 idx = mono_method_get_index (method);
9923 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9924 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9925 return get_declsec_action (method->klass->image, idx, action, entry);
9931 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9934 guint32 flags = mono_declsec_flags_from_class (klass);
9935 if (declsec_flags_map [action] & flags) {
9936 guint32 idx = mono_metadata_token_index (klass->type_token);
9937 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9938 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9939 return get_declsec_action (klass->image, idx, action, entry);
9945 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9947 guint32 idx = 1; /* there is only one assembly */
9948 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9949 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9951 return get_declsec_action (assembly->image, idx, action, entry);
9955 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9957 MonoObject *res, *exc;
9959 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9960 static MonoMethod *method = NULL;
9962 if (!System_Reflection_Emit_TypeBuilder) {
9963 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
9964 g_assert (System_Reflection_Emit_TypeBuilder);
9966 if (method == NULL) {
9967 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
9972 * The result of mono_type_get_object () might be a System.MonoType but we
9973 * need a TypeBuilder so use klass->reflection_info.
9975 g_assert (klass->reflection_info);
9976 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
9978 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
9980 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
9984 return *(MonoBoolean*)mono_object_unbox (res);