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->klass->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->klass->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 void 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); \
5065 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5067 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5070 #define CACHE_OBJECT(p,o,k) \
5072 ReflectedEntry *e = ALLOC_REFENTRY; \
5074 e->refclass = (k); \
5075 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5076 mono_domain_unlock (domain); \
5080 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5082 /* this is done only once */
5083 mono_domain_lock (domain);
5084 CACHE_OBJECT (assembly, res, NULL);
5088 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5090 /* this is done only once */
5091 mono_domain_lock (domain);
5092 CACHE_OBJECT (module, res, NULL);
5096 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5098 MonoDynamicImage *image = moduleb->dynamic_image;
5099 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5102 MonoImage **new_modules;
5105 * FIXME: we already created an image in mono_image_basic_init (), but
5106 * we don't know which module it belongs to, since that is only
5107 * determined at assembly save time.
5109 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5110 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5112 moduleb->module.image = &image->image;
5113 moduleb->dynamic_image = image;
5114 register_module (mono_object_domain (moduleb), moduleb, image);
5116 /* register the module with the assembly */
5117 ass = ab->dynamic_assembly->assembly.image;
5118 module_count = ass->module_count;
5119 new_modules = g_new0 (MonoImage *, module_count + 1);
5122 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5123 new_modules [module_count] = &image->image;
5125 g_free (ass->modules);
5126 ass->modules = new_modules;
5127 ass->module_count ++;
5132 * mono_assembly_get_object:
5133 * @domain: an app domain
5134 * @assembly: an assembly
5136 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5138 MonoReflectionAssembly*
5139 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5141 static MonoClass *System_Reflection_Assembly;
5142 MonoReflectionAssembly *res;
5144 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5145 if (!System_Reflection_Assembly)
5146 System_Reflection_Assembly = mono_class_from_name (
5147 mono_defaults.corlib, "System.Reflection", "Assembly");
5148 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5149 res->assembly = assembly;
5151 CACHE_OBJECT (assembly, res, NULL);
5157 MonoReflectionModule*
5158 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5160 static MonoClass *System_Reflection_Module;
5161 MonoReflectionModule *res;
5164 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5165 if (!System_Reflection_Module)
5166 System_Reflection_Module = mono_class_from_name (
5167 mono_defaults.corlib, "System.Reflection", "Module");
5168 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5171 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5173 res->fqname = mono_string_new (domain, image->name);
5174 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5175 res->scopename = mono_string_new (domain, image->module_name);
5179 if (image->assembly->image == image) {
5180 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5183 g_assert (image->assembly->image->modules);
5185 for (i = 0; i < image->assembly->image->module_count; i++) {
5186 if (image->assembly->image->modules [i] == image)
5187 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5189 g_assert (res->token);
5192 mono_image_addref (image);
5194 CACHE_OBJECT (image, res, NULL);
5198 MonoReflectionModule*
5199 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5201 static MonoClass *System_Reflection_Module;
5202 MonoReflectionModule *res;
5203 MonoTableInfo *table;
5204 guint32 cols [MONO_FILE_SIZE];
5206 guint32 i, name_idx;
5209 if (!System_Reflection_Module)
5210 System_Reflection_Module = mono_class_from_name (
5211 mono_defaults.corlib, "System.Reflection", "Module");
5212 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5214 table = &image->tables [MONO_TABLE_FILE];
5215 g_assert (table_index < table->rows);
5216 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5219 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5220 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5222 /* Check whenever the row has a corresponding row in the moduleref table */
5223 table = &image->tables [MONO_TABLE_MODULEREF];
5224 for (i = 0; i < table->rows; ++i) {
5225 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5226 val = mono_metadata_string_heap (image, name_idx);
5227 if (strcmp (val, name) == 0)
5228 res->image = image->modules [i];
5231 res->fqname = mono_string_new (domain, name);
5232 res->name = mono_string_new (domain, name);
5233 res->scopename = mono_string_new (domain, name);
5234 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5235 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5241 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5243 if ((t1->type != t2->type) ||
5244 (t1->byref != t2->byref))
5248 case MONO_TYPE_VOID:
5249 case MONO_TYPE_BOOLEAN:
5250 case MONO_TYPE_CHAR:
5261 case MONO_TYPE_STRING:
5264 case MONO_TYPE_OBJECT:
5265 case MONO_TYPE_TYPEDBYREF:
5267 case MONO_TYPE_VALUETYPE:
5268 case MONO_TYPE_CLASS:
5269 case MONO_TYPE_SZARRAY:
5270 return t1->data.klass == t2->data.klass;
5272 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5273 case MONO_TYPE_ARRAY:
5274 if (t1->data.array->rank != t2->data.array->rank)
5276 return t1->data.array->eklass == t2->data.array->eklass;
5277 case MONO_TYPE_GENERICINST: {
5279 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5281 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5282 &t2->data.generic_class->container_class->byval_arg))
5284 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5285 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5291 case MONO_TYPE_MVAR:
5292 return t1->data.generic_param == t2->data.generic_param;
5294 g_error ("implement type compare for %0x!", t1->type);
5302 mymono_metadata_type_hash (MonoType *t1)
5308 hash |= t1->byref << 6; /* do not collide with t1->type values */
5310 case MONO_TYPE_VALUETYPE:
5311 case MONO_TYPE_CLASS:
5312 case MONO_TYPE_SZARRAY:
5313 /* check if the distribution is good enough */
5314 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5316 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5321 static MonoReflectionGenericClass*
5322 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5324 static MonoClass *System_Reflection_MonoGenericClass;
5325 MonoReflectionGenericClass *res;
5326 MonoGenericClass *gclass;
5329 if (!System_Reflection_MonoGenericClass) {
5330 System_Reflection_MonoGenericClass = mono_class_from_name (
5331 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5332 g_assert (System_Reflection_MonoGenericClass);
5335 gclass = geninst->data.generic_class;
5336 gklass = gclass->container_class;
5338 mono_class_init (gclass->klass);
5340 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5342 res->type.type = geninst;
5343 if (gklass->wastypebuilder && gklass->reflection_info)
5344 res->generic_type = gklass->reflection_info;
5346 res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
5352 * mono_type_get_object:
5353 * @domain: an app domain
5356 * Return an System.MonoType object representing the type @type.
5359 mono_type_get_object (MonoDomain *domain, MonoType *type)
5361 MonoReflectionType *res;
5362 MonoClass *klass = mono_class_from_mono_type (type);
5364 mono_domain_lock (domain);
5365 if (!domain->type_hash)
5366 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5367 (GCompareFunc)mymono_metadata_type_equal);
5368 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5369 mono_domain_unlock (domain);
5372 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5373 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5374 mono_g_hash_table_insert (domain->type_hash, type, res);
5375 mono_domain_unlock (domain);
5378 if (klass->reflection_info && !klass->wastypebuilder) {
5379 /* g_assert_not_reached (); */
5380 /* should this be considered an error condition? */
5382 mono_domain_unlock (domain);
5383 return klass->reflection_info;
5386 mono_class_init (klass);
5387 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5389 mono_g_hash_table_insert (domain->type_hash, type, res);
5390 mono_domain_unlock (domain);
5395 * mono_method_get_object:
5396 * @domain: an app domain
5398 * @refclass: the reflected type (can be NULL)
5400 * Return an System.Reflection.MonoMethod object representing the method @method.
5402 MonoReflectionMethod*
5403 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5406 * We use the same C representation for methods and constructors, but the type
5407 * name in C# is different.
5411 MonoReflectionMethod *ret;
5413 if (method->is_inflated) {
5414 MonoReflectionGenericMethod *gret;
5416 refclass = method->klass;
5417 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5418 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5419 cname = "MonoGenericCMethod";
5421 cname = "MonoGenericMethod";
5422 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5424 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5425 gret->method.method = method;
5426 gret->method.name = mono_string_new (domain, method->name);
5427 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5428 CACHE_OBJECT (method, gret, refclass);
5429 return (MonoReflectionMethod *) gret;
5433 refclass = method->klass;
5435 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5436 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5437 cname = "MonoCMethod";
5439 cname = "MonoMethod";
5440 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5442 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5443 ret->method = method;
5444 ret->name = mono_string_new (domain, method->name);
5445 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5446 CACHE_OBJECT (method, ret, refclass);
5451 * mono_field_get_object:
5452 * @domain: an app domain
5456 * Return an System.Reflection.MonoField object representing the field @field
5459 MonoReflectionField*
5460 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5462 MonoReflectionField *res;
5465 CHECK_OBJECT (MonoReflectionField *, field, klass);
5466 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5467 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5470 res->name = mono_string_new (domain, field->name);
5471 if (field->generic_info)
5472 res->attrs = field->generic_info->generic_type->attrs;
5474 res->attrs = field->type->attrs;
5475 res->type = mono_type_get_object (domain, field->type);
5476 CACHE_OBJECT (field, res, klass);
5481 * mono_property_get_object:
5482 * @domain: an app domain
5484 * @property: a property
5486 * Return an System.Reflection.MonoProperty object representing the property @property
5489 MonoReflectionProperty*
5490 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5492 MonoReflectionProperty *res;
5495 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5496 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5497 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5499 res->property = property;
5500 CACHE_OBJECT (property, res, klass);
5505 * mono_event_get_object:
5506 * @domain: an app domain
5510 * Return an System.Reflection.MonoEvent object representing the event @event
5513 MonoReflectionEvent*
5514 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5516 MonoReflectionEvent *res;
5519 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5520 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5521 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5524 CACHE_OBJECT (event, res, klass);
5529 * mono_param_get_objects:
5530 * @domain: an app domain
5533 * Return an System.Reflection.ParameterInfo array object representing the parameters
5534 * in the method @method.
5537 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5539 static MonoClass *System_Reflection_ParameterInfo;
5540 MonoArray *res = NULL;
5541 MonoReflectionMethod *member = NULL;
5542 MonoReflectionParameter *param = NULL;
5543 char **names, **blobs = NULL;
5544 guint32 *types = NULL;
5545 MonoType *type = NULL;
5546 MonoObject *dbnull = mono_get_dbnull_object (domain);
5547 MonoMarshalSpec **mspecs;
5550 if (!System_Reflection_ParameterInfo)
5551 System_Reflection_ParameterInfo = mono_class_from_name (
5552 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5554 if (!mono_method_signature (method)->param_count)
5555 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5557 /* Note: the cache is based on the address of the signature into the method
5558 * since we already cache MethodInfos with the method as keys.
5560 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5562 member = mono_method_get_object (domain, method, NULL);
5563 names = g_new (char *, mono_method_signature (method)->param_count);
5564 mono_method_get_param_names (method, (const char **) names);
5566 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5567 mono_method_get_marshal_info (method, mspecs);
5569 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5570 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5571 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5572 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5573 param->MemberImpl = (MonoObject*)member;
5574 param->NameImpl = mono_string_new (domain, names [i]);
5575 param->PositionImpl = i;
5576 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5578 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5579 param->DefaultValueImpl = dbnull;
5583 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5584 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5585 get_default_param_value_blobs (method, blobs, types);
5588 /* Build MonoType for the type from the Constant Table */
5590 type = g_new0 (MonoType, 1);
5591 type->type = types [i];
5592 type->data.klass = NULL;
5593 if (types [i] == MONO_TYPE_CLASS)
5594 type->data.klass = mono_defaults.object_class;
5596 type->data.klass = mono_class_from_mono_type (type);
5598 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5600 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5601 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5602 param->DefaultValueImpl = dbnull;
5607 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5609 mono_array_set (res, gpointer, i, param);
5616 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5618 mono_metadata_free_marshal_spec (mspecs [i]);
5621 CACHE_OBJECT (&(method->signature), res, NULL);
5626 * mono_method_body_get_object:
5627 * @domain: an app domain
5630 * Return an System.Reflection.MethodBody object representing the method @method.
5632 MonoReflectionMethodBody*
5633 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5635 static MonoClass *System_Reflection_MethodBody = NULL;
5636 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5637 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5638 MonoReflectionMethodBody *ret;
5639 MonoMethodNormal *mn;
5640 MonoMethodHeader *header;
5641 guint32 method_rva, local_var_sig_token;
5643 unsigned char format, flags;
5646 if (!System_Reflection_MethodBody)
5647 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5648 if (!System_Reflection_LocalVariableInfo)
5649 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5650 if (!System_Reflection_ExceptionHandlingClause)
5651 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5653 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5655 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5656 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5657 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5658 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5660 mn = (MonoMethodNormal *)method;
5661 header = mono_method_get_header (method);
5663 /* Obtain local vars signature token */
5664 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5665 ptr = mono_image_rva_map (method->klass->image, method_rva);
5666 flags = *(const unsigned char *) ptr;
5667 format = flags & METHOD_HEADER_FORMAT_MASK;
5669 case METHOD_HEADER_TINY_FORMAT:
5670 case METHOD_HEADER_TINY_FORMAT1:
5671 local_var_sig_token = 0;
5673 case METHOD_HEADER_FAT_FORMAT:
5677 local_var_sig_token = read32 (ptr);
5680 g_assert_not_reached ();
5683 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5685 ret->init_locals = header->init_locals;
5686 ret->max_stack = header->max_stack;
5687 ret->local_var_sig_token = local_var_sig_token;
5688 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5689 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5692 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5693 for (i = 0; i < header->num_locals; ++i) {
5694 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5695 info->local_type = mono_type_get_object (domain, header->locals [i]);
5696 info->is_pinned = header->locals [i]->pinned;
5697 info->local_index = i;
5698 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5702 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5703 for (i = 0; i < header->num_clauses; ++i) {
5704 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5705 MonoExceptionClause *clause = &header->clauses [i];
5707 info->flags = clause->flags;
5708 info->try_offset = clause->try_offset;
5709 info->try_length = clause->try_len;
5710 info->handler_offset = clause->handler_offset;
5711 info->handler_length = clause->handler_len;
5712 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5713 info->filter_offset = clause->data.filter_offset;
5714 else if (clause->data.catch_class)
5715 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5717 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5720 CACHE_OBJECT (method, ret, NULL);
5725 mono_get_dbnull_object (MonoDomain *domain)
5729 static MonoClassField *dbnull_value_field = NULL;
5731 if (!dbnull_value_field) {
5732 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5733 mono_class_init (klass);
5734 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5735 g_assert (dbnull_value_field);
5737 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5744 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5746 guint32 param_index, i, lastp, crow = 0;
5747 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5750 MonoClass *klass = method->klass;
5751 MonoImage *image = klass->image;
5752 MonoMethodSignature *methodsig = mono_method_signature (method);
5754 MonoTableInfo *constt;
5755 MonoTableInfo *methodt;
5756 MonoTableInfo *paramt;
5758 if (!methodsig->param_count)
5761 if (klass->generic_class) {
5762 return; /* FIXME - ??? */
5765 mono_class_init (klass);
5767 if (klass->image->dynamic) {
5768 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5769 if (aux && aux->param_defaults) {
5770 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5771 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5776 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5777 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5778 constt = &image->tables [MONO_TABLE_CONSTANT];
5780 idx = mono_method_get_index (method) - 1;
5781 g_assert (idx != -1);
5783 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5784 if (idx + 1 < methodt->rows)
5785 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5787 lastp = paramt->rows + 1;
5789 for (i = param_index; i < lastp; ++i) {
5792 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5793 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5795 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5798 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5803 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5804 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5805 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5812 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5817 MonoType *basetype = type;
5822 klass = mono_class_from_mono_type (type);
5823 if (klass->valuetype) {
5824 object = mono_object_new (domain, klass);
5825 retval = ((gchar *) object + sizeof (MonoObject));
5826 if (klass->enumtype)
5827 basetype = klass->enum_basetype;
5832 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5839 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5843 memset (assembly, 0, sizeof (MonoAssemblyName));
5845 assembly->culture = "";
5846 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5848 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5851 while (g_ascii_isspace (*p) || *p == ',') {
5860 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5862 assembly->major = strtoul (p, &s, 10);
5863 if (s == p || *s != '.')
5866 assembly->minor = strtoul (p, &s, 10);
5867 if (s == p || *s != '.')
5870 assembly->build = strtoul (p, &s, 10);
5871 if (s == p || *s != '.')
5874 assembly->revision = strtoul (p, &s, 10);
5878 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5880 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5881 assembly->culture = "";
5884 assembly->culture = p;
5885 while (*p && *p != ',') {
5889 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5891 if (strncmp (p, "null", 4) == 0) {
5896 while (*p && *p != ',') {
5899 len = (p - start + 1);
5900 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5901 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5902 g_strlcpy (assembly->public_key_token, start, len);
5905 while (*p && *p != ',')
5909 while (g_ascii_isspace (*p) || *p == ',') {
5923 * mono_reflection_parse_type:
5926 * Parse a type name as accepted by the GetType () method and output the info
5927 * extracted in the info structure.
5928 * the name param will be mangled, so, make a copy before passing it to this function.
5929 * The fields in info will be valid until the memory pointed to by name is valid.
5931 * See also mono_type_get_name () below.
5933 * Returns: 0 on parse error.
5936 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5937 MonoTypeNameParse *info)
5939 char *start, *p, *w, *temp, *last_point, *startn;
5940 int in_modifiers = 0;
5941 int isbyref = 0, rank, arity = 0, i;
5943 start = p = w = name;
5945 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5946 info->name = info->name_space = NULL;
5947 info->nested = NULL;
5948 info->modifiers = NULL;
5949 info->type_arguments = NULL;
5951 /* last_point separates the namespace from the name */
5957 *p = 0; /* NULL terminate the name */
5959 info->nested = g_list_append (info->nested, startn);
5960 /* we have parsed the nesting namespace + name */
5964 info->name_space = start;
5966 info->name = last_point + 1;
5968 info->name_space = (char *)"";
5987 i = strtol (p, &temp, 10);
6004 info->name_space = start;
6006 info->name = last_point + 1;
6008 info->name_space = (char *)"";
6015 if (isbyref) /* only one level allowed by the spec */
6018 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6022 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6028 info->type_arguments = g_ptr_array_new ();
6029 for (i = 0; i < arity; i++) {
6030 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6031 gboolean fqname = FALSE;
6033 g_ptr_array_add (info->type_arguments, subinfo);
6040 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6051 while (*p && (*p != ']'))
6059 if (g_ascii_isspace (*aname)) {
6066 !assembly_name_to_aname (&subinfo->assembly, aname))
6070 if (i + 1 < arity) {
6090 else if (*p != '*') /* '*' means unknown lower bound */
6096 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6107 if (g_ascii_isspace (*p)) {
6114 return 0; /* missing assembly name */
6115 if (!assembly_name_to_aname (&info->assembly, p))
6121 if (info->assembly.name)
6124 // *w = 0; /* terminate class name */
6126 if (!info->name || !*info->name)
6130 /* add other consistency checks */
6135 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6137 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6141 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6143 gboolean type_resolve = FALSE;
6146 if (info->assembly.name) {
6147 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6149 /* then we must load the assembly ourselve - see #60439 */
6150 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6154 image = assembly->image;
6155 } else if (!image) {
6156 image = mono_defaults.corlib;
6159 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6160 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6161 image = mono_defaults.corlib;
6162 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6169 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6176 image = mono_defaults.corlib;
6179 klass = mono_class_from_name_case (image, info->name_space, info->name);
6181 klass = mono_class_from_name (image, info->name_space, info->name);
6184 for (mod = info->nested; mod; mod = mod->next) {
6187 mono_class_init (klass);
6188 nested = klass->nested_classes;
6191 klass = nested->data;
6193 if (g_strcasecmp (klass->name, mod->data) == 0)
6196 if (strcmp (klass->name, mod->data) == 0)
6200 nested = nested->next;
6207 mono_class_init (klass);
6209 if (info->type_arguments) {
6210 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6211 MonoReflectionType *the_type;
6215 for (i = 0; i < info->type_arguments->len; i++) {
6216 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6218 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6219 if (!type_args [i]) {
6225 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6227 instance = mono_reflection_bind_generic_parameters (
6228 the_type, info->type_arguments->len, type_args);
6235 klass = mono_class_from_mono_type (instance);
6238 for (mod = info->modifiers; mod; mod = mod->next) {
6239 modval = GPOINTER_TO_UINT (mod->data);
6240 if (!modval) { /* byref: must be last modifier */
6241 return &klass->this_arg;
6242 } else if (modval == -1) {
6243 klass = mono_ptr_class_get (&klass->byval_arg);
6244 } else { /* array rank */
6245 klass = mono_array_class_get (klass, modval);
6247 mono_class_init (klass);
6250 return &klass->byval_arg;
6254 * mono_reflection_get_type:
6255 * @image: a metadata context
6256 * @info: type description structure
6257 * @ignorecase: flag for case-insensitive string compares
6258 * @type_resolve: whenever type resolve was already tried
6260 * Build a MonoType from the type description in @info.
6265 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6268 MonoReflectionAssembly *assembly;
6272 type = mono_reflection_get_type_internal (image, info, ignorecase);
6275 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6282 *type_resolve = TRUE;
6285 /* Reconstruct the type name */
6286 fullName = g_string_new ("");
6287 if (info->name_space && (info->name_space [0] != '\0'))
6288 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6290 g_string_printf (fullName, info->name);
6291 for (mod = info->nested; mod; mod = mod->next)
6292 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6294 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6296 if (assembly->assembly->dynamic) {
6297 /* Enumerate all modules */
6298 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6302 if (abuilder->modules) {
6303 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6304 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6305 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6311 if (!type && abuilder->loaded_modules) {
6312 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6313 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6314 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6321 type = mono_reflection_get_type_internal (assembly->assembly->image,
6324 g_string_free (fullName, TRUE);
6329 free_type_info (MonoTypeNameParse *info)
6331 g_list_free (info->modifiers);
6332 g_list_free (info->nested);
6334 if (info->type_arguments) {
6337 for (i = 0; i < info->type_arguments->len; i++) {
6338 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6340 free_type_info (subinfo);
6343 g_ptr_array_free (info->type_arguments, TRUE);
6348 * mono_reflection_type_from_name:
6350 * @image: a metadata context (can be NULL).
6352 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6353 * it defaults to get the type from @image or, if @image is NULL or loading
6354 * from it fails, uses corlib.
6358 mono_reflection_type_from_name (char *name, MonoImage *image)
6360 MonoType *type = NULL;
6361 MonoTypeNameParse info;
6364 /* Make a copy since parse_type modifies its argument */
6365 tmp = g_strdup (name);
6367 /*g_print ("requested type %s\n", str);*/
6368 if (mono_reflection_parse_type (tmp, &info)) {
6369 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6373 free_type_info (&info);
6378 * mono_reflection_get_token:
6380 * Return the metadata token of OBJ which should be an object
6381 * representing a metadata element.
6384 mono_reflection_get_token (MonoObject *obj)
6389 klass = obj->vtable->klass;
6391 if (strcmp (klass->name, "MethodBuilder") == 0) {
6392 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6394 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6395 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6396 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6398 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6399 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6400 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6401 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6402 if (tb->generic_params) {
6403 g_assert_not_reached ();
6405 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6407 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6408 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6409 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6410 } else if (strcmp (klass->name, "MonoType") == 0) {
6411 MonoReflectionType *tb = (MonoReflectionType *)obj;
6412 token = mono_class_from_mono_type (tb->type)->type_token;
6413 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6414 strcmp (klass->name, "MonoMethod") == 0) {
6415 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6416 if (m->method->is_inflated) {
6417 g_assert_not_reached ();
6418 } else if (mono_method_signature (m->method)->generic_param_count) {
6419 g_assert_not_reached ();
6420 } else if (m->method->klass->generic_class) {
6421 g_assert_not_reached ();
6423 token = m->method->token;
6425 } else if (strcmp (klass->name, "MonoField") == 0) {
6426 MonoReflectionField *f = (MonoReflectionField*)obj;
6428 token = mono_class_get_field_token (f->field);
6429 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6430 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6432 token = mono_class_get_property_token (p->property);
6433 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6434 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6436 token = mono_class_get_event_token (p->event);
6437 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6438 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6440 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6441 } else if (strcmp (klass->name, "Module") == 0) {
6442 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6445 } else if (strcmp (klass->name, "Assembly") == 0) {
6446 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6448 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6449 MonoException *ex = mono_get_exception_not_implemented (msg);
6451 mono_raise_exception (ex);
6458 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6460 int slen, type = t->type;
6465 case MONO_TYPE_BOOLEAN: {
6466 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6471 case MONO_TYPE_CHAR:
6473 case MONO_TYPE_I2: {
6474 guint16 *val = g_malloc (sizeof (guint16));
6479 #if SIZEOF_VOID_P == 4
6485 case MONO_TYPE_I4: {
6486 guint32 *val = g_malloc (sizeof (guint32));
6491 #if SIZEOF_VOID_P == 8
6492 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6497 case MONO_TYPE_I8: {
6498 guint64 *val = g_malloc (sizeof (guint64));
6503 case MONO_TYPE_VALUETYPE:
6504 if (t->data.klass->enumtype) {
6505 type = t->data.klass->enum_basetype->type;
6508 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6511 case MONO_TYPE_STRING:
6512 if (*p == (char)0xFF) {
6516 slen = mono_metadata_decode_value (p, &p);
6518 return mono_string_new_len (mono_domain_get (), p, slen);
6519 case MONO_TYPE_CLASS: {
6522 if (*p == (char)0xFF) {
6527 slen = mono_metadata_decode_value (p, &p);
6528 n = g_memdup (p, slen + 1);
6530 t = mono_reflection_type_from_name (n, image);
6532 g_warning ("Cannot load type '%s'", n);
6536 return mono_type_get_object (mono_domain_get (), t);
6540 case MONO_TYPE_OBJECT: {
6543 MonoClass *subc = NULL;
6548 } else if (subt == 0x0E) {
6549 type = MONO_TYPE_STRING;
6551 } else if (subt == 0x55) {
6554 slen = mono_metadata_decode_value (p, &p);
6555 n = g_memdup (p, slen + 1);
6557 t = mono_reflection_type_from_name (n, image);
6559 g_warning ("Cannot load type '%s'", n);
6562 subc = mono_class_from_mono_type (t);
6563 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6564 MonoType simple_type = {{0}};
6565 simple_type.type = subt;
6566 subc = mono_class_from_mono_type (&simple_type);
6568 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6570 val = load_cattr_value (image, &subc->byval_arg, p, end);
6571 obj = mono_object_new (mono_domain_get (), subc);
6572 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6576 case MONO_TYPE_SZARRAY: {
6578 guint32 i, alen, basetype;
6581 if (alen == 0xffffffff) {
6585 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6586 basetype = t->data.klass->byval_arg.type;
6591 case MONO_TYPE_BOOLEAN:
6592 for (i = 0; i < alen; i++) {
6593 MonoBoolean val = *p++;
6594 mono_array_set (arr, MonoBoolean, i, val);
6597 case MONO_TYPE_CHAR:
6600 for (i = 0; i < alen; i++) {
6601 guint16 val = read16 (p);
6602 mono_array_set (arr, guint16, i, val);
6609 for (i = 0; i < alen; i++) {
6610 guint32 val = read32 (p);
6611 mono_array_set (arr, guint32, i, val);
6618 for (i = 0; i < alen; i++) {
6619 guint64 val = read64 (p);
6620 mono_array_set (arr, guint64, i, val);
6624 case MONO_TYPE_CLASS:
6625 case MONO_TYPE_OBJECT:
6626 case MONO_TYPE_STRING:
6627 for (i = 0; i < alen; i++) {
6628 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6629 mono_array_set (arr, gpointer, i, item);
6633 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6639 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6645 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6647 static MonoClass *klass;
6648 static MonoMethod *ctor;
6650 void *params [2], *unboxed;
6653 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6655 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6657 params [0] = mono_type_get_object (mono_domain_get (), t);
6659 retval = mono_object_new (mono_domain_get (), klass);
6660 unboxed = mono_object_unbox (retval);
6661 mono_runtime_invoke (ctor, unboxed, params, NULL);
6667 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6669 static MonoClass *klass;
6670 static MonoMethod *ctor;
6672 void *unboxed, *params [2];
6675 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6677 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6680 params [1] = typedarg;
6681 retval = mono_object_new (mono_domain_get (), klass);
6682 unboxed = mono_object_unbox (retval);
6683 mono_runtime_invoke (ctor, unboxed, params, NULL);
6689 type_is_reference (MonoType *type)
6691 switch (type->type) {
6692 case MONO_TYPE_BOOLEAN:
6693 case MONO_TYPE_CHAR:
6706 case MONO_TYPE_VALUETYPE:
6714 free_param_data (MonoMethodSignature *sig, void **params) {
6716 for (i = 0; i < sig->param_count; ++i) {
6717 if (!type_is_reference (sig->params [i]))
6718 g_free (params [i]);
6723 * Find the field index in the metadata FieldDef table.
6726 find_field_index (MonoClass *klass, MonoClassField *field) {
6729 for (i = 0; i < klass->field.count; ++i) {
6730 if (field == &klass->fields [i])
6731 return klass->field.first + 1 + i;
6737 * Find the property index in the metadata Property table.
6740 find_property_index (MonoClass *klass, MonoProperty *property) {
6743 for (i = 0; i < klass->property.count; ++i) {
6744 if (property == &klass->properties [i])
6745 return klass->property.first + 1 + i;
6751 * Find the event index in the metadata Event table.
6754 find_event_index (MonoClass *klass, MonoEvent *event) {
6757 for (i = 0; i < klass->event.count; ++i) {
6758 if (event == &klass->events [i])
6759 return klass->event.first + 1 + i;
6765 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6767 const char *p = data;
6769 guint32 i, j, num_named;
6773 mono_class_init (method->klass);
6776 attr = mono_object_new (mono_domain_get (), method->klass);
6777 mono_runtime_invoke (method, attr, NULL, NULL);
6781 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6784 /*g_print ("got attr %s\n", method->klass->name);*/
6786 /* Allocate using alloca so it gets GC tracking */
6787 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6791 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6792 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6796 attr = mono_object_new (mono_domain_get (), method->klass);
6797 mono_runtime_invoke (method, attr, params, NULL);
6798 free_param_data (method->signature, params);
6799 num_named = read16 (named);
6801 for (j = 0; j < num_named; j++) {
6803 gboolean is_boxed = FALSE;
6804 char *name, named_type, data_type;
6805 named_type = *named++;
6806 data_type = *named++; /* type of data */
6807 if (data_type == 0x51)
6810 if (data_type == 0x55) {
6813 type_len = mono_metadata_decode_blob_size (named, &named);
6814 type_name = g_malloc (type_len + 1);
6815 memcpy (type_name, named, type_len);
6816 type_name [type_len] = 0;
6818 /* FIXME: lookup the type and check type consistency */
6819 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6820 /* this seems to be the type of the element of the array */
6821 /* g_print ("skipping 0x%02x after prop\n", *named); */
6824 name_len = mono_metadata_decode_blob_size (named, &named);
6825 name = g_malloc (name_len + 1);
6826 memcpy (name, named, name_len);
6827 name [name_len] = 0;
6829 if (named_type == 0x53) {
6830 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6831 void *val = load_cattr_value (image, field->type, named, &named);
6832 mono_field_set_value (attr, field, val);
6833 if (!type_is_reference (field->type))
6835 } else if (named_type == 0x54) {
6838 MonoType *prop_type;
6840 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6841 /* can we have more that 1 arg in a custom attr named property? */
6842 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6843 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6844 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6845 mono_property_set_value (prop, attr, pparams, NULL);
6846 if (!type_is_reference (prop_type))
6847 g_free (pparams [0]);
6856 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6858 MonoArray *typedargs, *namedargs;
6859 MonoClass *attrklass;
6860 static MonoClass *klass;
6861 static MonoMethod *ctor;
6864 const char *p = data;
6866 guint32 i, j, num_named;
6869 mono_class_init (method->klass);
6872 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6874 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6876 domain = mono_domain_get ();
6878 /* This is for Attributes with no parameters */
6879 attr = mono_object_new (domain, klass);
6880 params [0] = mono_method_get_object (domain, method, NULL);
6881 params [1] = params [2] = NULL;
6882 mono_runtime_invoke (method, attr, params, NULL);
6886 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6889 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6893 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6894 MonoObject *obj, *typedarg;
6897 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6898 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6899 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6900 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6901 mono_array_set (typedargs, void*, i, typedarg);
6903 if (!type_is_reference (mono_method_signature (method)->params [i]))
6908 num_named = read16 (named);
6909 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6911 attrklass = method->klass;
6912 for (j = 0; j < num_named; j++) {
6914 char *name, named_type, data_type;
6915 named_type = *named++;
6916 data_type = *named++; /* type of data */
6917 if (data_type == 0x55) {
6920 type_len = mono_metadata_decode_blob_size (named, &named);
6921 type_name = g_malloc (type_len + 1);
6922 memcpy (type_name, named, type_len);
6923 type_name [type_len] = 0;
6925 /* FIXME: lookup the type and check type consistency */
6926 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6927 /* this seems to be the type of the element of the array */
6928 /* g_print ("skipping 0x%02x after prop\n", *named); */
6931 name_len = mono_metadata_decode_blob_size (named, &named);
6932 name = g_malloc (name_len + 1);
6933 memcpy (name, named, name_len);
6934 name [name_len] = 0;
6936 if (named_type == 0x53) {
6937 MonoObject *obj, *typedarg, *namedarg;
6938 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6939 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6941 minfo = mono_field_get_object (domain, NULL, field);
6942 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6943 typedarg = create_cattr_typed_arg (field->type, obj);
6944 namedarg = create_cattr_named_arg (minfo, typedarg);
6945 mono_array_set (namedargs, void*, j, namedarg);
6946 if (!type_is_reference (field->type))
6948 } else if (named_type == 0x54) {
6949 MonoObject *obj, *typedarg, *namedarg;
6950 MonoType *prop_type;
6952 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6954 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6955 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6956 minfo = mono_property_get_object (domain, NULL, prop);
6957 val = load_cattr_value (image, prop_type, named, &named);
6958 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6959 typedarg = create_cattr_typed_arg (prop_type, obj);
6960 namedarg = create_cattr_named_arg (minfo, typedarg);
6961 mono_array_set (namedargs, void*, j, namedarg);
6962 if (!type_is_reference (prop_type))
6967 attr = mono_object_new (domain, klass);
6968 params [0] = mono_method_get_object (domain, method, NULL);
6969 params [1] = typedargs;
6970 params [2] = namedargs;
6971 mono_runtime_invoke (ctor, attr, params, NULL);
6976 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6983 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6984 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6985 for (i = 0; i < cinfo->num_attrs; ++i) {
6986 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6987 mono_array_set (result, gpointer, i, attr);
6993 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
6996 static MonoClass *klass;
7001 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7003 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7004 for (i = 0; i < cinfo->num_attrs; ++i) {
7005 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7006 mono_array_set (result, gpointer, i, attr);
7012 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7014 guint32 mtoken, i, len;
7015 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7017 MonoCustomAttrInfo *ainfo;
7018 GList *tmp, *list = NULL;
7021 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7023 i = mono_metadata_custom_attrs_from_index (image, idx);
7027 while (i < ca->rows) {
7028 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7030 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7033 len = g_list_length (list);
7036 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7037 ainfo->num_attrs = len;
7038 ainfo->image = image;
7039 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7040 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7041 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7042 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7043 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7044 mtoken |= MONO_TOKEN_METHOD_DEF;
7046 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7047 mtoken |= MONO_TOKEN_MEMBER_REF;
7050 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7053 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7054 if (!ainfo->attrs [i].ctor)
7055 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7056 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7057 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7058 ainfo->attrs [i].data = data;
7066 mono_custom_attrs_from_method (MonoMethod *method)
7068 MonoCustomAttrInfo *cinfo;
7071 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7073 idx = mono_method_get_index (method);
7074 idx <<= MONO_CUSTOM_ATTR_BITS;
7075 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7076 return mono_custom_attrs_from_index (method->klass->image, idx);
7080 mono_custom_attrs_from_class (MonoClass *klass)
7082 MonoCustomAttrInfo *cinfo;
7085 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7087 idx = mono_metadata_token_index (klass->type_token);
7088 idx <<= MONO_CUSTOM_ATTR_BITS;
7089 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7090 return mono_custom_attrs_from_index (klass->image, idx);
7094 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7096 MonoCustomAttrInfo *cinfo;
7099 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7101 idx = 1; /* there is only one assembly */
7102 idx <<= MONO_CUSTOM_ATTR_BITS;
7103 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7104 return mono_custom_attrs_from_index (assembly->image, idx);
7107 static MonoCustomAttrInfo*
7108 mono_custom_attrs_from_module (MonoImage *image)
7110 MonoCustomAttrInfo *cinfo;
7113 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7115 idx = 1; /* there is only one module */
7116 idx <<= MONO_CUSTOM_ATTR_BITS;
7117 idx |= MONO_CUSTOM_ATTR_MODULE;
7118 return mono_custom_attrs_from_index (image, idx);
7122 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7124 MonoCustomAttrInfo *cinfo;
7127 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7129 idx = find_property_index (klass, property);
7130 idx <<= MONO_CUSTOM_ATTR_BITS;
7131 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7132 return mono_custom_attrs_from_index (klass->image, idx);
7136 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7138 MonoCustomAttrInfo *cinfo;
7141 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7143 idx = find_event_index (klass, event);
7144 idx <<= MONO_CUSTOM_ATTR_BITS;
7145 idx |= MONO_CUSTOM_ATTR_EVENT;
7146 return mono_custom_attrs_from_index (klass->image, idx);
7150 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7152 MonoCustomAttrInfo *cinfo;
7155 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7157 idx = find_field_index (klass, field);
7158 idx <<= MONO_CUSTOM_ATTR_BITS;
7159 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7160 return mono_custom_attrs_from_index (klass->image, idx);
7164 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7167 guint32 i, idx, method_index;
7168 guint32 param_list, param_last, param_pos, found;
7170 MonoReflectionMethodAux *aux;
7172 if (method->klass->image->dynamic) {
7173 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7174 if (!aux || !aux->param_cattr)
7176 return aux->param_cattr [param];
7179 image = method->klass->image;
7180 method_index = mono_method_get_index (method);
7181 ca = &image->tables [MONO_TABLE_METHOD];
7183 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7184 /* FIXME FIXME FIXME */
7188 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7189 if (method_index == ca->rows) {
7190 ca = &image->tables [MONO_TABLE_PARAM];
7191 param_last = ca->rows + 1;
7193 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7194 ca = &image->tables [MONO_TABLE_PARAM];
7197 for (i = param_list; i < param_last; ++i) {
7198 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7199 if (param_pos == param) {
7207 idx <<= MONO_CUSTOM_ATTR_BITS;
7208 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7209 return mono_custom_attrs_from_index (image, idx);
7213 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7217 for (i = 0; i < ainfo->num_attrs; ++i) {
7218 klass = ainfo->attrs [i].ctor->klass;
7219 if (mono_class_has_parent (klass, attr_klass))
7226 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7233 for (i = 0; i < ainfo->num_attrs; ++i) {
7234 klass = ainfo->attrs [i].ctor->klass;
7235 if (mono_class_has_parent (klass, attr_klass)) {
7240 if (attr_index == -1)
7243 attrs = mono_custom_attrs_construct (ainfo);
7245 return mono_array_get (attrs, MonoObject*, attr_index);
7251 * mono_reflection_get_custom_attrs_info:
7252 * @obj: a reflection object handle
7254 * Return the custom attribute info for attributes defined for the
7255 * reflection handle @obj. The objects.
7258 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7261 MonoCustomAttrInfo *cinfo = NULL;
7263 klass = obj->vtable->klass;
7264 if (klass == mono_defaults.monotype_class) {
7265 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7266 klass = mono_class_from_mono_type (rtype->type);
7267 cinfo = mono_custom_attrs_from_class (klass);
7268 } else if (strcmp ("Assembly", klass->name) == 0) {
7269 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7270 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7271 } else if (strcmp ("Module", klass->name) == 0) {
7272 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7273 cinfo = mono_custom_attrs_from_module (module->image);
7274 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7275 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7276 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7277 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7278 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7279 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7280 } else if (strcmp ("MonoField", klass->name) == 0) {
7281 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7282 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7283 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7284 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7285 cinfo = mono_custom_attrs_from_method (rmethod->method);
7286 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7287 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7288 cinfo = mono_custom_attrs_from_method (method);
7289 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7290 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7291 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7292 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7293 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7294 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7295 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7296 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7297 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7298 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7299 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7300 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7301 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7302 } else { /* handle other types here... */
7303 g_error ("get custom attrs not yet supported for %s", klass->name);
7310 * mono_reflection_get_custom_attrs:
7311 * @obj: a reflection object handle
7313 * Return an array with all the custom attributes defined of the
7314 * reflection handle @obj. The objects are fully build.
7317 mono_reflection_get_custom_attrs (MonoObject *obj)
7320 MonoCustomAttrInfo *cinfo;
7322 cinfo = mono_reflection_get_custom_attrs_info (obj);
7324 result = mono_custom_attrs_construct (cinfo);
7326 mono_custom_attrs_free (cinfo);
7329 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7330 result = mono_array_new (mono_domain_get (), klass, 0);
7337 * mono_reflection_get_custom_attrs_data:
7338 * @obj: a reflection obj handle
7340 * Returns an array of System.Reflection.CustomAttributeData,
7341 * which include information about attributes reflected on
7342 * types loaded using the Reflection Only methods
7345 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7348 MonoCustomAttrInfo *cinfo;
7350 cinfo = mono_reflection_get_custom_attrs_info (obj);
7352 result = mono_custom_attrs_data_construct (cinfo);
7354 mono_custom_attrs_free (cinfo);
7357 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7358 result = mono_array_new (mono_domain_get (), klass, 0);
7364 static MonoMethodSignature*
7365 parameters_to_signature (MonoArray *parameters) {
7366 MonoMethodSignature *sig;
7369 count = parameters? mono_array_length (parameters): 0;
7371 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7372 sig->param_count = count;
7373 sig->sentinelpos = -1; /* FIXME */
7374 for (i = 0; i < count; ++i) {
7375 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7376 sig->params [i] = pt->type;
7381 static MonoMethodSignature*
7382 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7383 MonoMethodSignature *sig;
7385 sig = parameters_to_signature (ctor->parameters);
7386 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7387 sig->ret = &mono_defaults.void_class->byval_arg;
7391 static MonoMethodSignature*
7392 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7393 MonoMethodSignature *sig;
7395 sig = parameters_to_signature (method->parameters);
7396 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7397 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7398 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7402 static MonoMethodSignature*
7403 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7404 MonoMethodSignature *sig;
7406 sig = parameters_to_signature (method->parameters);
7407 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7408 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7409 sig->generic_param_count = 0;
7414 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7416 MonoClass *klass = mono_object_class (prop);
7417 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7418 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7419 *name = mono_string_to_utf8 (pb->name);
7420 *type = pb->type->type;
7422 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7423 *name = g_strdup (p->property->name);
7424 if (p->property->get)
7425 *type = mono_method_signature (p->property->get)->ret;
7427 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7432 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7434 MonoClass *klass = mono_object_class (field);
7435 if (strcmp (klass->name, "FieldBuilder") == 0) {
7436 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7437 *name = mono_string_to_utf8 (fb->name);
7438 *type = fb->type->type;
7440 MonoReflectionField *f = (MonoReflectionField *)field;
7441 *name = g_strdup (f->field->name);
7442 *type = f->field->type;
7447 * Encode a value in a custom attribute stream of bytes.
7448 * The value to encode is either supplied as an object in argument val
7449 * (valuetypes are boxed), or as a pointer to the data in the
7451 * @type represents the type of the value
7452 * @buffer is the start of the buffer
7453 * @p the current position in the buffer
7454 * @buflen contains the size of the buffer and is used to return the new buffer size
7455 * if this needs to be realloced.
7456 * @retbuffer and @retp return the start and the position of the buffer
7459 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7461 MonoTypeEnum simple_type;
7463 if ((p-buffer) + 10 >= *buflen) {
7466 newbuf = g_realloc (buffer, *buflen);
7467 p = newbuf + (p-buffer);
7471 argval = ((char*)arg + sizeof (MonoObject));
7472 simple_type = type->type;
7474 switch (simple_type) {
7475 case MONO_TYPE_BOOLEAN:
7480 case MONO_TYPE_CHAR:
7483 swap_with_size (p, argval, 2, 1);
7489 swap_with_size (p, argval, 4, 1);
7495 swap_with_size (p, argval, 8, 1);
7498 case MONO_TYPE_VALUETYPE:
7499 if (type->data.klass->enumtype) {
7500 simple_type = type->data.klass->enum_basetype->type;
7503 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7506 case MONO_TYPE_STRING: {
7513 str = mono_string_to_utf8 ((MonoString*)arg);
7514 slen = strlen (str);
7515 if ((p-buffer) + 10 + slen >= *buflen) {
7519 newbuf = g_realloc (buffer, *buflen);
7520 p = newbuf + (p-buffer);
7523 mono_metadata_encode_value (slen, p, &p);
7524 memcpy (p, str, slen);
7529 case MONO_TYPE_CLASS: {
7537 k = mono_object_class (arg);
7538 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7539 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7540 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7542 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7543 slen = strlen (str);
7544 if ((p-buffer) + 10 + slen >= *buflen) {
7548 newbuf = g_realloc (buffer, *buflen);
7549 p = newbuf + (p-buffer);
7552 mono_metadata_encode_value (slen, p, &p);
7553 memcpy (p, str, slen);
7558 case MONO_TYPE_SZARRAY: {
7560 MonoClass *eclass, *arg_eclass;
7563 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7566 len = mono_array_length ((MonoArray*)arg);
7568 *p++ = (len >> 8) & 0xff;
7569 *p++ = (len >> 16) & 0xff;
7570 *p++ = (len >> 24) & 0xff;
7572 *retbuffer = buffer;
7573 eclass = type->data.klass;
7574 arg_eclass = mono_object_class (arg)->element_class;
7575 if (eclass->valuetype && arg_eclass->valuetype) {
7576 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7577 int elsize = mono_class_array_element_size (eclass);
7578 for (i = 0; i < len; ++i) {
7579 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7583 for (i = 0; i < len; ++i) {
7584 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7589 /* it may be a boxed value or a Type */
7590 case MONO_TYPE_OBJECT: {
7596 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7601 klass = mono_object_class (arg);
7603 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7606 } else if (klass->enumtype) {
7608 } else if (klass == mono_defaults.string_class) {
7609 simple_type = MONO_TYPE_STRING;
7612 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7613 *p++ = simple_type = klass->byval_arg.type;
7616 g_error ("unhandled type in custom attr");
7618 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7619 slen = strlen (str);
7620 if ((p-buffer) + 10 + slen >= *buflen) {
7624 newbuf = g_realloc (buffer, *buflen);
7625 p = newbuf + (p-buffer);
7628 mono_metadata_encode_value (slen, p, &p);
7629 memcpy (p, str, slen);
7632 simple_type = klass->enum_basetype->type;
7636 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7639 *retbuffer = buffer;
7643 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7646 /* Preallocate a large enough buffer */
7647 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7648 char *str = type_get_qualified_name (type, NULL);
7654 len += strlen (name);
7656 if ((p-buffer) + 20 + len >= *buflen) {
7660 newbuf = g_realloc (buffer, *buflen);
7661 p = newbuf + (p-buffer);
7665 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7666 char *str = type_get_qualified_name (type, NULL);
7667 int slen = strlen (str);
7671 * This seems to be optional...
7674 mono_metadata_encode_value (slen, p, &p);
7675 memcpy (p, str, slen);
7678 } else if (type->type == MONO_TYPE_OBJECT) {
7680 } else if (type->type == MONO_TYPE_CLASS) {
7681 /* it should be a type: encode_cattr_value () has the check */
7684 mono_metadata_encode_value (type->type, p, &p);
7685 if (type->type == MONO_TYPE_SZARRAY)
7686 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7688 len = strlen (name);
7689 mono_metadata_encode_value (len, p, &p);
7690 memcpy (p, name, len);
7692 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7694 *retbuffer = buffer;
7698 * mono_reflection_get_custom_attrs_blob:
7699 * @ctor: custom attribute constructor
7700 * @ctorArgs: arguments o the constructor
7706 * Creates the blob of data that needs to be saved in the metadata and that represents
7707 * the custom attributed described by @ctor, @ctorArgs etc.
7708 * Returns: a Byte array representing the blob of data.
7711 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7714 MonoMethodSignature *sig;
7719 MONO_ARCH_SAVE_REGS;
7721 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7722 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7724 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7726 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7728 p = buffer = g_malloc (buflen);
7729 /* write the prolog */
7732 for (i = 0; i < sig->param_count; ++i) {
7733 arg = mono_array_get (ctorArgs, MonoObject*, i);
7734 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7738 i += mono_array_length (properties);
7740 i += mono_array_length (fields);
7742 *p++ = (i >> 8) & 0xff;
7745 for (i = 0; i < mono_array_length (properties); ++i) {
7749 prop = mono_array_get (properties, gpointer, i);
7750 get_prop_name_and_type (prop, &pname, &ptype);
7751 *p++ = 0x54; /* PROPERTY signature */
7752 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7759 for (i = 0; i < mono_array_length (fields); ++i) {
7763 field = mono_array_get (fields, gpointer, i);
7764 get_field_name_and_type (field, &fname, &ftype);
7765 *p++ = 0x53; /* FIELD signature */
7766 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7771 g_assert (p - buffer <= buflen);
7772 buflen = p - buffer;
7773 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7774 p = mono_array_addr (result, char, 0);
7775 memcpy (p, buffer, buflen);
7777 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7783 * mono_reflection_setup_internal_class:
7784 * @tb: a TypeBuilder object
7786 * Creates a MonoClass that represents the TypeBuilder.
7787 * This is a trick that lets us simplify a lot of reflection code
7788 * (and will allow us to support Build and Run assemblies easier).
7791 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7793 MonoClass *klass, *parent;
7795 MONO_ARCH_SAVE_REGS;
7797 mono_loader_lock ();
7800 /* check so we can compile corlib correctly */
7801 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7802 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7803 parent = tb->parent->type->data.klass;
7805 parent = my_mono_class_from_mono_type (tb->parent->type);
7811 /* the type has already being created: it means we just have to change the parent */
7812 if (tb->type.type) {
7813 klass = mono_class_from_mono_type (tb->type.type);
7814 klass->parent = NULL;
7815 /* fool mono_class_setup_parent */
7816 g_free (klass->supertypes);
7817 klass->supertypes = NULL;
7818 mono_class_setup_parent (klass, parent);
7819 mono_class_setup_mono_type (klass);
7820 mono_loader_unlock ();
7824 klass = g_new0 (MonoClass, 1);
7826 klass->image = &tb->module->dynamic_image->image;
7828 klass->inited = 1; /* we lie to the runtime */
7829 klass->name = mono_string_to_utf8 (tb->name);
7830 klass->name_space = mono_string_to_utf8 (tb->nspace);
7831 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7832 klass->flags = tb->attrs;
7834 klass->element_class = klass;
7835 klass->reflection_info = tb; /* need to pin. */
7837 /* Put into cache so mono_class_get () will find it */
7838 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7840 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7841 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7843 if (parent != NULL) {
7844 mono_class_setup_parent (klass, parent);
7845 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7846 const char *old_n = klass->name;
7847 /* trick to get relative numbering right when compiling corlib */
7848 klass->name = "BuildingObject";
7849 mono_class_setup_parent (klass, mono_defaults.object_class);
7850 klass->name = old_n;
7853 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7854 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7855 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7856 klass->instance_size = sizeof (MonoObject);
7857 klass->size_inited = 1;
7858 mono_class_setup_vtable_general (klass, NULL, 0);
7861 mono_class_setup_mono_type (klass);
7863 mono_class_setup_supertypes (klass);
7866 * FIXME: handle interfaces.
7869 tb->type.type = &klass->byval_arg;
7871 if (tb->nesting_type) {
7872 g_assert (tb->nesting_type->type);
7873 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7876 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7878 mono_loader_unlock ();
7882 * mono_reflection_setup_generic_class:
7883 * @tb: a TypeBuilder object
7885 * Setup the generic class before adding the first generic parameter.
7888 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7892 MONO_ARCH_SAVE_REGS;
7894 klass = my_mono_class_from_mono_type (tb->type.type);
7895 if (tb->generic_container)
7898 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7899 tb->generic_container->klass = klass;
7901 tb->generic_container->context.container = tb->generic_container;
7905 * mono_reflection_create_generic_class:
7906 * @tb: a TypeBuilder object
7908 * Creates the generic class after all generic parameters have been added.
7911 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7916 MONO_ARCH_SAVE_REGS;
7918 klass = my_mono_class_from_mono_type (tb->type.type);
7920 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7922 if (klass->generic_container || (count == 0))
7925 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7927 klass->generic_container = tb->generic_container;
7929 klass->generic_container->type_argc = count;
7930 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7932 for (i = 0; i < count; i++) {
7933 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7934 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7935 g_assert (klass->generic_container->type_params [i].owner);
7938 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7942 * mono_reflection_create_internal_class:
7943 * @tb: a TypeBuilder object
7945 * Actually create the MonoClass that is associated with the TypeBuilder.
7948 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7952 MONO_ARCH_SAVE_REGS;
7954 klass = my_mono_class_from_mono_type (tb->type.type);
7956 mono_loader_lock ();
7957 if (klass->enumtype && klass->enum_basetype == NULL) {
7958 MonoReflectionFieldBuilder *fb;
7961 g_assert (tb->fields != NULL);
7962 g_assert (mono_array_length (tb->fields) >= 1);
7964 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7966 klass->enum_basetype = fb->type->type;
7967 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7968 if (!klass->element_class)
7969 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7972 * get the element_class from the current corlib.
7974 ec = default_class_from_mono_type (klass->enum_basetype);
7975 klass->instance_size = ec->instance_size;
7976 klass->size_inited = 1;
7978 * this is almost safe to do with enums and it's needed to be able
7979 * to create objects of the enum type (for use in SetConstant).
7981 /* FIXME: Does this mean enums can't have method overrides ? */
7982 mono_class_setup_vtable_general (klass, NULL, 0);
7984 mono_loader_unlock ();
7987 static MonoMarshalSpec*
7988 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7989 MonoReflectionMarshal *minfo)
7991 MonoMarshalSpec *res;
7993 res = g_new0 (MonoMarshalSpec, 1);
7994 res->native = minfo->type;
7996 switch (minfo->type) {
7997 case MONO_NATIVE_LPARRAY:
7998 res->data.array_data.elem_type = minfo->eltype;
7999 if (minfo->has_size) {
8000 res->data.array_data.param_num = minfo->param_num;
8001 res->data.array_data.num_elem = minfo->count;
8002 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8005 res->data.array_data.param_num = -1;
8006 res->data.array_data.num_elem = -1;
8007 res->data.array_data.elem_mult = -1;
8011 case MONO_NATIVE_BYVALTSTR:
8012 case MONO_NATIVE_BYVALARRAY:
8013 res->data.array_data.num_elem = minfo->count;
8016 case MONO_NATIVE_CUSTOM:
8017 if (minfo->marshaltyperef)
8018 res->data.custom_data.custom_name =
8019 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8021 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8031 MonoReflectionMarshal*
8032 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8033 MonoMarshalSpec *spec)
8035 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8036 MonoReflectionMarshal *minfo;
8039 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8040 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8041 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8042 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8045 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8046 minfo->type = spec->native;
8048 switch (minfo->type) {
8049 case MONO_NATIVE_LPARRAY:
8050 minfo->eltype = spec->data.array_data.elem_type;
8051 minfo->count = spec->data.array_data.num_elem;
8052 minfo->param_num = spec->data.array_data.param_num;
8055 case MONO_NATIVE_BYVALTSTR:
8056 case MONO_NATIVE_BYVALARRAY:
8057 minfo->count = spec->data.array_data.num_elem;
8060 case MONO_NATIVE_CUSTOM:
8061 if (spec->data.custom_data.custom_name) {
8062 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8064 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8066 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8068 if (spec->data.custom_data.cookie)
8069 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8080 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8081 ReflectionMethodBuilder *rmb,
8082 MonoMethodSignature *sig)
8085 MonoMethodNormal *pm;
8086 MonoMarshalSpec **specs;
8087 MonoReflectionMethodAux *method_aux;
8090 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8091 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8092 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8094 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8096 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8098 pm = (MonoMethodNormal*)m;
8101 m->flags = rmb->attrs;
8102 m->iflags = rmb->iattrs;
8103 m->name = mono_string_to_utf8 (rmb->name);
8107 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8109 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8110 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8113 m->signature->pinvoke = 1;
8114 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8115 m->signature->pinvoke = 1;
8117 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8119 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8120 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8122 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8124 if (klass->image->dynamic)
8125 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8128 } else if (!m->klass->dummy &&
8129 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8130 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8131 MonoMethodHeader *header;
8133 gint32 max_stack, i;
8134 gint32 num_locals = 0;
8135 gint32 num_clauses = 0;
8139 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8140 code_size = rmb->ilgen->code_len;
8141 max_stack = rmb->ilgen->max_stack;
8142 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8143 if (rmb->ilgen->ex_handlers)
8144 num_clauses = method_count_clauses (rmb->ilgen);
8147 code = mono_array_addr (rmb->code, guint8, 0);
8148 code_size = mono_array_length (rmb->code);
8149 /* we probably need to run a verifier on the code... */
8159 header = g_malloc0 (sizeof (MonoMethodHeader) +
8160 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8161 header->code_size = code_size;
8162 header->code = g_malloc (code_size);
8163 memcpy ((char*)header->code, code, code_size);
8164 header->max_stack = max_stack;
8165 header->init_locals = rmb->init_locals;
8166 header->num_locals = num_locals;
8168 for (i = 0; i < num_locals; ++i) {
8169 MonoReflectionLocalBuilder *lb =
8170 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8172 header->locals [i] = g_new0 (MonoType, 1);
8173 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8176 header->num_clauses = num_clauses;
8178 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8179 rmb->ilgen, num_clauses);
8182 pm->header = header;
8185 if (rmb->generic_params) {
8186 int count = mono_array_length (rmb->generic_params);
8187 MonoGenericContainer *container;
8189 pm->generic_container = container = rmb->generic_container;
8190 container->type_argc = count;
8191 container->type_params = g_new0 (MonoGenericParam, count);
8193 for (i = 0; i < count; i++) {
8194 MonoReflectionGenericParam *gp =
8195 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8197 container->type_params [i] = *gp->type.type->data.generic_param;
8202 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8206 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8208 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8209 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8210 for (i = 0; i < rmb->nrefs; ++i)
8211 data [i + 1] = rmb->refs [i];
8216 /* Parameter info */
8219 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8220 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8221 for (i = 0; i <= m->signature->param_count; ++i) {
8222 MonoReflectionParamBuilder *pb;
8223 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8224 if ((i > 0) && (pb->attrs)) {
8225 /* Make a copy since it might point to a shared type structure */
8226 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)));
8227 m->signature->params [i - 1]->attrs = pb->attrs;
8230 if (pb->def_value) {
8231 MonoDynamicImage *assembly;
8232 guint32 idx, def_type, len;
8236 if (!method_aux->param_defaults) {
8237 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8238 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8240 assembly = (MonoDynamicImage*)klass->image;
8241 idx = encode_constant (assembly, pb->def_value, &def_type);
8242 /* Copy the data from the blob since it might get realloc-ed */
8243 p = assembly->blob.data + idx;
8244 len = mono_metadata_decode_blob_size (p, &p2);
8246 method_aux->param_defaults [i] = g_malloc (len);
8247 method_aux->param_default_types [i] = def_type;
8248 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8252 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8254 if (!method_aux->param_cattr)
8255 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8256 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8262 /* Parameter marshalling */
8265 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8266 MonoReflectionParamBuilder *pb;
8267 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8268 if (pb->marshal_info) {
8270 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8271 specs [pb->position] =
8272 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8276 if (specs != NULL) {
8278 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8279 method_aux->param_marshall = specs;
8282 if (klass->image->dynamic && method_aux)
8283 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8289 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8291 ReflectionMethodBuilder rmb;
8292 MonoMethodSignature *sig;
8294 sig = ctor_builder_to_signature (mb);
8296 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8298 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8299 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8301 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8302 /* ilgen is no longer needed */
8310 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8312 ReflectionMethodBuilder rmb;
8313 MonoMethodSignature *sig;
8315 sig = method_builder_to_signature (mb);
8317 reflection_methodbuilder_from_method_builder (&rmb, mb);
8319 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8320 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8322 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8323 /* ilgen is no longer needed */
8329 static MonoClassField*
8330 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8332 MonoClassField *field;
8339 field = g_new0 (MonoClassField, 1);
8341 field->name = mono_string_to_utf8 (fb->name);
8343 /* FIXME: handle type modifiers */
8344 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8345 field->type->attrs = fb->attrs;
8347 field->type = fb->type->type;
8349 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8350 field->data = mono_array_addr (fb->rva_data, char, 0);
8351 if (fb->offset != -1)
8352 field->offset = fb->offset;
8353 field->parent = klass;
8355 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8357 if (fb->def_value) {
8358 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8359 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8360 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8361 /* Copy the data from the blob since it might get realloc-ed */
8362 p = assembly->blob.data + idx;
8363 len = mono_metadata_decode_blob_size (p, &p2);
8365 field->data = g_malloc (len);
8366 memcpy ((gpointer)field->data, p, len);
8373 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8377 MonoReflectionTypeBuilder *tb = NULL;
8378 MonoGenericClass *gclass, *cached;
8379 MonoDynamicGenericClass *dgclass = NULL;
8380 gboolean is_dynamic = FALSE;
8385 klass = mono_class_from_mono_type (type->type);
8386 if (!klass->generic_container && !klass->generic_class &&
8387 !(klass->nested_in && klass->nested_in->generic_container))
8390 mono_loader_lock ();
8392 domain = mono_object_domain (type);
8394 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8395 tb = (MonoReflectionTypeBuilder *) type;
8397 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8399 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8400 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8401 MonoReflectionType *rgt = rgi->generic_type;
8403 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8404 tb = (MonoReflectionTypeBuilder *) rgt;
8406 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8409 icount = klass->interface_count;
8413 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8414 gclass = &dgclass->generic_class;
8415 gclass->is_dynamic = TRUE;
8417 gclass = g_new0 (MonoGenericClass, 1);
8419 gclass->inst = g_new0 (MonoGenericInst, 1);
8421 gclass->inst->type_argc = type_argc;
8422 gclass->inst->type_argv = types;
8423 gclass->inst->is_reference = 1;
8425 for (i = 0; i < gclass->inst->type_argc; ++i) {
8426 if (!gclass->inst->is_open)
8427 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8428 if (gclass->inst->is_reference)
8429 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8432 gclass->container_class = klass;
8434 if (klass->generic_class) {
8435 MonoGenericClass *kgclass = klass->generic_class;
8436 MonoGenericClass *ogclass = gclass;
8438 ogclass->context = g_new0 (MonoGenericContext, 1);
8439 ogclass->context->container = ogclass->container_class->generic_container;
8440 ogclass->context->gclass = ogclass;
8443 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8444 gclass = &dgclass->generic_class;
8445 gclass->is_dynamic = TRUE;
8447 gclass = g_new0 (MonoGenericClass, 1);
8449 gclass->inst = g_new0 (MonoGenericInst, 1);
8451 gclass->inst->type_argc = kgclass->inst->type_argc;
8452 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8453 gclass->inst->is_reference = 1;
8455 for (i = 0; i < gclass->inst->type_argc; i++) {
8456 MonoType *t = kgclass->inst->type_argv [i];
8458 t = mono_class_inflate_generic_type (t, ogclass->context);
8460 if (!gclass->inst->is_open)
8461 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8462 if (gclass->inst->is_reference)
8463 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8465 gclass->inst->type_argv [i] = t;
8468 gclass->container_class = kgclass->container_class;
8471 geninst = g_new0 (MonoType, 1);
8472 geninst->type = MONO_TYPE_GENERICINST;
8474 cached = mono_metadata_lookup_generic_class (gclass);
8477 mono_loader_unlock ();
8478 geninst->data.generic_class = cached;
8482 geninst->data.generic_class = gclass;
8484 gclass->parent = parent;
8486 gclass->context = g_new0 (MonoGenericContext, 1);
8487 gclass->context->container = gclass->container_class->generic_container;
8488 gclass->context->gclass = gclass;
8490 gclass->ifaces = g_new0 (MonoType *, icount);
8491 gclass->count_ifaces = icount;
8493 for (i = 0; i < icount; i++) {
8494 MonoReflectionType *itype;
8497 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8499 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8500 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8501 if (!gclass->ifaces [i])
8502 gclass->ifaces [i] = itype->type;
8505 mono_class_create_generic (gclass);
8507 mono_loader_unlock ();
8513 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8515 MonoClass *klass, *pklass = NULL;
8516 MonoReflectionType *parent = NULL;
8517 MonoType *the_parent = NULL, *geninst;
8518 MonoReflectionTypeBuilder *tb = NULL;
8519 MonoGenericClass *gclass;
8522 domain = mono_object_domain (type);
8523 klass = mono_class_from_mono_type (type->type);
8525 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8526 tb = (MonoReflectionTypeBuilder *) type;
8529 parent = tb->parent;
8530 pklass = mono_class_from_mono_type (parent->type);
8533 pklass = klass->parent;
8535 parent = mono_type_get_object (domain, &pklass->byval_arg);
8536 else if (klass->generic_class && klass->generic_class->parent) {
8537 parent = mono_type_get_object (domain, klass->generic_class->parent);
8538 pklass = mono_class_from_mono_type (klass->generic_class->parent);
8542 if (pklass && pklass->generic_class)
8543 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8545 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8549 gclass = geninst->data.generic_class;
8555 do_mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types, MonoType *parent)
8558 MonoGenericClass *gclass, *cached;
8562 klass = mono_class_from_mono_type (type);
8563 if (!klass->generic_container && !klass->generic_class &&
8564 !(klass->nested_in && klass->nested_in->generic_container))
8567 mono_loader_lock ();
8569 icount = klass->interface_count;
8571 gclass = g_new0 (MonoGenericClass, 1);
8572 gclass->inst = g_new0 (MonoGenericInst, 1);
8573 gclass->inst->type_argc = type_argc;
8574 gclass->inst->type_argv = types;
8575 gclass->inst->is_reference = 1;
8577 for (i = 0; i < gclass->inst->type_argc; ++i) {
8578 if (!gclass->inst->is_open)
8579 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8580 if (gclass->inst->is_reference)
8581 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8584 gclass->container_class = klass;
8586 if (klass->generic_class) {
8587 MonoGenericClass *kgclass = klass->generic_class;
8588 MonoGenericClass *ogclass = gclass;
8590 ogclass->context = g_new0 (MonoGenericContext, 1);
8591 ogclass->context->container = ogclass->container_class->generic_container;
8592 ogclass->context->gclass = ogclass;
8594 gclass = g_new0 (MonoGenericClass, 1);
8595 gclass->inst = g_new0 (MonoGenericInst, 1);
8597 gclass->inst->type_argc = kgclass->inst->type_argc;
8598 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8599 gclass->inst->is_reference = 1;
8601 for (i = 0; i < gclass->inst->type_argc; i++) {
8602 MonoType *t = kgclass->inst->type_argv [i];
8604 t = mono_class_inflate_generic_type (t, ogclass->context);
8606 if (!gclass->inst->is_open)
8607 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8608 if (gclass->inst->is_reference)
8609 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8611 gclass->inst->type_argv [i] = t;
8614 gclass->container_class = kgclass->container_class;
8617 geninst = g_new0 (MonoType, 1);
8618 geninst->type = MONO_TYPE_GENERICINST;
8620 cached = mono_metadata_lookup_generic_class (gclass);
8623 mono_loader_unlock ();
8624 geninst->data.generic_class = cached;
8628 geninst->data.generic_class = gclass;
8630 gclass->parent = parent;
8632 gclass->context = g_new0 (MonoGenericContext, 1);
8633 gclass->context->container = gclass->container_class->generic_container;
8634 gclass->context->gclass = gclass;
8636 gclass->ifaces = g_new0 (MonoType *, icount);
8637 gclass->count_ifaces = icount;
8639 for (i = 0; i < icount; i++) {
8642 itype = &klass->interfaces [i]->byval_arg;
8643 gclass->ifaces [i] = mono_class_bind_generic_parameters (itype, type_argc, types);
8644 if (!gclass->ifaces [i])
8645 gclass->ifaces [i] = itype;
8648 mono_class_create_generic (gclass);
8650 mono_loader_unlock ();
8656 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8658 MonoClass *klass, *pklass = NULL;
8659 MonoType *parent = NULL, *the_parent = NULL, *geninst;
8660 MonoGenericClass *gclass;
8662 klass = mono_class_from_mono_type (type);
8664 pklass = klass->parent;
8666 parent = &pklass->byval_arg;
8667 else if (klass->generic_class && klass->generic_class->parent) {
8668 parent = klass->generic_class->parent;
8669 pklass = mono_class_from_mono_type (klass->generic_class->parent);
8672 if (pklass && pklass->generic_class)
8673 the_parent = mono_class_bind_generic_parameters (parent, type_argc, types);
8675 geninst = do_mono_class_bind_generic_parameters (type, type_argc, types, the_parent);
8679 gclass = geninst->data.generic_class;
8684 static inline MonoType*
8685 dup_type (const MonoType *original)
8687 MonoType *r = g_new0 (MonoType, 1);
8689 r->attrs = original->attrs;
8690 r->byref = original->byref;
8691 if (original->type == MONO_TYPE_PTR)
8692 r->data.type = dup_type (original->data.type);
8693 mono_stats.generics_metadata_size += sizeof (MonoType);
8697 MonoReflectionMethod*
8698 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8700 MonoMethod *method, *inflated;
8701 MonoReflectionMethodBuilder *mb = NULL;
8702 MonoGenericContainer *container;
8703 MonoGenericMethod *gmethod;
8704 MonoGenericContext *context;
8705 MonoGenericInst *ginst;
8708 MONO_ARCH_SAVE_REGS;
8709 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8710 MonoReflectionTypeBuilder *tb;
8713 mb = (MonoReflectionMethodBuilder *) rmethod;
8714 tb = (MonoReflectionTypeBuilder *) mb->type;
8715 klass = mono_class_from_mono_type (tb->type.type);
8717 method = methodbuilder_to_mono_method (klass, mb);
8719 method = rmethod->method;
8722 method = mono_get_inflated_method (method);
8724 count = mono_method_signature (method)->generic_param_count;
8725 if (count != mono_array_length (types))
8728 container = ((MonoMethodNormal*) method)->generic_container;
8729 g_assert (container);
8731 if (!container->method_hash)
8732 container->method_hash = g_hash_table_new (
8733 (GHashFunc) mono_metadata_generic_method_hash,
8734 (GCompareFunc) mono_metadata_generic_method_equal);
8736 ginst = g_new0 (MonoGenericInst,1 );
8737 ginst->type_argc = count;
8738 ginst->type_argv = g_new0 (MonoType *, count);
8739 ginst->is_reference = 1;
8740 for (i = 0; i < count; i++) {
8741 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8742 ginst->type_argv [i] = dup_type (garg->type);
8744 if (!ginst->is_open)
8745 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8746 if (ginst->is_reference)
8747 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8749 ginst = mono_metadata_lookup_generic_inst (ginst);
8751 gmethod = g_new0 (MonoGenericMethod, 1);
8752 gmethod->generic_class = method->klass->generic_class;
8753 gmethod->container = container;
8754 gmethod->inst = ginst;
8756 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8760 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8763 gmethod->reflection_info = rmethod;
8765 context = g_new0 (MonoGenericContext, 1);
8766 context->container = container;
8767 context->gclass = method->klass->generic_class;
8768 context->gmethod = gmethod;
8770 if (method->is_inflated)
8771 method = ((MonoMethodInflated *) method)->declaring;
8773 inflated = mono_class_inflate_generic_method (method, context, method->klass);
8774 g_hash_table_insert (container->method_hash, gmethod, inflated);
8776 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8780 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8782 MonoGenericMethod *gmethod;
8783 MonoGenericClass *gclass;
8784 MonoGenericContext *context;
8787 gclass = type->type.type->data.generic_class;
8789 gmethod = g_new0 (MonoGenericMethod, 1);
8790 gmethod->generic_class = gclass;
8791 gmethod->inst = g_new0 (MonoGenericInst, 1);
8792 gmethod->reflection_info = obj;
8794 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8795 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8797 for (i = 0; i < gmethod->inst->type_argc; i++) {
8798 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8799 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8801 g_assert (gparam->pklass);
8802 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8805 context = g_new0 (MonoGenericContext, 1);
8806 context->container = gclass->container_class->generic_container;
8807 context->gclass = gclass;
8808 context->gmethod = gmethod;
8810 return mono_class_inflate_generic_method (method, context, gclass->klass);
8814 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8819 klass = mono_class_from_mono_type (type->type.type);
8821 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8822 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8823 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8824 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8825 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8826 method = ((MonoReflectionMethod *) obj)->method;
8828 method = NULL; /* prevent compiler warning */
8829 g_assert_not_reached ();
8832 return inflate_mono_method (type, method, obj);
8836 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8837 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8840 MonoGenericClass *gclass;
8841 MonoDynamicGenericClass *dgclass;
8842 MonoClass *klass, *gklass, *pklass;
8845 MONO_ARCH_SAVE_REGS;
8847 klass = mono_class_from_mono_type (type->type.type);
8848 gclass = type->type.type->data.generic_class;
8850 g_assert (gclass->is_dynamic);
8851 dgclass = (MonoDynamicGenericClass *) gclass;
8853 if (dgclass->initialized)
8856 gklass = gclass->container_class;
8857 mono_class_init (gklass);
8860 pklass = mono_class_from_mono_type (gclass->parent);
8862 pklass = gklass->parent;
8864 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8865 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8866 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8867 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8868 dgclass->count_events = events ? mono_array_length (events) : 0;
8870 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8871 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8872 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8873 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8874 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8876 for (i = 0; i < dgclass->count_methods; i++) {
8877 MonoObject *obj = mono_array_get (methods, gpointer, i);
8879 dgclass->methods [i] = inflate_method (type, obj);
8882 for (i = 0; i < dgclass->count_ctors; i++) {
8883 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8885 dgclass->ctors [i] = inflate_method (type, obj);
8888 for (i = 0; i < dgclass->count_fields; i++) {
8889 MonoObject *obj = mono_array_get (fields, gpointer, i);
8890 MonoClassField *field;
8891 MonoInflatedField *ifield;
8893 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8894 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8895 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8896 field = ((MonoReflectionField *) obj)->field;
8898 field = NULL; /* prevent compiler warning */
8899 g_assert_not_reached ();
8902 ifield = g_new0 (MonoInflatedField, 1);
8903 ifield->generic_type = field->type;
8904 ifield->reflection_info = obj;
8906 dgclass->fields [i] = *field;
8907 dgclass->fields [i].generic_info = ifield;
8908 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8911 for (i = 0; i < dgclass->count_properties; i++) {
8912 MonoObject *obj = mono_array_get (properties, gpointer, i);
8913 MonoProperty *property = &dgclass->properties [i];
8915 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8916 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8918 property->parent = klass;
8919 property->attrs = pb->attrs;
8920 property->name = mono_string_to_utf8 (pb->name);
8922 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8924 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8925 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8926 *property = *((MonoReflectionProperty *) obj)->property;
8929 property->get = inflate_mono_method (type, property->get, NULL);
8931 property->set = inflate_mono_method (type, property->set, NULL);
8933 g_assert_not_reached ();
8936 for (i = 0; i < dgclass->count_events; i++) {
8937 MonoObject *obj = mono_array_get (events, gpointer, i);
8938 MonoEvent *event = &dgclass->events [i];
8940 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8941 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8943 event->parent = klass;
8944 event->attrs = eb->attrs;
8945 event->name = mono_string_to_utf8 (eb->name);
8947 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8948 if (eb->remove_method)
8949 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8950 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8951 *event = *((MonoReflectionEvent *) obj)->event;
8954 event->add = inflate_mono_method (type, event->add, NULL);
8956 event->remove = inflate_mono_method (type, event->remove, NULL);
8958 g_assert_not_reached ();
8961 dgclass->initialized = TRUE;
8965 ensure_runtime_vtable (MonoClass *klass)
8967 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8968 int i, num, j, onum;
8969 MonoMethod **overrides;
8971 if (!tb || klass->wastypebuilder)
8974 ensure_runtime_vtable (klass->parent);
8976 num = tb->ctors? mono_array_length (tb->ctors): 0;
8977 num += tb->num_methods;
8978 klass->method.count = num;
8979 klass->methods = g_new (MonoMethod*, num);
8980 num = tb->ctors? mono_array_length (tb->ctors): 0;
8981 for (i = 0; i < num; ++i)
8982 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8983 num = tb->num_methods;
8985 for (i = 0; i < num; ++i)
8986 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8988 if (tb->interfaces) {
8989 klass->interface_count = mono_array_length (tb->interfaces);
8990 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8991 for (i = 0; i < klass->interface_count; ++i) {
8992 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8993 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8997 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8998 for (i = 0; i < klass->method.count; ++i)
8999 klass->methods [i]->slot = i;
9001 if (!((MonoDynamicImage*)klass->image)->run)
9002 /* No need to create a generic vtable */
9008 for (i = 0; i < tb->num_methods; ++i) {
9009 MonoReflectionMethodBuilder *mb =
9010 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9011 if (mb->override_method)
9016 overrides = g_new0 (MonoMethod*, onum * 2);
9020 for (i = 0; i < tb->num_methods; ++i) {
9021 MonoReflectionMethodBuilder *mb =
9022 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9023 if (mb->override_method) {
9024 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9025 overrides [onum * 2] =
9026 mb->override_method->method;
9027 overrides [onum * 2 + 1] =
9030 g_assert (mb->mhandle);
9037 mono_class_setup_vtable_general (klass, overrides, onum);
9042 typebuilder_setup_fields (MonoClass *klass)
9044 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9045 MonoReflectionFieldBuilder *fb;
9046 MonoClassField *field;
9051 klass->field.count = tb->num_fields;
9052 klass->field.first = 0;
9053 klass->field.last = klass->field.count;
9055 if (!klass->field.count)
9058 klass->fields = g_new0 (MonoClassField, klass->field.count);
9060 for (i = 0; i < klass->field.count; ++i) {
9061 fb = mono_array_get (tb->fields, gpointer, i);
9062 field = &klass->fields [i];
9063 field->name = mono_string_to_utf8 (fb->name);
9065 /* FIXME: handle type modifiers */
9066 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9067 field->type->attrs = fb->attrs;
9069 field->type = fb->type->type;
9071 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9072 field->data = mono_array_addr (fb->rva_data, char, 0);
9073 if (fb->offset != -1)
9074 field->offset = fb->offset;
9075 field->parent = klass;
9077 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9079 if (fb->def_value) {
9080 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9081 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9082 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9083 /* Copy the data from the blob since it might get realloc-ed */
9084 p = assembly->blob.data + idx;
9085 len = mono_metadata_decode_blob_size (p, &p2);
9087 field->data = g_malloc (len);
9088 memcpy ((gpointer)field->data, p, len);
9091 mono_class_layout_fields (klass);
9095 typebuilder_setup_properties (MonoClass *klass)
9097 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9098 MonoReflectionPropertyBuilder *pb;
9101 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9102 klass->property.first = 0;
9103 klass->property.last = klass->property.count;
9105 klass->properties = g_new0 (MonoProperty, klass->property.count);
9106 for (i = 0; i < klass->property.count; ++i) {
9107 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9108 klass->properties [i].parent = klass;
9109 klass->properties [i].attrs = pb->attrs;
9110 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9112 klass->properties [i].get = pb->get_method->mhandle;
9114 klass->properties [i].set = pb->set_method->mhandle;
9118 MonoReflectionEvent *
9119 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9121 MonoEvent *event = g_new0 (MonoEvent, 1);
9125 klass = my_mono_class_from_mono_type (tb->type.type);
9127 event->parent = klass;
9128 event->attrs = eb->attrs;
9129 event->name = mono_string_to_utf8 (eb->name);
9131 event->add = eb->add_method->mhandle;
9132 if (eb->remove_method)
9133 event->remove = eb->remove_method->mhandle;
9134 if (eb->raise_method)
9135 event->raise = eb->raise_method->mhandle;
9137 if (eb->other_methods) {
9138 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9139 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9140 MonoReflectionMethodBuilder *mb =
9141 mono_array_get (eb->other_methods,
9142 MonoReflectionMethodBuilder*, j);
9143 event->other [j] = mb->mhandle;
9147 return mono_event_get_object (mono_object_domain (tb), klass, event);
9151 typebuilder_setup_events (MonoClass *klass)
9153 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9154 MonoReflectionEventBuilder *eb;
9157 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9158 klass->event.first = 0;
9159 klass->event.last = klass->event.count;
9161 klass->events = g_new0 (MonoEvent, klass->event.count);
9162 for (i = 0; i < klass->event.count; ++i) {
9163 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9164 klass->events [i].parent = klass;
9165 klass->events [i].attrs = eb->attrs;
9166 klass->events [i].name = mono_string_to_utf8 (eb->name);
9168 klass->events [i].add = eb->add_method->mhandle;
9169 if (eb->remove_method)
9170 klass->events [i].remove = eb->remove_method->mhandle;
9171 if (eb->raise_method)
9172 klass->events [i].raise = eb->raise_method->mhandle;
9174 if (eb->other_methods) {
9175 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9176 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9177 MonoReflectionMethodBuilder *mb =
9178 mono_array_get (eb->other_methods,
9179 MonoReflectionMethodBuilder*, j);
9180 klass->events [i].other [j] = mb->mhandle;
9187 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9191 MonoReflectionType* res;
9194 MONO_ARCH_SAVE_REGS;
9196 domain = mono_object_domain (tb);
9197 klass = my_mono_class_from_mono_type (tb->type.type);
9199 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9202 * we need to lock the domain because the lock will be taken inside
9203 * So, we need to keep the locking order correct.
9205 mono_domain_lock (domain);
9206 mono_loader_lock ();
9207 if (klass->wastypebuilder) {
9208 mono_loader_unlock ();
9209 mono_domain_unlock (domain);
9210 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9213 * Fields to set in klass:
9214 * the various flags: delegate/unicode/contextbound etc.
9216 klass->flags = tb->attrs;
9217 klass->has_cctor = 1;
9218 klass->has_finalize = 1;
9220 if (!((MonoDynamicImage*)klass->image)->run) {
9221 if (klass->generic_container) {
9222 /* FIXME: The code below can't handle generic classes */
9223 klass->wastypebuilder = TRUE;
9224 mono_loader_unlock ();
9225 mono_domain_unlock (domain);
9226 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9230 /* enums are done right away */
9231 if (!klass->enumtype)
9232 ensure_runtime_vtable (klass);
9235 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9236 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9237 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9241 /* fields and object layout */
9242 if (klass->parent) {
9243 if (!klass->parent->size_inited)
9244 mono_class_init (klass->parent);
9245 klass->instance_size += klass->parent->instance_size;
9246 klass->class_size += klass->parent->class_size;
9247 klass->min_align = klass->parent->min_align;
9248 /* if the type has no fields we won't call the field_setup
9249 * routine which sets up klass->has_references.
9251 klass->has_references |= klass->parent->has_references;
9253 klass->instance_size = sizeof (MonoObject);
9254 klass->min_align = 1;
9257 /* FIXME: handle packing_size and instance_size */
9258 typebuilder_setup_fields (klass);
9260 typebuilder_setup_properties (klass);
9262 typebuilder_setup_events (klass);
9264 klass->wastypebuilder = TRUE;
9265 mono_loader_unlock ();
9266 mono_domain_unlock (domain);
9268 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9269 g_assert (res != (MonoReflectionType*)tb);
9274 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9276 MonoGenericParam *param;
9279 MONO_ARCH_SAVE_REGS;
9281 param = g_new0 (MonoGenericParam, 1);
9283 if (gparam->mbuilder) {
9284 if (!gparam->mbuilder->generic_container)
9285 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9286 param->owner = gparam->mbuilder->generic_container;
9287 } else if (gparam->tbuilder) {
9288 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9289 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9294 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9295 if (gparam->index >= count)
9298 container = nesting->generic_container;
9299 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9302 g_assert (container);
9303 param->owner = container;
9306 param->method = NULL;
9307 param->name = mono_string_to_utf8 (gparam->name);
9308 param->num = gparam->index;
9310 image = &gparam->tbuilder->module->dynamic_image->image;
9311 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9313 param->pklass->reflection_info = gparam;
9315 gparam->type.type = g_new0 (MonoType, 1);
9316 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9317 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9318 gparam->type.type->data.generic_param = param;
9322 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9324 MonoDynamicImage *assembly = sig->module->dynamic_image;
9325 guint32 na = mono_array_length (sig->arguments);
9326 guint32 buflen, i, size;
9330 MONO_ARCH_SAVE_REGS;
9332 p = buf = g_malloc (size = 10 + na * 10);
9334 mono_metadata_encode_value (0x07, p, &p);
9335 mono_metadata_encode_value (na, p, &p);
9336 for (i = 0; i < na; ++i) {
9337 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9338 encode_reflection_type (assembly, type, p, &p);
9342 g_assert (buflen < size);
9343 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9344 p = mono_array_addr (result, char, 0);
9345 memcpy (p, buf, buflen);
9352 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9354 MonoDynamicImage *assembly = sig->module->dynamic_image;
9355 guint32 na = mono_array_length (sig->arguments);
9356 guint32 buflen, i, size;
9360 MONO_ARCH_SAVE_REGS;
9362 p = buf = g_malloc (size = 10 + na * 10);
9364 mono_metadata_encode_value (0x06, p, &p);
9365 for (i = 0; i < na; ++i) {
9366 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9367 encode_reflection_type (assembly, type, p, &p);
9371 g_assert (buflen < size);
9372 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9373 p = mono_array_addr (result, char, 0);
9374 memcpy (p, buf, buflen);
9381 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9383 ReflectionMethodBuilder rmb;
9384 MonoMethodSignature *sig;
9387 sig = dynamic_method_to_signature (mb);
9389 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9392 * Resolve references.
9394 rmb.nrefs = mb->nrefs;
9395 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9396 for (i = 0; i < mb->nrefs; ++i) {
9397 MonoClass *handle_class;
9398 gpointer ref = resolve_object (mb->module->image,
9399 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9402 mono_raise_exception (mono_get_exception_type_load (NULL));
9409 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9413 /* ilgen is no longer needed */
9418 * mono_reflection_lookup_dynamic_token:
9420 * Finish the Builder object pointed to by TOKEN and return the corresponding
9421 * runtime structure. HANDLE_CLASS is set to the class required by
9425 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9427 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9430 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9433 return resolve_object (image, obj, handle_class);
9437 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9439 gpointer result = NULL;
9441 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9442 result = mono_string_intern ((MonoString*)obj);
9443 *handle_class = NULL;
9445 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9446 MonoReflectionType *tb = (MonoReflectionType*)obj;
9447 result = mono_class_from_mono_type (tb->type);
9448 *handle_class = mono_defaults.typehandle_class;
9450 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
9451 result = ((MonoReflectionMethod*)obj)->method;
9452 *handle_class = mono_defaults.methodhandle_class;
9454 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
9455 result = ((MonoReflectionMethod*)obj)->method;
9456 *handle_class = mono_defaults.methodhandle_class;
9458 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9459 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9460 result = mb->mhandle;
9462 /* Type is not yet created */
9463 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9465 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9468 * Hopefully this has been filled in by calling CreateType() on the
9472 * TODO: This won't work if the application finishes another
9473 * TypeBuilder instance instead of this one.
9475 result = mb->mhandle;
9477 *handle_class = mono_defaults.methodhandle_class;
9478 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9479 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9481 result = cb->mhandle;
9483 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9485 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9486 result = cb->mhandle;
9488 *handle_class = mono_defaults.methodhandle_class;
9489 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9490 result = ((MonoReflectionField*)obj)->field;
9491 *handle_class = mono_defaults.fieldhandle_class;
9493 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9494 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9495 result = fb->handle;
9498 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9500 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9501 result = fb->handle;
9503 *handle_class = mono_defaults.fieldhandle_class;
9504 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9505 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9508 klass = tb->type.type->data.klass;
9509 if (klass->wastypebuilder) {
9510 /* Already created */
9514 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9515 result = tb->type.type->data.klass;
9518 *handle_class = mono_defaults.typehandle_class;
9519 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9520 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9521 MonoMethodSignature *sig;
9524 if (helper->arguments)
9525 nargs = mono_array_length (helper->arguments);
9529 sig = mono_metadata_signature_alloc (image, nargs);
9530 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9531 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9533 if (helper->call_conv == 0) /* unmanaged */
9534 sig->call_convention = helper->unmanaged_call_conv - 1;
9536 if (helper->call_conv & 0x02)
9537 sig->call_convention = MONO_CALL_VARARG;
9539 sig->call_convention = MONO_CALL_DEFAULT;
9541 sig->param_count = nargs;
9542 /* TODO: Copy type ? */
9543 sig->ret = helper->return_type->type;
9544 for (i = 0; i < nargs; ++i) {
9545 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9546 sig->params [i] = rt->type;
9550 *handle_class = NULL;
9552 g_print (obj->vtable->klass->name);
9553 g_assert_not_reached ();
9559 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9560 const static guint32 declsec_flags_map[] = {
9561 0x00000000, /* empty */
9562 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9563 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9564 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9565 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9566 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9567 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9568 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9569 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9570 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9571 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9572 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9573 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9574 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9575 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9576 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9577 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9578 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9579 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9583 * Returns flags that includes all available security action associated to the handle.
9584 * @token: metadata token (either for a class or a method)
9585 * @image: image where resides the metadata.
9588 mono_declsec_get_flags (MonoImage *image, guint32 token)
9590 guint32 index = mono_metadata_declsec_from_index (image, token);
9591 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9596 for (i = index; i < t->rows; i++) {
9597 guint32 cols [MONO_DECL_SECURITY_SIZE];
9599 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9600 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9603 action = cols [MONO_DECL_SECURITY_ACTION];
9604 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9605 result |= declsec_flags_map [action];
9607 g_assert_not_reached ();
9614 * Get the security actions (in the form of flags) associated with the specified method.
9616 * @method: The method for which we want the declarative security flags.
9617 * Return the declarative security flags for the method (only).
9619 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9620 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9623 mono_declsec_flags_from_method (MonoMethod *method)
9625 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9626 /* FIXME: No cache (for the moment) */
9627 guint32 idx = mono_method_get_index (method);
9628 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9629 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9630 return mono_declsec_get_flags (method->klass->image, idx);
9636 * Get the security actions (in the form of flags) associated with the specified class.
9638 * @klass: The class for which we want the declarative security flags.
9639 * Return the declarative security flags for the class.
9641 * Note: We cache the flags inside the MonoClass structure as this will get
9642 * called very often (at least for each method).
9645 mono_declsec_flags_from_class (MonoClass *klass)
9647 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9648 if (!klass->declsec_flags) {
9649 guint32 idx = mono_metadata_token_index (klass->type_token);
9650 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9651 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9652 /* we cache the flags on classes */
9653 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9655 return klass->declsec_flags;
9661 * Get the security actions (in the form of flags) associated with the specified assembly.
9663 * @assembly: The assembly for which we want the declarative security flags.
9664 * Return the declarative security flags for the assembly.
9667 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9669 guint32 idx = 1; /* there is only one assembly */
9670 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9671 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9672 return mono_declsec_get_flags (assembly->image, idx);
9677 * Fill actions for the specific index (which may either be an encoded class token or
9678 * an encoded method token) from the metadata image.
9679 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9682 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9683 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9685 MonoBoolean result = FALSE;
9687 guint32 cols [MONO_DECL_SECURITY_SIZE];
9688 int index = mono_metadata_declsec_from_index (image, token);
9691 t = &image->tables [MONO_TABLE_DECLSECURITY];
9692 for (i = index; i < t->rows; i++) {
9693 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9695 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9698 /* if present only replace (class) permissions with method permissions */
9699 /* if empty accept either class or method permissions */
9700 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9701 if (!actions->demand.blob) {
9702 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9703 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9704 actions->demand.blob = (char*) (blob + 2);
9705 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9708 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9709 if (!actions->noncasdemand.blob) {
9710 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9711 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9712 actions->noncasdemand.blob = (char*) (blob + 2);
9713 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9716 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9717 if (!actions->demandchoice.blob) {
9718 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9719 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9720 actions->demandchoice.blob = (char*) (blob + 2);
9721 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9731 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9732 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9734 guint32 idx = mono_metadata_token_index (klass->type_token);
9735 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9736 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9737 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9741 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9742 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9744 guint32 idx = mono_method_get_index (method);
9745 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9746 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9747 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9751 * Collect all actions (that requires to generate code in mini) assigned for
9752 * the specified method.
9753 * Note: Don't use the content of actions if the function return FALSE.
9756 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9758 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9759 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9760 MonoBoolean result = FALSE;
9763 /* quick exit if no declarative security is present in the metadata */
9764 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9767 /* we want the original as the wrapper is "free" of the security informations */
9768 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9769 method = mono_marshal_method_from_wrapper (method);
9774 /* First we look for method-level attributes */
9775 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9776 mono_class_init (method->klass);
9777 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9779 result = mono_declsec_get_method_demands_params (method, demands,
9780 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9783 /* Here we use (or create) the class declarative cache to look for demands */
9784 flags = mono_declsec_flags_from_class (method->klass);
9787 mono_class_init (method->klass);
9788 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9790 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9791 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9794 /* The boolean return value is used as a shortcut in case nothing needs to
9795 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9801 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9803 * Note: Don't use the content of actions if the function return FALSE.
9806 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9808 MonoBoolean result = FALSE;
9811 /* quick exit if no declarative security is present in the metadata */
9812 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9815 /* we want the original as the wrapper is "free" of the security informations */
9816 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9817 method = mono_marshal_method_from_wrapper (method);
9822 /* results are independant - zeroize both */
9823 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9824 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9826 /* First we look for method-level attributes */
9827 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9828 mono_class_init (method->klass);
9830 result = mono_declsec_get_method_demands_params (method, cmethod,
9831 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9834 /* Here we use (or create) the class declarative cache to look for demands */
9835 flags = mono_declsec_flags_from_class (method->klass);
9836 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9837 mono_class_init (method->klass);
9839 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9840 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9847 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9849 * @klass The inherited class - this is the class that provides the security check (attributes)
9851 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9853 * Note: Don't use the content of actions if the function return FALSE.
9856 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9858 MonoBoolean result = FALSE;
9861 /* quick exit if no declarative security is present in the metadata */
9862 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9865 /* Here we use (or create) the class declarative cache to look for demands */
9866 flags = mono_declsec_flags_from_class (klass);
9867 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9868 mono_class_init (klass);
9869 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9871 result |= mono_declsec_get_class_demands_params (klass, demands,
9872 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9879 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9881 * Note: Don't use the content of actions if the function return FALSE.
9884 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9886 /* quick exit if no declarative security is present in the metadata */
9887 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9890 /* we want the original as the wrapper is "free" of the security informations */
9891 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9892 method = mono_marshal_method_from_wrapper (method);
9897 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9898 mono_class_init (method->klass);
9899 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9901 return mono_declsec_get_method_demands_params (method, demands,
9902 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9909 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9911 guint32 cols [MONO_DECL_SECURITY_SIZE];
9915 int index = mono_metadata_declsec_from_index (image, token);
9919 t = &image->tables [MONO_TABLE_DECLSECURITY];
9920 for (i = index; i < t->rows; i++) {
9921 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9923 /* shortcut - index are ordered */
9924 if (token != cols [MONO_DECL_SECURITY_PARENT])
9927 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9928 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9929 entry->blob = (char*) (metadata + 2);
9930 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9939 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9941 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9942 guint32 idx = mono_method_get_index (method);
9943 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9944 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9945 return get_declsec_action (method->klass->image, idx, action, entry);
9951 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9954 guint32 flags = mono_declsec_flags_from_class (klass);
9955 if (declsec_flags_map [action] & flags) {
9956 guint32 idx = mono_metadata_token_index (klass->type_token);
9957 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9958 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9959 return get_declsec_action (klass->image, idx, action, entry);
9965 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9967 guint32 idx = 1; /* there is only one assembly */
9968 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9969 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9971 return get_declsec_action (assembly->image, idx, action, entry);
9975 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9977 MonoObject *res, *exc;
9979 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9980 static MonoMethod *method = NULL;
9982 if (!System_Reflection_Emit_TypeBuilder) {
9983 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
9984 g_assert (System_Reflection_Emit_TypeBuilder);
9986 if (method == NULL) {
9987 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
9992 * The result of mono_type_get_object () might be a System.MonoType but we
9993 * need a TypeBuilder so use klass->reflection_info.
9995 g_assert (klass->reflection_info);
9996 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
9998 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10000 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10004 return *(MonoBoolean*)mono_object_unbox (res);