2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/marshal.h>
31 #include "rawbuffer.h"
32 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
46 MonoGenericContainer *generic_container;
52 guint32 *table_idx; /* note: it's a pointer */
56 MonoBoolean init_locals;
57 MonoArray *return_modreq;
58 MonoArray *return_modopt;
59 MonoArray *param_modreq;
60 MonoArray *param_modopt;
61 MonoArray *permissions;
66 int charset, extra_flags, native_cc;
67 MonoString *dll, *dllentry;
68 } ReflectionMethodBuilder;
72 MonoReflectionGenericParam *gparam;
73 } GenericParamTableEntry;
75 const unsigned char table_sizes [MONO_TABLE_NUM] = {
85 MONO_INTERFACEIMPL_SIZE,
86 MONO_MEMBERREF_SIZE, /* 0x0A */
88 MONO_CUSTOM_ATTR_SIZE,
89 MONO_FIELD_MARSHAL_SIZE,
90 MONO_DECL_SECURITY_SIZE,
91 MONO_CLASS_LAYOUT_SIZE,
92 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
93 MONO_STAND_ALONE_SIGNATURE_SIZE,
97 MONO_PROPERTY_MAP_SIZE,
100 MONO_METHOD_SEMA_SIZE,
101 MONO_METHODIMPL_SIZE,
102 MONO_MODULEREF_SIZE, /* 0x1A */
108 MONO_ASSEMBLY_SIZE, /* 0x20 */
109 MONO_ASSEMBLY_PROCESSOR_SIZE,
110 MONO_ASSEMBLYOS_SIZE,
111 MONO_ASSEMBLYREF_SIZE,
112 MONO_ASSEMBLYREFPROC_SIZE,
113 MONO_ASSEMBLYREFOS_SIZE,
117 MONO_NESTED_CLASS_SIZE,
119 MONO_GENERICPARAM_SIZE, /* 0x2A */
120 MONO_METHODSPEC_SIZE,
121 MONO_GENPARCONSTRAINT_SIZE
125 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
126 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
127 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
128 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
129 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
130 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
131 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
132 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
133 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
134 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
135 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
136 static void ensure_runtime_vtable (MonoClass *klass);
137 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class);
138 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
139 static guint32 type_get_signature_size (MonoType *type);
140 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
141 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows) {
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
162 make_room_in_stream (MonoDynamicStream *stream, int size)
164 if (size <= stream->alloc_size)
167 while (stream->alloc_size <= size) {
168 if (stream->alloc_size < 4096)
169 stream->alloc_size = 4096;
171 stream->alloc_size *= 2;
174 stream->data = g_realloc (stream->data, stream->alloc_size);
178 string_heap_insert (MonoDynamicStream *sh, const char *str)
182 gpointer oldkey, oldval;
184 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
185 return GPOINTER_TO_UINT (oldval);
187 len = strlen (str) + 1;
190 make_room_in_stream (sh, idx + len);
193 * We strdup the string even if we already copy them in sh->data
194 * so that the string pointers in the hash remain valid even if
195 * we need to realloc sh->data. We may want to avoid that later.
197 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
198 memcpy (sh->data + idx, str, len);
204 string_heap_init (MonoDynamicStream *sh)
207 sh->alloc_size = 4096;
208 sh->data = g_malloc (4096);
209 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
210 string_heap_insert (sh, "");
214 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
218 make_room_in_stream (stream, stream->index + len);
219 memcpy (stream->data + stream->index, data, len);
221 stream->index += len;
223 * align index? Not without adding an additional param that controls it since
224 * we may store a blob value in pieces.
230 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
234 make_room_in_stream (stream, stream->index + len);
235 memset (stream->data + stream->index, 0, len);
237 stream->index += len;
242 stream_data_align (MonoDynamicStream *stream)
245 guint32 count = stream->index % 4;
247 /* we assume the stream data will be aligned */
249 mono_image_add_stream_data (stream, buf, 4 - count);
253 mono_blob_entry_hash (const char* str)
257 len = mono_metadata_decode_blob_size (str, &str);
261 for (str += 1; str < end; str++)
262 h = (h << 5) - h + *str;
270 mono_blob_entry_equal (const char *str1, const char *str2) {
274 len = mono_metadata_decode_blob_size (str1, &end1);
275 len2 = mono_metadata_decode_blob_size (str2, &end2);
278 return memcmp (end1, end2, len) == 0;
282 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
286 gpointer oldkey, oldval;
288 copy = g_malloc (s1+s2);
289 memcpy (copy, b1, s1);
290 memcpy (copy + s1, b2, s2);
291 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
293 idx = GPOINTER_TO_UINT (oldval);
295 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
296 mono_image_add_stream_data (&assembly->blob, b2, s2);
297 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
303 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
304 * dest may be misaligned.
307 swap_with_size (char *dest, const char* val, int len, int nelem) {
308 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
311 for (elem = 0; elem < nelem; ++elem) {
337 g_assert_not_reached ();
343 memcpy (dest, val, len * nelem);
348 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
352 guint32 idx = 0, len;
354 len = str->length * 2;
355 mono_metadata_encode_value (len, b, &b);
356 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
358 char *swapped = g_malloc (2 * mono_string_length (str));
359 const char *p = (const char*)mono_string_chars (str);
361 swap_with_size (swapped, p, 2, mono_string_length (str));
362 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
366 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
371 /* modified version needed to handle building corlib */
373 my_mono_class_from_mono_type (MonoType *type) {
374 switch (type->type) {
375 case MONO_TYPE_ARRAY:
377 case MONO_TYPE_SZARRAY:
378 case MONO_TYPE_GENERICINST:
379 return mono_class_from_mono_type (type);
382 g_assert (type->data.generic_param->pklass);
383 return type->data.generic_param->pklass;
385 /* should be always valid when we reach this case... */
386 return type->data.klass;
391 default_class_from_mono_type (MonoType *type)
393 switch (type->type) {
394 case MONO_TYPE_OBJECT:
395 return mono_defaults.object_class;
397 return mono_defaults.void_class;
398 case MONO_TYPE_BOOLEAN:
399 return mono_defaults.boolean_class;
401 return mono_defaults.char_class;
403 return mono_defaults.sbyte_class;
405 return mono_defaults.byte_class;
407 return mono_defaults.int16_class;
409 return mono_defaults.uint16_class;
411 return mono_defaults.int32_class;
413 return mono_defaults.uint32_class;
415 return mono_defaults.int_class;
417 return mono_defaults.uint_class;
419 return mono_defaults.int64_class;
421 return mono_defaults.uint64_class;
423 return mono_defaults.single_class;
425 return mono_defaults.double_class;
426 case MONO_TYPE_STRING:
427 return mono_defaults.string_class;
429 g_warning ("implement me 0x%02x\n", type->type);
430 g_assert_not_reached ();
437 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
442 g_assert_not_reached ();
446 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
447 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
448 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
449 for (i = 0; i < gclass->inst->type_argc; ++i)
450 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
456 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
459 g_assert_not_reached ();
464 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
468 case MONO_TYPE_BOOLEAN:
482 case MONO_TYPE_STRING:
483 case MONO_TYPE_OBJECT:
484 case MONO_TYPE_TYPEDBYREF:
485 mono_metadata_encode_value (type->type, p, &p);
488 mono_metadata_encode_value (type->type, p, &p);
489 encode_type (assembly, type->data.type, p, &p);
491 case MONO_TYPE_SZARRAY:
492 mono_metadata_encode_value (type->type, p, &p);
493 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
495 case MONO_TYPE_VALUETYPE:
496 case MONO_TYPE_CLASS: {
497 MonoClass *k = mono_class_from_mono_type (type);
498 mono_metadata_encode_value (type->type, p, &p);
500 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
501 * otherwise two typerefs could point to the same type, leading to
502 * verification errors.
504 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
507 case MONO_TYPE_ARRAY:
508 mono_metadata_encode_value (type->type, p, &p);
509 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
510 mono_metadata_encode_value (type->data.array->rank, p, &p);
511 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
512 mono_metadata_encode_value (0, p, &p);
514 case MONO_TYPE_GENERICINST:
515 encode_generic_class (assembly, type->data.generic_class, p, &p);
519 mono_metadata_encode_value (type->type, p, &p);
520 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
523 g_error ("need to encode type %x", type->type);
529 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
532 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
536 encode_type (assembly, type->type, p, endbuf);
540 g_assert_not_reached ();
545 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
550 for (i = 0; i < mono_array_length (modreq); ++i) {
551 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
552 *p = MONO_TYPE_CMOD_REQD;
554 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
558 for (i = 0; i < mono_array_length (modopt); ++i) {
559 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
560 *p = MONO_TYPE_CMOD_OPT;
562 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
569 generic_class_get_signature_size (MonoGenericClass *gclass)
575 g_assert_not_reached ();
578 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
580 for (i = 0; i < gclass->inst->type_argc; ++i)
581 size += type_get_signature_size (gclass->inst->type_argv [i]);
587 type_get_signature_size (MonoType *type)
592 g_assert_not_reached ();
600 case MONO_TYPE_BOOLEAN:
614 case MONO_TYPE_STRING:
615 case MONO_TYPE_OBJECT:
616 case MONO_TYPE_TYPEDBYREF:
619 return size + 1 + type_get_signature_size (type->data.type);
620 case MONO_TYPE_SZARRAY:
621 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
622 case MONO_TYPE_VALUETYPE:
623 case MONO_TYPE_CLASS:
625 case MONO_TYPE_ARRAY:
626 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
627 case MONO_TYPE_GENERICINST:
628 return size + generic_class_get_signature_size (type->data.generic_class);
633 g_error ("need to encode type %x", type->type);
639 method_get_signature_size (MonoMethodSignature *sig)
644 size = type_get_signature_size (sig->ret);
645 for (i = 0; i < sig->param_count; i++)
646 size += type_get_signature_size (sig->params [i]);
648 if (sig->generic_param_count)
650 if (sig->sentinelpos >= 0)
657 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
662 guint32 nparams = sig->param_count;
663 guint32 size = 11 + method_get_signature_size (sig);
671 p = buf = g_malloc (size);
673 * FIXME: vararg, explicit_this, differenc call_conv values...
675 *p = sig->call_convention;
677 *p |= 0x20; /* hasthis */
678 if (sig->generic_param_count)
679 *p |= 0x10; /* generic */
681 if (sig->generic_param_count)
682 mono_metadata_encode_value (sig->generic_param_count, p, &p);
683 mono_metadata_encode_value (nparams, p, &p);
684 encode_type (assembly, sig->ret, p, &p);
685 for (i = 0; i < nparams; ++i) {
686 if (i == sig->sentinelpos)
687 *p++ = MONO_TYPE_SENTINEL;
688 encode_type (assembly, sig->params [i], p, &p);
691 g_assert (p - buf < size);
692 mono_metadata_encode_value (p-buf, b, &b);
693 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
699 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
702 * FIXME: reuse code from method_encode_signature().
707 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
708 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
709 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
710 guint32 size = 41 + nparams * 40 + notypes * 40;
715 p = buf = g_malloc (size);
716 /* LAMESPEC: all the call conv spec is foobared */
717 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
718 if (mb->call_conv & 2)
719 *p |= 0x5; /* vararg */
720 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
721 *p |= 0x20; /* hasthis */
723 *p |= 0x10; /* generic */
726 mono_metadata_encode_value (ngparams, p, &p);
727 mono_metadata_encode_value (nparams + notypes, p, &p);
728 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
729 encode_reflection_type (assembly, mb->rtype, p, &p);
730 for (i = 0; i < nparams; ++i) {
731 MonoArray *modreq = NULL;
732 MonoArray *modopt = NULL;
733 MonoReflectionType *pt;
735 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
736 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
737 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
738 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
739 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
740 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
741 encode_reflection_type (assembly, pt, p, &p);
744 *p++ = MONO_TYPE_SENTINEL;
745 for (i = 0; i < notypes; ++i) {
746 MonoReflectionType *pt;
748 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
749 encode_reflection_type (assembly, pt, p, &p);
753 g_assert (p - buf < size);
754 mono_metadata_encode_value (p-buf, b, &b);
755 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
761 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
763 MonoDynamicTable *table;
766 guint32 idx, sig_idx, size;
767 guint nl = mono_array_length (ilgen->locals);
774 p = buf = g_malloc (size);
775 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
776 idx = table->next_idx ++;
778 alloc_table (table, table->rows);
779 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
781 mono_metadata_encode_value (0x07, p, &p);
782 mono_metadata_encode_value (nl, p, &p);
783 for (i = 0; i < nl; ++i) {
784 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
787 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
789 encode_reflection_type (assembly, lb->type, p, &p);
791 g_assert (p - buf < size);
792 mono_metadata_encode_value (p-buf, b, &b);
793 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
796 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
802 method_count_clauses (MonoReflectionILGen *ilgen)
804 guint32 num_clauses = 0;
807 MonoILExceptionInfo *ex_info;
808 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
809 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
810 if (ex_info->handlers)
811 num_clauses += mono_array_length (ex_info->handlers);
819 static MonoExceptionClause*
820 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
822 MonoExceptionClause *clauses;
823 MonoExceptionClause *clause;
824 MonoILExceptionInfo *ex_info;
825 MonoILExceptionBlock *ex_block;
826 guint32 finally_start;
827 int i, j, clause_index;;
829 clauses = g_new0 (MonoExceptionClause, num_clauses);
832 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
833 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
834 finally_start = ex_info->start + ex_info->len;
835 g_assert (ex_info->handlers);
836 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
837 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
838 clause = &(clauses [clause_index]);
840 clause->flags = ex_block->type;
841 clause->try_offset = ex_info->start;
843 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
844 clause->try_len = finally_start - ex_info->start;
846 clause->try_len = ex_info->len;
847 clause->handler_offset = ex_block->start;
848 clause->handler_len = ex_block->len;
849 if (ex_block->extype) {
850 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
852 /* FIXME: handle filters */
853 clause->data.filter_offset = 0;
855 finally_start = ex_block->start + ex_block->len;
865 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
871 gint32 num_locals = 0;
872 gint32 num_exception = 0;
875 char fat_header [12];
878 guint32 local_sig = 0;
879 guint32 header_size = 12;
882 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
883 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
887 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
889 code = mb->ilgen->code;
890 code_size = mb->ilgen->code_len;
891 max_stack = mb->ilgen->max_stack;
892 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
893 if (mb->ilgen->ex_handlers)
894 num_exception = method_count_clauses (mb->ilgen);
898 char *name = mono_string_to_utf8 (mb->name);
899 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
900 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
903 mono_raise_exception (exception);
906 code_size = mono_array_length (code);
907 max_stack = 8; /* we probably need to run a verifier on the code... */
910 stream_data_align (&assembly->code);
912 /* check for exceptions, maxstack, locals */
913 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
915 if (code_size < 64 && !(code_size & 1)) {
916 flags = (code_size << 2) | 0x2;
917 } else if (code_size < 32 && (code_size & 1)) {
918 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
922 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
923 /* add to the fixup todo list */
924 if (mb->ilgen && mb->ilgen->num_token_fixups)
925 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
926 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
927 return assembly->text_rva + idx;
931 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
933 * FIXME: need to set also the header size in fat_flags.
934 * (and more sects and init locals flags)
938 fat_flags |= METHOD_HEADER_MORE_SECTS;
940 fat_flags |= METHOD_HEADER_INIT_LOCALS;
941 fat_header [0] = fat_flags;
942 fat_header [1] = (header_size / 4 ) << 4;
943 shortp = (guint16*)(fat_header + 2);
944 *shortp = GUINT16_TO_LE (max_stack);
945 intp = (guint32*)(fat_header + 4);
946 *intp = GUINT32_TO_LE (code_size);
947 intp = (guint32*)(fat_header + 8);
948 *intp = GUINT32_TO_LE (local_sig);
949 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
954 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
956 unsigned char sheader [4];
957 MonoILExceptionInfo * ex_info;
958 MonoILExceptionBlock * ex_block;
961 stream_data_align (&assembly->code);
962 /* always use fat format for now */
963 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
964 num_exception *= 6 * sizeof (guint32);
965 num_exception += 4; /* include the size of the header */
966 sheader [1] = num_exception & 0xff;
967 sheader [2] = (num_exception >> 8) & 0xff;
968 sheader [3] = (num_exception >> 16) & 0xff;
969 mono_image_add_stream_data (&assembly->code, sheader, 4);
970 /* fat header, so we are already aligned */
972 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
973 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
974 if (ex_info->handlers) {
975 int finally_start = ex_info->start + ex_info->len;
976 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
978 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
980 val = GUINT32_TO_LE (ex_block->type);
981 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
983 val = GUINT32_TO_LE (ex_info->start);
984 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
985 /* need fault, too, probably */
986 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
987 val = GUINT32_TO_LE (finally_start - ex_info->start);
989 val = GUINT32_TO_LE (ex_info->len);
990 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
992 val = GUINT32_TO_LE (ex_block->start);
993 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
995 val = GUINT32_TO_LE (ex_block->len);
996 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
997 finally_start = ex_block->start + ex_block->len;
998 if (ex_block->extype) {
999 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1001 /* FIXME: handle filters */
1004 val = GUINT32_TO_LE (val);
1005 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1006 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1007 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1010 g_error ("No clauses for ex info block %d", i);
1014 return assembly->text_rva + idx;
1018 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1021 MonoDynamicTable *table;
1024 table = &assembly->tables [table_idx];
1026 g_assert (col < table->columns);
1028 values = table->values + table->columns;
1029 for (i = 1; i <= table->rows; ++i) {
1030 if (values [col] == token)
1032 values += table->columns;
1037 static GHashTable *dynamic_custom_attrs = NULL;
1039 static MonoCustomAttrInfo*
1040 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1043 MonoCustomAttrInfo *ainfo;
1044 MonoReflectionCustomAttr *cattr;
1048 /* FIXME: check in assembly the Run flag is set */
1050 count = mono_array_length (cattrs);
1052 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1054 ainfo->image = image;
1055 ainfo->num_attrs = count;
1056 for (i = 0; i < count; ++i) {
1057 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1058 ainfo->attrs [i].ctor = cattr->ctor->method;
1059 /* FIXME: might want to memdup the data here */
1060 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1061 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1068 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1070 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1075 if (!dynamic_custom_attrs)
1076 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1078 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1079 ainfo->cached = TRUE;
1083 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1085 /* they are cached, so we don't free them */
1086 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1092 * idx is the table index of the object
1093 * type is one of MONO_CUSTOM_ATTR_*
1096 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1098 MonoDynamicTable *table;
1099 MonoReflectionCustomAttr *cattr;
1101 guint32 count, i, token;
1103 char *p = blob_size;
1105 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1108 count = mono_array_length (cattrs);
1109 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1110 table->rows += count;
1111 alloc_table (table, table->rows);
1112 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1113 idx <<= MONO_CUSTOM_ATTR_BITS;
1115 for (i = 0; i < count; ++i) {
1116 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1117 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1118 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1119 type = mono_metadata_token_index (token);
1120 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1121 switch (mono_metadata_token_table (token)) {
1122 case MONO_TABLE_METHOD:
1123 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1125 case MONO_TABLE_MEMBERREF:
1126 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1129 g_warning ("got wrong token in custom attr");
1132 values [MONO_CUSTOM_ATTR_TYPE] = type;
1134 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1135 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1136 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1137 values += MONO_CUSTOM_ATTR_SIZE;
1143 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1145 MonoDynamicTable *table;
1147 guint32 count, i, idx;
1148 MonoReflectionPermissionSet *perm;
1153 count = mono_array_length (permissions);
1154 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1155 table->rows += count;
1156 alloc_table (table, table->rows);
1158 for (i = 0; i < mono_array_length (permissions); ++i) {
1159 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1161 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1163 idx = mono_metadata_token_index (parent_token);
1164 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1165 switch (mono_metadata_token_table (parent_token)) {
1166 case MONO_TABLE_TYPEDEF:
1167 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1169 case MONO_TABLE_METHOD:
1170 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1172 case MONO_TABLE_ASSEMBLY:
1173 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1176 g_assert_not_reached ();
1179 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1180 values [MONO_DECL_SECURITY_PARENT] = idx;
1181 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1188 * Fill in the MethodDef and ParamDef tables for a method.
1189 * This is used for both normal methods and constructors.
1192 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1194 MonoDynamicTable *table;
1199 /* room in this table is already allocated */
1200 table = &assembly->tables [MONO_TABLE_METHOD];
1201 *mb->table_idx = table->next_idx ++;
1202 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1203 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1204 name = mono_string_to_utf8 (mb->name);
1205 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1207 values [MONO_METHOD_FLAGS] = mb->attrs;
1208 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1209 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1210 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1212 table = &assembly->tables [MONO_TABLE_PARAM];
1213 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1215 mono_image_add_decl_security (assembly,
1216 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1219 MonoDynamicTable *mtable;
1222 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1223 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1226 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1227 if (mono_array_get (mb->pinfo, gpointer, i))
1230 table->rows += count;
1231 alloc_table (table, table->rows);
1232 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1233 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1234 MonoReflectionParamBuilder *pb;
1235 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1236 values [MONO_PARAM_FLAGS] = pb->attrs;
1237 values [MONO_PARAM_SEQUENCE] = i;
1238 if (pb->name != NULL) {
1239 name = mono_string_to_utf8 (pb->name);
1240 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1243 values [MONO_PARAM_NAME] = 0;
1245 values += MONO_PARAM_SIZE;
1246 if (pb->marshal_info) {
1248 alloc_table (mtable, mtable->rows);
1249 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1250 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1251 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1253 pb->table_idx = table->next_idx++;
1254 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1255 guint32 field_type = 0;
1256 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1258 alloc_table (mtable, mtable->rows);
1259 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1260 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1261 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1262 mvalues [MONO_CONSTANT_TYPE] = field_type;
1263 mvalues [MONO_CONSTANT_PADDING] = 0;
1271 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1273 rmb->ilgen = mb->ilgen;
1274 rmb->rtype = mb->rtype;
1275 rmb->parameters = mb->parameters;
1276 rmb->generic_params = mb->generic_params;
1277 rmb->generic_container = mb->generic_container;
1278 rmb->opt_types = NULL;
1279 rmb->pinfo = mb->pinfo;
1280 rmb->attrs = mb->attrs;
1281 rmb->iattrs = mb->iattrs;
1282 rmb->call_conv = mb->call_conv;
1283 rmb->code = mb->code;
1284 rmb->type = mb->type;
1285 rmb->name = mb->name;
1286 rmb->table_idx = &mb->table_idx;
1287 rmb->init_locals = mb->init_locals;
1288 rmb->return_modreq = mb->return_modreq;
1289 rmb->return_modopt = mb->return_modopt;
1290 rmb->param_modreq = mb->param_modreq;
1291 rmb->param_modopt = mb->param_modopt;
1292 rmb->permissions = mb->permissions;
1293 rmb->mhandle = mb->mhandle;
1298 rmb->charset = mb->charset;
1299 rmb->extra_flags = mb->extra_flags;
1300 rmb->native_cc = mb->native_cc;
1301 rmb->dllentry = mb->dllentry;
1307 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1309 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1311 rmb->ilgen = mb->ilgen;
1312 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1313 rmb->parameters = mb->parameters;
1314 rmb->generic_params = NULL;
1315 rmb->generic_container = NULL;
1316 rmb->opt_types = NULL;
1317 rmb->pinfo = mb->pinfo;
1318 rmb->attrs = mb->attrs;
1319 rmb->iattrs = mb->iattrs;
1320 rmb->call_conv = mb->call_conv;
1322 rmb->type = mb->type;
1323 rmb->name = mono_string_new (mono_domain_get (), name);
1324 rmb->table_idx = &mb->table_idx;
1325 rmb->init_locals = mb->init_locals;
1326 rmb->return_modreq = NULL;
1327 rmb->return_modopt = NULL;
1328 rmb->param_modreq = mb->param_modreq;
1329 rmb->param_modopt = mb->param_modopt;
1330 rmb->permissions = mb->permissions;
1331 rmb->mhandle = mb->mhandle;
1337 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1339 rmb->ilgen = mb->ilgen;
1340 rmb->rtype = mb->rtype;
1341 rmb->parameters = mb->parameters;
1342 rmb->generic_params = NULL;
1343 rmb->generic_container = NULL;
1344 rmb->opt_types = NULL;
1346 rmb->attrs = mb->attrs;
1348 rmb->call_conv = mb->call_conv;
1351 rmb->name = mb->name;
1352 rmb->table_idx = NULL;
1353 rmb->init_locals = mb->init_locals;
1354 rmb->return_modreq = NULL;
1355 rmb->return_modopt = NULL;
1356 rmb->param_modreq = NULL;
1357 rmb->param_modopt = NULL;
1358 rmb->permissions = NULL;
1359 rmb->mhandle = mb->mhandle;
1365 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1367 MonoDynamicTable *table;
1370 ReflectionMethodBuilder rmb;
1373 reflection_methodbuilder_from_method_builder (&rmb, mb);
1375 mono_image_basic_method (&rmb, assembly);
1376 mb->table_idx = *rmb.table_idx;
1378 if (mb->dll) { /* It's a P/Invoke method */
1380 /* map CharSet values to on-disk values */
1381 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1382 int extra_flags = mb->extra_flags;
1383 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1385 alloc_table (table, table->rows);
1386 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1388 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1389 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1391 name = mono_string_to_utf8 (mb->dllentry);
1393 name = mono_string_to_utf8 (mb->name);
1394 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1396 name = mono_string_to_utf8 (mb->dll);
1397 moduleref = string_heap_insert (&assembly->sheap, name);
1399 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1400 table = &assembly->tables [MONO_TABLE_MODULEREF];
1402 alloc_table (table, table->rows);
1403 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1404 values [MONO_IMPLMAP_SCOPE] = table->rows;
1408 if (mb->override_method) {
1409 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1411 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1413 alloc_table (table, table->rows);
1414 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1415 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1416 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1418 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1419 switch (mono_metadata_token_table (tok)) {
1420 case MONO_TABLE_MEMBERREF:
1421 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1423 case MONO_TABLE_METHOD:
1424 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1427 g_assert_not_reached ();
1429 values [MONO_METHODIMPL_DECLARATION] = tok;
1432 if (mb->generic_params) {
1433 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1434 table->rows += mono_array_length (mb->generic_params);
1435 alloc_table (table, table->rows);
1436 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1437 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1439 mono_image_get_generic_param_info (
1440 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1447 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1449 ReflectionMethodBuilder rmb;
1451 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1453 mono_image_basic_method (&rmb, assembly);
1454 mb->table_idx = *rmb.table_idx;
1458 type_get_fully_qualified_name (MonoType *type)
1460 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1464 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1468 klass = my_mono_class_from_mono_type (type);
1470 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1471 ta = klass->image->assembly;
1472 if (ta->dynamic || (ta == ass))
1473 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1475 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1479 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1481 char blob_size [64];
1482 char *b = blob_size;
1487 if (!assembly->save)
1490 p = buf = g_malloc (64);
1492 mono_metadata_encode_value (0x06, p, &p);
1493 /* encode custom attributes before the type */
1494 encode_type (assembly, type, p, &p);
1495 g_assert (p-buf < 64);
1496 mono_metadata_encode_value (p-buf, b, &b);
1497 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1503 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1505 char blob_size [64];
1506 char *b = blob_size;
1511 p = buf = g_malloc (256);
1513 mono_metadata_encode_value (0x06, p, &p);
1514 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1515 /* encode custom attributes before the type */
1516 encode_reflection_type (assembly, fb->type, p, &p);
1517 g_assert (p-buf < 256);
1518 mono_metadata_encode_value (p-buf, b, &b);
1519 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1525 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1526 char blob_size [64];
1527 char *b = blob_size;
1530 guint32 idx = 0, len = 0, dummy = 0;
1532 p = buf = g_malloc (64);
1534 *ret_type = MONO_TYPE_CLASS;
1536 box_val = (char*)&dummy;
1538 box_val = ((char*)val) + sizeof (MonoObject);
1539 *ret_type = val->vtable->klass->byval_arg.type;
1542 switch (*ret_type) {
1543 case MONO_TYPE_BOOLEAN:
1548 case MONO_TYPE_CHAR:
1563 case MONO_TYPE_VALUETYPE:
1564 if (val->vtable->klass->enumtype) {
1565 *ret_type = val->vtable->klass->enum_basetype->type;
1568 g_error ("we can't encode valuetypes");
1569 case MONO_TYPE_CLASS:
1571 case MONO_TYPE_STRING: {
1572 MonoString *str = (MonoString*)val;
1573 /* there is no signature */
1574 len = str->length * 2;
1575 mono_metadata_encode_value (len, b, &b);
1576 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1578 char *swapped = g_malloc (2 * mono_string_length (str));
1579 const char *p = (const char*)mono_string_chars (str);
1581 swap_with_size (swapped, p, 2, mono_string_length (str));
1582 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1586 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1593 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1596 /* there is no signature */
1597 mono_metadata_encode_value (len, b, &b);
1598 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1599 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1600 swap_with_size (blob_size, box_val, len, 1);
1601 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1603 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1611 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1612 char blob_size [64];
1613 char *b = blob_size;
1614 char *p, *buf, *str;
1615 guint32 idx, len, bufsize = 256;
1617 p = buf = g_malloc (bufsize);
1619 mono_metadata_encode_value (minfo->type, p, &p);
1621 switch (minfo->type) {
1622 case MONO_NATIVE_BYVALTSTR:
1623 case MONO_NATIVE_BYVALARRAY:
1624 mono_metadata_encode_value (minfo->count, p, &p);
1626 case MONO_NATIVE_LPARRAY:
1627 if (minfo->eltype || minfo->has_size) {
1628 mono_metadata_encode_value (minfo->eltype, p, &p);
1629 if (minfo->has_size) {
1630 if (minfo->param_num != -1)
1631 mono_metadata_encode_value (minfo->param_num, p, &p);
1633 mono_metadata_encode_value (0, p, &p);
1634 if (minfo->count != -1)
1635 mono_metadata_encode_value (minfo->count, p, &p);
1637 mono_metadata_encode_value (0, p, &p);
1639 /* LAMESPEC: ElemMult is undocumented */
1640 if (minfo->param_num != -1)
1641 mono_metadata_encode_value (1, p, &p);
1643 mono_metadata_encode_value (0, p, &p);
1647 case MONO_NATIVE_CUSTOM:
1649 str = mono_string_to_utf8 (minfo->guid);
1651 mono_metadata_encode_value (len, p, &p);
1652 memcpy (p, str, len);
1656 mono_metadata_encode_value (0, p, &p);
1658 if (minfo->marshaltype) {
1659 str = mono_string_to_utf8 (minfo->marshaltype);
1661 mono_metadata_encode_value (len, p, &p);
1662 if (p + len >= buf + bufsize) {
1665 buf = g_realloc (buf, bufsize);
1668 memcpy (p, str, len);
1672 mono_metadata_encode_value (0, p, &p);
1674 if (minfo->marshaltyperef) {
1675 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1677 mono_metadata_encode_value (len, p, &p);
1678 if (p + len >= buf + bufsize) {
1681 buf = g_realloc (buf, bufsize);
1684 memcpy (p, str, len);
1688 mono_metadata_encode_value (0, p, &p);
1690 if (minfo->mcookie) {
1691 str = mono_string_to_utf8 (minfo->mcookie);
1693 mono_metadata_encode_value (len, p, &p);
1694 if (p + len >= buf + bufsize) {
1697 buf = g_realloc (buf, bufsize);
1700 memcpy (p, str, len);
1704 mono_metadata_encode_value (0, p, &p);
1711 mono_metadata_encode_value (len, b, &b);
1712 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1718 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1720 MonoDynamicTable *table;
1724 /* maybe this fixup should be done in the C# code */
1725 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1726 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1727 table = &assembly->tables [MONO_TABLE_FIELD];
1728 fb->table_idx = table->next_idx ++;
1729 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1730 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1731 name = mono_string_to_utf8 (fb->name);
1732 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1734 values [MONO_FIELD_FLAGS] = fb->attrs;
1735 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1737 if (fb->offset != -1) {
1738 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1740 alloc_table (table, table->rows);
1741 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1742 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1743 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1745 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1746 guint32 field_type = 0;
1747 table = &assembly->tables [MONO_TABLE_CONSTANT];
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1751 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1752 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1753 values [MONO_CONSTANT_TYPE] = field_type;
1754 values [MONO_CONSTANT_PADDING] = 0;
1756 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1758 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1760 alloc_table (table, table->rows);
1761 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1762 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1764 * We store it in the code section because it's simpler for now.
1767 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1769 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1770 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1772 if (fb->marshal_info) {
1773 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1775 alloc_table (table, table->rows);
1776 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1777 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1778 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1783 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1787 char *b = blob_size;
1788 guint32 nparams = 0;
1789 MonoReflectionMethodBuilder *mb = fb->get_method;
1790 MonoReflectionMethodBuilder *smb = fb->set_method;
1791 guint32 idx, i, size;
1793 if (mb && mb->parameters)
1794 nparams = mono_array_length (mb->parameters);
1795 if (!mb && smb && smb->parameters)
1796 nparams = mono_array_length (smb->parameters) - 1;
1797 size = 24 + nparams * 10;
1798 buf = p = g_malloc (size);
1801 mono_metadata_encode_value (nparams, p, &p);
1803 encode_reflection_type (assembly, mb->rtype, p, &p);
1804 for (i = 0; i < nparams; ++i) {
1805 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1806 encode_reflection_type (assembly, pt, p, &p);
1809 /* the property type is the last param */
1810 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1811 for (i = 0; i < nparams; ++i) {
1812 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1813 encode_reflection_type (assembly, pt, p, &p);
1817 encode_reflection_type (assembly, fb->type, p, &p);
1821 g_assert (p - buf < size);
1822 mono_metadata_encode_value (p-buf, b, &b);
1823 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1829 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1831 MonoDynamicTable *table;
1834 guint num_methods = 0;
1838 * we need to set things in the following tables:
1839 * PROPERTYMAP (info already filled in _get_type_info ())
1840 * PROPERTY (rows already preallocated in _get_type_info ())
1841 * METHOD (method info already done with the generic method code)
1844 table = &assembly->tables [MONO_TABLE_PROPERTY];
1845 pb->table_idx = table->next_idx ++;
1846 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1847 name = mono_string_to_utf8 (pb->name);
1848 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1850 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1851 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1853 /* FIXME: we still don't handle 'other' methods */
1854 if (pb->get_method) num_methods ++;
1855 if (pb->set_method) num_methods ++;
1857 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1858 table->rows += num_methods;
1859 alloc_table (table, table->rows);
1861 if (pb->get_method) {
1862 semaidx = table->next_idx ++;
1863 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1864 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1865 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1866 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1868 if (pb->set_method) {
1869 semaidx = table->next_idx ++;
1870 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1871 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1872 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1873 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1878 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1880 MonoDynamicTable *table;
1883 guint num_methods = 0;
1887 * we need to set things in the following tables:
1888 * EVENTMAP (info already filled in _get_type_info ())
1889 * EVENT (rows already preallocated in _get_type_info ())
1890 * METHOD (method info already done with the generic method code)
1893 table = &assembly->tables [MONO_TABLE_EVENT];
1894 eb->table_idx = table->next_idx ++;
1895 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1896 name = mono_string_to_utf8 (eb->name);
1897 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1899 values [MONO_EVENT_FLAGS] = eb->attrs;
1900 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1903 * FIXME: we still don't handle 'other' methods
1905 if (eb->add_method) num_methods ++;
1906 if (eb->remove_method) num_methods ++;
1907 if (eb->raise_method) num_methods ++;
1909 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1910 table->rows += num_methods;
1911 alloc_table (table, table->rows);
1913 if (eb->add_method) {
1914 semaidx = table->next_idx ++;
1915 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1916 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1917 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1918 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1920 if (eb->remove_method) {
1921 semaidx = table->next_idx ++;
1922 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1923 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1924 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1925 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1927 if (eb->raise_method) {
1928 semaidx = table->next_idx ++;
1929 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1930 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1931 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1932 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1937 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1939 static MonoClass *NewConstraintAttr;
1940 static MonoMethod *NewConstraintAttr_ctor;
1941 MonoDynamicTable *table;
1943 guint32 token, type;
1944 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1947 if (!NewConstraintAttr)
1948 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1949 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1950 g_assert (NewConstraintAttr);
1952 if (!NewConstraintAttr_ctor) {
1953 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1954 g_assert (NewConstraintAttr_ctor);
1957 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1959 alloc_table (table, table->rows);
1961 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1962 owner <<= MONO_CUSTOM_ATTR_BITS;
1963 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1964 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1966 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1968 type = mono_metadata_token_index (token);
1969 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1970 switch (mono_metadata_token_table (token)) {
1971 case MONO_TABLE_METHOD:
1972 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1974 case MONO_TABLE_MEMBERREF:
1975 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1978 g_warning ("got wrong token in custom attr");
1981 values [MONO_CUSTOM_ATTR_TYPE] = type;
1983 buf = p = g_malloc (1);
1984 mono_metadata_encode_value (4, p, &p);
1985 g_assert (p-buf == 1);
1987 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1989 values += MONO_CUSTOM_ATTR_SIZE;
1994 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1996 MonoDynamicTable *table;
1997 guint32 num_constraints, i;
2001 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2002 num_constraints = gparam->iface_constraints ?
2003 mono_array_length (gparam->iface_constraints) : 0;
2004 table->rows += num_constraints;
2005 if (gparam->base_type)
2007 alloc_table (table, table->rows);
2009 if (gparam->base_type) {
2010 table_idx = table->next_idx ++;
2011 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2013 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2014 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2015 assembly, gparam->base_type->type);
2018 for (i = 0; i < num_constraints; i++) {
2019 MonoReflectionType *constraint = mono_array_get (
2020 gparam->iface_constraints, gpointer, i);
2022 table_idx = table->next_idx ++;
2023 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2025 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2026 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2027 assembly, constraint->type);
2030 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2031 encode_new_constraint (assembly, owner);
2035 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2037 GenericParamTableEntry *entry;
2040 * The GenericParam table must be sorted according to the `owner' field.
2041 * We need to do this sorting prior to writing the GenericParamConstraint
2042 * table, since we have to use the final GenericParam table indices there
2043 * and they must also be sorted.
2046 entry = g_new0 (GenericParamTableEntry, 1);
2047 entry->owner = owner;
2048 entry->gparam = gparam;
2050 g_ptr_array_add (assembly->gen_params, entry);
2054 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2056 MonoDynamicTable *table;
2057 MonoGenericParam *param;
2061 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2062 table_idx = table->next_idx ++;
2063 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2065 param = entry->gparam->type.type->data.generic_param;
2067 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2068 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2069 values [MONO_GENERICPARAM_NUMBER] = param->num;
2070 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2072 encode_constraints (entry->gparam, table_idx, assembly);
2076 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2078 MonoDynamicTable *table;
2081 guint32 cols [MONO_ASSEMBLY_SIZE];
2085 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2088 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2089 table = &assembly->tables [MONO_TABLE_MODULEREF];
2090 token = table->next_idx ++;
2092 alloc_table (table, table->rows);
2093 values = table->values + token * MONO_MODULEREF_SIZE;
2094 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2096 token <<= MONO_RESOLTION_SCOPE_BITS;
2097 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2098 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2103 if (image->assembly->dynamic)
2105 memset (cols, 0, sizeof (cols));
2107 /* image->assembly->image is the manifest module */
2108 image = image->assembly->image;
2109 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2112 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2113 token = table->next_idx ++;
2115 alloc_table (table, table->rows);
2116 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2117 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2118 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2119 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2120 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2121 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2122 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2123 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2124 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2126 if (strcmp ("", image->assembly->aname.culture)) {
2127 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2128 image->assembly->aname.culture);
2131 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2132 guchar pubtoken [9];
2134 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2135 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2137 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2139 token <<= MONO_RESOLTION_SCOPE_BITS;
2140 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2141 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2146 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2148 MonoDynamicTable *table;
2154 char *b = blob_size;
2156 switch (type->type) {
2157 case MONO_TYPE_FNPTR:
2159 case MONO_TYPE_SZARRAY:
2160 case MONO_TYPE_ARRAY:
2162 case MONO_TYPE_MVAR:
2163 case MONO_TYPE_GENERICINST:
2164 encode_type (assembly, type, p, &p);
2166 case MONO_TYPE_CLASS:
2167 case MONO_TYPE_VALUETYPE: {
2168 MonoClass *k = mono_class_from_mono_type (type);
2169 if (!k || !k->generic_class)
2171 encode_generic_class (assembly, k->generic_class, p, &p);
2178 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2179 if (assembly->save) {
2180 g_assert (p-sig < 128);
2181 mono_metadata_encode_value (p-sig, b, &b);
2182 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2183 alloc_table (table, table->rows + 1);
2184 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2185 values [MONO_TYPESPEC_SIGNATURE] = token;
2188 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2189 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2195 * Despite the name, we handle also TypeSpec (with the above helper).
2198 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2200 MonoDynamicTable *table;
2202 guint32 token, scope, enclosing;
2205 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2208 token = create_typespec (assembly, type);
2211 klass = my_mono_class_from_mono_type (type);
2213 klass = mono_class_from_mono_type (type);
2216 * If it's in the same module and not a generic type parameter:
2218 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2219 (type->type != MONO_TYPE_MVAR)) {
2220 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2221 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2222 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2226 if (klass->nested_in) {
2227 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2228 /* get the typeref idx of the enclosing type */
2229 enclosing >>= MONO_TYPEDEFORREF_BITS;
2230 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2232 scope = resolution_scope_from_image (assembly, klass->image);
2234 table = &assembly->tables [MONO_TABLE_TYPEREF];
2235 if (assembly->save) {
2236 alloc_table (table, table->rows + 1);
2237 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2238 values [MONO_TYPEREF_SCOPE] = scope;
2239 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2240 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2242 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2243 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2245 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2250 * Insert a memberef row into the metadata: the token that point to the memberref
2251 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2252 * mono_image_get_fieldref_token()).
2253 * The sig param is an index to an already built signature.
2256 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2258 MonoDynamicTable *table;
2260 guint32 token, pclass;
2263 parent = mono_image_typedef_or_ref (assembly, type);
2264 switch (parent & MONO_TYPEDEFORREF_MASK) {
2265 case MONO_TYPEDEFORREF_TYPEREF:
2266 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2268 case MONO_TYPEDEFORREF_TYPESPEC:
2269 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2271 case MONO_TYPEDEFORREF_TYPEDEF:
2272 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2275 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2278 /* extract the index */
2279 parent >>= MONO_TYPEDEFORREF_BITS;
2281 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2283 if (assembly->save) {
2284 alloc_table (table, table->rows + 1);
2285 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2286 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2287 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2288 values [MONO_MEMBERREF_SIGNATURE] = sig;
2291 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2298 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2301 MonoMethodSignature *sig;
2303 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2308 * A methodref signature can't contain an unmanaged calling convention.
2310 sig = mono_metadata_signature_dup (mono_method_signature (method));
2311 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2312 sig->call_convention = MONO_CALL_DEFAULT;
2313 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2314 method->name, method_encode_signature (assembly, sig));
2316 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2321 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2322 const gchar *name, guint32 sig)
2324 MonoDynamicTable *table;
2328 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2330 if (assembly->save) {
2331 alloc_table (table, table->rows + 1);
2332 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2333 values [MONO_MEMBERREF_CLASS] = original;
2334 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2335 values [MONO_MEMBERREF_SIGNATURE] = sig;
2338 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2345 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2348 ReflectionMethodBuilder rmb;
2350 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2354 reflection_methodbuilder_from_method_builder (&rmb, mb);
2356 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2357 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2358 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2363 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2366 ReflectionMethodBuilder rmb;
2368 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2372 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2374 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2375 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2376 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2381 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2386 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2389 g_assert (f->field->parent);
2390 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2391 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2392 f->field->name, fieldref_encode_signature (assembly, type));
2393 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2398 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2403 guint32 nparams = gmethod->inst->type_argc;
2404 guint32 size = 10 + nparams * 30;
2407 char *b = blob_size;
2409 if (!assembly->save)
2412 p = buf = g_malloc (size);
2414 * FIXME: vararg, explicit_this, differenc call_conv values...
2416 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2417 mono_metadata_encode_value (nparams, p, &p);
2419 for (i = 0; i < nparams; i++)
2420 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2423 g_assert (p - buf < size);
2424 mono_metadata_encode_value (p-buf, b, &b);
2425 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2431 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2433 MonoDynamicTable *table;
2435 guint32 token, mtoken = 0, sig;
2436 MonoMethodInflated *imethod;
2437 MonoMethod *declaring;
2439 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2441 g_assert (method->is_inflated);
2442 method = mono_get_inflated_method (method);
2443 imethod = (MonoMethodInflated *) method;
2444 declaring = imethod->declaring;
2446 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2447 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2449 if (!mono_method_signature (declaring)->generic_param_count)
2452 switch (mono_metadata_token_table (mtoken)) {
2453 case MONO_TABLE_MEMBERREF:
2454 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2456 case MONO_TABLE_METHOD:
2457 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2460 g_assert_not_reached ();
2463 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2465 if (assembly->save) {
2466 alloc_table (table, table->rows + 1);
2467 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2468 values [MONO_METHODSPEC_METHOD] = mtoken;
2469 values [MONO_METHODSPEC_SIGNATURE] = sig;
2472 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2479 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2481 MonoMethodInflated *imethod;
2484 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2488 g_assert (m->is_inflated);
2489 m = mono_get_inflated_method (m);
2490 imethod = (MonoMethodInflated *) m;
2492 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2493 token = method_encode_methodspec (assembly, m);
2495 guint32 sig = method_encode_signature (
2496 assembly, mono_method_signature (imethod->declaring));
2497 token = mono_image_get_memberref_token (
2498 assembly, &m->klass->byval_arg, m->name, sig);
2501 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2506 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2508 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2511 m = mono_get_inflated_method (m);
2513 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2514 token = mono_image_get_memberref_token (
2515 assembly, &m->klass->byval_arg, m->name, sig);
2521 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2523 MonoDynamicTable *table;
2530 char *b = blob_size;
2534 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2535 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2536 * Because of this, we must not insert it into the `typeref' hash table.
2539 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2543 g_assert (tb->generic_params);
2544 klass = mono_class_from_mono_type (tb->type.type);
2546 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2547 encode_type (assembly, &klass->byval_arg, p, &p);
2549 count = mono_array_length (tb->generic_params);
2550 mono_metadata_encode_value (count, p, &p);
2551 for (i = 0; i < count; i++) {
2552 MonoReflectionGenericParam *gparam;
2554 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2556 encode_type (assembly, gparam->type.type, p, &p);
2559 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2560 g_assert (p-sig < 128);
2562 if (assembly->save) {
2563 mono_metadata_encode_value (p-sig, b, &b);
2564 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2565 alloc_table (table, table->rows + 1);
2566 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2567 values [MONO_TYPESPEC_SIGNATURE] = token;
2570 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2571 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2577 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2579 MonoDynamicTable *table;
2582 guint32 token, pclass, parent, sig;
2585 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2589 klass = mono_class_from_mono_type (fb->typeb->type);
2590 name = mono_string_to_utf8 (fb->name);
2592 sig = fieldref_encode_signature (assembly, fb->type->type);
2594 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2595 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2597 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2598 parent >>= MONO_TYPEDEFORREF_BITS;
2600 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2602 if (assembly->save) {
2603 alloc_table (table, table->rows + 1);
2604 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2605 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2606 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2607 values [MONO_MEMBERREF_SIGNATURE] = sig;
2610 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2612 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2617 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2625 char *b = blob_size;
2627 if (!assembly->save)
2631 g_assert (helper->type == 2);
2633 if (helper->arguments)
2634 nargs = mono_array_length (helper->arguments);
2638 size = 10 + (nargs * 10);
2640 p = buf = g_malloc (size);
2642 /* Encode calling convention */
2643 /* Change Any to Standard */
2644 if ((helper->call_conv & 0x03) == 0x03)
2645 helper->call_conv = 0x01;
2646 /* explicit_this implies has_this */
2647 if (helper->call_conv & 0x40)
2648 helper->call_conv &= 0x20;
2650 if (helper->call_conv == 0) { /* Unmanaged */
2651 *p = helper->unmanaged_call_conv - 1;
2654 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2655 if (helper->call_conv & 0x02) /* varargs */
2660 mono_metadata_encode_value (nargs, p, &p);
2661 encode_reflection_type (assembly, helper->return_type, p, &p);
2662 for (i = 0; i < nargs; ++i) {
2663 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2664 encode_reflection_type (assembly, pt, p, &p);
2667 g_assert (p - buf < size);
2668 mono_metadata_encode_value (p-buf, b, &b);
2669 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2676 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2679 MonoDynamicTable *table;
2682 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2683 idx = table->next_idx ++;
2685 alloc_table (table, table->rows);
2686 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2688 values [MONO_STAND_ALONE_SIGNATURE] =
2689 mono_reflection_encode_sighelper (assembly, helper);
2695 reflection_cc_to_file (int call_conv) {
2696 switch (call_conv & 0x3) {
2698 case 1: return MONO_CALL_DEFAULT;
2699 case 2: return MONO_CALL_VARARG;
2701 g_assert_not_reached ();
2708 MonoMethodSignature *sig;
2714 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2719 MonoMethodSignature *sig;
2722 name = mono_string_to_utf8 (m->name);
2723 nparams = mono_array_length (m->parameters);
2724 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2726 sig->sentinelpos = -1;
2727 sig->call_convention = reflection_cc_to_file (m->call_conv);
2728 sig->param_count = nparams;
2729 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2730 for (i = 0; i < nparams; ++i) {
2731 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2732 sig->params [i] = t->type;
2735 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2737 if (strcmp (name, am->name) == 0 &&
2738 mono_metadata_type_equal (am->parent, m->parent->type) &&
2739 mono_metadata_signature_equal (am->sig, sig)) {
2742 m->table_idx = am->token & 0xffffff;
2746 am = g_new0 (ArrayMethod, 1);
2749 am->parent = m->parent->type;
2750 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2751 method_encode_signature (assembly, sig));
2752 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2753 m->table_idx = am->token & 0xffffff;
2758 * Insert into the metadata tables all the info about the TypeBuilder tb.
2759 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2762 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2764 MonoDynamicTable *table;
2766 int i, is_object = 0, is_system = 0;
2769 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2770 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2771 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2772 n = mono_string_to_utf8 (tb->name);
2773 if (strcmp (n, "Object") == 0)
2775 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2777 n = mono_string_to_utf8 (tb->nspace);
2778 if (strcmp (n, "System") == 0)
2780 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2782 if (tb->parent && !(is_system && is_object) &&
2783 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2784 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2786 values [MONO_TYPEDEF_EXTENDS] = 0;
2788 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2789 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2792 * if we have explicitlayout or sequentiallayouts, output data in the
2793 * ClassLayout table.
2795 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2796 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2797 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2799 alloc_table (table, table->rows);
2800 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2801 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2802 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2803 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2806 /* handle interfaces */
2807 if (tb->interfaces) {
2808 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2810 table->rows += mono_array_length (tb->interfaces);
2811 alloc_table (table, table->rows);
2812 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2813 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2814 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2815 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2816 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2817 values += MONO_INTERFACEIMPL_SIZE;
2823 table = &assembly->tables [MONO_TABLE_FIELD];
2824 table->rows += tb->num_fields;
2825 alloc_table (table, table->rows);
2826 for (i = 0; i < tb->num_fields; ++i)
2827 mono_image_get_field_info (
2828 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2831 /* handle constructors */
2833 table = &assembly->tables [MONO_TABLE_METHOD];
2834 table->rows += mono_array_length (tb->ctors);
2835 alloc_table (table, table->rows);
2836 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2837 mono_image_get_ctor_info (domain,
2838 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2841 /* handle methods */
2843 table = &assembly->tables [MONO_TABLE_METHOD];
2844 table->rows += tb->num_methods;
2845 alloc_table (table, table->rows);
2846 for (i = 0; i < tb->num_methods; ++i)
2847 mono_image_get_method_info (
2848 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2851 /* Do the same with properties etc.. */
2852 if (tb->events && mono_array_length (tb->events)) {
2853 table = &assembly->tables [MONO_TABLE_EVENT];
2854 table->rows += mono_array_length (tb->events);
2855 alloc_table (table, table->rows);
2856 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2858 alloc_table (table, table->rows);
2859 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2860 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2861 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2862 for (i = 0; i < mono_array_length (tb->events); ++i)
2863 mono_image_get_event_info (
2864 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2866 if (tb->properties && mono_array_length (tb->properties)) {
2867 table = &assembly->tables [MONO_TABLE_PROPERTY];
2868 table->rows += mono_array_length (tb->properties);
2869 alloc_table (table, table->rows);
2870 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2872 alloc_table (table, table->rows);
2873 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2874 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2875 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2876 for (i = 0; i < mono_array_length (tb->properties); ++i)
2877 mono_image_get_property_info (
2878 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2881 /* handle generic parameters */
2882 if (tb->generic_params) {
2883 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2884 table->rows += mono_array_length (tb->generic_params);
2885 alloc_table (table, table->rows);
2886 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2887 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2889 mono_image_get_generic_param_info (
2890 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2894 mono_image_add_decl_security (assembly,
2895 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2898 MonoDynamicTable *ntable;
2900 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2901 ntable->rows += mono_array_length (tb->subtypes);
2902 alloc_table (ntable, ntable->rows);
2903 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2905 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2906 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2908 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2909 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2910 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2911 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2912 mono_string_to_utf8 (tb->name), tb->table_idx,
2913 ntable->next_idx, ntable->rows);*/
2914 values += MONO_NESTED_CLASS_SIZE;
2921 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2925 g_ptr_array_add (types, type);
2927 if (!type->subtypes)
2930 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2932 collect_types (types, subtype);
2937 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2939 if ((*type1)->table_idx < (*type2)->table_idx)
2942 if ((*type1)->table_idx > (*type2)->table_idx)
2949 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2954 for (i = 0; i < mono_array_length (pinfo); ++i) {
2955 MonoReflectionParamBuilder *pb;
2956 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2959 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2964 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2967 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2969 for (i = 0; i < tb->num_fields; ++i) {
2970 MonoReflectionFieldBuilder* fb;
2971 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2972 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2976 for (i = 0; i < mono_array_length (tb->events); ++i) {
2977 MonoReflectionEventBuilder* eb;
2978 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2979 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2982 if (tb->properties) {
2983 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2984 MonoReflectionPropertyBuilder* pb;
2985 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2986 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2990 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2991 MonoReflectionCtorBuilder* cb;
2992 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2993 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2994 params_add_cattrs (assembly, cb->pinfo);
2999 for (i = 0; i < tb->num_methods; ++i) {
3000 MonoReflectionMethodBuilder* mb;
3001 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3002 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3003 params_add_cattrs (assembly, mb->pinfo);
3008 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3009 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3014 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3017 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3019 /* no types in the module */
3023 for (i = 0; i < mb->num_types; ++i)
3024 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3028 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3030 MonoDynamicTable *table;
3034 char *b = blob_size;
3037 table = &assembly->tables [MONO_TABLE_FILE];
3039 alloc_table (table, table->rows);
3040 values = table->values + table->next_idx * MONO_FILE_SIZE;
3041 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3042 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3043 if (module->image->dynamic) {
3044 /* This depends on the fact that the main module is emitted last */
3045 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3046 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3049 path = g_strdup (module->image->name);
3051 mono_sha1_get_digest_from_file (path, hash);
3054 mono_metadata_encode_value (20, b, &b);
3055 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3056 mono_image_add_stream_data (&assembly->blob, hash, 20);
3061 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3063 MonoDynamicTable *table;
3067 table = &assembly->tables [MONO_TABLE_MODULE];
3068 mb->table_idx = table->next_idx ++;
3069 name = mono_string_to_utf8 (mb->module.name);
3070 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3072 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3075 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3076 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3077 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3082 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3083 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3085 MonoDynamicTable *table;
3089 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3090 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3093 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3095 alloc_table (table, table->rows);
3096 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3098 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3099 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3100 if (klass->nested_in)
3101 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3103 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3104 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3105 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3107 res = table->next_idx;
3111 /* Emit nested types */
3112 if (klass->nested_classes) {
3115 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3116 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3123 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3124 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3129 klass = mono_class_from_mono_type (tb->type.type);
3131 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3133 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3134 parent_index, assembly);
3138 * We need to do this ourselves since klass->nested_classes is not set up.
3141 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3142 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3147 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3148 guint32 module_index, MonoDynamicImage *assembly)
3150 MonoImage *image = module->image;
3154 t = &image->tables [MONO_TABLE_TYPEDEF];
3156 for (i = 0; i < t->rows; ++i) {
3157 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3159 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3160 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3164 #define align_pointer(base,p)\
3166 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3168 (p) += 4 - (__diff & 3);\
3172 compare_constants (const void *a, const void *b)
3174 const guint32 *a_values = a;
3175 const guint32 *b_values = b;
3176 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3180 compare_semantics (const void *a, const void *b)
3182 const guint32 *a_values = a;
3183 const guint32 *b_values = b;
3184 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3187 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3191 compare_custom_attrs (const void *a, const void *b)
3193 const guint32 *a_values = a;
3194 const guint32 *b_values = b;
3196 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3200 compare_field_marshal (const void *a, const void *b)
3202 const guint32 *a_values = a;
3203 const guint32 *b_values = b;
3205 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3209 compare_nested (const void *a, const void *b)
3211 const guint32 *a_values = a;
3212 const guint32 *b_values = b;
3214 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3218 compare_genericparam (const void *a, const void *b)
3220 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3221 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3223 if ((*b_entry)->owner == (*a_entry)->owner)
3225 (*a_entry)->gparam->type.type->data.generic_param->num -
3226 (*b_entry)->gparam->type.type->data.generic_param->num;
3228 return (*a_entry)->owner - (*b_entry)->owner;
3232 compare_declsecurity_attrs (const void *a, const void *b)
3234 const guint32 *a_values = a;
3235 const guint32 *b_values = b;
3237 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3241 pad_heap (MonoDynamicStream *sh)
3243 if (sh->index & 3) {
3244 int sz = 4 - (sh->index & 3);
3245 memset (sh->data + sh->index, 0, sz);
3252 MonoDynamicStream *stream;
3256 * build_compressed_metadata() fills in the blob of data that represents the
3257 * raw metadata as it will be saved in the PE file. The five streams are output
3258 * and the metadata tables are comnpressed from the guint32 array representation,
3259 * to the compressed on-disk format.
3262 build_compressed_metadata (MonoDynamicImage *assembly)
3264 MonoDynamicTable *table;
3266 guint64 valid_mask = 0;
3267 guint64 sorted_mask;
3268 guint32 heapt_size = 0;
3269 guint32 meta_size = 256; /* allow for header and other stuff */
3270 guint32 table_offset;
3271 guint32 ntables = 0;
3277 struct StreamDesc stream_desc [5];
3279 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3280 for (i = 0; i < assembly->gen_params->len; i++){
3281 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3282 write_generic_param_entry (assembly, entry);
3285 stream_desc [0].name = "#~";
3286 stream_desc [0].stream = &assembly->tstream;
3287 stream_desc [1].name = "#Strings";
3288 stream_desc [1].stream = &assembly->sheap;
3289 stream_desc [2].name = "#US";
3290 stream_desc [2].stream = &assembly->us;
3291 stream_desc [3].name = "#Blob";
3292 stream_desc [3].stream = &assembly->blob;
3293 stream_desc [4].name = "#GUID";
3294 stream_desc [4].stream = &assembly->guid;
3296 /* tables that are sorted */
3297 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3298 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3299 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3300 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3301 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3302 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3304 /* Compute table sizes */
3305 /* the MonoImage has already been created in mono_image_basic_init() */
3306 meta = &assembly->image;
3308 /* sizes should be multiple of 4 */
3309 pad_heap (&assembly->blob);
3310 pad_heap (&assembly->guid);
3311 pad_heap (&assembly->sheap);
3312 pad_heap (&assembly->us);
3314 /* Setup the info used by compute_sizes () */
3315 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3316 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3317 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3319 meta_size += assembly->blob.index;
3320 meta_size += assembly->guid.index;
3321 meta_size += assembly->sheap.index;
3322 meta_size += assembly->us.index;
3324 for (i=0; i < MONO_TABLE_NUM; ++i)
3325 meta->tables [i].rows = assembly->tables [i].rows;
3327 for (i = 0; i < MONO_TABLE_NUM; i++){
3328 if (meta->tables [i].rows == 0)
3330 valid_mask |= (guint64)1 << i;
3332 meta->tables [i].row_size = mono_metadata_compute_size (
3333 meta, i, &meta->tables [i].size_bitfield);
3334 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3336 heapt_size += 24; /* #~ header size */
3337 heapt_size += ntables * 4;
3338 /* make multiple of 4 */
3341 meta_size += heapt_size;
3342 meta->raw_metadata = g_malloc0 (meta_size);
3343 p = meta->raw_metadata;
3344 /* the metadata signature */
3345 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3346 /* version numbers and 4 bytes reserved */
3347 int16val = (guint16*)p;
3348 *int16val++ = GUINT16_TO_LE (1);
3349 *int16val = GUINT16_TO_LE (1);
3351 /* version string */
3352 int32val = (guint32*)p;
3353 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3355 memcpy (p, meta->version, strlen (meta->version));
3356 p += GUINT32_FROM_LE (*int32val);
3357 align_pointer (meta->raw_metadata, p);
3358 int16val = (guint16*)p;
3359 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3360 *int16val = GUINT16_TO_LE (5); /* number of streams */
3364 * write the stream info.
3366 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3367 table_offset += 3; table_offset &= ~3;
3369 assembly->tstream.index = heapt_size;
3370 for (i = 0; i < 5; ++i) {
3371 int32val = (guint32*)p;
3372 stream_desc [i].stream->offset = table_offset;
3373 *int32val++ = GUINT32_TO_LE (table_offset);
3374 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3375 table_offset += GUINT32_FROM_LE (*int32val);
3376 table_offset += 3; table_offset &= ~3;
3378 strcpy (p, stream_desc [i].name);
3379 p += strlen (stream_desc [i].name) + 1;
3380 align_pointer (meta->raw_metadata, p);
3383 * now copy the data, the table stream header and contents goes first.
3385 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3386 p = meta->raw_metadata + assembly->tstream.offset;
3387 int32val = (guint32*)p;
3388 *int32val = GUINT32_TO_LE (0); /* reserved */
3391 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3392 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3393 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3394 *p++ = 2; /* version */
3397 *p++ = 1; /* version */
3401 if (meta->idx_string_wide)
3403 if (meta->idx_guid_wide)
3405 if (meta->idx_blob_wide)
3408 *p++ = 1; /* reserved */
3409 int64val = (guint64*)p;
3410 *int64val++ = GUINT64_TO_LE (valid_mask);
3411 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3413 int32val = (guint32*)p;
3414 for (i = 0; i < MONO_TABLE_NUM; i++){
3415 if (meta->tables [i].rows == 0)
3417 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3419 p = (unsigned char*)int32val;
3421 /* sort the tables that still need sorting */
3422 table = &assembly->tables [MONO_TABLE_CONSTANT];
3424 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3425 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3427 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3428 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3430 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3431 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3433 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3434 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3436 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3437 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3438 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3440 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3442 /* compress the tables */
3443 for (i = 0; i < MONO_TABLE_NUM; i++){
3446 guint32 bitfield = meta->tables [i].size_bitfield;
3447 if (!meta->tables [i].rows)
3449 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3450 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3451 meta->tables [i].base = p;
3452 for (row = 1; row <= meta->tables [i].rows; ++row) {
3453 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3454 for (col = 0; col < assembly->tables [i].columns; ++col) {
3455 switch (mono_metadata_table_size (bitfield, col)) {
3457 *p++ = values [col];
3460 *p++ = values [col] & 0xff;
3461 *p++ = (values [col] >> 8) & 0xff;
3464 *p++ = values [col] & 0xff;
3465 *p++ = (values [col] >> 8) & 0xff;
3466 *p++ = (values [col] >> 16) & 0xff;
3467 *p++ = (values [col] >> 24) & 0xff;
3470 g_assert_not_reached ();
3474 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3477 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3478 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3479 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3480 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3481 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3483 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3487 * Some tables in metadata need to be sorted according to some criteria, but
3488 * when methods and fields are first created with reflection, they may be assigned a token
3489 * that doesn't correspond to the final token they will get assigned after the sorting.
3490 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3491 * with the reflection objects that represent them. Once all the tables are set up, the
3492 * reflection objects will contains the correct table index. fixup_method() will fixup the
3493 * tokens for the method with ILGenerator @ilgen.
3496 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3497 guint32 code_idx = GPOINTER_TO_UINT (value);
3498 MonoReflectionILTokenInfo *iltoken;
3499 MonoReflectionFieldBuilder *field;
3500 MonoReflectionCtorBuilder *ctor;
3501 MonoReflectionMethodBuilder *method;
3502 MonoReflectionTypeBuilder *tb;
3503 MonoReflectionArrayMethod *am;
3505 unsigned char *target;
3507 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3508 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3509 target = assembly->code.data + code_idx + iltoken->code_pos;
3510 switch (target [3]) {
3511 case MONO_TABLE_FIELD:
3512 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3513 field = (MonoReflectionFieldBuilder *)iltoken->member;
3514 idx = field->table_idx;
3515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3516 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3517 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3519 g_assert_not_reached ();
3522 case MONO_TABLE_METHOD:
3523 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3524 method = (MonoReflectionMethodBuilder *)iltoken->member;
3525 idx = method->table_idx;
3526 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3527 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3528 idx = ctor->table_idx;
3529 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3530 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3531 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3532 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3534 g_assert_not_reached ();
3537 case MONO_TABLE_TYPEDEF:
3538 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3539 g_assert_not_reached ();
3540 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3541 idx = tb->table_idx;
3543 case MONO_TABLE_MEMBERREF:
3544 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3545 am = (MonoReflectionArrayMethod*)iltoken->member;
3546 idx = am->table_idx;
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3548 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3549 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3550 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3551 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3552 g_assert (m->klass->generic_class || m->klass->generic_container);
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3556 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3557 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3558 g_assert (f->generic_info);
3560 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3563 g_assert_not_reached ();
3566 case MONO_TABLE_METHODSPEC:
3567 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3568 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3569 g_assert (mono_method_signature (m)->generic_param_count);
3572 g_assert_not_reached ();
3576 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3578 target [0] = idx & 0xff;
3579 target [1] = (idx >> 8) & 0xff;
3580 target [2] = (idx >> 16) & 0xff;
3587 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3588 * value is not known when the table is emitted.
3591 fixup_cattrs (MonoDynamicImage *assembly)
3593 MonoDynamicTable *table;
3595 guint32 type, i, idx, token;
3598 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3600 for (i = 0; i < table->rows; ++i) {
3601 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3603 type = values [MONO_CUSTOM_ATTR_TYPE];
3604 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3605 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3606 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3607 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3610 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3611 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3612 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3613 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3622 * The METHODIMPL table might contain METHODDEF tokens whose final
3623 * value is not known when the table is emitted.
3626 fixup_methodimpl (MonoDynamicImage *assembly)
3628 MonoDynamicTable *table;
3630 guint32 decl, i, idx, token;
3633 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3635 for (i = 0; i < table->rows; ++i) {
3636 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3637 decl = values [MONO_METHODIMPL_DECLARATION];
3639 idx = decl >> MONO_METHODDEFORREF_BITS;
3640 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3643 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3644 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3647 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3648 token = mono_image_create_token (assembly, method, FALSE);
3649 idx = mono_metadata_token_index (token);
3650 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3656 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3658 MonoDynamicTable *table;
3662 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3664 alloc_table (table, table->rows);
3665 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3666 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3667 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3668 name = mono_string_to_utf8 (rsrc->name);
3669 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3671 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3676 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3678 MonoDynamicTable *table;
3682 char *b = blob_size;
3684 guint32 idx, offset;
3686 if (rsrc->filename) {
3687 name = mono_string_to_utf8 (rsrc->filename);
3688 sname = g_path_get_basename (name);
3690 table = &assembly->tables [MONO_TABLE_FILE];
3692 alloc_table (table, table->rows);
3693 values = table->values + table->next_idx * MONO_FILE_SIZE;
3694 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3695 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3698 mono_sha1_get_digest_from_file (name, hash);
3699 mono_metadata_encode_value (20, b, &b);
3700 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3701 mono_image_add_stream_data (&assembly->blob, hash, 20);
3703 idx = table->next_idx++;
3705 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3708 offset = mono_array_length (rsrc->data);
3709 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3710 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3711 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3712 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3716 * The entry should be emitted into the MANIFESTRESOURCE table of
3717 * the main module, but that needs to reference the FILE table
3718 * which isn't emitted yet.
3725 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3729 set_version_from_string (MonoString *version, guint32 *values)
3731 gchar *ver, *p, *str;
3734 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3735 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3736 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3737 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3740 ver = str = mono_string_to_utf8 (version);
3741 for (i = 0; i < 4; ++i) {
3742 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3748 /* handle Revision and Build */
3758 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3762 char *b = blob_size;
3767 len = mono_array_length (pkey);
3768 mono_metadata_encode_value (len, b, &b);
3769 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3770 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3772 /* need to get the actual value from the key type... */
3773 assembly->strong_name_size = 128;
3774 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3780 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3782 MonoDynamicTable *table;
3783 MonoDynamicImage *assembly;
3784 MonoReflectionAssemblyBuilder *assemblyb;
3789 guint32 module_index;
3791 assemblyb = moduleb->assemblyb;
3792 assembly = moduleb->dynamic_image;
3793 domain = mono_object_domain (assemblyb);
3795 /* Emit ASSEMBLY table */
3796 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3797 alloc_table (table, 1);
3798 values = table->values + MONO_ASSEMBLY_SIZE;
3799 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3800 name = mono_string_to_utf8 (assemblyb->name);
3801 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3803 if (assemblyb->culture) {
3804 name = mono_string_to_utf8 (assemblyb->culture);
3805 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3808 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3810 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3811 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3812 set_version_from_string (assemblyb->version, values);
3814 /* Emit FILE + EXPORTED_TYPE table */
3816 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3818 MonoReflectionModuleBuilder *file_module =
3819 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3820 if (file_module != moduleb) {
3821 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3823 if (file_module->types) {
3824 for (j = 0; j < file_module->num_types; ++j) {
3825 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3826 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3831 if (assemblyb->loaded_modules) {
3832 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3833 MonoReflectionModule *file_module =
3834 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3835 mono_image_fill_file_table (domain, file_module, assembly);
3837 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3841 /* Emit MANIFESTRESOURCE table */
3843 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3845 MonoReflectionModuleBuilder *file_module =
3846 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3847 /* The table for the main module is emitted later */
3848 if (file_module != moduleb) {
3850 if (file_module->resources) {
3851 int len = mono_array_length (file_module->resources);
3852 for (j = 0; j < len; ++j) {
3853 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3854 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3862 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3863 * for the modulebuilder @moduleb.
3864 * At the end of the process, method and field tokens are fixed up and the
3865 * on-disk compressed metadata representation is created.
3868 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3870 MonoDynamicTable *table;
3871 MonoDynamicImage *assembly;
3872 MonoReflectionAssemblyBuilder *assemblyb;
3877 assemblyb = moduleb->assemblyb;
3878 assembly = moduleb->dynamic_image;
3879 domain = mono_object_domain (assemblyb);
3881 if (assembly->text_rva)
3884 assembly->text_rva = START_TEXT_RVA;
3886 if (moduleb->is_main) {
3887 mono_image_emit_manifest (moduleb);
3890 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3891 table->rows = 1; /* .<Module> */
3893 alloc_table (table, table->rows);
3895 * Set the first entry.
3897 values = table->values + table->columns;
3898 values [MONO_TYPEDEF_FLAGS] = 0;
3899 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3900 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3901 values [MONO_TYPEDEF_EXTENDS] = 0;
3902 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3903 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3906 * handle global methods
3907 * FIXME: test what to do when global methods are defined in multiple modules.
3909 if (moduleb->global_methods) {
3910 table = &assembly->tables [MONO_TABLE_METHOD];
3911 table->rows += mono_array_length (moduleb->global_methods);
3912 alloc_table (table, table->rows);
3913 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3914 mono_image_get_method_info (
3915 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3917 if (moduleb->global_fields) {
3918 table = &assembly->tables [MONO_TABLE_FIELD];
3919 table->rows += mono_array_length (moduleb->global_fields);
3920 alloc_table (table, table->rows);
3921 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3922 mono_image_get_field_info (
3923 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3926 table = &assembly->tables [MONO_TABLE_MODULE];
3927 alloc_table (table, 1);
3928 mono_image_fill_module_table (domain, moduleb, assembly);
3932 /* Collect all types into a list sorted by their table_idx */
3933 GPtrArray *types = g_ptr_array_new ();
3936 for (i = 0; i < moduleb->num_types; ++i) {
3937 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3938 collect_types (types, type);
3941 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3942 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3943 table->rows += types->len;
3944 alloc_table (table, table->rows);
3946 for (i = 0; i < types->len; ++i) {
3947 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3948 mono_image_get_type_info (domain, type, assembly);
3950 g_ptr_array_free (types, TRUE);
3954 * table->rows is already set above and in mono_image_fill_module_table.
3956 /* add all the custom attributes at the end, once all the indexes are stable */
3957 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3959 /* CAS assembly permissions */
3960 if (assemblyb->permissions_minimum)
3961 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3962 if (assemblyb->permissions_optional)
3963 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3964 if (assemblyb->permissions_refused)
3965 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3967 module_add_cattrs (assembly, moduleb);
3970 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3971 fixup_cattrs (assembly);
3972 fixup_methodimpl (assembly);
3976 * mono_image_insert_string:
3977 * @module: module builder object
3980 * Insert @str into the user string stream of @module.
3983 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3985 MonoDynamicImage *assembly;
3990 MONO_ARCH_SAVE_REGS;
3992 if (!module->dynamic_image)
3993 mono_image_module_basic_init (module);
3995 assembly = module->dynamic_image;
3997 if (assembly->save) {
3998 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3999 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4000 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4002 char *swapped = g_malloc (2 * mono_string_length (str));
4003 const char *p = (const char*)mono_string_chars (str);
4005 swap_with_size (swapped, p, 2, mono_string_length (str));
4006 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4010 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4012 mono_image_add_stream_data (&assembly->us, "", 1);
4014 idx = assembly->us.index ++;
4017 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4019 return MONO_TOKEN_STRING | idx;
4023 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4028 klass = obj->vtable->klass;
4029 if (strcmp (klass->name, "MonoMethod") == 0) {
4030 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4031 MonoMethodSignature *sig, *old;
4032 guint32 sig_token, parent;
4035 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4037 nargs = mono_array_length (opt_param_types);
4038 old = mono_method_signature (method);
4039 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4041 sig->hasthis = old->hasthis;
4042 sig->explicit_this = old->explicit_this;
4043 sig->call_convention = old->call_convention;
4044 sig->generic_param_count = old->generic_param_count;
4045 sig->param_count = old->param_count + nargs;
4046 sig->sentinelpos = old->param_count;
4047 sig->ret = old->ret;
4049 for (i = 0; i < old->param_count; i++)
4050 sig->params [i] = old->params [i];
4052 for (i = 0; i < nargs; i++) {
4053 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4054 sig->params [old->param_count + i] = rt->type;
4057 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4058 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4059 parent >>= MONO_TYPEDEFORREF_BITS;
4061 parent <<= MONO_MEMBERREF_PARENT_BITS;
4062 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4064 sig_token = method_encode_signature (assembly, sig);
4065 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4066 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4067 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4068 ReflectionMethodBuilder rmb;
4069 guint32 parent, sig;
4071 reflection_methodbuilder_from_method_builder (&rmb, mb);
4072 rmb.opt_types = opt_param_types;
4074 sig = method_builder_encode_signature (assembly, &rmb);
4076 parent = mono_image_create_token (assembly, obj, TRUE);
4077 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4079 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4080 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4082 token = mono_image_get_varargs_method_token (
4083 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4085 g_error ("requested method token for %s\n", klass->name);
4092 * mono_image_create_token:
4093 * @assembly: a dynamic assembly
4096 * Get a token to insert in the IL code stream for the given MemberInfo.
4097 * @obj can be one of:
4098 * ConstructorBuilder
4108 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4113 klass = obj->vtable->klass;
4114 if (strcmp (klass->name, "MethodBuilder") == 0) {
4115 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4117 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4118 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4120 token = mono_image_get_methodbuilder_token (assembly, mb);
4121 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4122 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4123 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4125 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4126 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4128 token = mono_image_get_ctorbuilder_token (assembly, mb);
4129 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4130 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4131 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4132 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4133 if (tb->generic_params) {
4134 token = mono_image_get_generic_field_token (assembly, fb);
4136 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4138 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4139 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4140 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4141 } else if (strcmp (klass->name, "MonoType") == 0 ||
4142 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4143 MonoReflectionType *tb = (MonoReflectionType *)obj;
4144 token = mono_metadata_token_from_dor (
4145 mono_image_typedef_or_ref (assembly, tb->type));
4146 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4147 MonoReflectionType *tb = (MonoReflectionType *)obj;
4148 token = mono_metadata_token_from_dor (
4149 mono_image_typedef_or_ref (assembly, tb->type));
4150 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4151 strcmp (klass->name, "MonoMethod") == 0 ||
4152 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4153 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4154 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4155 if (m->method->is_inflated) {
4156 if (create_methodspec)
4157 token = mono_image_get_methodspec_token (assembly, m->method);
4159 token = mono_image_get_inflated_method_token (assembly, m->method);
4160 } else if ((m->method->klass->image == &assembly->image) &&
4161 !m->method->klass->generic_class) {
4162 static guint32 method_table_idx = 0xffffff;
4163 if (m->method->klass->wastypebuilder) {
4164 /* we use the same token as the one that was assigned
4165 * to the Methodbuilder.
4166 * FIXME: do the equivalent for Fields.
4168 token = m->method->token;
4171 * Each token should have a unique index, but the indexes are
4172 * assigned by managed code, so we don't know about them. An
4173 * easy solution is to count backwards...
4175 method_table_idx --;
4176 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4179 token = mono_image_get_methodref_token (assembly, m->method);
4181 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4182 } else if (strcmp (klass->name, "MonoField") == 0) {
4183 MonoReflectionField *f = (MonoReflectionField *)obj;
4184 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4185 static guint32 field_table_idx = 0xffffff;
4187 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4189 token = mono_image_get_fieldref_token (assembly, f);
4191 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4192 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4193 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4194 token = mono_image_get_array_token (assembly, m);
4195 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4196 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4197 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4199 g_error ("requested token for %s\n", klass->name);
4202 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4208 guint32 import_lookup_table;
4212 guint32 import_address_table_rva;
4220 static 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 if (!domain->refobject_hash)
5085 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);
5086 CACHE_OBJECT (assembly, res, NULL);
5090 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5092 /* this is done only once */
5093 mono_domain_lock (domain);
5094 if (!domain->refobject_hash)
5095 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);
5096 CACHE_OBJECT (module, res, NULL);
5100 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5102 MonoDynamicImage *image = moduleb->dynamic_image;
5103 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5106 MonoImage **new_modules;
5109 * FIXME: we already created an image in mono_image_basic_init (), but
5110 * we don't know which module it belongs to, since that is only
5111 * determined at assembly save time.
5113 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5114 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5116 moduleb->module.image = &image->image;
5117 moduleb->dynamic_image = image;
5118 register_module (mono_object_domain (moduleb), moduleb, image);
5120 /* register the module with the assembly */
5121 ass = ab->dynamic_assembly->assembly.image;
5122 module_count = ass->module_count;
5123 new_modules = g_new0 (MonoImage *, module_count + 1);
5126 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5127 new_modules [module_count] = &image->image;
5129 g_free (ass->modules);
5130 ass->modules = new_modules;
5131 ass->module_count ++;
5136 * mono_assembly_get_object:
5137 * @domain: an app domain
5138 * @assembly: an assembly
5140 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5142 MonoReflectionAssembly*
5143 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5145 static MonoClass *System_Reflection_Assembly;
5146 MonoReflectionAssembly *res;
5148 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5149 if (!System_Reflection_Assembly)
5150 System_Reflection_Assembly = mono_class_from_name (
5151 mono_defaults.corlib, "System.Reflection", "Assembly");
5152 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5153 res->assembly = assembly;
5155 CACHE_OBJECT (assembly, res, NULL);
5161 MonoReflectionModule*
5162 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5164 static MonoClass *System_Reflection_Module;
5165 MonoReflectionModule *res;
5168 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5169 if (!System_Reflection_Module)
5170 System_Reflection_Module = mono_class_from_name (
5171 mono_defaults.corlib, "System.Reflection", "Module");
5172 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5175 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5177 res->fqname = mono_string_new (domain, image->name);
5178 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5179 res->scopename = mono_string_new (domain, image->module_name);
5183 if (image->assembly->image == image) {
5184 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5187 g_assert (image->assembly->image->modules);
5189 for (i = 0; i < image->assembly->image->module_count; i++) {
5190 if (image->assembly->image->modules [i] == image)
5191 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5193 g_assert (res->token);
5196 mono_image_addref (image);
5198 CACHE_OBJECT (image, res, NULL);
5202 MonoReflectionModule*
5203 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5205 static MonoClass *System_Reflection_Module;
5206 MonoReflectionModule *res;
5207 MonoTableInfo *table;
5208 guint32 cols [MONO_FILE_SIZE];
5210 guint32 i, name_idx;
5213 if (!System_Reflection_Module)
5214 System_Reflection_Module = mono_class_from_name (
5215 mono_defaults.corlib, "System.Reflection", "Module");
5216 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5218 table = &image->tables [MONO_TABLE_FILE];
5219 g_assert (table_index < table->rows);
5220 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5223 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5224 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5226 /* Check whenever the row has a corresponding row in the moduleref table */
5227 table = &image->tables [MONO_TABLE_MODULEREF];
5228 for (i = 0; i < table->rows; ++i) {
5229 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5230 val = mono_metadata_string_heap (image, name_idx);
5231 if (strcmp (val, name) == 0)
5232 res->image = image->modules [i];
5235 res->fqname = mono_string_new (domain, name);
5236 res->name = mono_string_new (domain, name);
5237 res->scopename = mono_string_new (domain, name);
5238 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5239 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5245 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5247 if ((t1->type != t2->type) ||
5248 (t1->byref != t2->byref))
5252 case MONO_TYPE_VOID:
5253 case MONO_TYPE_BOOLEAN:
5254 case MONO_TYPE_CHAR:
5265 case MONO_TYPE_STRING:
5268 case MONO_TYPE_OBJECT:
5269 case MONO_TYPE_TYPEDBYREF:
5271 case MONO_TYPE_VALUETYPE:
5272 case MONO_TYPE_CLASS:
5273 case MONO_TYPE_SZARRAY:
5274 return t1->data.klass == t2->data.klass;
5276 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5277 case MONO_TYPE_ARRAY:
5278 if (t1->data.array->rank != t2->data.array->rank)
5280 return t1->data.array->eklass == t2->data.array->eklass;
5281 case MONO_TYPE_GENERICINST: {
5283 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5285 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5286 &t2->data.generic_class->container_class->byval_arg))
5288 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5289 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5295 case MONO_TYPE_MVAR:
5296 return t1->data.generic_param == t2->data.generic_param;
5298 g_error ("implement type compare for %0x!", t1->type);
5306 mymono_metadata_type_hash (MonoType *t1)
5312 hash |= t1->byref << 6; /* do not collide with t1->type values */
5314 case MONO_TYPE_VALUETYPE:
5315 case MONO_TYPE_CLASS:
5316 case MONO_TYPE_SZARRAY:
5317 /* check if the distribution is good enough */
5318 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5320 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5325 static MonoReflectionGenericClass*
5326 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5328 static MonoClass *System_Reflection_MonoGenericClass;
5329 MonoReflectionGenericClass *res;
5330 MonoInflatedGenericClass *gclass;
5333 if (!System_Reflection_MonoGenericClass) {
5334 System_Reflection_MonoGenericClass = mono_class_from_name (
5335 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5336 g_assert (System_Reflection_MonoGenericClass);
5339 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5340 gklass = gclass->generic_class.container_class;
5342 mono_class_init (gclass->klass);
5344 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5346 res->type.type = geninst;
5347 if (gklass->wastypebuilder && gklass->reflection_info)
5348 res->generic_type = gklass->reflection_info;
5350 res->generic_type = mono_type_get_object (
5351 domain, &gclass->generic_class.container_class->byval_arg);
5357 * mono_type_get_object:
5358 * @domain: an app domain
5361 * Return an System.MonoType object representing the type @type.
5364 mono_type_get_object (MonoDomain *domain, MonoType *type)
5366 MonoReflectionType *res;
5367 MonoClass *klass = mono_class_from_mono_type (type);
5369 mono_domain_lock (domain);
5370 if (!domain->type_hash)
5371 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5372 (GCompareFunc)mymono_metadata_type_equal);
5373 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5374 mono_domain_unlock (domain);
5377 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5378 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5379 mono_g_hash_table_insert (domain->type_hash, type, res);
5380 mono_domain_unlock (domain);
5383 if (klass->reflection_info && !klass->wastypebuilder) {
5384 /* g_assert_not_reached (); */
5385 /* should this be considered an error condition? */
5387 mono_domain_unlock (domain);
5388 return klass->reflection_info;
5391 mono_class_init (klass);
5392 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5394 mono_g_hash_table_insert (domain->type_hash, type, res);
5395 mono_domain_unlock (domain);
5400 * mono_method_get_object:
5401 * @domain: an app domain
5403 * @refclass: the reflected type (can be NULL)
5405 * Return an System.Reflection.MonoMethod object representing the method @method.
5407 MonoReflectionMethod*
5408 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5411 * We use the same C representation for methods and constructors, but the type
5412 * name in C# is different.
5416 MonoReflectionMethod *ret;
5418 if (method->is_inflated) {
5419 MonoReflectionGenericMethod *gret;
5421 refclass = method->klass;
5422 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5423 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5424 cname = "MonoGenericCMethod";
5426 cname = "MonoGenericMethod";
5427 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5429 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5430 gret->method.method = method;
5431 gret->method.name = mono_string_new (domain, method->name);
5432 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5433 CACHE_OBJECT (method, gret, refclass);
5434 return (MonoReflectionMethod *) gret;
5438 refclass = method->klass;
5440 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5441 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5442 cname = "MonoCMethod";
5444 cname = "MonoMethod";
5445 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5447 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5448 ret->method = method;
5449 ret->name = mono_string_new (domain, method->name);
5450 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5451 CACHE_OBJECT (method, ret, refclass);
5456 * mono_field_get_object:
5457 * @domain: an app domain
5461 * Return an System.Reflection.MonoField object representing the field @field
5464 MonoReflectionField*
5465 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5467 MonoReflectionField *res;
5470 CHECK_OBJECT (MonoReflectionField *, field, klass);
5471 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5472 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5475 res->name = mono_string_new (domain, field->name);
5476 if (field->generic_info)
5477 res->attrs = field->generic_info->generic_type->attrs;
5479 res->attrs = field->type->attrs;
5480 res->type = mono_type_get_object (domain, field->type);
5481 CACHE_OBJECT (field, res, klass);
5486 * mono_property_get_object:
5487 * @domain: an app domain
5489 * @property: a property
5491 * Return an System.Reflection.MonoProperty object representing the property @property
5494 MonoReflectionProperty*
5495 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5497 MonoReflectionProperty *res;
5500 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5501 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5502 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5504 res->property = property;
5505 CACHE_OBJECT (property, res, klass);
5510 * mono_event_get_object:
5511 * @domain: an app domain
5515 * Return an System.Reflection.MonoEvent object representing the event @event
5518 MonoReflectionEvent*
5519 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5521 MonoReflectionEvent *res;
5524 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5525 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5526 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5529 CACHE_OBJECT (event, res, klass);
5534 * mono_param_get_objects:
5535 * @domain: an app domain
5538 * Return an System.Reflection.ParameterInfo array object representing the parameters
5539 * in the method @method.
5542 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5544 static MonoClass *System_Reflection_ParameterInfo;
5545 MonoArray *res = NULL;
5546 MonoReflectionMethod *member = NULL;
5547 MonoReflectionParameter *param = NULL;
5548 char **names, **blobs = NULL;
5549 guint32 *types = NULL;
5550 MonoType *type = NULL;
5551 MonoObject *dbnull = mono_get_dbnull_object (domain);
5552 MonoMarshalSpec **mspecs;
5555 if (!System_Reflection_ParameterInfo)
5556 System_Reflection_ParameterInfo = mono_class_from_name (
5557 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5559 if (!mono_method_signature (method)->param_count)
5560 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5562 /* Note: the cache is based on the address of the signature into the method
5563 * since we already cache MethodInfos with the method as keys.
5565 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5567 member = mono_method_get_object (domain, method, NULL);
5568 names = g_new (char *, mono_method_signature (method)->param_count);
5569 mono_method_get_param_names (method, (const char **) names);
5571 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5572 mono_method_get_marshal_info (method, mspecs);
5574 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5575 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5576 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5577 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5578 param->MemberImpl = (MonoObject*)member;
5579 param->NameImpl = mono_string_new (domain, names [i]);
5580 param->PositionImpl = i;
5581 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5583 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5584 param->DefaultValueImpl = dbnull;
5588 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5589 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5590 get_default_param_value_blobs (method, blobs, types);
5593 /* Build MonoType for the type from the Constant Table */
5595 type = g_new0 (MonoType, 1);
5596 type->type = types [i];
5597 type->data.klass = NULL;
5598 if (types [i] == MONO_TYPE_CLASS)
5599 type->data.klass = mono_defaults.object_class;
5601 type->data.klass = mono_class_from_mono_type (type);
5603 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5605 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5606 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5607 param->DefaultValueImpl = dbnull;
5612 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5614 mono_array_set (res, gpointer, i, param);
5621 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5623 mono_metadata_free_marshal_spec (mspecs [i]);
5626 CACHE_OBJECT (&(method->signature), res, NULL);
5631 * mono_method_body_get_object:
5632 * @domain: an app domain
5635 * Return an System.Reflection.MethodBody object representing the method @method.
5637 MonoReflectionMethodBody*
5638 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5640 static MonoClass *System_Reflection_MethodBody = NULL;
5641 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5642 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5643 MonoReflectionMethodBody *ret;
5644 MonoMethodNormal *mn;
5645 MonoMethodHeader *header;
5646 guint32 method_rva, local_var_sig_token;
5648 unsigned char format, flags;
5651 if (!System_Reflection_MethodBody)
5652 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5653 if (!System_Reflection_LocalVariableInfo)
5654 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5655 if (!System_Reflection_ExceptionHandlingClause)
5656 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5658 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5660 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5661 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5662 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5663 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5665 mn = (MonoMethodNormal *)method;
5666 header = mono_method_get_header (method);
5668 /* Obtain local vars signature token */
5669 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5670 ptr = mono_image_rva_map (method->klass->image, method_rva);
5671 flags = *(const unsigned char *) ptr;
5672 format = flags & METHOD_HEADER_FORMAT_MASK;
5674 case METHOD_HEADER_TINY_FORMAT:
5675 case METHOD_HEADER_TINY_FORMAT1:
5676 local_var_sig_token = 0;
5678 case METHOD_HEADER_FAT_FORMAT:
5682 local_var_sig_token = read32 (ptr);
5685 g_assert_not_reached ();
5688 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5690 ret->init_locals = header->init_locals;
5691 ret->max_stack = header->max_stack;
5692 ret->local_var_sig_token = local_var_sig_token;
5693 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5694 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5697 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5698 for (i = 0; i < header->num_locals; ++i) {
5699 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5700 info->local_type = mono_type_get_object (domain, header->locals [i]);
5701 info->is_pinned = header->locals [i]->pinned;
5702 info->local_index = i;
5703 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5707 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5708 for (i = 0; i < header->num_clauses; ++i) {
5709 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5710 MonoExceptionClause *clause = &header->clauses [i];
5712 info->flags = clause->flags;
5713 info->try_offset = clause->try_offset;
5714 info->try_length = clause->try_len;
5715 info->handler_offset = clause->handler_offset;
5716 info->handler_length = clause->handler_len;
5717 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5718 info->filter_offset = clause->data.filter_offset;
5719 else if (clause->data.catch_class)
5720 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5722 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5725 CACHE_OBJECT (method, ret, NULL);
5730 mono_get_dbnull_object (MonoDomain *domain)
5734 static MonoClassField *dbnull_value_field = NULL;
5736 if (!dbnull_value_field) {
5737 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5738 mono_class_init (klass);
5739 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5740 g_assert (dbnull_value_field);
5742 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5749 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5751 guint32 param_index, i, lastp, crow = 0;
5752 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5755 MonoClass *klass = method->klass;
5756 MonoImage *image = klass->image;
5757 MonoMethodSignature *methodsig = mono_method_signature (method);
5759 MonoTableInfo *constt;
5760 MonoTableInfo *methodt;
5761 MonoTableInfo *paramt;
5763 if (!methodsig->param_count)
5766 if (klass->generic_class) {
5767 return; /* FIXME - ??? */
5770 mono_class_init (klass);
5772 if (klass->image->dynamic) {
5773 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5774 if (aux && aux->param_defaults) {
5775 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5776 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5781 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5782 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5783 constt = &image->tables [MONO_TABLE_CONSTANT];
5785 idx = mono_method_get_index (method) - 1;
5786 g_assert (idx != -1);
5788 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5789 if (idx + 1 < methodt->rows)
5790 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5792 lastp = paramt->rows + 1;
5794 for (i = param_index; i < lastp; ++i) {
5797 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5798 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5800 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5803 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5808 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5809 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5810 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5817 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5822 MonoType *basetype = type;
5827 klass = mono_class_from_mono_type (type);
5828 if (klass->valuetype) {
5829 object = mono_object_new (domain, klass);
5830 retval = ((gchar *) object + sizeof (MonoObject));
5831 if (klass->enumtype)
5832 basetype = klass->enum_basetype;
5837 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5844 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5848 memset (assembly, 0, sizeof (MonoAssemblyName));
5850 assembly->culture = "";
5851 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5853 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5856 while (g_ascii_isspace (*p) || *p == ',') {
5865 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5867 assembly->major = strtoul (p, &s, 10);
5868 if (s == p || *s != '.')
5871 assembly->minor = strtoul (p, &s, 10);
5872 if (s == p || *s != '.')
5875 assembly->build = strtoul (p, &s, 10);
5876 if (s == p || *s != '.')
5879 assembly->revision = strtoul (p, &s, 10);
5883 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5885 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5886 assembly->culture = "";
5889 assembly->culture = p;
5890 while (*p && *p != ',') {
5894 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5896 if (strncmp (p, "null", 4) == 0) {
5901 while (*p && *p != ',') {
5904 len = (p - start + 1);
5905 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5906 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5907 g_strlcpy (assembly->public_key_token, start, len);
5910 while (*p && *p != ',')
5914 while (g_ascii_isspace (*p) || *p == ',') {
5928 * mono_reflection_parse_type:
5931 * Parse a type name as accepted by the GetType () method and output the info
5932 * extracted in the info structure.
5933 * the name param will be mangled, so, make a copy before passing it to this function.
5934 * The fields in info will be valid until the memory pointed to by name is valid.
5936 * See also mono_type_get_name () below.
5938 * Returns: 0 on parse error.
5941 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5942 MonoTypeNameParse *info)
5944 char *start, *p, *w, *temp, *last_point, *startn;
5945 int in_modifiers = 0;
5946 int isbyref = 0, rank, arity = 0, i;
5948 start = p = w = name;
5950 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5951 info->name = info->name_space = NULL;
5952 info->nested = NULL;
5953 info->modifiers = NULL;
5954 info->type_arguments = NULL;
5956 /* last_point separates the namespace from the name */
5962 *p = 0; /* NULL terminate the name */
5964 info->nested = g_list_append (info->nested, startn);
5965 /* we have parsed the nesting namespace + name */
5969 info->name_space = start;
5971 info->name = last_point + 1;
5973 info->name_space = (char *)"";
5992 i = strtol (p, &temp, 10);
6009 info->name_space = start;
6011 info->name = last_point + 1;
6013 info->name_space = (char *)"";
6020 if (isbyref) /* only one level allowed by the spec */
6023 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6027 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6033 info->type_arguments = g_ptr_array_new ();
6034 for (i = 0; i < arity; i++) {
6035 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6036 gboolean fqname = FALSE;
6038 g_ptr_array_add (info->type_arguments, subinfo);
6045 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6056 while (*p && (*p != ']'))
6064 if (g_ascii_isspace (*aname)) {
6071 !assembly_name_to_aname (&subinfo->assembly, aname))
6075 if (i + 1 < arity) {
6095 else if (*p != '*') /* '*' means unknown lower bound */
6101 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6112 if (g_ascii_isspace (*p)) {
6119 return 0; /* missing assembly name */
6120 if (!assembly_name_to_aname (&info->assembly, p))
6126 if (info->assembly.name)
6129 // *w = 0; /* terminate class name */
6131 if (!info->name || !*info->name)
6135 /* add other consistency checks */
6140 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6142 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6146 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6148 gboolean type_resolve = FALSE;
6151 if (info->assembly.name) {
6152 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6154 /* then we must load the assembly ourselve - see #60439 */
6155 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6159 image = assembly->image;
6160 } else if (!image) {
6161 image = mono_defaults.corlib;
6164 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6165 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6166 image = mono_defaults.corlib;
6167 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6174 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6181 image = mono_defaults.corlib;
6184 klass = mono_class_from_name_case (image, info->name_space, info->name);
6186 klass = mono_class_from_name (image, info->name_space, info->name);
6189 for (mod = info->nested; mod; mod = mod->next) {
6192 mono_class_init (klass);
6193 nested = klass->nested_classes;
6196 klass = nested->data;
6198 if (g_strcasecmp (klass->name, mod->data) == 0)
6201 if (strcmp (klass->name, mod->data) == 0)
6205 nested = nested->next;
6212 mono_class_init (klass);
6214 if (info->type_arguments) {
6215 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6216 MonoReflectionType *the_type;
6220 for (i = 0; i < info->type_arguments->len; i++) {
6221 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6223 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6224 if (!type_args [i]) {
6230 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6232 instance = mono_reflection_bind_generic_parameters (
6233 the_type, info->type_arguments->len, type_args);
6240 klass = mono_class_from_mono_type (instance);
6243 for (mod = info->modifiers; mod; mod = mod->next) {
6244 modval = GPOINTER_TO_UINT (mod->data);
6245 if (!modval) { /* byref: must be last modifier */
6246 return &klass->this_arg;
6247 } else if (modval == -1) {
6248 klass = mono_ptr_class_get (&klass->byval_arg);
6249 } else { /* array rank */
6250 klass = mono_array_class_get (klass, modval);
6252 mono_class_init (klass);
6255 return &klass->byval_arg;
6259 * mono_reflection_get_type:
6260 * @image: a metadata context
6261 * @info: type description structure
6262 * @ignorecase: flag for case-insensitive string compares
6263 * @type_resolve: whenever type resolve was already tried
6265 * Build a MonoType from the type description in @info.
6270 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6273 MonoReflectionAssembly *assembly;
6277 type = mono_reflection_get_type_internal (image, info, ignorecase);
6280 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6287 *type_resolve = TRUE;
6290 /* Reconstruct the type name */
6291 fullName = g_string_new ("");
6292 if (info->name_space && (info->name_space [0] != '\0'))
6293 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6295 g_string_printf (fullName, info->name);
6296 for (mod = info->nested; mod; mod = mod->next)
6297 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6299 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6301 if (assembly->assembly->dynamic) {
6302 /* Enumerate all modules */
6303 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6307 if (abuilder->modules) {
6308 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6309 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6310 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6316 if (!type && abuilder->loaded_modules) {
6317 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6318 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6319 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6326 type = mono_reflection_get_type_internal (assembly->assembly->image,
6329 g_string_free (fullName, TRUE);
6334 free_type_info (MonoTypeNameParse *info)
6336 g_list_free (info->modifiers);
6337 g_list_free (info->nested);
6339 if (info->type_arguments) {
6342 for (i = 0; i < info->type_arguments->len; i++) {
6343 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6345 free_type_info (subinfo);
6348 g_ptr_array_free (info->type_arguments, TRUE);
6353 * mono_reflection_type_from_name:
6355 * @image: a metadata context (can be NULL).
6357 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6358 * it defaults to get the type from @image or, if @image is NULL or loading
6359 * from it fails, uses corlib.
6363 mono_reflection_type_from_name (char *name, MonoImage *image)
6365 MonoType *type = NULL;
6366 MonoTypeNameParse info;
6369 /* Make a copy since parse_type modifies its argument */
6370 tmp = g_strdup (name);
6372 /*g_print ("requested type %s\n", str);*/
6373 if (mono_reflection_parse_type (tmp, &info)) {
6374 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6378 free_type_info (&info);
6383 * mono_reflection_get_token:
6385 * Return the metadata token of OBJ which should be an object
6386 * representing a metadata element.
6389 mono_reflection_get_token (MonoObject *obj)
6394 klass = obj->vtable->klass;
6396 if (strcmp (klass->name, "MethodBuilder") == 0) {
6397 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6399 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6400 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6401 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6403 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6404 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6405 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6406 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6407 if (tb->generic_params) {
6408 g_assert_not_reached ();
6410 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6412 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6414 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6415 } else if (strcmp (klass->name, "MonoType") == 0) {
6416 MonoReflectionType *tb = (MonoReflectionType *)obj;
6417 token = mono_class_from_mono_type (tb->type)->type_token;
6418 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6419 strcmp (klass->name, "MonoMethod") == 0) {
6420 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6421 if (m->method->is_inflated) {
6422 g_assert_not_reached ();
6423 } else if (mono_method_signature (m->method)->generic_param_count) {
6424 g_assert_not_reached ();
6425 } else if (m->method->klass->generic_class) {
6426 g_assert_not_reached ();
6428 token = m->method->token;
6430 } else if (strcmp (klass->name, "MonoField") == 0) {
6431 MonoReflectionField *f = (MonoReflectionField*)obj;
6433 token = mono_class_get_field_token (f->field);
6434 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6435 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6437 token = mono_class_get_property_token (p->property);
6438 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6439 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6441 token = mono_class_get_event_token (p->event);
6442 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6443 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6445 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6446 } else if (strcmp (klass->name, "Module") == 0) {
6447 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6450 } else if (strcmp (klass->name, "Assembly") == 0) {
6451 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6453 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6454 MonoException *ex = mono_get_exception_not_implemented (msg);
6456 mono_raise_exception (ex);
6463 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6465 int slen, type = t->type;
6470 case MONO_TYPE_BOOLEAN: {
6471 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6476 case MONO_TYPE_CHAR:
6478 case MONO_TYPE_I2: {
6479 guint16 *val = g_malloc (sizeof (guint16));
6484 #if SIZEOF_VOID_P == 4
6490 case MONO_TYPE_I4: {
6491 guint32 *val = g_malloc (sizeof (guint32));
6496 #if SIZEOF_VOID_P == 8
6497 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6502 case MONO_TYPE_I8: {
6503 guint64 *val = g_malloc (sizeof (guint64));
6508 case MONO_TYPE_VALUETYPE:
6509 if (t->data.klass->enumtype) {
6510 type = t->data.klass->enum_basetype->type;
6513 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6516 case MONO_TYPE_STRING:
6517 if (*p == (char)0xFF) {
6521 slen = mono_metadata_decode_value (p, &p);
6523 return mono_string_new_len (mono_domain_get (), p, slen);
6524 case MONO_TYPE_CLASS: {
6527 if (*p == (char)0xFF) {
6532 slen = mono_metadata_decode_value (p, &p);
6533 n = g_memdup (p, slen + 1);
6535 t = mono_reflection_type_from_name (n, image);
6537 g_warning ("Cannot load type '%s'", n);
6541 return mono_type_get_object (mono_domain_get (), t);
6545 case MONO_TYPE_OBJECT: {
6548 MonoClass *subc = NULL;
6553 } else if (subt == 0x0E) {
6554 type = MONO_TYPE_STRING;
6556 } else if (subt == 0x55) {
6559 slen = mono_metadata_decode_value (p, &p);
6560 n = g_memdup (p, slen + 1);
6562 t = mono_reflection_type_from_name (n, image);
6564 g_warning ("Cannot load type '%s'", n);
6567 subc = mono_class_from_mono_type (t);
6568 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6569 MonoType simple_type = {{0}};
6570 simple_type.type = subt;
6571 subc = mono_class_from_mono_type (&simple_type);
6573 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6575 val = load_cattr_value (image, &subc->byval_arg, p, end);
6576 obj = mono_object_new (mono_domain_get (), subc);
6577 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6581 case MONO_TYPE_SZARRAY: {
6583 guint32 i, alen, basetype;
6586 if (alen == 0xffffffff) {
6590 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6591 basetype = t->data.klass->byval_arg.type;
6596 case MONO_TYPE_BOOLEAN:
6597 for (i = 0; i < alen; i++) {
6598 MonoBoolean val = *p++;
6599 mono_array_set (arr, MonoBoolean, i, val);
6602 case MONO_TYPE_CHAR:
6605 for (i = 0; i < alen; i++) {
6606 guint16 val = read16 (p);
6607 mono_array_set (arr, guint16, i, val);
6614 for (i = 0; i < alen; i++) {
6615 guint32 val = read32 (p);
6616 mono_array_set (arr, guint32, i, val);
6623 for (i = 0; i < alen; i++) {
6624 guint64 val = read64 (p);
6625 mono_array_set (arr, guint64, i, val);
6629 case MONO_TYPE_CLASS:
6630 case MONO_TYPE_OBJECT:
6631 case MONO_TYPE_STRING:
6632 for (i = 0; i < alen; i++) {
6633 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6634 mono_array_set (arr, gpointer, i, item);
6638 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6644 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6650 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6652 static MonoClass *klass;
6653 static MonoMethod *ctor;
6655 void *params [2], *unboxed;
6658 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6660 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6662 params [0] = mono_type_get_object (mono_domain_get (), t);
6664 retval = mono_object_new (mono_domain_get (), klass);
6665 unboxed = mono_object_unbox (retval);
6666 mono_runtime_invoke (ctor, unboxed, params, NULL);
6672 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6674 static MonoClass *klass;
6675 static MonoMethod *ctor;
6677 void *unboxed, *params [2];
6680 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6682 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6685 params [1] = typedarg;
6686 retval = mono_object_new (mono_domain_get (), klass);
6687 unboxed = mono_object_unbox (retval);
6688 mono_runtime_invoke (ctor, unboxed, params, NULL);
6694 type_is_reference (MonoType *type)
6696 switch (type->type) {
6697 case MONO_TYPE_BOOLEAN:
6698 case MONO_TYPE_CHAR:
6711 case MONO_TYPE_VALUETYPE:
6719 free_param_data (MonoMethodSignature *sig, void **params) {
6721 for (i = 0; i < sig->param_count; ++i) {
6722 if (!type_is_reference (sig->params [i]))
6723 g_free (params [i]);
6728 * Find the field index in the metadata FieldDef table.
6731 find_field_index (MonoClass *klass, MonoClassField *field) {
6734 for (i = 0; i < klass->field.count; ++i) {
6735 if (field == &klass->fields [i])
6736 return klass->field.first + 1 + i;
6742 * Find the property index in the metadata Property table.
6745 find_property_index (MonoClass *klass, MonoProperty *property) {
6748 for (i = 0; i < klass->property.count; ++i) {
6749 if (property == &klass->properties [i])
6750 return klass->property.first + 1 + i;
6756 * Find the event index in the metadata Event table.
6759 find_event_index (MonoClass *klass, MonoEvent *event) {
6762 for (i = 0; i < klass->event.count; ++i) {
6763 if (event == &klass->events [i])
6764 return klass->event.first + 1 + i;
6770 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6772 const char *p = data;
6774 guint32 i, j, num_named;
6778 mono_class_init (method->klass);
6781 attr = mono_object_new (mono_domain_get (), method->klass);
6782 mono_runtime_invoke (method, attr, NULL, NULL);
6786 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6789 /*g_print ("got attr %s\n", method->klass->name);*/
6791 /* Allocate using alloca so it gets GC tracking */
6792 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6796 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6797 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6801 attr = mono_object_new (mono_domain_get (), method->klass);
6802 mono_runtime_invoke (method, attr, params, NULL);
6803 free_param_data (method->signature, params);
6804 num_named = read16 (named);
6806 for (j = 0; j < num_named; j++) {
6808 gboolean is_boxed = FALSE;
6809 char *name, named_type, data_type;
6810 named_type = *named++;
6811 data_type = *named++; /* type of data */
6812 if (data_type == 0x51)
6815 if (data_type == 0x55) {
6818 type_len = mono_metadata_decode_blob_size (named, &named);
6819 type_name = g_malloc (type_len + 1);
6820 memcpy (type_name, named, type_len);
6821 type_name [type_len] = 0;
6823 /* FIXME: lookup the type and check type consistency */
6824 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6825 /* this seems to be the type of the element of the array */
6826 /* g_print ("skipping 0x%02x after prop\n", *named); */
6829 name_len = mono_metadata_decode_blob_size (named, &named);
6830 name = g_malloc (name_len + 1);
6831 memcpy (name, named, name_len);
6832 name [name_len] = 0;
6834 if (named_type == 0x53) {
6835 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6836 void *val = load_cattr_value (image, field->type, named, &named);
6837 mono_field_set_value (attr, field, val);
6838 if (!type_is_reference (field->type))
6840 } else if (named_type == 0x54) {
6843 MonoType *prop_type;
6845 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6846 /* can we have more that 1 arg in a custom attr named property? */
6847 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6848 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6849 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6850 mono_property_set_value (prop, attr, pparams, NULL);
6851 if (!type_is_reference (prop_type))
6852 g_free (pparams [0]);
6861 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6863 MonoArray *typedargs, *namedargs;
6864 MonoClass *attrklass;
6865 static MonoClass *klass;
6866 static MonoMethod *ctor;
6869 const char *p = data;
6871 guint32 i, j, num_named;
6874 mono_class_init (method->klass);
6877 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6879 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6881 domain = mono_domain_get ();
6883 /* This is for Attributes with no parameters */
6884 attr = mono_object_new (domain, klass);
6885 params [0] = mono_method_get_object (domain, method, NULL);
6886 params [1] = params [2] = NULL;
6887 mono_runtime_invoke (method, attr, params, NULL);
6891 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6894 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6898 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6899 MonoObject *obj, *typedarg;
6902 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6903 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6904 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6905 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6906 mono_array_set (typedargs, void*, i, typedarg);
6908 if (!type_is_reference (mono_method_signature (method)->params [i]))
6913 num_named = read16 (named);
6914 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6916 attrklass = method->klass;
6917 for (j = 0; j < num_named; j++) {
6919 char *name, named_type, data_type;
6920 named_type = *named++;
6921 data_type = *named++; /* type of data */
6922 if (data_type == 0x55) {
6925 type_len = mono_metadata_decode_blob_size (named, &named);
6926 type_name = g_malloc (type_len + 1);
6927 memcpy (type_name, named, type_len);
6928 type_name [type_len] = 0;
6930 /* FIXME: lookup the type and check type consistency */
6931 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6932 /* this seems to be the type of the element of the array */
6933 /* g_print ("skipping 0x%02x after prop\n", *named); */
6936 name_len = mono_metadata_decode_blob_size (named, &named);
6937 name = g_malloc (name_len + 1);
6938 memcpy (name, named, name_len);
6939 name [name_len] = 0;
6941 if (named_type == 0x53) {
6942 MonoObject *obj, *typedarg, *namedarg;
6943 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6944 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6946 minfo = mono_field_get_object (domain, NULL, field);
6947 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6948 typedarg = create_cattr_typed_arg (field->type, obj);
6949 namedarg = create_cattr_named_arg (minfo, typedarg);
6950 mono_array_set (namedargs, void*, j, namedarg);
6951 if (!type_is_reference (field->type))
6953 } else if (named_type == 0x54) {
6954 MonoObject *obj, *typedarg, *namedarg;
6955 MonoType *prop_type;
6957 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6959 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6960 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6961 minfo = mono_property_get_object (domain, NULL, prop);
6962 val = load_cattr_value (image, prop_type, named, &named);
6963 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6964 typedarg = create_cattr_typed_arg (prop_type, obj);
6965 namedarg = create_cattr_named_arg (minfo, typedarg);
6966 mono_array_set (namedargs, void*, j, namedarg);
6967 if (!type_is_reference (prop_type))
6972 attr = mono_object_new (domain, klass);
6973 params [0] = mono_method_get_object (domain, method, NULL);
6974 params [1] = typedargs;
6975 params [2] = namedargs;
6976 mono_runtime_invoke (ctor, attr, params, NULL);
6981 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6988 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6989 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6990 for (i = 0; i < cinfo->num_attrs; ++i) {
6991 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6992 mono_array_set (result, gpointer, i, attr);
6998 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7001 static MonoClass *klass;
7006 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7008 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7009 for (i = 0; i < cinfo->num_attrs; ++i) {
7010 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7011 mono_array_set (result, gpointer, i, attr);
7017 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7019 guint32 mtoken, i, len;
7020 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7022 MonoCustomAttrInfo *ainfo;
7023 GList *tmp, *list = NULL;
7026 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7028 i = mono_metadata_custom_attrs_from_index (image, idx);
7032 while (i < ca->rows) {
7033 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7035 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7038 len = g_list_length (list);
7041 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7042 ainfo->num_attrs = len;
7043 ainfo->image = image;
7044 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7045 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7046 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7047 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7048 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7049 mtoken |= MONO_TOKEN_METHOD_DEF;
7051 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7052 mtoken |= MONO_TOKEN_MEMBER_REF;
7055 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7058 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7059 if (!ainfo->attrs [i].ctor)
7060 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7061 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7062 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7063 ainfo->attrs [i].data = data;
7071 mono_custom_attrs_from_method (MonoMethod *method)
7073 MonoCustomAttrInfo *cinfo;
7076 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7078 idx = mono_method_get_index (method);
7079 idx <<= MONO_CUSTOM_ATTR_BITS;
7080 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7081 return mono_custom_attrs_from_index (method->klass->image, idx);
7085 mono_custom_attrs_from_class (MonoClass *klass)
7087 MonoCustomAttrInfo *cinfo;
7090 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7092 idx = mono_metadata_token_index (klass->type_token);
7093 idx <<= MONO_CUSTOM_ATTR_BITS;
7094 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7095 return mono_custom_attrs_from_index (klass->image, idx);
7099 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7101 MonoCustomAttrInfo *cinfo;
7104 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7106 idx = 1; /* there is only one assembly */
7107 idx <<= MONO_CUSTOM_ATTR_BITS;
7108 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7109 return mono_custom_attrs_from_index (assembly->image, idx);
7112 static MonoCustomAttrInfo*
7113 mono_custom_attrs_from_module (MonoImage *image)
7115 MonoCustomAttrInfo *cinfo;
7118 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7120 idx = 1; /* there is only one module */
7121 idx <<= MONO_CUSTOM_ATTR_BITS;
7122 idx |= MONO_CUSTOM_ATTR_MODULE;
7123 return mono_custom_attrs_from_index (image, idx);
7127 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7129 MonoCustomAttrInfo *cinfo;
7132 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7134 idx = find_property_index (klass, property);
7135 idx <<= MONO_CUSTOM_ATTR_BITS;
7136 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7137 return mono_custom_attrs_from_index (klass->image, idx);
7141 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7143 MonoCustomAttrInfo *cinfo;
7146 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7148 idx = find_event_index (klass, event);
7149 idx <<= MONO_CUSTOM_ATTR_BITS;
7150 idx |= MONO_CUSTOM_ATTR_EVENT;
7151 return mono_custom_attrs_from_index (klass->image, idx);
7155 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7157 MonoCustomAttrInfo *cinfo;
7160 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7162 idx = find_field_index (klass, field);
7163 idx <<= MONO_CUSTOM_ATTR_BITS;
7164 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7165 return mono_custom_attrs_from_index (klass->image, idx);
7169 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7172 guint32 i, idx, method_index;
7173 guint32 param_list, param_last, param_pos, found;
7175 MonoReflectionMethodAux *aux;
7177 if (method->klass->image->dynamic) {
7178 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7179 if (!aux || !aux->param_cattr)
7181 return aux->param_cattr [param];
7184 image = method->klass->image;
7185 method_index = mono_method_get_index (method);
7186 ca = &image->tables [MONO_TABLE_METHOD];
7188 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7189 /* FIXME FIXME FIXME */
7193 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7194 if (method_index == ca->rows) {
7195 ca = &image->tables [MONO_TABLE_PARAM];
7196 param_last = ca->rows + 1;
7198 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7199 ca = &image->tables [MONO_TABLE_PARAM];
7202 for (i = param_list; i < param_last; ++i) {
7203 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7204 if (param_pos == param) {
7212 idx <<= MONO_CUSTOM_ATTR_BITS;
7213 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7214 return mono_custom_attrs_from_index (image, idx);
7218 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7222 for (i = 0; i < ainfo->num_attrs; ++i) {
7223 klass = ainfo->attrs [i].ctor->klass;
7224 if (mono_class_has_parent (klass, attr_klass))
7231 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7238 for (i = 0; i < ainfo->num_attrs; ++i) {
7239 klass = ainfo->attrs [i].ctor->klass;
7240 if (mono_class_has_parent (klass, attr_klass)) {
7245 if (attr_index == -1)
7248 attrs = mono_custom_attrs_construct (ainfo);
7250 return mono_array_get (attrs, MonoObject*, attr_index);
7256 * mono_reflection_get_custom_attrs_info:
7257 * @obj: a reflection object handle
7259 * Return the custom attribute info for attributes defined for the
7260 * reflection handle @obj. The objects.
7263 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7266 MonoCustomAttrInfo *cinfo = NULL;
7268 klass = obj->vtable->klass;
7269 if (klass == mono_defaults.monotype_class) {
7270 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7271 klass = mono_class_from_mono_type (rtype->type);
7272 cinfo = mono_custom_attrs_from_class (klass);
7273 } else if (strcmp ("Assembly", klass->name) == 0) {
7274 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7275 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7276 } else if (strcmp ("Module", klass->name) == 0) {
7277 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7278 cinfo = mono_custom_attrs_from_module (module->image);
7279 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7280 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7281 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7282 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7283 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7284 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7285 } else if (strcmp ("MonoField", klass->name) == 0) {
7286 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7287 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7288 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7289 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7290 cinfo = mono_custom_attrs_from_method (rmethod->method);
7291 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7292 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7293 cinfo = mono_custom_attrs_from_method (method);
7294 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7295 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7296 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7297 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7298 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7299 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7300 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7301 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7302 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7303 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7304 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7305 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7306 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7307 } else { /* handle other types here... */
7308 g_error ("get custom attrs not yet supported for %s", klass->name);
7315 * mono_reflection_get_custom_attrs:
7316 * @obj: a reflection object handle
7318 * Return an array with all the custom attributes defined of the
7319 * reflection handle @obj. The objects are fully build.
7322 mono_reflection_get_custom_attrs (MonoObject *obj)
7325 MonoCustomAttrInfo *cinfo;
7327 cinfo = mono_reflection_get_custom_attrs_info (obj);
7329 result = mono_custom_attrs_construct (cinfo);
7331 mono_custom_attrs_free (cinfo);
7334 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7335 result = mono_array_new (mono_domain_get (), klass, 0);
7342 * mono_reflection_get_custom_attrs_data:
7343 * @obj: a reflection obj handle
7345 * Returns an array of System.Reflection.CustomAttributeData,
7346 * which include information about attributes reflected on
7347 * types loaded using the Reflection Only methods
7350 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7353 MonoCustomAttrInfo *cinfo;
7355 cinfo = mono_reflection_get_custom_attrs_info (obj);
7357 result = mono_custom_attrs_data_construct (cinfo);
7359 mono_custom_attrs_free (cinfo);
7362 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7363 result = mono_array_new (mono_domain_get (), klass, 0);
7369 static MonoMethodSignature*
7370 parameters_to_signature (MonoArray *parameters) {
7371 MonoMethodSignature *sig;
7374 count = parameters? mono_array_length (parameters): 0;
7376 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7377 sig->param_count = count;
7378 sig->sentinelpos = -1; /* FIXME */
7379 for (i = 0; i < count; ++i) {
7380 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7381 sig->params [i] = pt->type;
7386 static MonoMethodSignature*
7387 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7388 MonoMethodSignature *sig;
7390 sig = parameters_to_signature (ctor->parameters);
7391 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7392 sig->ret = &mono_defaults.void_class->byval_arg;
7396 static MonoMethodSignature*
7397 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7398 MonoMethodSignature *sig;
7400 sig = parameters_to_signature (method->parameters);
7401 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7402 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7403 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7407 static MonoMethodSignature*
7408 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7409 MonoMethodSignature *sig;
7411 sig = parameters_to_signature (method->parameters);
7412 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7413 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7414 sig->generic_param_count = 0;
7419 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7421 MonoClass *klass = mono_object_class (prop);
7422 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7423 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7424 *name = mono_string_to_utf8 (pb->name);
7425 *type = pb->type->type;
7427 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7428 *name = g_strdup (p->property->name);
7429 if (p->property->get)
7430 *type = mono_method_signature (p->property->get)->ret;
7432 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7437 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7439 MonoClass *klass = mono_object_class (field);
7440 if (strcmp (klass->name, "FieldBuilder") == 0) {
7441 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7442 *name = mono_string_to_utf8 (fb->name);
7443 *type = fb->type->type;
7445 MonoReflectionField *f = (MonoReflectionField *)field;
7446 *name = g_strdup (f->field->name);
7447 *type = f->field->type;
7452 * Encode a value in a custom attribute stream of bytes.
7453 * The value to encode is either supplied as an object in argument val
7454 * (valuetypes are boxed), or as a pointer to the data in the
7456 * @type represents the type of the value
7457 * @buffer is the start of the buffer
7458 * @p the current position in the buffer
7459 * @buflen contains the size of the buffer and is used to return the new buffer size
7460 * if this needs to be realloced.
7461 * @retbuffer and @retp return the start and the position of the buffer
7464 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7466 MonoTypeEnum simple_type;
7468 if ((p-buffer) + 10 >= *buflen) {
7471 newbuf = g_realloc (buffer, *buflen);
7472 p = newbuf + (p-buffer);
7476 argval = ((char*)arg + sizeof (MonoObject));
7477 simple_type = type->type;
7479 switch (simple_type) {
7480 case MONO_TYPE_BOOLEAN:
7485 case MONO_TYPE_CHAR:
7488 swap_with_size (p, argval, 2, 1);
7494 swap_with_size (p, argval, 4, 1);
7500 swap_with_size (p, argval, 8, 1);
7503 case MONO_TYPE_VALUETYPE:
7504 if (type->data.klass->enumtype) {
7505 simple_type = type->data.klass->enum_basetype->type;
7508 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7511 case MONO_TYPE_STRING: {
7518 str = mono_string_to_utf8 ((MonoString*)arg);
7519 slen = strlen (str);
7520 if ((p-buffer) + 10 + slen >= *buflen) {
7524 newbuf = g_realloc (buffer, *buflen);
7525 p = newbuf + (p-buffer);
7528 mono_metadata_encode_value (slen, p, &p);
7529 memcpy (p, str, slen);
7534 case MONO_TYPE_CLASS: {
7542 k = mono_object_class (arg);
7543 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7544 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7545 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7547 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7548 slen = strlen (str);
7549 if ((p-buffer) + 10 + slen >= *buflen) {
7553 newbuf = g_realloc (buffer, *buflen);
7554 p = newbuf + (p-buffer);
7557 mono_metadata_encode_value (slen, p, &p);
7558 memcpy (p, str, slen);
7563 case MONO_TYPE_SZARRAY: {
7565 MonoClass *eclass, *arg_eclass;
7568 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7571 len = mono_array_length ((MonoArray*)arg);
7573 *p++ = (len >> 8) & 0xff;
7574 *p++ = (len >> 16) & 0xff;
7575 *p++ = (len >> 24) & 0xff;
7577 *retbuffer = buffer;
7578 eclass = type->data.klass;
7579 arg_eclass = mono_object_class (arg)->element_class;
7580 if (eclass->valuetype && arg_eclass->valuetype) {
7581 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7582 int elsize = mono_class_array_element_size (eclass);
7583 for (i = 0; i < len; ++i) {
7584 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7588 for (i = 0; i < len; ++i) {
7589 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7594 /* it may be a boxed value or a Type */
7595 case MONO_TYPE_OBJECT: {
7601 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7606 klass = mono_object_class (arg);
7608 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7611 } else if (klass->enumtype) {
7613 } else if (klass == mono_defaults.string_class) {
7614 simple_type = MONO_TYPE_STRING;
7617 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7618 *p++ = simple_type = klass->byval_arg.type;
7621 g_error ("unhandled type in custom attr");
7623 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7624 slen = strlen (str);
7625 if ((p-buffer) + 10 + slen >= *buflen) {
7629 newbuf = g_realloc (buffer, *buflen);
7630 p = newbuf + (p-buffer);
7633 mono_metadata_encode_value (slen, p, &p);
7634 memcpy (p, str, slen);
7637 simple_type = klass->enum_basetype->type;
7641 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7644 *retbuffer = buffer;
7648 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7651 /* Preallocate a large enough buffer */
7652 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7653 char *str = type_get_qualified_name (type, NULL);
7659 len += strlen (name);
7661 if ((p-buffer) + 20 + len >= *buflen) {
7665 newbuf = g_realloc (buffer, *buflen);
7666 p = newbuf + (p-buffer);
7670 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7671 char *str = type_get_qualified_name (type, NULL);
7672 int slen = strlen (str);
7676 * This seems to be optional...
7679 mono_metadata_encode_value (slen, p, &p);
7680 memcpy (p, str, slen);
7683 } else if (type->type == MONO_TYPE_OBJECT) {
7685 } else if (type->type == MONO_TYPE_CLASS) {
7686 /* it should be a type: encode_cattr_value () has the check */
7689 mono_metadata_encode_value (type->type, p, &p);
7690 if (type->type == MONO_TYPE_SZARRAY)
7691 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7693 len = strlen (name);
7694 mono_metadata_encode_value (len, p, &p);
7695 memcpy (p, name, len);
7697 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7699 *retbuffer = buffer;
7703 * mono_reflection_get_custom_attrs_blob:
7704 * @ctor: custom attribute constructor
7705 * @ctorArgs: arguments o the constructor
7711 * Creates the blob of data that needs to be saved in the metadata and that represents
7712 * the custom attributed described by @ctor, @ctorArgs etc.
7713 * Returns: a Byte array representing the blob of data.
7716 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7719 MonoMethodSignature *sig;
7724 MONO_ARCH_SAVE_REGS;
7726 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7727 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7729 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7731 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7733 p = buffer = g_malloc (buflen);
7734 /* write the prolog */
7737 for (i = 0; i < sig->param_count; ++i) {
7738 arg = mono_array_get (ctorArgs, MonoObject*, i);
7739 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7743 i += mono_array_length (properties);
7745 i += mono_array_length (fields);
7747 *p++ = (i >> 8) & 0xff;
7750 for (i = 0; i < mono_array_length (properties); ++i) {
7754 prop = mono_array_get (properties, gpointer, i);
7755 get_prop_name_and_type (prop, &pname, &ptype);
7756 *p++ = 0x54; /* PROPERTY signature */
7757 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7764 for (i = 0; i < mono_array_length (fields); ++i) {
7768 field = mono_array_get (fields, gpointer, i);
7769 get_field_name_and_type (field, &fname, &ftype);
7770 *p++ = 0x53; /* FIELD signature */
7771 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7776 g_assert (p - buffer <= buflen);
7777 buflen = p - buffer;
7778 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7779 p = mono_array_addr (result, char, 0);
7780 memcpy (p, buffer, buflen);
7782 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7788 * mono_reflection_setup_internal_class:
7789 * @tb: a TypeBuilder object
7791 * Creates a MonoClass that represents the TypeBuilder.
7792 * This is a trick that lets us simplify a lot of reflection code
7793 * (and will allow us to support Build and Run assemblies easier).
7796 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7798 MonoClass *klass, *parent;
7800 MONO_ARCH_SAVE_REGS;
7802 mono_loader_lock ();
7805 /* check so we can compile corlib correctly */
7806 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7807 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7808 parent = tb->parent->type->data.klass;
7810 parent = my_mono_class_from_mono_type (tb->parent->type);
7816 /* the type has already being created: it means we just have to change the parent */
7817 if (tb->type.type) {
7818 klass = mono_class_from_mono_type (tb->type.type);
7819 klass->parent = NULL;
7820 /* fool mono_class_setup_parent */
7821 g_free (klass->supertypes);
7822 klass->supertypes = NULL;
7823 mono_class_setup_parent (klass, parent);
7824 mono_class_setup_mono_type (klass);
7825 mono_loader_unlock ();
7829 klass = g_new0 (MonoClass, 1);
7831 klass->image = &tb->module->dynamic_image->image;
7833 klass->inited = 1; /* we lie to the runtime */
7834 klass->name = mono_string_to_utf8 (tb->name);
7835 klass->name_space = mono_string_to_utf8 (tb->nspace);
7836 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7837 klass->flags = tb->attrs;
7839 klass->element_class = klass;
7840 klass->reflection_info = tb; /* need to pin. */
7842 /* Put into cache so mono_class_get () will find it */
7843 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7845 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7846 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7848 if (parent != NULL) {
7849 mono_class_setup_parent (klass, parent);
7850 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7851 const char *old_n = klass->name;
7852 /* trick to get relative numbering right when compiling corlib */
7853 klass->name = "BuildingObject";
7854 mono_class_setup_parent (klass, mono_defaults.object_class);
7855 klass->name = old_n;
7858 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7859 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7860 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7861 klass->instance_size = sizeof (MonoObject);
7862 klass->size_inited = 1;
7863 mono_class_setup_vtable_general (klass, NULL, 0);
7866 mono_class_setup_mono_type (klass);
7868 mono_class_setup_supertypes (klass);
7871 * FIXME: handle interfaces.
7874 tb->type.type = &klass->byval_arg;
7876 if (tb->nesting_type) {
7877 g_assert (tb->nesting_type->type);
7878 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7881 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7883 mono_loader_unlock ();
7887 * mono_reflection_setup_generic_class:
7888 * @tb: a TypeBuilder object
7890 * Setup the generic class before adding the first generic parameter.
7893 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7897 MONO_ARCH_SAVE_REGS;
7899 klass = my_mono_class_from_mono_type (tb->type.type);
7900 if (tb->generic_container)
7903 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7904 tb->generic_container->klass = klass;
7906 tb->generic_container->context.container = tb->generic_container;
7910 * mono_reflection_create_generic_class:
7911 * @tb: a TypeBuilder object
7913 * Creates the generic class after all generic parameters have been added.
7916 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7921 MONO_ARCH_SAVE_REGS;
7923 klass = my_mono_class_from_mono_type (tb->type.type);
7925 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7927 if (klass->generic_container || (count == 0))
7930 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7932 klass->generic_container = tb->generic_container;
7934 klass->generic_container->type_argc = count;
7935 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7937 for (i = 0; i < count; i++) {
7938 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7939 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7940 g_assert (klass->generic_container->type_params [i].owner);
7943 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7947 * mono_reflection_create_internal_class:
7948 * @tb: a TypeBuilder object
7950 * Actually create the MonoClass that is associated with the TypeBuilder.
7953 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7957 MONO_ARCH_SAVE_REGS;
7959 klass = my_mono_class_from_mono_type (tb->type.type);
7961 mono_loader_lock ();
7962 if (klass->enumtype && klass->enum_basetype == NULL) {
7963 MonoReflectionFieldBuilder *fb;
7966 g_assert (tb->fields != NULL);
7967 g_assert (mono_array_length (tb->fields) >= 1);
7969 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7971 klass->enum_basetype = fb->type->type;
7972 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7973 if (!klass->element_class)
7974 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7977 * get the element_class from the current corlib.
7979 ec = default_class_from_mono_type (klass->enum_basetype);
7980 klass->instance_size = ec->instance_size;
7981 klass->size_inited = 1;
7983 * this is almost safe to do with enums and it's needed to be able
7984 * to create objects of the enum type (for use in SetConstant).
7986 /* FIXME: Does this mean enums can't have method overrides ? */
7987 mono_class_setup_vtable_general (klass, NULL, 0);
7989 mono_loader_unlock ();
7992 static MonoMarshalSpec*
7993 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7994 MonoReflectionMarshal *minfo)
7996 MonoMarshalSpec *res;
7998 res = g_new0 (MonoMarshalSpec, 1);
7999 res->native = minfo->type;
8001 switch (minfo->type) {
8002 case MONO_NATIVE_LPARRAY:
8003 res->data.array_data.elem_type = minfo->eltype;
8004 if (minfo->has_size) {
8005 res->data.array_data.param_num = minfo->param_num;
8006 res->data.array_data.num_elem = minfo->count;
8007 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8010 res->data.array_data.param_num = -1;
8011 res->data.array_data.num_elem = -1;
8012 res->data.array_data.elem_mult = -1;
8016 case MONO_NATIVE_BYVALTSTR:
8017 case MONO_NATIVE_BYVALARRAY:
8018 res->data.array_data.num_elem = minfo->count;
8021 case MONO_NATIVE_CUSTOM:
8022 if (minfo->marshaltyperef)
8023 res->data.custom_data.custom_name =
8024 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8026 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8036 MonoReflectionMarshal*
8037 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8038 MonoMarshalSpec *spec)
8040 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8041 MonoReflectionMarshal *minfo;
8044 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8045 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8046 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8047 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8050 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8051 minfo->type = spec->native;
8053 switch (minfo->type) {
8054 case MONO_NATIVE_LPARRAY:
8055 minfo->eltype = spec->data.array_data.elem_type;
8056 minfo->count = spec->data.array_data.num_elem;
8057 minfo->param_num = spec->data.array_data.param_num;
8060 case MONO_NATIVE_BYVALTSTR:
8061 case MONO_NATIVE_BYVALARRAY:
8062 minfo->count = spec->data.array_data.num_elem;
8065 case MONO_NATIVE_CUSTOM:
8066 if (spec->data.custom_data.custom_name) {
8067 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8069 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8071 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8073 if (spec->data.custom_data.cookie)
8074 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8085 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8086 ReflectionMethodBuilder *rmb,
8087 MonoMethodSignature *sig)
8090 MonoMethodNormal *pm;
8091 MonoMarshalSpec **specs;
8092 MonoReflectionMethodAux *method_aux;
8095 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8096 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8097 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8099 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8101 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8103 pm = (MonoMethodNormal*)m;
8106 m->flags = rmb->attrs;
8107 m->iflags = rmb->iattrs;
8108 m->name = mono_string_to_utf8 (rmb->name);
8112 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8114 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8115 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8118 m->signature->pinvoke = 1;
8119 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8120 m->signature->pinvoke = 1;
8122 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8124 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8125 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8127 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8129 if (klass->image->dynamic)
8130 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8133 } else if (!m->klass->dummy &&
8134 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8135 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8136 MonoMethodHeader *header;
8138 gint32 max_stack, i;
8139 gint32 num_locals = 0;
8140 gint32 num_clauses = 0;
8144 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8145 code_size = rmb->ilgen->code_len;
8146 max_stack = rmb->ilgen->max_stack;
8147 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8148 if (rmb->ilgen->ex_handlers)
8149 num_clauses = method_count_clauses (rmb->ilgen);
8152 code = mono_array_addr (rmb->code, guint8, 0);
8153 code_size = mono_array_length (rmb->code);
8154 /* we probably need to run a verifier on the code... */
8164 header = g_malloc0 (sizeof (MonoMethodHeader) +
8165 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8166 header->code_size = code_size;
8167 header->code = g_malloc (code_size);
8168 memcpy ((char*)header->code, code, code_size);
8169 header->max_stack = max_stack;
8170 header->init_locals = rmb->init_locals;
8171 header->num_locals = num_locals;
8173 for (i = 0; i < num_locals; ++i) {
8174 MonoReflectionLocalBuilder *lb =
8175 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8177 header->locals [i] = g_new0 (MonoType, 1);
8178 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8181 header->num_clauses = num_clauses;
8183 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8184 rmb->ilgen, num_clauses);
8187 pm->header = header;
8190 if (rmb->generic_params) {
8191 int count = mono_array_length (rmb->generic_params);
8192 MonoGenericContainer *container;
8194 pm->generic_container = container = rmb->generic_container;
8195 container->type_argc = count;
8196 container->type_params = g_new0 (MonoGenericParam, count);
8198 for (i = 0; i < count; i++) {
8199 MonoReflectionGenericParam *gp =
8200 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8202 container->type_params [i] = *gp->type.type->data.generic_param;
8207 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8211 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8213 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8214 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8215 for (i = 0; i < rmb->nrefs; ++i)
8216 data [i + 1] = rmb->refs [i];
8221 /* Parameter info */
8224 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8225 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8226 for (i = 0; i <= m->signature->param_count; ++i) {
8227 MonoReflectionParamBuilder *pb;
8228 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8229 if ((i > 0) && (pb->attrs)) {
8230 /* Make a copy since it might point to a shared type structure */
8231 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)));
8232 m->signature->params [i - 1]->attrs = pb->attrs;
8235 if (pb->def_value) {
8236 MonoDynamicImage *assembly;
8237 guint32 idx, def_type, len;
8241 if (!method_aux->param_defaults) {
8242 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8243 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8245 assembly = (MonoDynamicImage*)klass->image;
8246 idx = encode_constant (assembly, pb->def_value, &def_type);
8247 /* Copy the data from the blob since it might get realloc-ed */
8248 p = assembly->blob.data + idx;
8249 len = mono_metadata_decode_blob_size (p, &p2);
8251 method_aux->param_defaults [i] = g_malloc (len);
8252 method_aux->param_default_types [i] = def_type;
8253 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8257 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8259 if (!method_aux->param_cattr)
8260 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8261 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8267 /* Parameter marshalling */
8270 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8271 MonoReflectionParamBuilder *pb;
8272 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8273 if (pb->marshal_info) {
8275 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8276 specs [pb->position] =
8277 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8281 if (specs != NULL) {
8283 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8284 method_aux->param_marshall = specs;
8287 if (klass->image->dynamic && method_aux)
8288 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8294 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8296 ReflectionMethodBuilder rmb;
8297 MonoMethodSignature *sig;
8299 sig = ctor_builder_to_signature (mb);
8301 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8303 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8304 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8306 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8307 /* ilgen is no longer needed */
8315 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8317 ReflectionMethodBuilder rmb;
8318 MonoMethodSignature *sig;
8320 sig = method_builder_to_signature (mb);
8322 reflection_methodbuilder_from_method_builder (&rmb, mb);
8324 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8325 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8327 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8328 /* ilgen is no longer needed */
8334 static MonoClassField*
8335 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8337 MonoClassField *field;
8344 field = g_new0 (MonoClassField, 1);
8346 field->name = mono_string_to_utf8 (fb->name);
8348 /* FIXME: handle type modifiers */
8349 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8350 field->type->attrs = fb->attrs;
8352 field->type = fb->type->type;
8354 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8355 field->data = mono_array_addr (fb->rva_data, char, 0);
8356 if (fb->offset != -1)
8357 field->offset = fb->offset;
8358 field->parent = klass;
8360 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8362 if (fb->def_value) {
8363 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8364 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8365 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8366 /* Copy the data from the blob since it might get realloc-ed */
8367 p = assembly->blob.data + idx;
8368 len = mono_metadata_decode_blob_size (p, &p2);
8370 field->data = g_malloc (len);
8371 memcpy ((gpointer)field->data, p, len);
8378 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8382 MonoReflectionTypeBuilder *tb = NULL;
8383 MonoGenericClass *gclass, *cached;
8384 MonoInflatedGenericClass *igclass;
8385 MonoDynamicGenericClass *dgclass = NULL;
8386 gboolean is_dynamic = FALSE;
8391 klass = mono_class_from_mono_type (type->type);
8392 if (!klass->generic_container && !klass->generic_class &&
8393 !(klass->nested_in && klass->nested_in->generic_container))
8396 mono_loader_lock ();
8398 domain = mono_object_domain (type);
8400 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8401 tb = (MonoReflectionTypeBuilder *) type;
8403 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8405 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8406 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8407 MonoReflectionType *rgt = rgi->generic_type;
8409 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8410 tb = (MonoReflectionTypeBuilder *) rgt;
8412 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8415 icount = klass->interface_count;
8419 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8420 igclass = &dgclass->generic_class;
8421 gclass = &igclass->generic_class;
8422 gclass->is_dynamic = TRUE;
8423 gclass->is_inflated = TRUE;
8425 igclass = g_new0 (MonoInflatedGenericClass, 1);
8426 gclass = &igclass->generic_class;
8427 gclass->is_inflated = TRUE;
8430 gclass->inst = g_new0 (MonoGenericInst, 1);
8432 gclass->inst->type_argc = type_argc;
8433 gclass->inst->type_argv = types;
8434 gclass->inst->is_reference = 1;
8436 for (i = 0; i < gclass->inst->type_argc; ++i) {
8437 if (!gclass->inst->is_open)
8438 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8439 if (gclass->inst->is_reference)
8440 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8443 gclass->container_class = klass;
8445 if (klass->generic_class) {
8446 MonoGenericClass *kgclass = klass->generic_class;
8447 MonoGenericClass *ogclass = gclass;
8449 ogclass->context = g_new0 (MonoGenericContext, 1);
8450 ogclass->context->container = gclass->container_class->generic_container;
8451 ogclass->context->gclass = gclass;
8454 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8455 igclass = &dgclass->generic_class;
8456 gclass = &igclass->generic_class;
8457 gclass->is_dynamic = TRUE;
8458 gclass->is_inflated = TRUE;
8460 igclass = g_new0 (MonoInflatedGenericClass, 1);
8461 gclass = &igclass->generic_class;
8462 gclass->is_inflated = TRUE;
8465 gclass->inst = g_new0 (MonoGenericInst, 1);
8467 gclass->inst->type_argc = kgclass->inst->type_argc;
8468 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8469 gclass->inst->is_reference = 1;
8471 for (i = 0; i < gclass->inst->type_argc; i++) {
8472 MonoType *t = kgclass->inst->type_argv [i];
8474 t = mono_class_inflate_generic_type (t, ogclass->context);
8476 if (!gclass->inst->is_open)
8477 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8478 if (gclass->inst->is_reference)
8479 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8481 gclass->inst->type_argv [i] = t;
8484 gclass->container_class = kgclass->container_class;
8487 geninst = g_new0 (MonoType, 1);
8488 geninst->type = MONO_TYPE_GENERICINST;
8490 cached = mono_metadata_lookup_generic_class (gclass);
8493 mono_loader_unlock ();
8494 geninst->data.generic_class = cached;
8498 geninst->data.generic_class = gclass;
8500 igclass->parent = parent;
8502 gclass->context = g_new0 (MonoGenericContext, 1);
8503 gclass->context->container = gclass->container_class->generic_container;
8504 gclass->context->gclass = gclass;
8507 dgclass->ifaces = g_new0 (MonoType *, icount);
8508 dgclass->count_ifaces = icount;
8510 for (i = 0; i < icount; i++) {
8511 MonoReflectionType *itype;
8514 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8516 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8517 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8518 if (!dgclass->ifaces [i])
8519 dgclass->ifaces [i] = itype->type;
8523 mono_loader_unlock ();
8529 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8531 MonoClass *klass, *pklass = NULL;
8532 MonoReflectionType *parent = NULL;
8533 MonoType *the_parent = NULL, *geninst;
8534 MonoReflectionTypeBuilder *tb = NULL;
8535 MonoGenericClass *gclass;
8538 domain = mono_object_domain (type);
8539 klass = mono_class_from_mono_type (type->type);
8541 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8542 tb = (MonoReflectionTypeBuilder *) type;
8545 parent = tb->parent;
8546 pklass = mono_class_from_mono_type (parent->type);
8549 pklass = klass->parent;
8551 parent = mono_type_get_object (domain, &pklass->byval_arg);
8552 else if (klass->generic_class) {
8553 MonoInflatedGenericClass *igclass;
8554 igclass = mono_get_inflated_generic_class (klass->generic_class);
8555 if (igclass->parent) {
8556 parent = mono_type_get_object (domain, igclass->parent);
8557 pklass = mono_class_from_mono_type (igclass->parent);
8562 if (pklass && pklass->generic_class)
8563 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8565 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8569 gclass = geninst->data.generic_class;
8575 do_mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types, MonoType *parent)
8578 MonoGenericClass *gclass, *cached;
8579 MonoInflatedGenericClass *igclass;
8583 klass = mono_class_from_mono_type (type);
8584 if (!klass->generic_container && !klass->generic_class &&
8585 !(klass->nested_in && klass->nested_in->generic_container))
8588 mono_loader_lock ();
8590 icount = klass->interface_count;
8592 igclass = g_new0 (MonoInflatedGenericClass, 1);
8593 gclass = &igclass->generic_class;
8594 gclass->is_inflated = TRUE;
8596 gclass->inst = g_new0 (MonoGenericInst, 1);
8597 gclass->inst->type_argc = type_argc;
8598 gclass->inst->type_argv = types;
8599 gclass->inst->is_reference = 1;
8601 for (i = 0; i < gclass->inst->type_argc; ++i) {
8602 if (!gclass->inst->is_open)
8603 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8604 if (gclass->inst->is_reference)
8605 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8608 gclass->container_class = klass;
8610 if (klass->generic_class) {
8611 MonoGenericClass *kgclass = klass->generic_class;
8612 MonoGenericClass *ogclass = gclass;
8614 gclass->context = g_new0 (MonoGenericContext, 1);
8615 gclass->context->container = gclass->container_class->generic_container;
8616 gclass->context->gclass = gclass;
8618 igclass = g_new0 (MonoInflatedGenericClass, 1);
8619 gclass = &igclass->generic_class;
8620 gclass->is_inflated = TRUE;
8622 gclass->inst = g_new0 (MonoGenericInst, 1);
8623 gclass->inst->type_argc = kgclass->inst->type_argc;
8624 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8625 gclass->inst->is_reference = 1;
8627 for (i = 0; i < gclass->inst->type_argc; i++) {
8628 MonoType *t = kgclass->inst->type_argv [i];
8630 t = mono_class_inflate_generic_type (t, ogclass->context);
8632 if (!gclass->inst->is_open)
8633 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8634 if (gclass->inst->is_reference)
8635 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8637 gclass->inst->type_argv [i] = t;
8640 gclass->container_class = kgclass->container_class;
8643 geninst = g_new0 (MonoType, 1);
8644 geninst->type = MONO_TYPE_GENERICINST;
8646 cached = mono_metadata_lookup_generic_class (gclass);
8649 mono_loader_unlock ();
8650 geninst->data.generic_class = cached;
8654 geninst->data.generic_class = gclass;
8656 igclass->parent = parent;
8658 gclass->context = g_new0 (MonoGenericContext, 1);
8659 gclass->context->container = gclass->container_class->generic_container;
8660 gclass->context->gclass = gclass;
8662 mono_loader_unlock ();
8668 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8670 MonoClass *klass, *pklass = NULL;
8671 MonoType *parent = NULL, *the_parent = NULL, *geninst;
8672 MonoGenericClass *gclass;
8674 klass = mono_class_from_mono_type (type);
8676 pklass = klass->parent;
8678 parent = &pklass->byval_arg;
8679 else if (klass->generic_class) {
8680 MonoInflatedGenericClass *igclass;
8681 igclass = mono_get_inflated_generic_class (klass->generic_class);
8682 if (igclass->parent) {
8683 parent = igclass->parent;
8684 pklass = mono_class_from_mono_type (igclass->parent);
8688 if (pklass && pklass->generic_class)
8689 the_parent = mono_class_bind_generic_parameters (parent, type_argc, types);
8691 geninst = do_mono_class_bind_generic_parameters (type, type_argc, types, the_parent);
8695 gclass = geninst->data.generic_class;
8700 static inline MonoType*
8701 dup_type (const MonoType *original)
8703 MonoType *r = g_new0 (MonoType, 1);
8705 r->attrs = original->attrs;
8706 r->byref = original->byref;
8707 if (original->type == MONO_TYPE_PTR)
8708 r->data.type = dup_type (original->data.type);
8709 mono_stats.generics_metadata_size += sizeof (MonoType);
8713 MonoReflectionMethod*
8714 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8716 MonoMethod *method, *inflated;
8717 MonoReflectionMethodBuilder *mb = NULL;
8718 MonoGenericContainer *container;
8719 MonoGenericMethod *gmethod;
8720 MonoGenericContext *context;
8721 MonoGenericInst *ginst;
8724 MONO_ARCH_SAVE_REGS;
8725 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8726 MonoReflectionTypeBuilder *tb;
8729 mb = (MonoReflectionMethodBuilder *) rmethod;
8730 tb = (MonoReflectionTypeBuilder *) mb->type;
8731 klass = mono_class_from_mono_type (tb->type.type);
8733 method = methodbuilder_to_mono_method (klass, mb);
8735 method = rmethod->method;
8738 method = mono_get_inflated_method (method);
8740 count = mono_method_signature (method)->generic_param_count;
8741 if (count != mono_array_length (types))
8744 container = ((MonoMethodNormal*) method)->generic_container;
8745 g_assert (container);
8747 if (!container->method_hash)
8748 container->method_hash = g_hash_table_new (
8749 (GHashFunc) mono_metadata_generic_method_hash,
8750 (GCompareFunc) mono_metadata_generic_method_equal);
8752 ginst = g_new0 (MonoGenericInst,1 );
8753 ginst->type_argc = count;
8754 ginst->type_argv = g_new0 (MonoType *, count);
8755 ginst->is_reference = 1;
8756 for (i = 0; i < count; i++) {
8757 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8758 ginst->type_argv [i] = dup_type (garg->type);
8760 if (!ginst->is_open)
8761 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8762 if (ginst->is_reference)
8763 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8765 ginst = mono_metadata_lookup_generic_inst (ginst);
8767 gmethod = g_new0 (MonoGenericMethod, 1);
8768 gmethod->generic_class = method->klass->generic_class;
8769 gmethod->container = container;
8770 gmethod->inst = ginst;
8772 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8776 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8779 gmethod->reflection_info = rmethod;
8781 context = g_new0 (MonoGenericContext, 1);
8782 context->container = container;
8783 context->gclass = method->klass->generic_class;
8784 context->gmethod = gmethod;
8786 if (method->is_inflated)
8787 method = ((MonoMethodInflated *) method)->declaring;
8789 inflated = mono_class_inflate_generic_method (method, context);
8790 g_hash_table_insert (container->method_hash, gmethod, inflated);
8792 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8796 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8798 MonoGenericMethod *gmethod;
8799 MonoInflatedGenericClass *gclass;
8800 MonoGenericContext *context;
8803 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8805 gmethod = g_new0 (MonoGenericMethod, 1);
8806 gmethod->generic_class = &gclass->generic_class;
8807 gmethod->inst = g_new0 (MonoGenericInst, 1);
8808 gmethod->reflection_info = obj;
8810 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8811 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8813 for (i = 0; i < gmethod->inst->type_argc; i++) {
8814 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8815 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8817 g_assert (gparam->pklass);
8818 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8821 context = g_new0 (MonoGenericContext, 1);
8822 context->container = gclass->generic_class.container_class->generic_container;
8823 context->gclass = &gclass->generic_class;
8824 context->gmethod = gmethod;
8826 return mono_class_inflate_generic_method (method, context);
8830 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8835 klass = mono_class_from_mono_type (type->type.type);
8837 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8838 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8839 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8840 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8841 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8842 method = ((MonoReflectionMethod *) obj)->method;
8844 method = NULL; /* prevent compiler warning */
8845 g_assert_not_reached ();
8848 return inflate_mono_method (type, method, obj);
8852 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8853 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8856 MonoGenericClass *gclass;
8857 MonoDynamicGenericClass *dgclass;
8858 MonoClass *klass, *gklass, *pklass;
8861 MONO_ARCH_SAVE_REGS;
8863 klass = mono_class_from_mono_type (type->type.type);
8864 gclass = type->type.type->data.generic_class;
8866 g_assert (gclass->is_dynamic);
8867 dgclass = (MonoDynamicGenericClass *) gclass;
8869 if (dgclass->initialized)
8872 gklass = gclass->container_class;
8873 mono_class_init (gklass);
8875 if (dgclass->generic_class.parent)
8876 pklass = mono_class_from_mono_type (dgclass->generic_class.parent);
8878 pklass = gklass->parent;
8880 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8881 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8882 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8883 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8884 dgclass->count_events = events ? mono_array_length (events) : 0;
8886 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8887 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8888 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8889 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8890 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8892 for (i = 0; i < dgclass->count_methods; i++) {
8893 MonoObject *obj = mono_array_get (methods, gpointer, i);
8895 dgclass->methods [i] = inflate_method (type, obj);
8898 for (i = 0; i < dgclass->count_ctors; i++) {
8899 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8901 dgclass->ctors [i] = inflate_method (type, obj);
8904 for (i = 0; i < dgclass->count_fields; i++) {
8905 MonoObject *obj = mono_array_get (fields, gpointer, i);
8906 MonoClassField *field;
8907 MonoInflatedField *ifield;
8909 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8910 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8911 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8912 field = ((MonoReflectionField *) obj)->field;
8914 field = NULL; /* prevent compiler warning */
8915 g_assert_not_reached ();
8918 ifield = g_new0 (MonoInflatedField, 1);
8919 ifield->generic_type = field->type;
8920 ifield->reflection_info = obj;
8922 dgclass->fields [i] = *field;
8923 dgclass->fields [i].parent = klass;
8924 dgclass->fields [i].generic_info = ifield;
8925 dgclass->fields [i].type = mono_class_inflate_generic_type (
8926 field->type, dgclass->generic_class.generic_class.context);
8929 for (i = 0; i < dgclass->count_properties; i++) {
8930 MonoObject *obj = mono_array_get (properties, gpointer, i);
8931 MonoProperty *property = &dgclass->properties [i];
8933 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8934 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8936 property->parent = klass;
8937 property->attrs = pb->attrs;
8938 property->name = mono_string_to_utf8 (pb->name);
8940 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8942 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8943 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8944 *property = *((MonoReflectionProperty *) obj)->property;
8947 property->get = inflate_mono_method (type, property->get, NULL);
8949 property->set = inflate_mono_method (type, property->set, NULL);
8951 g_assert_not_reached ();
8954 for (i = 0; i < dgclass->count_events; i++) {
8955 MonoObject *obj = mono_array_get (events, gpointer, i);
8956 MonoEvent *event = &dgclass->events [i];
8958 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8959 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8961 event->parent = klass;
8962 event->attrs = eb->attrs;
8963 event->name = mono_string_to_utf8 (eb->name);
8965 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8966 if (eb->remove_method)
8967 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8968 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8969 *event = *((MonoReflectionEvent *) obj)->event;
8972 event->add = inflate_mono_method (type, event->add, NULL);
8974 event->remove = inflate_mono_method (type, event->remove, NULL);
8976 g_assert_not_reached ();
8979 dgclass->initialized = TRUE;
8983 ensure_runtime_vtable (MonoClass *klass)
8985 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8986 int i, num, j, onum;
8987 MonoMethod **overrides;
8989 if (!tb || klass->wastypebuilder)
8992 ensure_runtime_vtable (klass->parent);
8994 num = tb->ctors? mono_array_length (tb->ctors): 0;
8995 num += tb->num_methods;
8996 klass->method.count = num;
8997 klass->methods = g_new (MonoMethod*, num);
8998 num = tb->ctors? mono_array_length (tb->ctors): 0;
8999 for (i = 0; i < num; ++i)
9000 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
9001 num = tb->num_methods;
9003 for (i = 0; i < num; ++i)
9004 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
9006 if (tb->interfaces) {
9007 klass->interface_count = mono_array_length (tb->interfaces);
9008 klass->interfaces = g_new (MonoClass*, klass->interface_count);
9009 for (i = 0; i < klass->interface_count; ++i) {
9010 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
9011 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
9015 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9016 for (i = 0; i < klass->method.count; ++i)
9017 klass->methods [i]->slot = i;
9019 if (!((MonoDynamicImage*)klass->image)->run)
9020 /* No need to create a generic vtable */
9026 for (i = 0; i < tb->num_methods; ++i) {
9027 MonoReflectionMethodBuilder *mb =
9028 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9029 if (mb->override_method)
9034 overrides = g_new0 (MonoMethod*, onum * 2);
9038 for (i = 0; i < tb->num_methods; ++i) {
9039 MonoReflectionMethodBuilder *mb =
9040 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9041 if (mb->override_method) {
9042 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9043 overrides [onum * 2] =
9044 mb->override_method->method;
9045 overrides [onum * 2 + 1] =
9048 g_assert (mb->mhandle);
9055 mono_class_setup_vtable_general (klass, overrides, onum);
9060 typebuilder_setup_fields (MonoClass *klass)
9062 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9063 MonoReflectionFieldBuilder *fb;
9064 MonoClassField *field;
9069 klass->field.count = tb->num_fields;
9070 klass->field.first = 0;
9071 klass->field.last = klass->field.count;
9073 if (!klass->field.count)
9076 klass->fields = g_new0 (MonoClassField, klass->field.count);
9078 for (i = 0; i < klass->field.count; ++i) {
9079 fb = mono_array_get (tb->fields, gpointer, i);
9080 field = &klass->fields [i];
9081 field->name = mono_string_to_utf8 (fb->name);
9083 /* FIXME: handle type modifiers */
9084 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9085 field->type->attrs = fb->attrs;
9087 field->type = fb->type->type;
9089 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9090 field->data = mono_array_addr (fb->rva_data, char, 0);
9091 if (fb->offset != -1)
9092 field->offset = fb->offset;
9093 field->parent = klass;
9095 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9097 if (fb->def_value) {
9098 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9099 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9100 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9101 /* Copy the data from the blob since it might get realloc-ed */
9102 p = assembly->blob.data + idx;
9103 len = mono_metadata_decode_blob_size (p, &p2);
9105 field->data = g_malloc (len);
9106 memcpy ((gpointer)field->data, p, len);
9109 mono_class_layout_fields (klass);
9113 typebuilder_setup_properties (MonoClass *klass)
9115 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9116 MonoReflectionPropertyBuilder *pb;
9119 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9120 klass->property.first = 0;
9121 klass->property.last = klass->property.count;
9123 klass->properties = g_new0 (MonoProperty, klass->property.count);
9124 for (i = 0; i < klass->property.count; ++i) {
9125 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9126 klass->properties [i].parent = klass;
9127 klass->properties [i].attrs = pb->attrs;
9128 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9130 klass->properties [i].get = pb->get_method->mhandle;
9132 klass->properties [i].set = pb->set_method->mhandle;
9136 MonoReflectionEvent *
9137 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9139 MonoEvent *event = g_new0 (MonoEvent, 1);
9143 klass = my_mono_class_from_mono_type (tb->type.type);
9145 event->parent = klass;
9146 event->attrs = eb->attrs;
9147 event->name = mono_string_to_utf8 (eb->name);
9149 event->add = eb->add_method->mhandle;
9150 if (eb->remove_method)
9151 event->remove = eb->remove_method->mhandle;
9152 if (eb->raise_method)
9153 event->raise = eb->raise_method->mhandle;
9155 if (eb->other_methods) {
9156 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9157 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9158 MonoReflectionMethodBuilder *mb =
9159 mono_array_get (eb->other_methods,
9160 MonoReflectionMethodBuilder*, j);
9161 event->other [j] = mb->mhandle;
9165 return mono_event_get_object (mono_object_domain (tb), klass, event);
9169 typebuilder_setup_events (MonoClass *klass)
9171 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9172 MonoReflectionEventBuilder *eb;
9175 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9176 klass->event.first = 0;
9177 klass->event.last = klass->event.count;
9179 klass->events = g_new0 (MonoEvent, klass->event.count);
9180 for (i = 0; i < klass->event.count; ++i) {
9181 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9182 klass->events [i].parent = klass;
9183 klass->events [i].attrs = eb->attrs;
9184 klass->events [i].name = mono_string_to_utf8 (eb->name);
9186 klass->events [i].add = eb->add_method->mhandle;
9187 if (eb->remove_method)
9188 klass->events [i].remove = eb->remove_method->mhandle;
9189 if (eb->raise_method)
9190 klass->events [i].raise = eb->raise_method->mhandle;
9192 if (eb->other_methods) {
9193 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9194 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9195 MonoReflectionMethodBuilder *mb =
9196 mono_array_get (eb->other_methods,
9197 MonoReflectionMethodBuilder*, j);
9198 klass->events [i].other [j] = mb->mhandle;
9205 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9209 MonoReflectionType* res;
9212 MONO_ARCH_SAVE_REGS;
9214 domain = mono_object_domain (tb);
9215 klass = my_mono_class_from_mono_type (tb->type.type);
9217 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9220 * we need to lock the domain because the lock will be taken inside
9221 * So, we need to keep the locking order correct.
9223 mono_domain_lock (domain);
9224 mono_loader_lock ();
9225 if (klass->wastypebuilder) {
9226 mono_loader_unlock ();
9227 mono_domain_unlock (domain);
9228 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9231 * Fields to set in klass:
9232 * the various flags: delegate/unicode/contextbound etc.
9234 klass->flags = tb->attrs;
9235 klass->has_cctor = 1;
9236 klass->has_finalize = 1;
9238 if (!((MonoDynamicImage*)klass->image)->run) {
9239 if (klass->generic_container) {
9240 /* FIXME: The code below can't handle generic classes */
9241 klass->wastypebuilder = TRUE;
9242 mono_loader_unlock ();
9243 mono_domain_unlock (domain);
9244 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9248 /* enums are done right away */
9249 if (!klass->enumtype)
9250 ensure_runtime_vtable (klass);
9253 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9254 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9255 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9259 /* fields and object layout */
9260 if (klass->parent) {
9261 if (!klass->parent->size_inited)
9262 mono_class_init (klass->parent);
9263 klass->instance_size += klass->parent->instance_size;
9264 klass->class_size += klass->parent->class_size;
9265 klass->min_align = klass->parent->min_align;
9266 /* if the type has no fields we won't call the field_setup
9267 * routine which sets up klass->has_references.
9269 klass->has_references |= klass->parent->has_references;
9271 klass->instance_size = sizeof (MonoObject);
9272 klass->min_align = 1;
9275 /* FIXME: handle packing_size and instance_size */
9276 typebuilder_setup_fields (klass);
9278 typebuilder_setup_properties (klass);
9280 typebuilder_setup_events (klass);
9282 klass->wastypebuilder = TRUE;
9283 mono_loader_unlock ();
9284 mono_domain_unlock (domain);
9286 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9287 g_assert (res != (MonoReflectionType*)tb);
9292 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9294 MonoGenericParam *param;
9297 MONO_ARCH_SAVE_REGS;
9299 param = g_new0 (MonoGenericParam, 1);
9301 if (gparam->mbuilder) {
9302 if (!gparam->mbuilder->generic_container)
9303 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9304 param->owner = gparam->mbuilder->generic_container;
9305 } else if (gparam->tbuilder) {
9306 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9307 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9312 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9313 if (gparam->index >= count)
9316 container = nesting->generic_container;
9317 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9320 g_assert (container);
9321 param->owner = container;
9324 param->method = NULL;
9325 param->name = mono_string_to_utf8 (gparam->name);
9326 param->num = gparam->index;
9328 image = &gparam->tbuilder->module->dynamic_image->image;
9329 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9331 param->pklass->reflection_info = gparam;
9333 gparam->type.type = g_new0 (MonoType, 1);
9334 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9335 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9336 gparam->type.type->data.generic_param = param;
9340 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9342 MonoDynamicImage *assembly = sig->module->dynamic_image;
9343 guint32 na = mono_array_length (sig->arguments);
9344 guint32 buflen, i, size;
9348 MONO_ARCH_SAVE_REGS;
9350 p = buf = g_malloc (size = 10 + na * 10);
9352 mono_metadata_encode_value (0x07, p, &p);
9353 mono_metadata_encode_value (na, p, &p);
9354 for (i = 0; i < na; ++i) {
9355 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9356 encode_reflection_type (assembly, type, p, &p);
9360 g_assert (buflen < size);
9361 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9362 p = mono_array_addr (result, char, 0);
9363 memcpy (p, buf, buflen);
9370 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9372 MonoDynamicImage *assembly = sig->module->dynamic_image;
9373 guint32 na = mono_array_length (sig->arguments);
9374 guint32 buflen, i, size;
9378 MONO_ARCH_SAVE_REGS;
9380 p = buf = g_malloc (size = 10 + na * 10);
9382 mono_metadata_encode_value (0x06, p, &p);
9383 for (i = 0; i < na; ++i) {
9384 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9385 encode_reflection_type (assembly, type, p, &p);
9389 g_assert (buflen < size);
9390 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9391 p = mono_array_addr (result, char, 0);
9392 memcpy (p, buf, buflen);
9399 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9401 ReflectionMethodBuilder rmb;
9402 MonoMethodSignature *sig;
9405 sig = dynamic_method_to_signature (mb);
9407 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9410 * Resolve references.
9412 rmb.nrefs = mb->nrefs;
9413 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9414 for (i = 0; i < mb->nrefs; ++i) {
9415 MonoClass *handle_class;
9416 gpointer ref = resolve_object (mb->module->image,
9417 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9420 mono_raise_exception (mono_get_exception_type_load (NULL));
9427 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9431 /* ilgen is no longer needed */
9436 * mono_reflection_lookup_dynamic_token:
9438 * Finish the Builder object pointed to by TOKEN and return the corresponding
9439 * runtime structure. HANDLE_CLASS is set to the class required by
9443 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9445 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9448 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9451 return resolve_object (image, obj, handle_class);
9455 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9457 gpointer result = NULL;
9459 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9460 result = mono_string_intern ((MonoString*)obj);
9461 *handle_class = NULL;
9463 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9464 MonoReflectionType *tb = (MonoReflectionType*)obj;
9465 result = mono_class_from_mono_type (tb->type);
9466 *handle_class = mono_defaults.typehandle_class;
9468 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
9469 result = ((MonoReflectionMethod*)obj)->method;
9470 *handle_class = mono_defaults.methodhandle_class;
9472 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
9473 result = ((MonoReflectionMethod*)obj)->method;
9474 *handle_class = mono_defaults.methodhandle_class;
9476 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9477 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9478 result = mb->mhandle;
9480 /* Type is not yet created */
9481 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9483 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9486 * Hopefully this has been filled in by calling CreateType() on the
9490 * TODO: This won't work if the application finishes another
9491 * TypeBuilder instance instead of this one.
9493 result = mb->mhandle;
9495 *handle_class = mono_defaults.methodhandle_class;
9496 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9497 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9499 result = cb->mhandle;
9501 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9503 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9504 result = cb->mhandle;
9506 *handle_class = mono_defaults.methodhandle_class;
9507 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9508 result = ((MonoReflectionField*)obj)->field;
9509 *handle_class = mono_defaults.fieldhandle_class;
9511 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9512 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9513 result = fb->handle;
9516 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9518 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9519 result = fb->handle;
9521 *handle_class = mono_defaults.fieldhandle_class;
9522 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9523 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9526 klass = tb->type.type->data.klass;
9527 if (klass->wastypebuilder) {
9528 /* Already created */
9532 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9533 result = tb->type.type->data.klass;
9536 *handle_class = mono_defaults.typehandle_class;
9537 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9538 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9539 MonoMethodSignature *sig;
9542 if (helper->arguments)
9543 nargs = mono_array_length (helper->arguments);
9547 sig = mono_metadata_signature_alloc (image, nargs);
9548 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9549 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9551 if (helper->call_conv == 0) /* unmanaged */
9552 sig->call_convention = helper->unmanaged_call_conv - 1;
9554 if (helper->call_conv & 0x02)
9555 sig->call_convention = MONO_CALL_VARARG;
9557 sig->call_convention = MONO_CALL_DEFAULT;
9559 sig->param_count = nargs;
9560 /* TODO: Copy type ? */
9561 sig->ret = helper->return_type->type;
9562 for (i = 0; i < nargs; ++i) {
9563 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9564 sig->params [i] = rt->type;
9568 *handle_class = NULL;
9570 g_print (obj->vtable->klass->name);
9571 g_assert_not_reached ();
9577 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9578 const static guint32 declsec_flags_map[] = {
9579 0x00000000, /* empty */
9580 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9581 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9582 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9583 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9584 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9585 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9586 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9587 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9588 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9589 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9590 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9591 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9592 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9593 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9594 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9595 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9596 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9597 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9601 * Returns flags that includes all available security action associated to the handle.
9602 * @token: metadata token (either for a class or a method)
9603 * @image: image where resides the metadata.
9606 mono_declsec_get_flags (MonoImage *image, guint32 token)
9608 guint32 index = mono_metadata_declsec_from_index (image, token);
9609 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9614 for (i = index; i < t->rows; i++) {
9615 guint32 cols [MONO_DECL_SECURITY_SIZE];
9617 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9618 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9621 action = cols [MONO_DECL_SECURITY_ACTION];
9622 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9623 result |= declsec_flags_map [action];
9625 g_assert_not_reached ();
9632 * Get the security actions (in the form of flags) associated with the specified method.
9634 * @method: The method for which we want the declarative security flags.
9635 * Return the declarative security flags for the method (only).
9637 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9638 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9641 mono_declsec_flags_from_method (MonoMethod *method)
9643 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9644 /* FIXME: No cache (for the moment) */
9645 guint32 idx = mono_method_get_index (method);
9646 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9647 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9648 return mono_declsec_get_flags (method->klass->image, idx);
9654 * Get the security actions (in the form of flags) associated with the specified class.
9656 * @klass: The class for which we want the declarative security flags.
9657 * Return the declarative security flags for the class.
9659 * Note: We cache the flags inside the MonoClass structure as this will get
9660 * called very often (at least for each method).
9663 mono_declsec_flags_from_class (MonoClass *klass)
9665 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9666 if (!klass->declsec_flags) {
9667 guint32 idx = mono_metadata_token_index (klass->type_token);
9668 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9669 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9670 /* we cache the flags on classes */
9671 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9673 return klass->declsec_flags;
9679 * Get the security actions (in the form of flags) associated with the specified assembly.
9681 * @assembly: The assembly for which we want the declarative security flags.
9682 * Return the declarative security flags for the assembly.
9685 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9687 guint32 idx = 1; /* there is only one assembly */
9688 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9689 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9690 return mono_declsec_get_flags (assembly->image, idx);
9695 * Fill actions for the specific index (which may either be an encoded class token or
9696 * an encoded method token) from the metadata image.
9697 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9700 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9701 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9703 MonoBoolean result = FALSE;
9705 guint32 cols [MONO_DECL_SECURITY_SIZE];
9706 int index = mono_metadata_declsec_from_index (image, token);
9709 t = &image->tables [MONO_TABLE_DECLSECURITY];
9710 for (i = index; i < t->rows; i++) {
9711 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9713 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9716 /* if present only replace (class) permissions with method permissions */
9717 /* if empty accept either class or method permissions */
9718 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9719 if (!actions->demand.blob) {
9720 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9721 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9722 actions->demand.blob = (char*) (blob + 2);
9723 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9726 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9727 if (!actions->noncasdemand.blob) {
9728 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9729 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9730 actions->noncasdemand.blob = (char*) (blob + 2);
9731 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9734 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9735 if (!actions->demandchoice.blob) {
9736 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9737 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9738 actions->demandchoice.blob = (char*) (blob + 2);
9739 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9749 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9750 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9752 guint32 idx = mono_metadata_token_index (klass->type_token);
9753 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9754 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9755 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9759 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9760 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9762 guint32 idx = mono_method_get_index (method);
9763 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9764 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9765 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9769 * Collect all actions (that requires to generate code in mini) assigned for
9770 * the specified method.
9771 * Note: Don't use the content of actions if the function return FALSE.
9774 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9776 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9777 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9778 MonoBoolean result = FALSE;
9781 /* quick exit if no declarative security is present in the metadata */
9782 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9785 /* we want the original as the wrapper is "free" of the security informations */
9786 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9787 method = mono_marshal_method_from_wrapper (method);
9792 /* First we look for method-level attributes */
9793 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9794 mono_class_init (method->klass);
9795 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9797 result = mono_declsec_get_method_demands_params (method, demands,
9798 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9801 /* Here we use (or create) the class declarative cache to look for demands */
9802 flags = mono_declsec_flags_from_class (method->klass);
9805 mono_class_init (method->klass);
9806 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9808 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9809 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9812 /* The boolean return value is used as a shortcut in case nothing needs to
9813 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9819 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9821 * Note: Don't use the content of actions if the function return FALSE.
9824 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9826 MonoBoolean result = FALSE;
9829 /* quick exit if no declarative security is present in the metadata */
9830 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9833 /* we want the original as the wrapper is "free" of the security informations */
9834 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9835 method = mono_marshal_method_from_wrapper (method);
9840 /* results are independant - zeroize both */
9841 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9842 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9844 /* First we look for method-level attributes */
9845 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9846 mono_class_init (method->klass);
9848 result = mono_declsec_get_method_demands_params (method, cmethod,
9849 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9852 /* Here we use (or create) the class declarative cache to look for demands */
9853 flags = mono_declsec_flags_from_class (method->klass);
9854 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9855 mono_class_init (method->klass);
9857 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9858 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9865 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9867 * @klass The inherited class - this is the class that provides the security check (attributes)
9869 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9871 * Note: Don't use the content of actions if the function return FALSE.
9874 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9876 MonoBoolean result = FALSE;
9879 /* quick exit if no declarative security is present in the metadata */
9880 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9883 /* Here we use (or create) the class declarative cache to look for demands */
9884 flags = mono_declsec_flags_from_class (klass);
9885 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9886 mono_class_init (klass);
9887 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9889 result |= mono_declsec_get_class_demands_params (klass, demands,
9890 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9897 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9899 * Note: Don't use the content of actions if the function return FALSE.
9902 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9904 /* quick exit if no declarative security is present in the metadata */
9905 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9908 /* we want the original as the wrapper is "free" of the security informations */
9909 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9910 method = mono_marshal_method_from_wrapper (method);
9915 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9916 mono_class_init (method->klass);
9917 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9919 return mono_declsec_get_method_demands_params (method, demands,
9920 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9927 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9929 guint32 cols [MONO_DECL_SECURITY_SIZE];
9933 int index = mono_metadata_declsec_from_index (image, token);
9937 t = &image->tables [MONO_TABLE_DECLSECURITY];
9938 for (i = index; i < t->rows; i++) {
9939 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9941 /* shortcut - index are ordered */
9942 if (token != cols [MONO_DECL_SECURITY_PARENT])
9945 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9946 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9947 entry->blob = (char*) (metadata + 2);
9948 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9957 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9959 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9960 guint32 idx = mono_method_get_index (method);
9961 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9962 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9963 return get_declsec_action (method->klass->image, idx, action, entry);
9969 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9972 guint32 flags = mono_declsec_flags_from_class (klass);
9973 if (declsec_flags_map [action] & flags) {
9974 guint32 idx = mono_metadata_token_index (klass->type_token);
9975 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9976 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9977 return get_declsec_action (klass->image, idx, action, entry);
9983 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9985 guint32 idx = 1; /* there is only one assembly */
9986 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9987 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9989 return get_declsec_action (assembly->image, idx, action, entry);
9993 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9995 MonoObject *res, *exc;
9997 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9998 static MonoMethod *method = NULL;
10000 if (!System_Reflection_Emit_TypeBuilder) {
10001 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
10002 g_assert (System_Reflection_Emit_TypeBuilder);
10004 if (method == NULL) {
10005 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
10010 * The result of mono_type_get_object () might be a System.MonoType but we
10011 * need a TypeBuilder so use klass->reflection_info.
10013 g_assert (klass->reflection_info);
10014 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10016 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10018 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10022 return *(MonoBoolean*)mono_object_unbox (res);