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, lasterr, 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 = 21 + nparams * 20 + notypes * 20;
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 & 0xf;
1299 rmb->lasterr = mb->charset & 0x40;
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 int charset = mb->charset & 0xf;
1381 int lasterr = mb->charset & 0x40;
1382 int best_fit_mapping = mb->charset & 0x30;
1383 int throw_on_unmappable = mb->charset & 0x3000;
1384 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1386 alloc_table (table, table->rows);
1387 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1388 /* map CharSet values to on-disk values */
1390 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr | best_fit_mapping | throw_on_unmappable;
1391 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1392 name = mono_string_to_utf8 (mb->dllentry);
1393 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1395 name = mono_string_to_utf8 (mb->dll);
1396 moduleref = string_heap_insert (&assembly->sheap, name);
1398 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1399 table = &assembly->tables [MONO_TABLE_MODULEREF];
1401 alloc_table (table, table->rows);
1402 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1403 values [MONO_IMPLMAP_SCOPE] = table->rows;
1407 if (mb->override_method) {
1408 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1410 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1412 alloc_table (table, table->rows);
1413 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1414 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1415 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1417 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1418 switch (mono_metadata_token_table (tok)) {
1419 case MONO_TABLE_MEMBERREF:
1420 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1422 case MONO_TABLE_METHOD:
1423 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1426 g_assert_not_reached ();
1428 values [MONO_METHODIMPL_DECLARATION] = tok;
1431 if (mb->generic_params) {
1432 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1433 table->rows += mono_array_length (mb->generic_params);
1434 alloc_table (table, table->rows);
1435 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1436 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1438 mono_image_get_generic_param_info (
1439 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1446 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1448 ReflectionMethodBuilder rmb;
1450 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1452 mono_image_basic_method (&rmb, assembly);
1453 mb->table_idx = *rmb.table_idx;
1457 type_get_fully_qualified_name (MonoType *type) {
1458 char *name, *result;
1462 name = mono_type_get_name (type);
1463 klass = my_mono_class_from_mono_type (type);
1464 ta = klass->image->assembly;
1466 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1467 name, ta->aname.name,
1468 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1469 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1470 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1476 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1480 klass = my_mono_class_from_mono_type (type);
1482 return mono_type_get_name (type);
1483 ta = klass->image->assembly;
1484 if (ta == ass || klass->image == mono_defaults.corlib)
1485 return mono_type_get_name (type);
1487 return type_get_fully_qualified_name (type);
1491 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1493 char blob_size [64];
1494 char *b = blob_size;
1499 if (!assembly->save)
1502 p = buf = g_malloc (64);
1504 mono_metadata_encode_value (0x06, p, &p);
1505 /* encode custom attributes before the type */
1506 encode_type (assembly, type, p, &p);
1507 g_assert (p-buf < 64);
1508 mono_metadata_encode_value (p-buf, b, &b);
1509 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1515 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1517 char blob_size [64];
1518 char *b = blob_size;
1523 p = buf = g_malloc (64);
1525 mono_metadata_encode_value (0x06, p, &p);
1526 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1527 /* encode custom attributes before the type */
1528 encode_reflection_type (assembly, fb->type, p, &p);
1529 g_assert (p-buf < 64);
1530 mono_metadata_encode_value (p-buf, b, &b);
1531 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1537 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1538 char blob_size [64];
1539 char *b = blob_size;
1542 guint32 idx = 0, len = 0, dummy = 0;
1544 p = buf = g_malloc (64);
1546 *ret_type = MONO_TYPE_CLASS;
1548 box_val = (char*)&dummy;
1550 box_val = ((char*)val) + sizeof (MonoObject);
1551 *ret_type = val->vtable->klass->byval_arg.type;
1554 switch (*ret_type) {
1555 case MONO_TYPE_BOOLEAN:
1560 case MONO_TYPE_CHAR:
1575 case MONO_TYPE_VALUETYPE:
1576 if (val->vtable->klass->enumtype) {
1577 *ret_type = val->vtable->klass->enum_basetype->type;
1580 g_error ("we can't encode valuetypes");
1581 case MONO_TYPE_CLASS:
1583 case MONO_TYPE_STRING: {
1584 MonoString *str = (MonoString*)val;
1585 /* there is no signature */
1586 len = str->length * 2;
1587 mono_metadata_encode_value (len, b, &b);
1588 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1590 char *swapped = g_malloc (2 * mono_string_length (str));
1591 const char *p = (const char*)mono_string_chars (str);
1593 swap_with_size (swapped, p, 2, mono_string_length (str));
1594 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1598 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1605 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1608 /* there is no signature */
1609 mono_metadata_encode_value (len, b, &b);
1610 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1611 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1612 swap_with_size (blob_size, box_val, len, 1);
1613 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1615 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1623 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1624 char blob_size [64];
1625 char *b = blob_size;
1626 char *p, *buf, *str;
1627 guint32 idx, len, bufsize = 256;
1629 p = buf = g_malloc (bufsize);
1631 mono_metadata_encode_value (minfo->type, p, &p);
1633 switch (minfo->type) {
1634 case MONO_NATIVE_BYVALTSTR:
1635 case MONO_NATIVE_BYVALARRAY:
1636 mono_metadata_encode_value (minfo->count, p, &p);
1638 case MONO_NATIVE_LPARRAY:
1639 if (minfo->eltype || minfo->has_size) {
1640 mono_metadata_encode_value (minfo->eltype, p, &p);
1641 if (minfo->has_size) {
1642 if (minfo->param_num != -1)
1643 mono_metadata_encode_value (minfo->param_num, p, &p);
1645 mono_metadata_encode_value (0, p, &p);
1646 if (minfo->count != -1)
1647 mono_metadata_encode_value (minfo->count, p, &p);
1649 mono_metadata_encode_value (0, p, &p);
1651 /* LAMESPEC: ElemMult is undocumented */
1652 if (minfo->param_num != -1)
1653 mono_metadata_encode_value (1, p, &p);
1655 mono_metadata_encode_value (0, p, &p);
1659 case MONO_NATIVE_CUSTOM:
1661 str = mono_string_to_utf8 (minfo->guid);
1663 mono_metadata_encode_value (len, p, &p);
1664 memcpy (p, str, len);
1668 mono_metadata_encode_value (0, p, &p);
1670 if (minfo->marshaltype) {
1671 str = mono_string_to_utf8 (minfo->marshaltype);
1673 mono_metadata_encode_value (len, p, &p);
1674 if (p + len >= buf + bufsize) {
1677 buf = g_realloc (buf, bufsize);
1680 memcpy (p, str, len);
1684 mono_metadata_encode_value (0, p, &p);
1686 if (minfo->marshaltyperef) {
1687 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1689 mono_metadata_encode_value (len, p, &p);
1690 if (p + len >= buf + bufsize) {
1693 buf = g_realloc (buf, bufsize);
1696 memcpy (p, str, len);
1700 mono_metadata_encode_value (0, p, &p);
1702 if (minfo->mcookie) {
1703 str = mono_string_to_utf8 (minfo->mcookie);
1705 mono_metadata_encode_value (len, p, &p);
1706 if (p + len >= buf + bufsize) {
1709 buf = g_realloc (buf, bufsize);
1712 memcpy (p, str, len);
1716 mono_metadata_encode_value (0, p, &p);
1723 mono_metadata_encode_value (len, b, &b);
1724 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1730 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1732 MonoDynamicTable *table;
1736 /* maybe this fixup should be done in the C# code */
1737 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1738 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1739 table = &assembly->tables [MONO_TABLE_FIELD];
1740 fb->table_idx = table->next_idx ++;
1741 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1742 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1743 name = mono_string_to_utf8 (fb->name);
1744 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1746 values [MONO_FIELD_FLAGS] = fb->attrs;
1747 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1749 if (fb->offset != -1) {
1750 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1752 alloc_table (table, table->rows);
1753 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1754 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1755 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1757 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1758 guint32 field_type = 0;
1759 table = &assembly->tables [MONO_TABLE_CONSTANT];
1761 alloc_table (table, table->rows);
1762 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1763 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1764 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1765 values [MONO_CONSTANT_TYPE] = field_type;
1766 values [MONO_CONSTANT_PADDING] = 0;
1768 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1770 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1772 alloc_table (table, table->rows);
1773 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1774 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1776 * We store it in the code section because it's simpler for now.
1779 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1781 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1782 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1784 if (fb->marshal_info) {
1785 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1787 alloc_table (table, table->rows);
1788 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1789 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1790 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1795 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1799 char *b = blob_size;
1800 guint32 nparams = 0;
1801 MonoReflectionMethodBuilder *mb = fb->get_method;
1802 MonoReflectionMethodBuilder *smb = fb->set_method;
1803 guint32 idx, i, size;
1805 if (mb && mb->parameters)
1806 nparams = mono_array_length (mb->parameters);
1807 if (!mb && smb && smb->parameters)
1808 nparams = mono_array_length (smb->parameters) - 1;
1809 size = 24 + nparams * 10;
1810 buf = p = g_malloc (size);
1813 mono_metadata_encode_value (nparams, p, &p);
1815 encode_reflection_type (assembly, mb->rtype, p, &p);
1816 for (i = 0; i < nparams; ++i) {
1817 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1818 encode_reflection_type (assembly, pt, p, &p);
1821 /* the property type is the last param */
1822 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1823 for (i = 0; i < nparams; ++i) {
1824 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1825 encode_reflection_type (assembly, pt, p, &p);
1829 encode_reflection_type (assembly, fb->type, p, &p);
1833 g_assert (p - buf < size);
1834 mono_metadata_encode_value (p-buf, b, &b);
1835 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1841 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1843 MonoDynamicTable *table;
1846 guint num_methods = 0;
1850 * we need to set things in the following tables:
1851 * PROPERTYMAP (info already filled in _get_type_info ())
1852 * PROPERTY (rows already preallocated in _get_type_info ())
1853 * METHOD (method info already done with the generic method code)
1856 table = &assembly->tables [MONO_TABLE_PROPERTY];
1857 pb->table_idx = table->next_idx ++;
1858 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1859 name = mono_string_to_utf8 (pb->name);
1860 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1862 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1863 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1865 /* FIXME: we still don't handle 'other' methods */
1866 if (pb->get_method) num_methods ++;
1867 if (pb->set_method) num_methods ++;
1869 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1870 table->rows += num_methods;
1871 alloc_table (table, table->rows);
1873 if (pb->get_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1880 if (pb->set_method) {
1881 semaidx = table->next_idx ++;
1882 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1883 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1884 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1885 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1890 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1892 MonoDynamicTable *table;
1895 guint num_methods = 0;
1899 * we need to set things in the following tables:
1900 * EVENTMAP (info already filled in _get_type_info ())
1901 * EVENT (rows already preallocated in _get_type_info ())
1902 * METHOD (method info already done with the generic method code)
1905 table = &assembly->tables [MONO_TABLE_EVENT];
1906 eb->table_idx = table->next_idx ++;
1907 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1908 name = mono_string_to_utf8 (eb->name);
1909 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1911 values [MONO_EVENT_FLAGS] = eb->attrs;
1912 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1915 * FIXME: we still don't handle 'other' methods
1917 if (eb->add_method) num_methods ++;
1918 if (eb->remove_method) num_methods ++;
1919 if (eb->raise_method) num_methods ++;
1921 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1922 table->rows += num_methods;
1923 alloc_table (table, table->rows);
1925 if (eb->add_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->remove_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1939 if (eb->raise_method) {
1940 semaidx = table->next_idx ++;
1941 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1942 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1943 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1944 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1949 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1951 static MonoClass *NewConstraintAttr;
1952 static MonoMethod *NewConstraintAttr_ctor;
1953 MonoDynamicTable *table;
1955 guint32 token, type;
1956 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1959 if (!NewConstraintAttr)
1960 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1961 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1962 g_assert (NewConstraintAttr);
1964 if (!NewConstraintAttr_ctor) {
1965 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1966 g_assert (NewConstraintAttr_ctor);
1969 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1971 alloc_table (table, table->rows);
1973 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1974 owner <<= MONO_CUSTOM_ATTR_BITS;
1975 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1976 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1978 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1980 type = mono_metadata_token_index (token);
1981 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1982 switch (mono_metadata_token_table (token)) {
1983 case MONO_TABLE_METHOD:
1984 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1986 case MONO_TABLE_MEMBERREF:
1987 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1990 g_warning ("got wrong token in custom attr");
1993 values [MONO_CUSTOM_ATTR_TYPE] = type;
1995 buf = p = g_malloc (1);
1996 mono_metadata_encode_value (4, p, &p);
1997 g_assert (p-buf == 1);
1999 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2001 values += MONO_CUSTOM_ATTR_SIZE;
2006 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2008 MonoDynamicTable *table;
2009 guint32 num_constraints, i;
2013 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2014 num_constraints = gparam->iface_constraints ?
2015 mono_array_length (gparam->iface_constraints) : 0;
2016 table->rows += num_constraints;
2017 if (gparam->base_type)
2019 alloc_table (table, table->rows);
2021 if (gparam->base_type) {
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, gparam->base_type->type);
2030 for (i = 0; i < num_constraints; i++) {
2031 MonoReflectionType *constraint = mono_array_get (
2032 gparam->iface_constraints, gpointer, i);
2034 table_idx = table->next_idx ++;
2035 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2037 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2038 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2039 assembly, constraint->type);
2042 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2043 encode_new_constraint (assembly, owner);
2047 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2049 GenericParamTableEntry *entry;
2052 * The GenericParam table must be sorted according to the `owner' field.
2053 * We need to do this sorting prior to writing the GenericParamConstraint
2054 * table, since we have to use the final GenericParam table indices there
2055 * and they must also be sorted.
2058 entry = g_new0 (GenericParamTableEntry, 1);
2059 entry->owner = owner;
2060 entry->gparam = gparam;
2062 g_ptr_array_add (assembly->gen_params, entry);
2066 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2068 MonoDynamicTable *table;
2069 MonoGenericParam *param;
2073 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2074 table_idx = table->next_idx ++;
2075 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2077 param = entry->gparam->type.type->data.generic_param;
2079 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2080 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2081 values [MONO_GENERICPARAM_NUMBER] = param->num;
2082 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2084 encode_constraints (entry->gparam, table_idx, assembly);
2088 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2090 MonoDynamicTable *table;
2093 guint32 cols [MONO_ASSEMBLY_SIZE];
2097 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2100 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2101 table = &assembly->tables [MONO_TABLE_MODULEREF];
2102 token = table->next_idx ++;
2104 alloc_table (table, table->rows);
2105 values = table->values + token * MONO_MODULEREF_SIZE;
2106 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2108 token <<= MONO_RESOLTION_SCOPE_BITS;
2109 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2110 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2115 if (image->assembly->dynamic)
2117 memset (cols, 0, sizeof (cols));
2119 /* image->assembly->image is the manifest module */
2120 image = image->assembly->image;
2121 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2124 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2125 token = table->next_idx ++;
2127 alloc_table (table, table->rows);
2128 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2129 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2130 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2131 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2132 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2133 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2134 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2135 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2136 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2138 if (strcmp ("", image->assembly->aname.culture)) {
2139 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2140 image->assembly->aname.culture);
2143 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2144 guchar pubtoken [9];
2146 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2147 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2149 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2151 token <<= MONO_RESOLTION_SCOPE_BITS;
2152 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2153 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2158 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2160 MonoDynamicTable *table;
2166 char *b = blob_size;
2168 switch (type->type) {
2169 case MONO_TYPE_FNPTR:
2171 case MONO_TYPE_SZARRAY:
2172 case MONO_TYPE_ARRAY:
2174 case MONO_TYPE_MVAR:
2175 case MONO_TYPE_GENERICINST:
2176 encode_type (assembly, type, p, &p);
2178 case MONO_TYPE_CLASS:
2179 case MONO_TYPE_VALUETYPE: {
2180 MonoClass *k = mono_class_from_mono_type (type);
2181 if (!k || !k->generic_class)
2183 encode_generic_class (assembly, k->generic_class, p, &p);
2190 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2191 if (assembly->save) {
2192 g_assert (p-sig < 128);
2193 mono_metadata_encode_value (p-sig, b, &b);
2194 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2195 alloc_table (table, table->rows + 1);
2196 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2197 values [MONO_TYPESPEC_SIGNATURE] = token;
2200 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2201 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2207 * Despite the name, we handle also TypeSpec (with the above helper).
2210 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2212 MonoDynamicTable *table;
2214 guint32 token, scope, enclosing;
2217 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2220 token = create_typespec (assembly, type);
2223 klass = my_mono_class_from_mono_type (type);
2225 klass = mono_class_from_mono_type (type);
2228 * If it's in the same module and not a generic type parameter:
2230 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2231 (type->type != MONO_TYPE_MVAR)) {
2232 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2233 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2234 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2238 if (klass->nested_in) {
2239 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2240 /* get the typeref idx of the enclosing type */
2241 enclosing >>= MONO_TYPEDEFORREF_BITS;
2242 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2244 scope = resolution_scope_from_image (assembly, klass->image);
2246 table = &assembly->tables [MONO_TABLE_TYPEREF];
2247 if (assembly->save) {
2248 alloc_table (table, table->rows + 1);
2249 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2250 values [MONO_TYPEREF_SCOPE] = scope;
2251 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2252 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2254 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2255 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2257 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2262 * Insert a memberef row into the metadata: the token that point to the memberref
2263 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2264 * mono_image_get_fieldref_token()).
2265 * The sig param is an index to an already built signature.
2268 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2270 MonoDynamicTable *table;
2272 guint32 token, pclass;
2275 parent = mono_image_typedef_or_ref (assembly, type);
2276 switch (parent & MONO_TYPEDEFORREF_MASK) {
2277 case MONO_TYPEDEFORREF_TYPEREF:
2278 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2280 case MONO_TYPEDEFORREF_TYPESPEC:
2281 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2283 case MONO_TYPEDEFORREF_TYPEDEF:
2284 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2287 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2290 /* extract the index */
2291 parent >>= MONO_TYPEDEFORREF_BITS;
2293 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2295 if (assembly->save) {
2296 alloc_table (table, table->rows + 1);
2297 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2298 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2299 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2300 values [MONO_MEMBERREF_SIGNATURE] = sig;
2303 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2310 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2313 MonoMethodSignature *sig;
2315 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2320 * A methodref signature can't contain an unmanaged calling convention.
2322 sig = mono_metadata_signature_dup (mono_method_signature (method));
2323 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2324 sig->call_convention = MONO_CALL_DEFAULT;
2325 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2326 method->name, method_encode_signature (assembly, sig));
2328 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2333 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2334 const gchar *name, guint32 sig)
2336 MonoDynamicTable *table;
2340 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2342 if (assembly->save) {
2343 alloc_table (table, table->rows + 1);
2344 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2345 values [MONO_MEMBERREF_CLASS] = original;
2346 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2347 values [MONO_MEMBERREF_SIGNATURE] = sig;
2350 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2357 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2360 ReflectionMethodBuilder rmb;
2362 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2366 reflection_methodbuilder_from_method_builder (&rmb, mb);
2368 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2369 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2370 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2375 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2378 ReflectionMethodBuilder rmb;
2380 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2384 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2386 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2387 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2388 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2393 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2398 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2401 g_assert (f->field->parent);
2402 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2403 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2404 f->field->name, fieldref_encode_signature (assembly, type));
2405 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2410 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2415 guint32 nparams = gmethod->inst->type_argc;
2416 guint32 size = 10 + nparams * 10;
2419 char *b = blob_size;
2421 if (!assembly->save)
2424 p = buf = g_malloc (size);
2426 * FIXME: vararg, explicit_this, differenc call_conv values...
2428 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2429 mono_metadata_encode_value (nparams, p, &p);
2431 for (i = 0; i < nparams; i++)
2432 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2435 g_assert (p - buf < size);
2436 mono_metadata_encode_value (p-buf, b, &b);
2437 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2445 MonoDynamicTable *table;
2447 guint32 token, mtoken = 0, sig;
2448 MonoMethodInflated *imethod;
2449 MonoMethod *declaring;
2451 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2453 g_assert (method->is_inflated);
2454 method = mono_get_inflated_method (method);
2455 imethod = (MonoMethodInflated *) method;
2456 declaring = imethod->declaring;
2458 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2459 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2461 if (!mono_method_signature (declaring)->generic_param_count)
2464 switch (mono_metadata_token_table (mtoken)) {
2465 case MONO_TABLE_MEMBERREF:
2466 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2468 case MONO_TABLE_METHOD:
2469 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2472 g_assert_not_reached ();
2475 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2477 if (assembly->save) {
2478 alloc_table (table, table->rows + 1);
2479 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2480 values [MONO_METHODSPEC_METHOD] = mtoken;
2481 values [MONO_METHODSPEC_SIGNATURE] = sig;
2484 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2491 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2493 MonoMethodInflated *imethod;
2496 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2500 g_assert (m->is_inflated);
2501 m = mono_get_inflated_method (m);
2502 imethod = (MonoMethodInflated *) m;
2504 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2505 token = method_encode_methodspec (assembly, m);
2507 guint32 sig = method_encode_signature (
2508 assembly, mono_method_signature (imethod->declaring));
2509 token = mono_image_get_memberref_token (
2510 assembly, &m->klass->byval_arg, m->name, sig);
2513 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2518 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2520 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2523 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2524 token = mono_image_get_memberref_token (
2525 assembly, &m->klass->byval_arg, m->name, sig);
2531 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2533 MonoDynamicTable *table;
2540 char *b = blob_size;
2544 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2545 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2546 * Because of this, we must not insert it into the `typeref' hash table.
2549 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2553 g_assert (tb->generic_params);
2554 klass = mono_class_from_mono_type (tb->type.type);
2556 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2557 encode_type (assembly, &klass->byval_arg, p, &p);
2559 count = mono_array_length (tb->generic_params);
2560 mono_metadata_encode_value (count, p, &p);
2561 for (i = 0; i < count; i++) {
2562 MonoReflectionGenericParam *gparam;
2564 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2566 encode_type (assembly, gparam->type.type, p, &p);
2569 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2570 if (assembly->save) {
2571 g_assert (p-sig < 128);
2572 mono_metadata_encode_value (p-sig, b, &b);
2573 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2574 alloc_table (table, table->rows + 1);
2575 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2576 values [MONO_TYPESPEC_SIGNATURE] = token;
2579 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2580 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2586 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2588 MonoDynamicTable *table;
2591 guint32 token, pclass, parent, sig;
2594 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2598 klass = mono_class_from_mono_type (fb->typeb->type);
2599 name = mono_string_to_utf8 (fb->name);
2601 sig = fieldref_encode_signature (assembly, fb->type->type);
2603 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2604 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2606 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2607 parent >>= MONO_TYPEDEFORREF_BITS;
2609 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2611 if (assembly->save) {
2612 alloc_table (table, table->rows + 1);
2613 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2614 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2615 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2616 values [MONO_MEMBERREF_SIGNATURE] = sig;
2619 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2621 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2626 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2634 char *b = blob_size;
2636 if (!assembly->save)
2640 g_assert (helper->type == 2);
2642 if (helper->arguments)
2643 nargs = mono_array_length (helper->arguments);
2647 size = 10 + (nargs * 10);
2649 p = buf = g_malloc (size);
2651 /* Encode calling convention */
2652 /* Change Any to Standard */
2653 if ((helper->call_conv & 0x03) == 0x03)
2654 helper->call_conv = 0x01;
2655 /* explicit_this implies has_this */
2656 if (helper->call_conv & 0x40)
2657 helper->call_conv &= 0x20;
2659 if (helper->call_conv == 0) { /* Unmanaged */
2660 *p = helper->unmanaged_call_conv - 1;
2663 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2664 if (helper->call_conv & 0x02) /* varargs */
2669 mono_metadata_encode_value (nargs, p, &p);
2670 encode_reflection_type (assembly, helper->return_type, p, &p);
2671 for (i = 0; i < nargs; ++i) {
2672 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2673 encode_reflection_type (assembly, pt, p, &p);
2676 g_assert (p - buf < size);
2677 mono_metadata_encode_value (p-buf, b, &b);
2678 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2685 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2688 MonoDynamicTable *table;
2691 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2692 idx = table->next_idx ++;
2694 alloc_table (table, table->rows);
2695 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2697 values [MONO_STAND_ALONE_SIGNATURE] =
2698 mono_reflection_encode_sighelper (assembly, helper);
2704 reflection_cc_to_file (int call_conv) {
2705 switch (call_conv & 0x3) {
2707 case 1: return MONO_CALL_DEFAULT;
2708 case 2: return MONO_CALL_VARARG;
2710 g_assert_not_reached ();
2717 MonoMethodSignature *sig;
2723 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2728 MonoMethodSignature *sig;
2731 name = mono_string_to_utf8 (m->name);
2732 nparams = mono_array_length (m->parameters);
2733 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2735 sig->sentinelpos = -1;
2736 sig->call_convention = reflection_cc_to_file (m->call_conv);
2737 sig->param_count = nparams;
2738 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2739 for (i = 0; i < nparams; ++i) {
2740 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2741 sig->params [i] = t->type;
2744 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2746 if (strcmp (name, am->name) == 0 &&
2747 mono_metadata_type_equal (am->parent, m->parent->type) &&
2748 mono_metadata_signature_equal (am->sig, sig)) {
2751 m->table_idx = am->token & 0xffffff;
2755 am = g_new0 (ArrayMethod, 1);
2758 am->parent = m->parent->type;
2759 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2760 method_encode_signature (assembly, sig));
2761 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2762 m->table_idx = am->token & 0xffffff;
2767 * Insert into the metadata tables all the info about the TypeBuilder tb.
2768 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2771 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2773 MonoDynamicTable *table;
2775 int i, is_object = 0, is_system = 0;
2778 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2779 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2780 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2781 n = mono_string_to_utf8 (tb->name);
2782 if (strcmp (n, "Object") == 0)
2784 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2786 n = mono_string_to_utf8 (tb->nspace);
2787 if (strcmp (n, "System") == 0)
2789 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2791 if (tb->parent && !(is_system && is_object) &&
2792 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2793 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2795 values [MONO_TYPEDEF_EXTENDS] = 0;
2797 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2798 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2801 * if we have explicitlayout or sequentiallayouts, output data in the
2802 * ClassLayout table.
2804 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2805 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2806 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2808 alloc_table (table, table->rows);
2809 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2810 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2811 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2812 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2815 /* handle interfaces */
2816 if (tb->interfaces) {
2817 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2819 table->rows += mono_array_length (tb->interfaces);
2820 alloc_table (table, table->rows);
2821 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2822 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2823 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2824 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2825 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2826 values += MONO_INTERFACEIMPL_SIZE;
2832 table = &assembly->tables [MONO_TABLE_FIELD];
2833 table->rows += tb->num_fields;
2834 alloc_table (table, table->rows);
2835 for (i = 0; i < tb->num_fields; ++i)
2836 mono_image_get_field_info (
2837 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2840 /* handle constructors */
2842 table = &assembly->tables [MONO_TABLE_METHOD];
2843 table->rows += mono_array_length (tb->ctors);
2844 alloc_table (table, table->rows);
2845 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2846 mono_image_get_ctor_info (domain,
2847 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2850 /* handle methods */
2852 table = &assembly->tables [MONO_TABLE_METHOD];
2853 table->rows += tb->num_methods;
2854 alloc_table (table, table->rows);
2855 for (i = 0; i < tb->num_methods; ++i)
2856 mono_image_get_method_info (
2857 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2860 /* Do the same with properties etc.. */
2861 if (tb->events && mono_array_length (tb->events)) {
2862 table = &assembly->tables [MONO_TABLE_EVENT];
2863 table->rows += mono_array_length (tb->events);
2864 alloc_table (table, table->rows);
2865 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2867 alloc_table (table, table->rows);
2868 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2869 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2870 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2871 for (i = 0; i < mono_array_length (tb->events); ++i)
2872 mono_image_get_event_info (
2873 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2875 if (tb->properties && mono_array_length (tb->properties)) {
2876 table = &assembly->tables [MONO_TABLE_PROPERTY];
2877 table->rows += mono_array_length (tb->properties);
2878 alloc_table (table, table->rows);
2879 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2881 alloc_table (table, table->rows);
2882 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2883 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2884 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2885 for (i = 0; i < mono_array_length (tb->properties); ++i)
2886 mono_image_get_property_info (
2887 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2890 /* handle generic parameters */
2891 if (tb->generic_params) {
2892 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2893 table->rows += mono_array_length (tb->generic_params);
2894 alloc_table (table, table->rows);
2895 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2896 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2898 mono_image_get_generic_param_info (
2899 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2903 mono_image_add_decl_security (assembly,
2904 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2907 MonoDynamicTable *ntable;
2909 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2910 ntable->rows += mono_array_length (tb->subtypes);
2911 alloc_table (ntable, ntable->rows);
2912 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2914 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2915 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2917 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2918 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2919 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2920 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2921 mono_string_to_utf8 (tb->name), tb->table_idx,
2922 ntable->next_idx, ntable->rows);*/
2923 values += MONO_NESTED_CLASS_SIZE;
2930 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2934 g_ptr_array_add (types, type);
2936 if (!type->subtypes)
2939 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2940 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2941 collect_types (types, subtype);
2946 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2948 if ((*type1)->table_idx < (*type2)->table_idx)
2951 if ((*type1)->table_idx > (*type2)->table_idx)
2958 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2963 for (i = 0; i < mono_array_length (pinfo); ++i) {
2964 MonoReflectionParamBuilder *pb;
2965 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2968 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2973 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2976 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2978 for (i = 0; i < tb->num_fields; ++i) {
2979 MonoReflectionFieldBuilder* fb;
2980 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2981 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2985 for (i = 0; i < mono_array_length (tb->events); ++i) {
2986 MonoReflectionEventBuilder* eb;
2987 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2988 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2991 if (tb->properties) {
2992 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2993 MonoReflectionPropertyBuilder* pb;
2994 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2995 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2999 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3000 MonoReflectionCtorBuilder* cb;
3001 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3002 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3003 params_add_cattrs (assembly, cb->pinfo);
3008 for (i = 0; i < tb->num_methods; ++i) {
3009 MonoReflectionMethodBuilder* mb;
3010 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3011 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3012 params_add_cattrs (assembly, mb->pinfo);
3017 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3018 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3023 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3026 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3028 /* no types in the module */
3032 for (i = 0; i < mb->num_types; ++i)
3033 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3037 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3039 MonoDynamicTable *table;
3043 char *b = blob_size;
3046 table = &assembly->tables [MONO_TABLE_FILE];
3048 alloc_table (table, table->rows);
3049 values = table->values + table->next_idx * MONO_FILE_SIZE;
3050 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3051 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3052 if (module->image->dynamic) {
3053 /* This depends on the fact that the main module is emitted last */
3054 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3055 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3058 path = g_strdup (module->image->name);
3060 mono_sha1_get_digest_from_file (path, hash);
3063 mono_metadata_encode_value (20, b, &b);
3064 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3065 mono_image_add_stream_data (&assembly->blob, hash, 20);
3070 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3072 MonoDynamicTable *table;
3076 table = &assembly->tables [MONO_TABLE_MODULE];
3077 mb->table_idx = table->next_idx ++;
3078 name = mono_string_to_utf8 (mb->module.name);
3079 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3081 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3084 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3085 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3086 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3091 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3092 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3094 MonoDynamicTable *table;
3098 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3099 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3102 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3104 alloc_table (table, table->rows);
3105 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3107 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3108 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3109 if (klass->nested_in)
3110 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3113 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3114 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3116 res = table->next_idx;
3120 /* Emit nested types */
3121 if (klass->nested_classes) {
3124 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3125 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3132 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3133 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3138 klass = mono_class_from_mono_type (tb->type.type);
3140 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3142 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3143 parent_index, assembly);
3147 * We need to do this ourselves since klass->nested_classes is not set up.
3150 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3151 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3156 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3157 guint32 module_index, MonoDynamicImage *assembly)
3159 MonoImage *image = module->image;
3163 t = &image->tables [MONO_TABLE_TYPEDEF];
3165 for (i = 0; i < t->rows; ++i) {
3166 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3168 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3169 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3173 #define align_pointer(base,p)\
3175 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3177 (p) += 4 - (__diff & 3);\
3181 compare_constants (const void *a, const void *b)
3183 const guint32 *a_values = a;
3184 const guint32 *b_values = b;
3185 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3189 compare_semantics (const void *a, const void *b)
3191 const guint32 *a_values = a;
3192 const guint32 *b_values = b;
3193 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3196 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3200 compare_custom_attrs (const void *a, const void *b)
3202 const guint32 *a_values = a;
3203 const guint32 *b_values = b;
3205 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3209 compare_field_marshal (const void *a, const void *b)
3211 const guint32 *a_values = a;
3212 const guint32 *b_values = b;
3214 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3218 compare_nested (const void *a, const void *b)
3220 const guint32 *a_values = a;
3221 const guint32 *b_values = b;
3223 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3227 compare_genericparam (const void *a, const void *b)
3229 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3230 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3232 if ((*b_entry)->owner == (*a_entry)->owner)
3234 (*a_entry)->gparam->type.type->data.generic_param->num -
3235 (*b_entry)->gparam->type.type->data.generic_param->num;
3237 return (*a_entry)->owner - (*b_entry)->owner;
3241 compare_declsecurity_attrs (const void *a, const void *b)
3243 const guint32 *a_values = a;
3244 const guint32 *b_values = b;
3246 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3250 pad_heap (MonoDynamicStream *sh)
3252 if (sh->index & 3) {
3253 int sz = 4 - (sh->index & 3);
3254 memset (sh->data + sh->index, 0, sz);
3261 MonoDynamicStream *stream;
3265 * build_compressed_metadata() fills in the blob of data that represents the
3266 * raw metadata as it will be saved in the PE file. The five streams are output
3267 * and the metadata tables are comnpressed from the guint32 array representation,
3268 * to the compressed on-disk format.
3271 build_compressed_metadata (MonoDynamicImage *assembly)
3273 MonoDynamicTable *table;
3275 guint64 valid_mask = 0;
3276 guint64 sorted_mask;
3277 guint32 heapt_size = 0;
3278 guint32 meta_size = 256; /* allow for header and other stuff */
3279 guint32 table_offset;
3280 guint32 ntables = 0;
3286 struct StreamDesc stream_desc [5];
3288 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3289 for (i = 0; i < assembly->gen_params->len; i++){
3290 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3291 write_generic_param_entry (assembly, entry);
3294 stream_desc [0].name = "#~";
3295 stream_desc [0].stream = &assembly->tstream;
3296 stream_desc [1].name = "#Strings";
3297 stream_desc [1].stream = &assembly->sheap;
3298 stream_desc [2].name = "#US";
3299 stream_desc [2].stream = &assembly->us;
3300 stream_desc [3].name = "#Blob";
3301 stream_desc [3].stream = &assembly->blob;
3302 stream_desc [4].name = "#GUID";
3303 stream_desc [4].stream = &assembly->guid;
3305 /* tables that are sorted */
3306 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3307 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3308 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3309 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3310 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3311 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3313 /* Compute table sizes */
3314 /* the MonoImage has already been created in mono_image_basic_init() */
3315 meta = &assembly->image;
3317 /* sizes should be multiple of 4 */
3318 pad_heap (&assembly->blob);
3319 pad_heap (&assembly->guid);
3320 pad_heap (&assembly->sheap);
3321 pad_heap (&assembly->us);
3323 /* Setup the info used by compute_sizes () */
3324 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3325 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3326 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3328 meta_size += assembly->blob.index;
3329 meta_size += assembly->guid.index;
3330 meta_size += assembly->sheap.index;
3331 meta_size += assembly->us.index;
3333 for (i=0; i < MONO_TABLE_NUM; ++i)
3334 meta->tables [i].rows = assembly->tables [i].rows;
3336 for (i = 0; i < MONO_TABLE_NUM; i++){
3337 if (meta->tables [i].rows == 0)
3339 valid_mask |= (guint64)1 << i;
3341 meta->tables [i].row_size = mono_metadata_compute_size (
3342 meta, i, &meta->tables [i].size_bitfield);
3343 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3345 heapt_size += 24; /* #~ header size */
3346 heapt_size += ntables * 4;
3347 /* make multiple of 4 */
3350 meta_size += heapt_size;
3351 meta->raw_metadata = g_malloc0 (meta_size);
3352 p = meta->raw_metadata;
3353 /* the metadata signature */
3354 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3355 /* version numbers and 4 bytes reserved */
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (1);
3358 *int16val = GUINT16_TO_LE (1);
3360 /* version string */
3361 int32val = (guint32*)p;
3362 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3364 memcpy (p, meta->version, strlen (meta->version));
3365 p += GUINT32_FROM_LE (*int32val);
3366 align_pointer (meta->raw_metadata, p);
3367 int16val = (guint16*)p;
3368 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3369 *int16val = GUINT16_TO_LE (5); /* number of streams */
3373 * write the stream info.
3375 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3376 table_offset += 3; table_offset &= ~3;
3378 assembly->tstream.index = heapt_size;
3379 for (i = 0; i < 5; ++i) {
3380 int32val = (guint32*)p;
3381 stream_desc [i].stream->offset = table_offset;
3382 *int32val++ = GUINT32_TO_LE (table_offset);
3383 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3384 table_offset += GUINT32_FROM_LE (*int32val);
3385 table_offset += 3; table_offset &= ~3;
3387 strcpy (p, stream_desc [i].name);
3388 p += strlen (stream_desc [i].name) + 1;
3389 align_pointer (meta->raw_metadata, p);
3392 * now copy the data, the table stream header and contents goes first.
3394 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3395 p = meta->raw_metadata + assembly->tstream.offset;
3396 int32val = (guint32*)p;
3397 *int32val = GUINT32_TO_LE (0); /* reserved */
3400 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3401 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3402 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3403 *p++ = 2; /* version */
3406 *p++ = 1; /* version */
3410 if (meta->idx_string_wide)
3412 if (meta->idx_guid_wide)
3414 if (meta->idx_blob_wide)
3417 *p++ = 1; /* reserved */
3418 int64val = (guint64*)p;
3419 *int64val++ = GUINT64_TO_LE (valid_mask);
3420 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3422 int32val = (guint32*)p;
3423 for (i = 0; i < MONO_TABLE_NUM; i++){
3424 if (meta->tables [i].rows == 0)
3426 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3428 p = (unsigned char*)int32val;
3430 /* sort the tables that still need sorting */
3431 table = &assembly->tables [MONO_TABLE_CONSTANT];
3433 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3434 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3436 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3437 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3439 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3440 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3442 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3443 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3445 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3446 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3447 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3449 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3451 /* compress the tables */
3452 for (i = 0; i < MONO_TABLE_NUM; i++){
3455 guint32 bitfield = meta->tables [i].size_bitfield;
3456 if (!meta->tables [i].rows)
3458 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3459 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3460 meta->tables [i].base = p;
3461 for (row = 1; row <= meta->tables [i].rows; ++row) {
3462 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3463 for (col = 0; col < assembly->tables [i].columns; ++col) {
3464 switch (mono_metadata_table_size (bitfield, col)) {
3466 *p++ = values [col];
3469 *p++ = values [col] & 0xff;
3470 *p++ = (values [col] >> 8) & 0xff;
3473 *p++ = values [col] & 0xff;
3474 *p++ = (values [col] >> 8) & 0xff;
3475 *p++ = (values [col] >> 16) & 0xff;
3476 *p++ = (values [col] >> 24) & 0xff;
3479 g_assert_not_reached ();
3483 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3486 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3487 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3488 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3489 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3490 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3492 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3496 * Some tables in metadata need to be sorted according to some criteria, but
3497 * when methods and fields are first created with reflection, they may be assigned a token
3498 * that doesn't correspond to the final token they will get assigned after the sorting.
3499 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3500 * with the reflection objects that represent them. Once all the tables are set up, the
3501 * reflection objects will contains the correct table index. fixup_method() will fixup the
3502 * tokens for the method with ILGenerator @ilgen.
3505 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3506 guint32 code_idx = GPOINTER_TO_UINT (value);
3507 MonoReflectionILTokenInfo *iltoken;
3508 MonoReflectionFieldBuilder *field;
3509 MonoReflectionCtorBuilder *ctor;
3510 MonoReflectionMethodBuilder *method;
3511 MonoReflectionTypeBuilder *tb;
3512 MonoReflectionArrayMethod *am;
3514 unsigned char *target;
3516 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3517 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3518 target = assembly->code.data + code_idx + iltoken->code_pos;
3519 switch (target [3]) {
3520 case MONO_TABLE_FIELD:
3521 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3522 field = (MonoReflectionFieldBuilder *)iltoken->member;
3523 idx = field->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3525 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3526 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3528 g_assert_not_reached ();
3531 case MONO_TABLE_METHOD:
3532 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3533 method = (MonoReflectionMethodBuilder *)iltoken->member;
3534 idx = method->table_idx;
3535 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3536 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3537 idx = ctor->table_idx;
3538 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3539 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3540 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3541 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3543 g_assert_not_reached ();
3546 case MONO_TABLE_TYPEDEF:
3547 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3548 g_assert_not_reached ();
3549 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3550 idx = tb->table_idx;
3552 case MONO_TABLE_MEMBERREF:
3553 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3554 am = (MonoReflectionArrayMethod*)iltoken->member;
3555 idx = am->table_idx;
3556 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3557 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3558 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3559 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3560 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3561 g_assert (m->klass->generic_class || m->klass->generic_container);
3563 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3565 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3566 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3567 g_assert (f->generic_info);
3569 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3572 g_assert_not_reached ();
3575 case MONO_TABLE_METHODSPEC:
3576 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3577 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3578 g_assert (mono_method_signature (m)->generic_param_count);
3581 g_assert_not_reached ();
3585 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3587 target [0] = idx & 0xff;
3588 target [1] = (idx >> 8) & 0xff;
3589 target [2] = (idx >> 16) & 0xff;
3596 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3597 * value is not known when the table is emitted.
3600 fixup_cattrs (MonoDynamicImage *assembly)
3602 MonoDynamicTable *table;
3604 guint32 type, i, idx, token;
3607 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3609 for (i = 0; i < table->rows; ++i) {
3610 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3612 type = values [MONO_CUSTOM_ATTR_TYPE];
3613 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3614 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3615 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3616 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3619 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3620 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3621 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3622 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3631 * The METHODIMPL table might contain METHODDEF tokens whose final
3632 * value is not known when the table is emitted.
3635 fixup_methodimpl (MonoDynamicImage *assembly)
3637 MonoDynamicTable *table;
3639 guint32 decl, i, idx, token;
3642 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3644 for (i = 0; i < table->rows; ++i) {
3645 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3646 decl = values [MONO_METHODIMPL_DECLARATION];
3648 idx = decl >> MONO_METHODDEFORREF_BITS;
3649 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3652 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3653 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3656 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3657 token = mono_image_create_token (assembly, method, FALSE);
3658 idx = mono_metadata_token_index (token);
3659 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3665 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3667 MonoDynamicTable *table;
3671 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3673 alloc_table (table, table->rows);
3674 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3675 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3676 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3677 name = mono_string_to_utf8 (rsrc->name);
3678 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3680 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3685 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3687 MonoDynamicTable *table;
3691 char *b = blob_size;
3693 guint32 idx, offset;
3695 if (rsrc->filename) {
3696 name = mono_string_to_utf8 (rsrc->filename);
3697 sname = g_path_get_basename (name);
3699 table = &assembly->tables [MONO_TABLE_FILE];
3701 alloc_table (table, table->rows);
3702 values = table->values + table->next_idx * MONO_FILE_SIZE;
3703 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3704 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3707 mono_sha1_get_digest_from_file (name, hash);
3708 mono_metadata_encode_value (20, b, &b);
3709 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3710 mono_image_add_stream_data (&assembly->blob, hash, 20);
3712 idx = table->next_idx++;
3714 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3717 offset = mono_array_length (rsrc->data);
3718 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3719 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3720 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3721 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3725 * The entry should be emitted into the MANIFESTRESOURCE table of
3726 * the main module, but that needs to reference the FILE table
3727 * which isn't emitted yet.
3734 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3738 set_version_from_string (MonoString *version, guint32 *values)
3740 gchar *ver, *p, *str;
3743 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3744 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3745 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3746 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3749 ver = str = mono_string_to_utf8 (version);
3750 for (i = 0; i < 4; ++i) {
3751 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3757 /* handle Revision and Build */
3767 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3771 char *b = blob_size;
3776 len = mono_array_length (pkey);
3777 mono_metadata_encode_value (len, b, &b);
3778 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3779 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3781 /* need to get the actual value from the key type... */
3782 assembly->strong_name_size = 128;
3783 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3789 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3791 MonoDynamicTable *table;
3792 MonoDynamicImage *assembly;
3793 MonoReflectionAssemblyBuilder *assemblyb;
3798 guint32 module_index;
3800 assemblyb = moduleb->assemblyb;
3801 assembly = moduleb->dynamic_image;
3802 domain = mono_object_domain (assemblyb);
3804 /* Emit ASSEMBLY table */
3805 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3806 alloc_table (table, 1);
3807 values = table->values + MONO_ASSEMBLY_SIZE;
3808 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3809 name = mono_string_to_utf8 (assemblyb->name);
3810 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3812 if (assemblyb->culture) {
3813 name = mono_string_to_utf8 (assemblyb->culture);
3814 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3817 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3819 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3820 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3821 set_version_from_string (assemblyb->version, values);
3823 /* Emit FILE + EXPORTED_TYPE table */
3825 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3827 MonoReflectionModuleBuilder *file_module =
3828 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3829 if (file_module != moduleb) {
3830 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3832 if (file_module->types) {
3833 for (j = 0; j < file_module->num_types; ++j) {
3834 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3835 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3840 if (assemblyb->loaded_modules) {
3841 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3842 MonoReflectionModule *file_module =
3843 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3844 mono_image_fill_file_table (domain, file_module, assembly);
3846 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3850 /* Emit MANIFESTRESOURCE table */
3852 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3854 MonoReflectionModuleBuilder *file_module =
3855 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3856 /* The table for the main module is emitted later */
3857 if (file_module != moduleb) {
3859 if (file_module->resources) {
3860 int len = mono_array_length (file_module->resources);
3861 for (j = 0; j < len; ++j) {
3862 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3863 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3871 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3872 * for the modulebuilder @moduleb.
3873 * At the end of the process, method and field tokens are fixed up and the
3874 * on-disk compressed metadata representation is created.
3877 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3879 MonoDynamicTable *table;
3880 MonoDynamicImage *assembly;
3881 MonoReflectionAssemblyBuilder *assemblyb;
3886 assemblyb = moduleb->assemblyb;
3887 assembly = moduleb->dynamic_image;
3888 domain = mono_object_domain (assemblyb);
3890 if (assembly->text_rva)
3893 assembly->text_rva = START_TEXT_RVA;
3895 if (moduleb->is_main) {
3896 mono_image_emit_manifest (moduleb);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows = 1; /* .<Module> */
3902 alloc_table (table, table->rows);
3904 * Set the first entry.
3906 values = table->values + table->columns;
3907 values [MONO_TYPEDEF_FLAGS] = 0;
3908 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3909 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3910 values [MONO_TYPEDEF_EXTENDS] = 0;
3911 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3912 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3915 * handle global methods
3916 * FIXME: test what to do when global methods are defined in multiple modules.
3918 if (moduleb->global_methods) {
3919 table = &assembly->tables [MONO_TABLE_METHOD];
3920 table->rows += mono_array_length (moduleb->global_methods);
3921 alloc_table (table, table->rows);
3922 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3923 mono_image_get_method_info (
3924 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3926 if (moduleb->global_fields) {
3927 table = &assembly->tables [MONO_TABLE_FIELD];
3928 table->rows += mono_array_length (moduleb->global_fields);
3929 alloc_table (table, table->rows);
3930 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3931 mono_image_get_field_info (
3932 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3935 table = &assembly->tables [MONO_TABLE_MODULE];
3936 alloc_table (table, 1);
3937 mono_image_fill_module_table (domain, moduleb, assembly);
3941 /* Collect all types into a list sorted by their table_idx */
3942 GPtrArray *types = g_ptr_array_new ();
3945 for (i = 0; i < moduleb->num_types; ++i) {
3946 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3947 collect_types (types, type);
3950 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3951 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3952 table->rows += types->len;
3953 alloc_table (table, table->rows);
3955 for (i = 0; i < types->len; ++i) {
3956 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3957 mono_image_get_type_info (domain, type, assembly);
3959 g_ptr_array_free (types, TRUE);
3963 * table->rows is already set above and in mono_image_fill_module_table.
3965 /* add all the custom attributes at the end, once all the indexes are stable */
3966 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3968 /* CAS assembly permissions */
3969 if (assemblyb->permissions_minimum)
3970 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3971 if (assemblyb->permissions_optional)
3972 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3973 if (assemblyb->permissions_refused)
3974 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3976 module_add_cattrs (assembly, moduleb);
3979 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3980 fixup_cattrs (assembly);
3981 fixup_methodimpl (assembly);
3985 * mono_image_insert_string:
3986 * @module: module builder object
3989 * Insert @str into the user string stream of @module.
3992 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3994 MonoDynamicImage *assembly;
3999 MONO_ARCH_SAVE_REGS;
4001 if (!module->dynamic_image)
4002 mono_image_module_basic_init (module);
4004 assembly = module->dynamic_image;
4006 if (assembly->save) {
4007 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4008 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4009 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4011 char *swapped = g_malloc (2 * mono_string_length (str));
4012 const char *p = (const char*)mono_string_chars (str);
4014 swap_with_size (swapped, p, 2, mono_string_length (str));
4015 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4019 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4021 mono_image_add_stream_data (&assembly->us, "", 1);
4023 idx = assembly->us.index ++;
4026 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4028 return MONO_TOKEN_STRING | idx;
4032 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4037 klass = obj->vtable->klass;
4038 if (strcmp (klass->name, "MonoMethod") == 0) {
4039 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4040 MonoMethodSignature *sig, *old;
4041 guint32 sig_token, parent;
4044 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4046 nargs = mono_array_length (opt_param_types);
4047 old = mono_method_signature (method);
4048 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4050 sig->hasthis = old->hasthis;
4051 sig->explicit_this = old->explicit_this;
4052 sig->call_convention = old->call_convention;
4053 sig->generic_param_count = old->generic_param_count;
4054 sig->param_count = old->param_count + nargs;
4055 sig->sentinelpos = old->param_count;
4056 sig->ret = old->ret;
4058 for (i = 0; i < old->param_count; i++)
4059 sig->params [i] = old->params [i];
4061 for (i = 0; i < nargs; i++) {
4062 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4063 sig->params [old->param_count + i] = rt->type;
4066 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4067 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4068 parent >>= MONO_TYPEDEFORREF_BITS;
4070 parent <<= MONO_MEMBERREF_PARENT_BITS;
4071 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4073 sig_token = method_encode_signature (assembly, sig);
4074 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4075 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4076 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4077 ReflectionMethodBuilder rmb;
4078 guint32 parent, sig;
4080 reflection_methodbuilder_from_method_builder (&rmb, mb);
4081 rmb.opt_types = opt_param_types;
4083 sig = method_builder_encode_signature (assembly, &rmb);
4085 parent = mono_image_create_token (assembly, obj, TRUE);
4086 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4088 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4089 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4091 token = mono_image_get_varargs_method_token (
4092 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4094 g_error ("requested method token for %s\n", klass->name);
4101 * mono_image_create_token:
4102 * @assembly: a dynamic assembly
4105 * Get a token to insert in the IL code stream for the given MemberInfo.
4106 * @obj can be one of:
4107 * ConstructorBuilder
4117 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4122 klass = obj->vtable->klass;
4123 if (strcmp (klass->name, "MethodBuilder") == 0) {
4124 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4126 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4127 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4129 token = mono_image_get_methodbuilder_token (assembly, mb);
4130 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4131 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4132 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4134 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4135 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4137 token = mono_image_get_ctorbuilder_token (assembly, mb);
4138 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4139 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4140 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4141 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4142 if (tb->generic_params) {
4143 token = mono_image_get_generic_field_token (assembly, fb);
4145 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4147 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4148 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4149 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4150 } else if (strcmp (klass->name, "MonoType") == 0 ||
4151 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4152 MonoReflectionType *tb = (MonoReflectionType *)obj;
4153 token = mono_metadata_token_from_dor (
4154 mono_image_typedef_or_ref (assembly, tb->type));
4155 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4156 MonoReflectionType *tb = (MonoReflectionType *)obj;
4157 token = mono_metadata_token_from_dor (
4158 mono_image_typedef_or_ref (assembly, tb->type));
4159 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4160 strcmp (klass->name, "MonoMethod") == 0 ||
4161 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4162 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4163 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4164 if (m->method->is_inflated) {
4165 if (create_methodspec)
4166 token = mono_image_get_methodspec_token (assembly, m->method);
4168 token = mono_image_get_inflated_method_token (assembly, m->method);
4169 } else if ((m->method->klass->image == &assembly->image) &&
4170 !m->method->klass->generic_class) {
4171 static guint32 method_table_idx = 0xffffff;
4172 if (m->method->klass->wastypebuilder) {
4173 /* we use the same token as the one that was assigned
4174 * to the Methodbuilder.
4175 * FIXME: do the equivalent for Fields.
4177 token = m->method->token;
4180 * Each token should have a unique index, but the indexes are
4181 * assigned by managed code, so we don't know about them. An
4182 * easy solution is to count backwards...
4184 method_table_idx --;
4185 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4188 token = mono_image_get_methodref_token (assembly, m->method);
4190 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4191 } else if (strcmp (klass->name, "MonoField") == 0) {
4192 MonoReflectionField *f = (MonoReflectionField *)obj;
4193 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4194 static guint32 field_table_idx = 0xffffff;
4196 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4198 token = mono_image_get_fieldref_token (assembly, f);
4200 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4201 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4202 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4203 token = mono_image_get_array_token (assembly, m);
4204 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4205 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4206 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4208 g_error ("requested token for %s\n", klass->name);
4211 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4217 guint32 import_lookup_table;
4221 guint32 import_address_table_rva;
4229 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4231 static MonoDynamicImage*
4232 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4234 static const guchar entrycode [16] = {0xff, 0x25, 0};
4235 MonoDynamicImage *image;
4238 const char *version = mono_get_runtime_info ()->runtime_version;
4241 image = GC_MALLOC (sizeof (MonoDynamicImage));
4243 image = g_new0 (MonoDynamicImage, 1);
4246 /*g_print ("created image %p\n", image);*/
4247 /* keep in sync with image.c */
4248 image->image.name = assembly_name;
4249 image->image.assembly_name = image->image.name; /* they may be different */
4250 image->image.module_name = module_name;
4251 image->image.version = version;
4252 image->image.dynamic = TRUE;
4253 image->image.ref_count = 1;
4255 image->image.references = g_new0 (MonoAssembly*, 1);
4256 image->image.references [0] = NULL;
4258 mono_image_init (&image->image);
4260 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4261 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4262 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4263 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4264 image->handleref = g_hash_table_new (NULL, NULL);
4265 image->tokens = mono_g_hash_table_new (NULL, NULL);
4266 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4267 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4268 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4269 image->gen_params = g_ptr_array_new ();
4271 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4272 string_heap_init (&image->sheap);
4273 mono_image_add_stream_data (&image->us, "", 1);
4274 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4275 /* import tables... */
4276 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4277 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4278 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4279 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4280 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4281 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4282 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4283 stream_data_align (&image->code);
4285 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4287 for (i=0; i < MONO_TABLE_NUM; ++i) {
4288 image->tables [i].next_idx = 1;
4289 image->tables [i].columns = table_sizes [i];
4292 image->image.assembly = (MonoAssembly*)assembly;
4293 image->run = assembly->run;
4294 image->save = assembly->save;
4295 image->pe_kind = 0x1; /* ILOnly */
4296 image->machine = 0x14c; /* I386 */
4302 * mono_image_basic_init:
4303 * @assembly: an assembly builder object
4305 * Create the MonoImage that represents the assembly builder and setup some
4306 * of the helper hash table and the basic metadata streams.
4309 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4311 MonoDynamicAssembly *assembly;
4312 MonoDynamicImage *image;
4313 MonoDomain *domain = mono_object_domain (assemblyb);
4315 MONO_ARCH_SAVE_REGS;
4317 if (assemblyb->dynamic_assembly)
4321 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4323 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4326 assembly->assembly.ref_count = 1;
4327 assembly->assembly.dynamic = TRUE;
4328 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4329 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4330 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4331 if (assemblyb->culture)
4332 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4334 assembly->assembly.aname.culture = g_strdup ("");
4336 assembly->run = assemblyb->access != 2;
4337 assembly->save = assemblyb->access != 1;
4339 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4340 image->initial_image = TRUE;
4341 assembly->assembly.aname.name = image->image.name;
4342 assembly->assembly.image = &image->image;
4344 mono_domain_lock (domain);
4345 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4346 mono_domain_unlock (domain);
4348 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4349 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4353 calc_section_size (MonoDynamicImage *assembly)
4357 /* alignment constraints */
4358 assembly->code.index += 3;
4359 assembly->code.index &= ~3;
4360 assembly->meta_size += 3;
4361 assembly->meta_size &= ~3;
4362 assembly->resources.index += 3;
4363 assembly->resources.index &= ~3;
4365 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4366 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4369 if (assembly->win32_res) {
4370 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4372 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4373 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4377 assembly->sections [MONO_SECTION_RELOC].size = 12;
4378 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4388 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4392 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4394 ResTreeNode *t1 = (ResTreeNode*)a;
4395 ResTreeNode *t2 = (ResTreeNode*)b;
4397 return t1->id - t2->id;
4401 * resource_tree_create:
4403 * Organize the resources into a resource tree.
4405 static ResTreeNode *
4406 resource_tree_create (MonoArray *win32_resources)
4408 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4412 tree = g_new0 (ResTreeNode, 1);
4414 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4415 MonoReflectionWin32Resource *win32_res =
4416 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4420 lang_node = g_new0 (ResTreeNode, 1);
4421 lang_node->id = win32_res->lang_id;
4422 lang_node->win32_res = win32_res;
4424 /* Create type node if neccesary */
4426 for (l = tree->children; l; l = l->next)
4427 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4428 type_node = (ResTreeNode*)l->data;
4433 type_node = g_new0 (ResTreeNode, 1);
4434 type_node->id = win32_res->res_type;
4437 * The resource types have to be sorted otherwise
4438 * Windows Explorer can't display the version information.
4440 tree->children = g_slist_insert_sorted (tree->children,
4441 type_node, resource_tree_compare_by_id);
4444 /* Create res node if neccesary */
4446 for (l = type_node->children; l; l = l->next)
4447 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4448 res_node = (ResTreeNode*)l->data;
4453 res_node = g_new0 (ResTreeNode, 1);
4454 res_node->id = win32_res->res_id;
4455 type_node->children = g_slist_append (type_node->children, res_node);
4458 res_node->children = g_slist_append (res_node->children, lang_node);
4465 * resource_tree_encode:
4467 * Encode the resource tree into the format used in the PE file.
4470 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4473 MonoPEResourceDir dir;
4474 MonoPEResourceDirEntry dir_entry;
4475 MonoPEResourceDataEntry data_entry;
4479 * For the format of the resource directory, see the article
4480 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4484 memset (&dir, 0, sizeof (dir));
4485 memset (&dir_entry, 0, sizeof (dir_entry));
4486 memset (&data_entry, 0, sizeof (data_entry));
4488 g_assert (sizeof (dir) == 16);
4489 g_assert (sizeof (dir_entry) == 8);
4490 g_assert (sizeof (data_entry) == 16);
4492 node->offset = p - begin;
4494 /* IMAGE_RESOURCE_DIRECTORY */
4495 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4497 memcpy (p, &dir, sizeof (dir));
4500 /* Reserve space for entries */
4502 p += sizeof (dir_entry) * dir.res_id_entries;
4504 /* Write children */
4505 for (l = node->children; l; l = l->next) {
4506 ResTreeNode *child = (ResTreeNode*)l->data;
4508 if (child->win32_res) {
4510 child->offset = p - begin;
4512 /* IMAGE_RESOURCE_DATA_ENTRY */
4513 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4514 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4516 memcpy (p, &data_entry, sizeof (data_entry));
4517 p += sizeof (data_entry);
4519 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4520 p += data_entry.rde_size;
4522 resource_tree_encode (child, begin, p, &p);
4526 /* IMAGE_RESOURCE_ENTRY */
4527 for (l = node->children; l; l = l->next) {
4528 ResTreeNode *child = (ResTreeNode*)l->data;
4529 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4531 dir_entry.is_dir = child->win32_res ? 0 : 1;
4532 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4534 memcpy (entries, &dir_entry, sizeof (dir_entry));
4535 entries += sizeof (dir_entry);
4542 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4547 MonoReflectionWin32Resource *win32_res;
4550 if (!assemblyb->win32_resources)
4554 * Resources are stored in a three level tree inside the PE file.
4555 * - level one contains a node for each type of resource
4556 * - level two contains a node for each resource
4557 * - level three contains a node for each instance of a resource for a
4558 * specific language.
4561 tree = resource_tree_create (assemblyb->win32_resources);
4563 /* Estimate the size of the encoded tree */
4565 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4566 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4567 size += mono_array_length (win32_res->res_data);
4569 /* Directory structure */
4570 size += mono_array_length (assemblyb->win32_resources) * 256;
4571 p = buf = g_malloc (size);
4573 resource_tree_encode (tree, p, p, &p);
4575 g_assert (p - buf < size);
4577 assembly->win32_res = g_malloc (p - buf);
4578 assembly->win32_res_size = p - buf;
4579 memcpy (assembly->win32_res, buf, p - buf);
4585 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4587 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4590 p += sizeof (MonoPEResourceDir);
4591 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4592 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4593 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4594 if (dir_entry->is_dir) {
4595 fixup_resource_directory (res_section, child, rva);
4597 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4598 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4601 p += sizeof (MonoPEResourceDirEntry);
4606 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4609 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4610 g_error ("WriteFile returned %d\n", GetLastError ());
4614 * mono_image_create_pefile:
4615 * @mb: a module builder object
4617 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4618 * assembly->pefile where it can be easily retrieved later in chunks.
4621 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4622 MonoMSDOSHeader *msdos;
4623 MonoDotNetHeader *header;
4624 MonoSectionTable *section;
4625 MonoCLIHeader *cli_header;
4626 guint32 size, image_size, virtual_base, text_offset;
4627 guint32 header_start, section_start, file_offset, virtual_offset;
4628 MonoDynamicImage *assembly;
4629 MonoReflectionAssemblyBuilder *assemblyb;
4630 MonoDynamicStream pefile_stream = {0};
4631 MonoDynamicStream *pefile = &pefile_stream;
4633 guint32 *rva, value;
4635 static const unsigned char msheader[] = {
4636 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4637 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4638 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4640 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4641 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4642 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4643 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4646 assemblyb = mb->assemblyb;
4648 mono_image_basic_init (assemblyb);
4649 assembly = mb->dynamic_image;
4651 assembly->pe_kind = assemblyb->pe_kind;
4652 assembly->machine = assemblyb->machine;
4653 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4654 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4656 mono_image_build_metadata (mb);
4658 if (mb->is_main && assemblyb->resources) {
4659 int len = mono_array_length (assemblyb->resources);
4660 for (i = 0; i < len; ++i)
4661 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4664 if (mb->resources) {
4665 int len = mono_array_length (mb->resources);
4666 for (i = 0; i < len; ++i)
4667 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4670 build_compressed_metadata (assembly);
4673 assembly_add_win32_resources (assembly, assemblyb);
4675 nsections = calc_section_size (assembly);
4677 /* The DOS header and stub */
4678 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4679 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4681 /* the dotnet header */
4682 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4684 /* the section tables */
4685 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4687 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4688 virtual_offset = VIRT_ALIGN;
4691 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4692 if (!assembly->sections [i].size)
4695 file_offset += FILE_ALIGN - 1;
4696 file_offset &= ~(FILE_ALIGN - 1);
4697 virtual_offset += VIRT_ALIGN - 1;
4698 virtual_offset &= ~(VIRT_ALIGN - 1);
4700 assembly->sections [i].offset = file_offset;
4701 assembly->sections [i].rva = virtual_offset;
4703 file_offset += assembly->sections [i].size;
4704 virtual_offset += assembly->sections [i].size;
4705 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4708 file_offset += FILE_ALIGN - 1;
4709 file_offset &= ~(FILE_ALIGN - 1);
4711 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4713 /* back-patch info */
4714 msdos = (MonoMSDOSHeader*)pefile->data;
4715 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4717 header = (MonoDotNetHeader*)(pefile->data + header_start);
4718 header->pesig [0] = 'P';
4719 header->pesig [1] = 'E';
4721 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4722 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4723 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4724 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4725 if (assemblyb->pekind == 1) {
4727 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4730 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4733 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4735 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4736 header->pe.pe_major = 6;
4737 header->pe.pe_minor = 0;
4738 size = assembly->sections [MONO_SECTION_TEXT].size;
4739 size += FILE_ALIGN - 1;
4740 size &= ~(FILE_ALIGN - 1);
4741 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4742 size = assembly->sections [MONO_SECTION_RSRC].size;
4743 size += FILE_ALIGN - 1;
4744 size &= ~(FILE_ALIGN - 1);
4745 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4746 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4747 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4748 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4749 /* pe_rva_entry_point always at the beginning of the text section */
4750 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4752 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4753 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4754 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4755 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4756 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4757 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4758 size = section_start;
4759 size += FILE_ALIGN - 1;
4760 size &= ~(FILE_ALIGN - 1);
4761 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4763 size += VIRT_ALIGN - 1;
4764 size &= ~(VIRT_ALIGN - 1);
4765 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4768 // Translate the PEFileKind value to the value expected by the Windows loader
4774 // PEFileKinds.Dll == 1
4775 // PEFileKinds.ConsoleApplication == 2
4776 // PEFileKinds.WindowApplication == 3
4779 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4780 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4782 if (assemblyb->pekind == 3)
4787 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4789 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4790 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4791 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4792 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4793 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4794 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4796 /* fill data directory entries */
4798 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4799 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4801 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4802 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4804 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4805 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4806 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4807 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4808 /* patch entrypoint name */
4809 if (assemblyb->pekind == 1)
4810 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4812 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4813 /* patch imported function RVA name */
4814 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4815 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4817 /* the import table */
4818 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4819 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4820 /* patch imported dll RVA name and other entries in the dir */
4821 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4822 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4823 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4824 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4825 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4826 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4828 p = (assembly->code.data + assembly->ilt_offset);
4829 value = (assembly->text_rva + assembly->imp_names_offset);
4830 *p++ = (value) & 0xff;
4831 *p++ = (value >> 8) & (0xff);
4832 *p++ = (value >> 16) & (0xff);
4833 *p++ = (value >> 24) & (0xff);
4835 /* the CLI header info */
4836 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4837 cli_header->ch_size = GUINT32_FROM_LE (72);
4838 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4839 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4840 if (assemblyb->entry_point) {
4841 guint32 table_idx = 0;
4842 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4843 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4844 table_idx = methodb->table_idx;
4846 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4848 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4850 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4852 /* The embedded managed resources */
4853 text_offset = assembly->text_rva + assembly->code.index;
4854 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4855 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4856 text_offset += assembly->resources.index;
4857 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4858 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4859 text_offset += assembly->meta_size;
4860 if (assembly->strong_name_size) {
4861 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4862 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4863 text_offset += assembly->strong_name_size;
4866 /* write the section tables and section content */
4867 section = (MonoSectionTable*)(pefile->data + section_start);
4868 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4869 static const char *section_names [] = {
4870 ".text", ".rsrc", ".reloc"
4872 if (!assembly->sections [i].size)
4874 strcpy (section->st_name, section_names [i]);
4875 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4876 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4877 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4878 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4879 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4880 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4881 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4885 checked_write_file (file, pefile->data, pefile->index);
4887 mono_dynamic_stream_reset (pefile);
4889 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4890 if (!assembly->sections [i].size)
4893 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4894 g_error ("SetFilePointer returned %d\n", GetLastError ());
4897 case MONO_SECTION_TEXT:
4898 /* patch entry point */
4899 p = (assembly->code.data + 2);
4900 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4901 *p++ = (value) & 0xff;
4902 *p++ = (value >> 8) & 0xff;
4903 *p++ = (value >> 16) & 0xff;
4904 *p++ = (value >> 24) & 0xff;
4906 checked_write_file (file, assembly->code.data, assembly->code.index);
4907 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4908 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4909 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4912 g_free (assembly->image.raw_metadata);
4914 case MONO_SECTION_RELOC: {
4918 guint16 type_and_offset;
4922 g_assert (sizeof (reloc) == 12);
4924 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4925 reloc.block_size = GUINT32_FROM_LE (12);
4928 * the entrypoint is always at the start of the text section
4929 * 3 is IMAGE_REL_BASED_HIGHLOW
4930 * 2 is patch_size_rva - text_rva
4932 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4935 checked_write_file (file, &reloc, sizeof (reloc));
4939 case MONO_SECTION_RSRC:
4940 if (assembly->win32_res) {
4942 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4943 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4944 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4948 g_assert_not_reached ();
4952 /* check that the file is properly padded */
4953 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4954 g_error ("SetFilePointer returned %d\n", GetLastError ());
4955 if (! SetEndOfFile (file))
4956 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4958 mono_dynamic_stream_reset (&assembly->code);
4959 mono_dynamic_stream_reset (&assembly->us);
4960 mono_dynamic_stream_reset (&assembly->blob);
4961 mono_dynamic_stream_reset (&assembly->guid);
4962 mono_dynamic_stream_reset (&assembly->sheap);
4964 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4965 g_hash_table_destroy (assembly->blob_cache);
4966 assembly->blob_cache = NULL;
4969 MonoReflectionModule *
4970 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4974 MonoImageOpenStatus status;
4975 MonoDynamicAssembly *assembly;
4976 guint32 module_count;
4977 MonoImage **new_modules;
4979 name = mono_string_to_utf8 (fileName);
4981 image = mono_image_open (name, &status);
4984 if (status == MONO_IMAGE_ERROR_ERRNO)
4985 exc = mono_get_exception_file_not_found (fileName);
4987 exc = mono_get_exception_bad_image_format (name);
4989 mono_raise_exception (exc);
4994 assembly = ab->dynamic_assembly;
4995 image->assembly = (MonoAssembly*)assembly;
4997 module_count = image->assembly->image->module_count;
4998 new_modules = g_new0 (MonoImage *, module_count + 1);
5000 if (image->assembly->image->modules)
5001 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5002 new_modules [module_count] = image;
5004 g_free (image->assembly->image->modules);
5005 image->assembly->image->modules = new_modules;
5006 image->assembly->image->module_count ++;
5008 mono_assembly_load_references (image, &status);
5010 mono_image_close (image);
5011 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5014 return mono_module_get_object (mono_domain_get (), image);
5018 * We need to return always the same object for MethodInfo, FieldInfo etc..
5019 * but we need to consider the reflected type.
5020 * type uses a different hash, since it uses custom hash/equal functions.
5025 MonoClass *refclass;
5029 reflected_equal (gconstpointer a, gconstpointer b) {
5030 const ReflectedEntry *ea = a;
5031 const ReflectedEntry *eb = b;
5033 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5037 reflected_hash (gconstpointer a) {
5038 const ReflectedEntry *ea = a;
5039 return GPOINTER_TO_UINT (ea->item);
5042 #define CHECK_OBJECT(t,p,k) \
5048 mono_domain_lock (domain); \
5049 if (!domain->refobject_hash) \
5050 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5051 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5052 mono_domain_unlock (domain); \
5058 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5060 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5063 #define CACHE_OBJECT(p,o,k) \
5065 ReflectedEntry *e = ALLOC_REFENTRY; \
5067 e->refclass = (k); \
5068 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5069 mono_domain_unlock (domain); \
5073 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5075 /* this is done only once */
5076 mono_domain_lock (domain);
5077 CACHE_OBJECT (assembly, res, NULL);
5081 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5083 /* this is done only once */
5084 mono_domain_lock (domain);
5085 CACHE_OBJECT (module, res, NULL);
5089 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5091 MonoDynamicImage *image = moduleb->dynamic_image;
5092 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5095 MonoImage **new_modules;
5098 * FIXME: we already created an image in mono_image_basic_init (), but
5099 * we don't know which module it belongs to, since that is only
5100 * determined at assembly save time.
5102 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5103 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5105 moduleb->module.image = &image->image;
5106 moduleb->dynamic_image = image;
5107 register_module (mono_object_domain (moduleb), moduleb, image);
5109 /* register the module with the assembly */
5110 ass = ab->dynamic_assembly->assembly.image;
5111 module_count = ass->module_count;
5112 new_modules = g_new0 (MonoImage *, module_count + 1);
5115 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5116 new_modules [module_count] = &image->image;
5118 g_free (ass->modules);
5119 ass->modules = new_modules;
5120 ass->module_count ++;
5125 * mono_assembly_get_object:
5126 * @domain: an app domain
5127 * @assembly: an assembly
5129 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5131 MonoReflectionAssembly*
5132 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5134 static MonoClass *System_Reflection_Assembly;
5135 MonoReflectionAssembly *res;
5137 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5138 if (!System_Reflection_Assembly)
5139 System_Reflection_Assembly = mono_class_from_name (
5140 mono_defaults.corlib, "System.Reflection", "Assembly");
5141 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5142 res->assembly = assembly;
5144 CACHE_OBJECT (assembly, res, NULL);
5150 MonoReflectionModule*
5151 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5153 static MonoClass *System_Reflection_Module;
5154 MonoReflectionModule *res;
5157 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5158 if (!System_Reflection_Module)
5159 System_Reflection_Module = mono_class_from_name (
5160 mono_defaults.corlib, "System.Reflection", "Module");
5161 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5164 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5166 res->fqname = mono_string_new (domain, image->name);
5167 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5168 res->scopename = mono_string_new (domain, image->module_name);
5172 if (image->assembly->image == image) {
5173 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5176 g_assert (image->assembly->image->modules);
5178 for (i = 0; i < image->assembly->image->module_count; i++) {
5179 if (image->assembly->image->modules [i] == image)
5180 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5182 g_assert (res->token);
5185 mono_image_addref (image);
5187 CACHE_OBJECT (image, res, NULL);
5191 MonoReflectionModule*
5192 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5194 static MonoClass *System_Reflection_Module;
5195 MonoReflectionModule *res;
5196 MonoTableInfo *table;
5197 guint32 cols [MONO_FILE_SIZE];
5199 guint32 i, name_idx;
5202 if (!System_Reflection_Module)
5203 System_Reflection_Module = mono_class_from_name (
5204 mono_defaults.corlib, "System.Reflection", "Module");
5205 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5207 table = &image->tables [MONO_TABLE_FILE];
5208 g_assert (table_index < table->rows);
5209 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5212 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5213 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5215 /* Check whenever the row has a corresponding row in the moduleref table */
5216 table = &image->tables [MONO_TABLE_MODULEREF];
5217 for (i = 0; i < table->rows; ++i) {
5218 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5219 val = mono_metadata_string_heap (image, name_idx);
5220 if (strcmp (val, name) == 0)
5221 res->image = image->modules [i];
5224 res->fqname = mono_string_new (domain, name);
5225 res->name = mono_string_new (domain, name);
5226 res->scopename = mono_string_new (domain, name);
5227 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5228 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5234 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5236 if ((t1->type != t2->type) ||
5237 (t1->byref != t2->byref))
5241 case MONO_TYPE_VOID:
5242 case MONO_TYPE_BOOLEAN:
5243 case MONO_TYPE_CHAR:
5254 case MONO_TYPE_STRING:
5257 case MONO_TYPE_OBJECT:
5258 case MONO_TYPE_TYPEDBYREF:
5260 case MONO_TYPE_VALUETYPE:
5261 case MONO_TYPE_CLASS:
5262 case MONO_TYPE_SZARRAY:
5263 return t1->data.klass == t2->data.klass;
5265 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5266 case MONO_TYPE_ARRAY:
5267 if (t1->data.array->rank != t2->data.array->rank)
5269 return t1->data.array->eklass == t2->data.array->eklass;
5270 case MONO_TYPE_GENERICINST: {
5272 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5274 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5275 &t2->data.generic_class->container_class->byval_arg))
5277 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5278 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5284 case MONO_TYPE_MVAR:
5285 return t1->data.generic_param == t2->data.generic_param;
5287 g_error ("implement type compare for %0x!", t1->type);
5295 mymono_metadata_type_hash (MonoType *t1)
5301 hash |= t1->byref << 6; /* do not collide with t1->type values */
5303 case MONO_TYPE_VALUETYPE:
5304 case MONO_TYPE_CLASS:
5305 case MONO_TYPE_SZARRAY:
5306 /* check if the distribution is good enough */
5307 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5309 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5314 static MonoReflectionGenericClass*
5315 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5317 static MonoClass *System_Reflection_MonoGenericClass;
5318 MonoReflectionGenericClass *res;
5319 MonoGenericClass *gclass;
5322 if (!System_Reflection_MonoGenericClass) {
5323 System_Reflection_MonoGenericClass = mono_class_from_name (
5324 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5325 g_assert (System_Reflection_MonoGenericClass);
5328 gclass = geninst->data.generic_class;
5329 gklass = gclass->container_class;
5331 mono_class_init (gclass->klass);
5333 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5335 res->type.type = geninst;
5336 if (gklass->wastypebuilder && gklass->reflection_info)
5337 res->generic_type = gklass->reflection_info;
5339 res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
5345 * mono_type_get_object:
5346 * @domain: an app domain
5349 * Return an System.MonoType object representing the type @type.
5352 mono_type_get_object (MonoDomain *domain, MonoType *type)
5354 MonoReflectionType *res;
5355 MonoClass *klass = mono_class_from_mono_type (type);
5357 mono_domain_lock (domain);
5358 if (!domain->type_hash)
5359 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5360 (GCompareFunc)mymono_metadata_type_equal);
5361 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5362 mono_domain_unlock (domain);
5365 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5366 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5367 mono_g_hash_table_insert (domain->type_hash, type, res);
5368 mono_domain_unlock (domain);
5371 if (klass->reflection_info && !klass->wastypebuilder) {
5372 /* g_assert_not_reached (); */
5373 /* should this be considered an error condition? */
5375 mono_domain_unlock (domain);
5376 return klass->reflection_info;
5379 mono_class_init (klass);
5380 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5382 mono_g_hash_table_insert (domain->type_hash, type, res);
5383 mono_domain_unlock (domain);
5388 * mono_method_get_object:
5389 * @domain: an app domain
5391 * @refclass: the reflected type (can be NULL)
5393 * Return an System.Reflection.MonoMethod object representing the method @method.
5395 MonoReflectionMethod*
5396 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5399 * We use the same C representation for methods and constructors, but the type
5400 * name in C# is different.
5404 MonoReflectionMethod *ret;
5406 if (method->is_inflated) {
5407 MonoReflectionGenericMethod *gret;
5409 refclass = method->klass;
5410 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5411 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5412 cname = "MonoGenericCMethod";
5414 cname = "MonoGenericMethod";
5415 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5417 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5418 gret->method.method = method;
5419 gret->method.name = mono_string_new (domain, method->name);
5420 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5421 CACHE_OBJECT (method, gret, refclass);
5422 return (MonoReflectionMethod *) gret;
5426 refclass = method->klass;
5428 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5429 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5430 cname = "MonoCMethod";
5432 cname = "MonoMethod";
5433 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5435 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5436 ret->method = method;
5437 ret->name = mono_string_new (domain, method->name);
5438 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5439 CACHE_OBJECT (method, ret, refclass);
5444 * mono_field_get_object:
5445 * @domain: an app domain
5449 * Return an System.Reflection.MonoField object representing the field @field
5452 MonoReflectionField*
5453 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5455 MonoReflectionField *res;
5458 CHECK_OBJECT (MonoReflectionField *, field, klass);
5459 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5460 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5463 res->name = mono_string_new (domain, field->name);
5464 if (field->generic_info)
5465 res->attrs = field->generic_info->generic_type->attrs;
5467 res->attrs = field->type->attrs;
5468 res->type = mono_type_get_object (domain, field->type);
5469 CACHE_OBJECT (field, res, klass);
5474 * mono_property_get_object:
5475 * @domain: an app domain
5477 * @property: a property
5479 * Return an System.Reflection.MonoProperty object representing the property @property
5482 MonoReflectionProperty*
5483 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5485 MonoReflectionProperty *res;
5488 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5489 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5490 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5492 res->property = property;
5493 CACHE_OBJECT (property, res, klass);
5498 * mono_event_get_object:
5499 * @domain: an app domain
5503 * Return an System.Reflection.MonoEvent object representing the event @event
5506 MonoReflectionEvent*
5507 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5509 MonoReflectionEvent *res;
5512 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5513 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5514 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5517 CACHE_OBJECT (event, res, klass);
5522 * mono_param_get_objects:
5523 * @domain: an app domain
5526 * Return an System.Reflection.ParameterInfo array object representing the parameters
5527 * in the method @method.
5530 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5532 static MonoClass *System_Reflection_ParameterInfo;
5533 MonoArray *res = NULL;
5534 MonoReflectionMethod *member = NULL;
5535 MonoReflectionParameter *param = NULL;
5536 char **names, **blobs = NULL;
5537 guint32 *types = NULL;
5538 MonoType *type = NULL;
5539 MonoObject *dbnull = mono_get_dbnull_object (domain);
5540 MonoMarshalSpec **mspecs;
5543 if (!System_Reflection_ParameterInfo)
5544 System_Reflection_ParameterInfo = mono_class_from_name (
5545 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5547 if (!mono_method_signature (method)->param_count)
5548 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5550 /* Note: the cache is based on the address of the signature into the method
5551 * since we already cache MethodInfos with the method as keys.
5553 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5555 member = mono_method_get_object (domain, method, NULL);
5556 names = g_new (char *, mono_method_signature (method)->param_count);
5557 mono_method_get_param_names (method, (const char **) names);
5559 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5560 mono_method_get_marshal_info (method, mspecs);
5562 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5563 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5564 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5565 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5566 param->MemberImpl = (MonoObject*)member;
5567 param->NameImpl = mono_string_new (domain, names [i]);
5568 param->PositionImpl = i;
5569 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5571 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5572 param->DefaultValueImpl = dbnull;
5576 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5577 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5578 get_default_param_value_blobs (method, blobs, types);
5581 /* Build MonoType for the type from the Constant Table */
5583 type = g_new0 (MonoType, 1);
5584 type->type = types [i];
5585 type->data.klass = NULL;
5586 if (types [i] == MONO_TYPE_CLASS)
5587 type->data.klass = mono_defaults.object_class;
5589 type->data.klass = mono_class_from_mono_type (type);
5591 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5593 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5594 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5595 param->DefaultValueImpl = dbnull;
5600 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5602 mono_array_set (res, gpointer, i, param);
5609 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5611 mono_metadata_free_marshal_spec (mspecs [i]);
5614 CACHE_OBJECT (&(method->signature), res, NULL);
5619 * mono_method_body_get_object:
5620 * @domain: an app domain
5623 * Return an System.Reflection.MethodBody object representing the method @method.
5625 MonoReflectionMethodBody*
5626 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5628 static MonoClass *System_Reflection_MethodBody = NULL;
5629 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5630 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5631 MonoReflectionMethodBody *ret;
5632 MonoMethodNormal *mn;
5633 MonoMethodHeader *header;
5634 guint32 method_rva, local_var_sig_token;
5636 unsigned char format, flags;
5639 if (!System_Reflection_MethodBody)
5640 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5641 if (!System_Reflection_LocalVariableInfo)
5642 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5643 if (!System_Reflection_ExceptionHandlingClause)
5644 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5646 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5648 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5649 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5650 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5651 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5653 mn = (MonoMethodNormal *)method;
5654 header = mono_method_get_header (method);
5656 /* Obtain local vars signature token */
5657 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5658 ptr = mono_image_rva_map (method->klass->image, method_rva);
5659 flags = *(const unsigned char *) ptr;
5660 format = flags & METHOD_HEADER_FORMAT_MASK;
5662 case METHOD_HEADER_TINY_FORMAT:
5663 case METHOD_HEADER_TINY_FORMAT1:
5664 local_var_sig_token = 0;
5666 case METHOD_HEADER_FAT_FORMAT:
5670 local_var_sig_token = read32 (ptr);
5673 g_assert_not_reached ();
5676 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5678 ret->init_locals = header->init_locals;
5679 ret->max_stack = header->max_stack;
5680 ret->local_var_sig_token = local_var_sig_token;
5681 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5682 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5685 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5686 for (i = 0; i < header->num_locals; ++i) {
5687 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5688 info->local_type = mono_type_get_object (domain, header->locals [i]);
5689 info->is_pinned = header->locals [i]->pinned;
5690 info->local_index = i;
5691 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5695 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5696 for (i = 0; i < header->num_clauses; ++i) {
5697 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5698 MonoExceptionClause *clause = &header->clauses [i];
5700 info->flags = clause->flags;
5701 info->try_offset = clause->try_offset;
5702 info->try_length = clause->try_len;
5703 info->handler_offset = clause->handler_offset;
5704 info->handler_length = clause->handler_len;
5705 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5706 info->filter_offset = clause->data.filter_offset;
5707 else if (clause->data.catch_class)
5708 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5710 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5713 CACHE_OBJECT (method, ret, NULL);
5718 mono_get_dbnull_object (MonoDomain *domain)
5722 static MonoClassField *dbnull_value_field = NULL;
5724 if (!dbnull_value_field) {
5725 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5726 mono_class_init (klass);
5727 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5728 g_assert (dbnull_value_field);
5730 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5737 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5739 guint32 param_index, i, lastp, crow = 0;
5740 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5743 MonoClass *klass = method->klass;
5744 MonoImage *image = klass->image;
5745 MonoMethodSignature *methodsig = mono_method_signature (method);
5747 MonoTableInfo *constt;
5748 MonoTableInfo *methodt;
5749 MonoTableInfo *paramt;
5751 if (!methodsig->param_count)
5754 if (klass->generic_class) {
5755 return; /* FIXME - ??? */
5758 mono_class_init (klass);
5760 if (klass->image->dynamic) {
5761 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5762 if (aux && aux->param_defaults) {
5763 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5764 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5769 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5770 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5771 constt = &image->tables [MONO_TABLE_CONSTANT];
5773 idx = mono_method_get_index (method) - 1;
5774 g_assert (idx != -1);
5776 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5777 if (idx + 1 < methodt->rows)
5778 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5780 lastp = paramt->rows + 1;
5782 for (i = param_index; i < lastp; ++i) {
5785 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5786 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5788 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5791 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5796 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5797 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5798 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5805 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5810 MonoType *basetype = type;
5815 klass = mono_class_from_mono_type (type);
5816 if (klass->valuetype) {
5817 object = mono_object_new (domain, klass);
5818 retval = ((gchar *) object + sizeof (MonoObject));
5819 if (klass->enumtype)
5820 basetype = klass->enum_basetype;
5825 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5832 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5836 memset (assembly, 0, sizeof (MonoAssemblyName));
5838 assembly->culture = "";
5839 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5841 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5844 while (g_ascii_isspace (*p) || *p == ',') {
5853 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5855 assembly->major = strtoul (p, &s, 10);
5856 if (s == p || *s != '.')
5859 assembly->minor = strtoul (p, &s, 10);
5860 if (s == p || *s != '.')
5863 assembly->build = strtoul (p, &s, 10);
5864 if (s == p || *s != '.')
5867 assembly->revision = strtoul (p, &s, 10);
5871 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5873 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5874 assembly->culture = "";
5877 assembly->culture = p;
5878 while (*p && *p != ',') {
5882 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5884 if (strncmp (p, "null", 4) == 0) {
5889 while (*p && *p != ',') {
5892 len = (p - start + 1);
5893 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5894 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5895 g_strlcpy (assembly->public_key_token, start, len);
5898 while (*p && *p != ',')
5902 while (g_ascii_isspace (*p) || *p == ',') {
5916 * mono_reflection_parse_type:
5919 * Parse a type name as accepted by the GetType () method and output the info
5920 * extracted in the info structure.
5921 * the name param will be mangled, so, make a copy before passing it to this function.
5922 * The fields in info will be valid until the memory pointed to by name is valid.
5924 * See also mono_type_get_name () below.
5926 * Returns: 0 on parse error.
5929 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5931 char *start, *p, *w, *last_point, *startn;
5932 int in_modifiers = 0;
5933 int isbyref = 0, rank;
5935 start = p = w = name;
5937 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5938 info->name = info->name_space = NULL;
5939 info->nested = NULL;
5940 info->modifiers = NULL;
5942 /* last_point separates the namespace from the name */
5948 *p = 0; /* NULL terminate the name */
5950 info->nested = g_list_append (info->nested, startn);
5951 /* we have parsed the nesting namespace + name */
5955 info->name_space = start;
5957 info->name = last_point + 1;
5959 info->name_space = (char *)"";
5985 info->name_space = start;
5987 info->name = last_point + 1;
5989 info->name_space = (char *)"";
5996 if (isbyref) /* only one level allowed by the spec */
5999 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6003 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6014 else if (*p != '*') /* '*' means unknown lower bound */
6020 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6025 if (g_ascii_isspace (*p)) {
6032 return 0; /* missing assembly name */
6033 if (!assembly_name_to_aname (&info->assembly, p))
6040 if (info->assembly.name)
6043 *w = 0; /* terminate class name */
6044 if (!info->name || !*info->name)
6046 /* add other consistency checks */
6051 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6058 image = mono_defaults.corlib;
6061 klass = mono_class_from_name_case (image, info->name_space, info->name);
6063 klass = mono_class_from_name (image, info->name_space, info->name);
6066 for (mod = info->nested; mod; mod = mod->next) {
6069 mono_class_init (klass);
6070 nested = klass->nested_classes;
6073 klass = nested->data;
6075 if (g_strcasecmp (klass->name, mod->data) == 0)
6078 if (strcmp (klass->name, mod->data) == 0)
6082 nested = nested->next;
6089 mono_class_init (klass);
6090 for (mod = info->modifiers; mod; mod = mod->next) {
6091 modval = GPOINTER_TO_UINT (mod->data);
6092 if (!modval) { /* byref: must be last modifier */
6093 return &klass->this_arg;
6094 } else if (modval == -1) {
6095 klass = mono_ptr_class_get (&klass->byval_arg);
6096 } else { /* array rank */
6097 klass = mono_array_class_get (klass, modval);
6099 mono_class_init (klass);
6102 return &klass->byval_arg;
6106 * mono_reflection_get_type:
6107 * @image: a metadata context
6108 * @info: type description structure
6109 * @ignorecase: flag for case-insensitive string compares
6110 * @type_resolve: whenever type resolve was already tried
6112 * Build a MonoType from the type description in @info.
6117 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6120 MonoReflectionAssembly *assembly;
6124 type = mono_reflection_get_type_internal (image, info, ignorecase);
6127 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6134 *type_resolve = TRUE;
6137 /* Reconstruct the type name */
6138 fullName = g_string_new ("");
6139 if (info->name_space && (info->name_space [0] != '\0'))
6140 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6142 g_string_printf (fullName, info->name);
6143 for (mod = info->nested; mod; mod = mod->next)
6144 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6146 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6148 if (assembly->assembly->dynamic) {
6149 /* Enumerate all modules */
6150 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6154 if (abuilder->modules) {
6155 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6156 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6157 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6163 if (!type && abuilder->loaded_modules) {
6164 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6165 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6166 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6173 type = mono_reflection_get_type_internal (assembly->assembly->image,
6176 g_string_free (fullName, TRUE);
6181 * mono_reflection_type_from_name:
6183 * @image: a metadata context (can be NULL).
6185 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6186 * it defaults to get the type from @image or, if @image is NULL or loading
6187 * from it fails, uses corlib.
6191 mono_reflection_type_from_name (char *name, MonoImage *image)
6194 MonoTypeNameParse info;
6195 MonoAssembly *assembly;
6197 gboolean type_resolve = FALSE;
6199 /* Make a copy since parse_type modifies its argument */
6200 tmp = g_strdup (name);
6202 /*g_print ("requested type %s\n", str);*/
6203 if (!mono_reflection_parse_type (tmp, &info)) {
6205 g_list_free (info.modifiers);
6206 g_list_free (info.nested);
6210 if (info.assembly.name) {
6211 assembly = mono_assembly_loaded (&info.assembly);
6213 /* then we must load the assembly ourselve - see #60439 */
6214 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6217 g_list_free (info.modifiers);
6218 g_list_free (info.nested);
6222 image = assembly->image;
6223 } else if (image == NULL) {
6224 image = mono_defaults.corlib;
6227 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6228 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6229 image = mono_defaults.corlib;
6230 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6234 g_list_free (info.modifiers);
6235 g_list_free (info.nested);
6240 * mono_reflection_get_token:
6242 * Return the metadata token of OBJ which should be an object
6243 * representing a metadata element.
6246 mono_reflection_get_token (MonoObject *obj)
6251 klass = obj->vtable->klass;
6253 if (strcmp (klass->name, "MethodBuilder") == 0) {
6254 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6256 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6257 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6258 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6260 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6261 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6262 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6263 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6264 if (tb->generic_params) {
6265 g_assert_not_reached ();
6267 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6269 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6270 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6271 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6272 } else if (strcmp (klass->name, "MonoType") == 0) {
6273 MonoReflectionType *tb = (MonoReflectionType *)obj;
6274 token = mono_class_from_mono_type (tb->type)->type_token;
6275 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6276 strcmp (klass->name, "MonoMethod") == 0) {
6277 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6278 if (m->method->is_inflated) {
6279 g_assert_not_reached ();
6280 } else if (mono_method_signature (m->method)->generic_param_count) {
6281 g_assert_not_reached ();
6282 } else if (m->method->klass->generic_class) {
6283 g_assert_not_reached ();
6285 token = m->method->token;
6287 } else if (strcmp (klass->name, "MonoField") == 0) {
6288 MonoReflectionField *f = (MonoReflectionField*)obj;
6290 token = mono_class_get_field_token (f->field);
6291 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6292 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6294 token = mono_class_get_property_token (p->property);
6295 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6296 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6298 token = mono_class_get_event_token (p->event);
6299 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6300 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6302 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6303 } else if (strcmp (klass->name, "Module") == 0) {
6304 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6307 } else if (strcmp (klass->name, "Assembly") == 0) {
6308 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6310 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6311 MonoException *ex = mono_get_exception_not_implemented (msg);
6313 mono_raise_exception (ex);
6320 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6322 int slen, type = t->type;
6327 case MONO_TYPE_BOOLEAN: {
6328 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6333 case MONO_TYPE_CHAR:
6335 case MONO_TYPE_I2: {
6336 guint16 *val = g_malloc (sizeof (guint16));
6341 #if SIZEOF_VOID_P == 4
6347 case MONO_TYPE_I4: {
6348 guint32 *val = g_malloc (sizeof (guint32));
6353 #if SIZEOF_VOID_P == 8
6354 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6359 case MONO_TYPE_I8: {
6360 guint64 *val = g_malloc (sizeof (guint64));
6365 case MONO_TYPE_VALUETYPE:
6366 if (t->data.klass->enumtype) {
6367 type = t->data.klass->enum_basetype->type;
6370 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6373 case MONO_TYPE_STRING:
6374 if (*p == (char)0xFF) {
6378 slen = mono_metadata_decode_value (p, &p);
6380 return mono_string_new_len (mono_domain_get (), p, slen);
6381 case MONO_TYPE_CLASS: {
6384 if (*p == (char)0xFF) {
6389 slen = mono_metadata_decode_value (p, &p);
6390 n = g_memdup (p, slen + 1);
6392 t = mono_reflection_type_from_name (n, image);
6394 g_warning ("Cannot load type '%s'", n);
6398 return mono_type_get_object (mono_domain_get (), t);
6402 case MONO_TYPE_OBJECT: {
6405 MonoClass *subc = NULL;
6410 } else if (subt == 0x0E) {
6411 type = MONO_TYPE_STRING;
6413 } else if (subt == 0x55) {
6416 slen = mono_metadata_decode_value (p, &p);
6417 n = g_memdup (p, slen + 1);
6419 t = mono_reflection_type_from_name (n, image);
6421 g_warning ("Cannot load type '%s'", n);
6424 subc = mono_class_from_mono_type (t);
6425 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6426 MonoType simple_type = {{0}};
6427 simple_type.type = subt;
6428 subc = mono_class_from_mono_type (&simple_type);
6430 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6432 val = load_cattr_value (image, &subc->byval_arg, p, end);
6433 obj = mono_object_new (mono_domain_get (), subc);
6434 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6438 case MONO_TYPE_SZARRAY: {
6440 guint32 i, alen, basetype;
6443 if (alen == 0xffffffff) {
6447 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6448 basetype = t->data.klass->byval_arg.type;
6453 case MONO_TYPE_BOOLEAN:
6454 for (i = 0; i < alen; i++) {
6455 MonoBoolean val = *p++;
6456 mono_array_set (arr, MonoBoolean, i, val);
6459 case MONO_TYPE_CHAR:
6462 for (i = 0; i < alen; i++) {
6463 guint16 val = read16 (p);
6464 mono_array_set (arr, guint16, i, val);
6471 for (i = 0; i < alen; i++) {
6472 guint32 val = read32 (p);
6473 mono_array_set (arr, guint32, i, val);
6480 for (i = 0; i < alen; i++) {
6481 guint64 val = read64 (p);
6482 mono_array_set (arr, guint64, i, val);
6486 case MONO_TYPE_CLASS:
6487 case MONO_TYPE_OBJECT:
6488 case MONO_TYPE_STRING:
6489 for (i = 0; i < alen; i++) {
6490 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6491 mono_array_set (arr, gpointer, i, item);
6495 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6501 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6507 type_is_reference (MonoType *type)
6509 switch (type->type) {
6510 case MONO_TYPE_BOOLEAN:
6511 case MONO_TYPE_CHAR:
6524 case MONO_TYPE_VALUETYPE:
6532 free_param_data (MonoMethodSignature *sig, void **params) {
6534 for (i = 0; i < sig->param_count; ++i) {
6535 if (!type_is_reference (sig->params [i]))
6536 g_free (params [i]);
6541 * Find the field index in the metadata FieldDef table.
6544 find_field_index (MonoClass *klass, MonoClassField *field) {
6547 for (i = 0; i < klass->field.count; ++i) {
6548 if (field == &klass->fields [i])
6549 return klass->field.first + 1 + i;
6555 * Find the property index in the metadata Property table.
6558 find_property_index (MonoClass *klass, MonoProperty *property) {
6561 for (i = 0; i < klass->property.count; ++i) {
6562 if (property == &klass->properties [i])
6563 return klass->property.first + 1 + i;
6569 * Find the event index in the metadata Event table.
6572 find_event_index (MonoClass *klass, MonoEvent *event) {
6575 for (i = 0; i < klass->event.count; ++i) {
6576 if (event == &klass->events [i])
6577 return klass->event.first + 1 + i;
6583 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6585 const char *p = data;
6587 guint32 i, j, num_named;
6591 mono_class_init (method->klass);
6594 attr = mono_object_new (mono_domain_get (), method->klass);
6595 mono_runtime_invoke (method, attr, NULL, NULL);
6599 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6602 /*g_print ("got attr %s\n", method->klass->name);*/
6604 /* Allocate using alloca so it gets GC tracking */
6605 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6609 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6610 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6614 attr = mono_object_new (mono_domain_get (), method->klass);
6615 mono_runtime_invoke (method, attr, params, NULL);
6616 free_param_data (method->signature, params);
6617 num_named = read16 (named);
6619 for (j = 0; j < num_named; j++) {
6621 gboolean is_boxed = FALSE;
6622 char *name, named_type, data_type;
6623 named_type = *named++;
6624 data_type = *named++; /* type of data */
6625 if (data_type == 0x51)
6628 if (data_type == 0x55) {
6631 type_len = mono_metadata_decode_blob_size (named, &named);
6632 type_name = g_malloc (type_len + 1);
6633 memcpy (type_name, named, type_len);
6634 type_name [type_len] = 0;
6636 /* FIXME: lookup the type and check type consistency */
6637 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6638 /* this seems to be the type of the element of the array */
6639 /* g_print ("skipping 0x%02x after prop\n", *named); */
6642 name_len = mono_metadata_decode_blob_size (named, &named);
6643 name = g_malloc (name_len + 1);
6644 memcpy (name, named, name_len);
6645 name [name_len] = 0;
6647 if (named_type == 0x53) {
6648 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6649 void *val = load_cattr_value (image, field->type, named, &named);
6650 mono_field_set_value (attr, field, val);
6651 if (!type_is_reference (field->type))
6653 } else if (named_type == 0x54) {
6656 MonoType *prop_type;
6658 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6659 /* can we have more that 1 arg in a custom attr named property? */
6660 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6661 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6662 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6663 mono_property_set_value (prop, attr, pparams, NULL);
6664 if (!type_is_reference (prop_type))
6665 g_free (pparams [0]);
6674 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6681 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6682 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6683 for (i = 0; i < cinfo->num_attrs; ++i) {
6684 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6685 mono_array_set (result, gpointer, i, attr);
6691 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6693 guint32 mtoken, i, len;
6694 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6696 MonoCustomAttrInfo *ainfo;
6697 GList *tmp, *list = NULL;
6700 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6702 i = mono_metadata_custom_attrs_from_index (image, idx);
6706 while (i < ca->rows) {
6707 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6709 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6712 len = g_list_length (list);
6715 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6716 ainfo->num_attrs = len;
6717 ainfo->image = image;
6718 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6719 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6720 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6721 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6722 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6723 mtoken |= MONO_TOKEN_METHOD_DEF;
6725 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6726 mtoken |= MONO_TOKEN_MEMBER_REF;
6729 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6732 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6733 if (!ainfo->attrs [i].ctor)
6734 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6735 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6736 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6737 ainfo->attrs [i].data = data;
6745 mono_custom_attrs_from_method (MonoMethod *method)
6747 MonoCustomAttrInfo *cinfo;
6750 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6752 idx = mono_method_get_index (method);
6753 idx <<= MONO_CUSTOM_ATTR_BITS;
6754 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6755 return mono_custom_attrs_from_index (method->klass->image, idx);
6759 mono_custom_attrs_from_class (MonoClass *klass)
6761 MonoCustomAttrInfo *cinfo;
6764 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6766 idx = mono_metadata_token_index (klass->type_token);
6767 idx <<= MONO_CUSTOM_ATTR_BITS;
6768 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6769 return mono_custom_attrs_from_index (klass->image, idx);
6773 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6775 MonoCustomAttrInfo *cinfo;
6778 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6780 idx = 1; /* there is only one assembly */
6781 idx <<= MONO_CUSTOM_ATTR_BITS;
6782 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6783 return mono_custom_attrs_from_index (assembly->image, idx);
6786 static MonoCustomAttrInfo*
6787 mono_custom_attrs_from_module (MonoImage *image)
6789 MonoCustomAttrInfo *cinfo;
6792 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6794 idx = 1; /* there is only one module */
6795 idx <<= MONO_CUSTOM_ATTR_BITS;
6796 idx |= MONO_CUSTOM_ATTR_MODULE;
6797 return mono_custom_attrs_from_index (image, idx);
6801 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6803 MonoCustomAttrInfo *cinfo;
6806 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6808 idx = find_property_index (klass, property);
6809 idx <<= MONO_CUSTOM_ATTR_BITS;
6810 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6811 return mono_custom_attrs_from_index (klass->image, idx);
6815 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6817 MonoCustomAttrInfo *cinfo;
6820 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6822 idx = find_event_index (klass, event);
6823 idx <<= MONO_CUSTOM_ATTR_BITS;
6824 idx |= MONO_CUSTOM_ATTR_EVENT;
6825 return mono_custom_attrs_from_index (klass->image, idx);
6829 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6831 MonoCustomAttrInfo *cinfo;
6834 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6836 idx = find_field_index (klass, field);
6837 idx <<= MONO_CUSTOM_ATTR_BITS;
6838 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6839 return mono_custom_attrs_from_index (klass->image, idx);
6843 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6846 guint32 i, idx, method_index;
6847 guint32 param_list, param_last, param_pos, found;
6849 MonoReflectionMethodAux *aux;
6851 if (method->klass->image->dynamic) {
6852 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6853 if (!aux || !aux->param_cattr)
6855 return aux->param_cattr [param];
6858 image = method->klass->image;
6859 method_index = mono_method_get_index (method);
6860 ca = &image->tables [MONO_TABLE_METHOD];
6862 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
6863 /* FIXME FIXME FIXME */
6867 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6868 if (method_index == ca->rows) {
6869 ca = &image->tables [MONO_TABLE_PARAM];
6870 param_last = ca->rows + 1;
6872 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6873 ca = &image->tables [MONO_TABLE_PARAM];
6876 for (i = param_list; i < param_last; ++i) {
6877 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6878 if (param_pos == param) {
6886 idx <<= MONO_CUSTOM_ATTR_BITS;
6887 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6888 return mono_custom_attrs_from_index (image, idx);
6892 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
6896 for (i = 0; i < ainfo->num_attrs; ++i) {
6897 klass = ainfo->attrs [i].ctor->klass;
6898 if (mono_class_has_parent (klass, attr_klass))
6905 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
6912 for (i = 0; i < ainfo->num_attrs; ++i) {
6913 klass = ainfo->attrs [i].ctor->klass;
6914 if (mono_class_has_parent (klass, attr_klass)) {
6919 if (attr_index == -1)
6922 attrs = mono_custom_attrs_construct (ainfo);
6924 return mono_array_get (attrs, MonoObject*, attr_index);
6930 * mono_reflection_get_custom_attrs_info:
6931 * @obj: a reflection object handle
6933 * Return the custom attribute info for attributes defined for the
6934 * reflection handle @obj. The objects.
6937 mono_reflection_get_custom_attrs_info (MonoObject *obj)
6940 MonoCustomAttrInfo *cinfo = NULL;
6942 klass = obj->vtable->klass;
6943 if (klass == mono_defaults.monotype_class) {
6944 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6945 klass = mono_class_from_mono_type (rtype->type);
6946 cinfo = mono_custom_attrs_from_class (klass);
6947 } else if (strcmp ("Assembly", klass->name) == 0) {
6948 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6949 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6950 } else if (strcmp ("Module", klass->name) == 0) {
6951 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6952 cinfo = mono_custom_attrs_from_module (module->image);
6953 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6954 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6955 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6956 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6957 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6958 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6959 } else if (strcmp ("MonoField", klass->name) == 0) {
6960 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6961 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6962 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6963 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6964 cinfo = mono_custom_attrs_from_method (rmethod->method);
6965 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
6966 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
6967 cinfo = mono_custom_attrs_from_method (method);
6968 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6969 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6970 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6971 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6972 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6973 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6974 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6975 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6976 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6977 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6978 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6979 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6980 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6981 } else { /* handle other types here... */
6982 g_error ("get custom attrs not yet supported for %s", klass->name);
6989 * mono_reflection_get_custom_attrs:
6990 * @obj: a reflection object handle
6992 * Return an array with all the custom attributes defined of the
6993 * reflection handle @obj. The objects are fully build.
6996 mono_reflection_get_custom_attrs (MonoObject *obj)
6999 MonoCustomAttrInfo *cinfo;
7001 cinfo = mono_reflection_get_custom_attrs_info (obj);
7003 result = mono_custom_attrs_construct (cinfo);
7005 mono_custom_attrs_free (cinfo);
7008 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7009 result = mono_array_new (mono_domain_get (), klass, 0);
7015 static MonoMethodSignature*
7016 parameters_to_signature (MonoArray *parameters) {
7017 MonoMethodSignature *sig;
7020 count = parameters? mono_array_length (parameters): 0;
7022 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7023 sig->param_count = count;
7024 sig->sentinelpos = -1; /* FIXME */
7025 for (i = 0; i < count; ++i) {
7026 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7027 sig->params [i] = pt->type;
7032 static MonoMethodSignature*
7033 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7034 MonoMethodSignature *sig;
7036 sig = parameters_to_signature (ctor->parameters);
7037 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7038 sig->ret = &mono_defaults.void_class->byval_arg;
7042 static MonoMethodSignature*
7043 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7044 MonoMethodSignature *sig;
7046 sig = parameters_to_signature (method->parameters);
7047 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7048 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7049 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7053 static MonoMethodSignature*
7054 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7055 MonoMethodSignature *sig;
7057 sig = parameters_to_signature (method->parameters);
7058 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7059 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7060 sig->generic_param_count = 0;
7065 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7067 MonoClass *klass = mono_object_class (prop);
7068 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7069 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7070 *name = mono_string_to_utf8 (pb->name);
7071 *type = pb->type->type;
7073 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7074 *name = g_strdup (p->property->name);
7075 if (p->property->get)
7076 *type = mono_method_signature (p->property->get)->ret;
7078 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7083 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7085 MonoClass *klass = mono_object_class (field);
7086 if (strcmp (klass->name, "FieldBuilder") == 0) {
7087 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7088 *name = mono_string_to_utf8 (fb->name);
7089 *type = fb->type->type;
7091 MonoReflectionField *f = (MonoReflectionField *)field;
7092 *name = g_strdup (f->field->name);
7093 *type = f->field->type;
7098 * Encode a value in a custom attribute stream of bytes.
7099 * The value to encode is either supplied as an object in argument val
7100 * (valuetypes are boxed), or as a pointer to the data in the
7102 * @type represents the type of the value
7103 * @buffer is the start of the buffer
7104 * @p the current position in the buffer
7105 * @buflen contains the size of the buffer and is used to return the new buffer size
7106 * if this needs to be realloced.
7107 * @retbuffer and @retp return the start and the position of the buffer
7110 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7112 MonoTypeEnum simple_type;
7114 if ((p-buffer) + 10 >= *buflen) {
7117 newbuf = g_realloc (buffer, *buflen);
7118 p = newbuf + (p-buffer);
7122 argval = ((char*)arg + sizeof (MonoObject));
7123 simple_type = type->type;
7125 switch (simple_type) {
7126 case MONO_TYPE_BOOLEAN:
7131 case MONO_TYPE_CHAR:
7134 swap_with_size (p, argval, 2, 1);
7140 swap_with_size (p, argval, 4, 1);
7146 swap_with_size (p, argval, 8, 1);
7149 case MONO_TYPE_VALUETYPE:
7150 if (type->data.klass->enumtype) {
7151 simple_type = type->data.klass->enum_basetype->type;
7154 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7157 case MONO_TYPE_STRING: {
7164 str = mono_string_to_utf8 ((MonoString*)arg);
7165 slen = strlen (str);
7166 if ((p-buffer) + 10 + slen >= *buflen) {
7170 newbuf = g_realloc (buffer, *buflen);
7171 p = newbuf + (p-buffer);
7174 mono_metadata_encode_value (slen, p, &p);
7175 memcpy (p, str, slen);
7180 case MONO_TYPE_CLASS: {
7188 k = mono_object_class (arg);
7189 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7190 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7191 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7193 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7194 slen = strlen (str);
7195 if ((p-buffer) + 10 + slen >= *buflen) {
7199 newbuf = g_realloc (buffer, *buflen);
7200 p = newbuf + (p-buffer);
7203 mono_metadata_encode_value (slen, p, &p);
7204 memcpy (p, str, slen);
7209 case MONO_TYPE_SZARRAY: {
7211 MonoClass *eclass, *arg_eclass;
7214 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7217 len = mono_array_length ((MonoArray*)arg);
7219 *p++ = (len >> 8) & 0xff;
7220 *p++ = (len >> 16) & 0xff;
7221 *p++ = (len >> 24) & 0xff;
7223 *retbuffer = buffer;
7224 eclass = type->data.klass;
7225 arg_eclass = mono_object_class (arg)->element_class;
7226 if (eclass->valuetype && arg_eclass->valuetype) {
7227 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7228 int elsize = mono_class_array_element_size (eclass);
7229 for (i = 0; i < len; ++i) {
7230 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7234 for (i = 0; i < len; ++i) {
7235 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7240 /* it may be a boxed value or a Type */
7241 case MONO_TYPE_OBJECT: {
7247 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7252 klass = mono_object_class (arg);
7254 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7257 } else if (klass->enumtype) {
7259 } else if (klass == mono_defaults.string_class) {
7260 simple_type = MONO_TYPE_STRING;
7263 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7264 *p++ = simple_type = klass->byval_arg.type;
7267 g_error ("unhandled type in custom attr");
7269 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7270 slen = strlen (str);
7271 if ((p-buffer) + 10 + slen >= *buflen) {
7275 newbuf = g_realloc (buffer, *buflen);
7276 p = newbuf + (p-buffer);
7279 mono_metadata_encode_value (slen, p, &p);
7280 memcpy (p, str, slen);
7283 simple_type = klass->enum_basetype->type;
7287 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7290 *retbuffer = buffer;
7294 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7297 /* Preallocate a large enough buffer */
7298 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7299 char *str = type_get_qualified_name (type, NULL);
7305 len += strlen (name);
7307 if ((p-buffer) + 20 + len >= *buflen) {
7311 newbuf = g_realloc (buffer, *buflen);
7312 p = newbuf + (p-buffer);
7316 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7317 char *str = type_get_qualified_name (type, NULL);
7318 int slen = strlen (str);
7322 * This seems to be optional...
7325 mono_metadata_encode_value (slen, p, &p);
7326 memcpy (p, str, slen);
7329 } else if (type->type == MONO_TYPE_OBJECT) {
7331 } else if (type->type == MONO_TYPE_CLASS) {
7332 /* it should be a type: encode_cattr_value () has the check */
7335 mono_metadata_encode_value (type->type, p, &p);
7336 if (type->type == MONO_TYPE_SZARRAY)
7337 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7339 len = strlen (name);
7340 mono_metadata_encode_value (len, p, &p);
7341 memcpy (p, name, len);
7343 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7345 *retbuffer = buffer;
7349 * mono_reflection_get_custom_attrs_blob:
7350 * @ctor: custom attribute constructor
7351 * @ctorArgs: arguments o the constructor
7357 * Creates the blob of data that needs to be saved in the metadata and that represents
7358 * the custom attributed described by @ctor, @ctorArgs etc.
7359 * Returns: a Byte array representing the blob of data.
7362 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7365 MonoMethodSignature *sig;
7370 MONO_ARCH_SAVE_REGS;
7372 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7373 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7375 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7377 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7379 p = buffer = g_malloc (buflen);
7380 /* write the prolog */
7383 for (i = 0; i < sig->param_count; ++i) {
7384 arg = mono_array_get (ctorArgs, MonoObject*, i);
7385 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7389 i += mono_array_length (properties);
7391 i += mono_array_length (fields);
7393 *p++ = (i >> 8) & 0xff;
7396 for (i = 0; i < mono_array_length (properties); ++i) {
7400 prop = mono_array_get (properties, gpointer, i);
7401 get_prop_name_and_type (prop, &pname, &ptype);
7402 *p++ = 0x54; /* PROPERTY signature */
7403 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7410 for (i = 0; i < mono_array_length (fields); ++i) {
7414 field = mono_array_get (fields, gpointer, i);
7415 get_field_name_and_type (field, &fname, &ftype);
7416 *p++ = 0x53; /* FIELD signature */
7417 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7422 g_assert (p - buffer <= buflen);
7423 buflen = p - buffer;
7424 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7425 p = mono_array_addr (result, char, 0);
7426 memcpy (p, buffer, buflen);
7428 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7434 * mono_reflection_setup_internal_class:
7435 * @tb: a TypeBuilder object
7437 * Creates a MonoClass that represents the TypeBuilder.
7438 * This is a trick that lets us simplify a lot of reflection code
7439 * (and will allow us to support Build and Run assemblies easier).
7442 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7444 MonoClass *klass, *parent;
7446 MONO_ARCH_SAVE_REGS;
7448 mono_loader_lock ();
7451 /* check so we can compile corlib correctly */
7452 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7453 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7454 parent = tb->parent->type->data.klass;
7456 parent = my_mono_class_from_mono_type (tb->parent->type);
7462 /* the type has already being created: it means we just have to change the parent */
7463 if (tb->type.type) {
7464 klass = mono_class_from_mono_type (tb->type.type);
7465 klass->parent = NULL;
7466 /* fool mono_class_setup_parent */
7467 g_free (klass->supertypes);
7468 klass->supertypes = NULL;
7469 mono_class_setup_parent (klass, parent);
7470 mono_class_setup_mono_type (klass);
7471 mono_loader_unlock ();
7475 klass = g_new0 (MonoClass, 1);
7477 klass->image = &tb->module->dynamic_image->image;
7479 klass->inited = 1; /* we lie to the runtime */
7480 klass->name = mono_string_to_utf8 (tb->name);
7481 klass->name_space = mono_string_to_utf8 (tb->nspace);
7482 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7483 klass->flags = tb->attrs;
7485 klass->element_class = klass;
7486 klass->reflection_info = tb; /* need to pin. */
7488 /* Put into cache so mono_class_get () will find it */
7489 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7491 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7492 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7494 if (parent != NULL) {
7495 mono_class_setup_parent (klass, parent);
7496 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7497 const char *old_n = klass->name;
7498 /* trick to get relative numbering right when compiling corlib */
7499 klass->name = "BuildingObject";
7500 mono_class_setup_parent (klass, mono_defaults.object_class);
7501 klass->name = old_n;
7504 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7505 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7506 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7507 klass->instance_size = sizeof (MonoObject);
7508 klass->size_inited = 1;
7509 mono_class_setup_vtable_general (klass, NULL, 0);
7512 mono_class_setup_mono_type (klass);
7514 mono_class_setup_supertypes (klass);
7517 * FIXME: handle interfaces.
7520 tb->type.type = &klass->byval_arg;
7522 if (tb->nesting_type) {
7523 g_assert (tb->nesting_type->type);
7524 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7527 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7529 mono_loader_unlock ();
7533 * mono_reflection_setup_generic_class:
7534 * @tb: a TypeBuilder object
7536 * Setup the generic class before adding the first generic parameter.
7539 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7543 MONO_ARCH_SAVE_REGS;
7545 klass = my_mono_class_from_mono_type (tb->type.type);
7546 if (tb->generic_container)
7549 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7550 tb->generic_container->klass = klass;
7552 tb->generic_container->context.container = tb->generic_container;
7556 * mono_reflection_create_generic_class:
7557 * @tb: a TypeBuilder object
7559 * Creates the generic class after all generic parameters have been added.
7562 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7567 MONO_ARCH_SAVE_REGS;
7569 klass = my_mono_class_from_mono_type (tb->type.type);
7571 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7573 if (klass->generic_container || (count == 0))
7576 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7578 klass->generic_container = tb->generic_container;
7580 klass->generic_container->type_argc = count;
7581 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7583 for (i = 0; i < count; i++) {
7584 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7585 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7586 g_assert (klass->generic_container->type_params [i].owner);
7589 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7593 * mono_reflection_create_internal_class:
7594 * @tb: a TypeBuilder object
7596 * Actually create the MonoClass that is associated with the TypeBuilder.
7599 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7603 MONO_ARCH_SAVE_REGS;
7605 klass = my_mono_class_from_mono_type (tb->type.type);
7607 mono_loader_lock ();
7608 if (klass->enumtype && klass->enum_basetype == NULL) {
7609 MonoReflectionFieldBuilder *fb;
7612 g_assert (tb->fields != NULL);
7613 g_assert (mono_array_length (tb->fields) >= 1);
7615 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7617 klass->enum_basetype = fb->type->type;
7618 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7619 if (!klass->element_class)
7620 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7623 * get the element_class from the current corlib.
7625 ec = default_class_from_mono_type (klass->enum_basetype);
7626 klass->instance_size = ec->instance_size;
7627 klass->size_inited = 1;
7629 * this is almost safe to do with enums and it's needed to be able
7630 * to create objects of the enum type (for use in SetConstant).
7632 /* FIXME: Does this mean enums can't have method overrides ? */
7633 mono_class_setup_vtable_general (klass, NULL, 0);
7635 mono_loader_unlock ();
7638 static MonoMarshalSpec*
7639 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7640 MonoReflectionMarshal *minfo)
7642 MonoMarshalSpec *res;
7644 res = g_new0 (MonoMarshalSpec, 1);
7645 res->native = minfo->type;
7647 switch (minfo->type) {
7648 case MONO_NATIVE_LPARRAY:
7649 res->data.array_data.elem_type = minfo->eltype;
7650 if (minfo->has_size) {
7651 res->data.array_data.param_num = minfo->param_num;
7652 res->data.array_data.num_elem = minfo->count;
7653 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
7656 res->data.array_data.param_num = -1;
7657 res->data.array_data.num_elem = -1;
7658 res->data.array_data.elem_mult = -1;
7662 case MONO_NATIVE_BYVALTSTR:
7663 case MONO_NATIVE_BYVALARRAY:
7664 res->data.array_data.num_elem = minfo->count;
7667 case MONO_NATIVE_CUSTOM:
7668 if (minfo->marshaltyperef)
7669 res->data.custom_data.custom_name =
7670 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7672 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7682 MonoReflectionMarshal*
7683 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7684 MonoMarshalSpec *spec)
7686 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7687 MonoReflectionMarshal *minfo;
7690 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7691 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7692 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7693 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7696 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7697 minfo->type = spec->native;
7699 switch (minfo->type) {
7700 case MONO_NATIVE_LPARRAY:
7701 minfo->eltype = spec->data.array_data.elem_type;
7702 minfo->count = spec->data.array_data.num_elem;
7703 minfo->param_num = spec->data.array_data.param_num;
7706 case MONO_NATIVE_BYVALTSTR:
7707 case MONO_NATIVE_BYVALARRAY:
7708 minfo->count = spec->data.array_data.num_elem;
7711 case MONO_NATIVE_CUSTOM:
7712 if (spec->data.custom_data.custom_name) {
7713 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7715 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7717 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7719 if (spec->data.custom_data.cookie)
7720 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7731 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7732 ReflectionMethodBuilder *rmb,
7733 MonoMethodSignature *sig)
7736 MonoMethodNormal *pm;
7737 MonoMarshalSpec **specs;
7738 MonoReflectionMethodAux *method_aux;
7741 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7742 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7743 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7745 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7747 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7749 pm = (MonoMethodNormal*)m;
7752 m->flags = rmb->attrs;
7753 m->iflags = rmb->iattrs;
7754 m->name = mono_string_to_utf8 (rmb->name);
7758 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7760 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7761 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7764 m->signature->pinvoke = 1;
7765 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7766 m->signature->pinvoke = 1;
7768 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7770 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7771 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7773 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7775 if (klass->image->dynamic)
7776 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7779 } else if (!m->klass->dummy &&
7780 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7781 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7782 MonoMethodHeader *header;
7784 gint32 max_stack, i;
7785 gint32 num_locals = 0;
7786 gint32 num_clauses = 0;
7790 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7791 code_size = rmb->ilgen->code_len;
7792 max_stack = rmb->ilgen->max_stack;
7793 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7794 if (rmb->ilgen->ex_handlers)
7795 num_clauses = method_count_clauses (rmb->ilgen);
7798 code = mono_array_addr (rmb->code, guint8, 0);
7799 code_size = mono_array_length (rmb->code);
7800 /* we probably need to run a verifier on the code... */
7810 header = g_malloc0 (sizeof (MonoMethodHeader) +
7811 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7812 header->code_size = code_size;
7813 header->code = g_malloc (code_size);
7814 memcpy ((char*)header->code, code, code_size);
7815 header->max_stack = max_stack;
7816 header->init_locals = rmb->init_locals;
7817 header->num_locals = num_locals;
7819 for (i = 0; i < num_locals; ++i) {
7820 MonoReflectionLocalBuilder *lb =
7821 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7823 header->locals [i] = g_new0 (MonoType, 1);
7824 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7827 header->num_clauses = num_clauses;
7829 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7830 rmb->ilgen, num_clauses);
7833 pm->header = header;
7836 if (rmb->generic_params) {
7837 int count = mono_array_length (rmb->generic_params);
7838 MonoGenericContainer *container;
7840 pm->generic_container = container = rmb->generic_container;
7841 container->type_argc = count;
7842 container->type_params = g_new0 (MonoGenericParam, count);
7844 for (i = 0; i < count; i++) {
7845 MonoReflectionGenericParam *gp =
7846 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7848 container->type_params [i] = *gp->type.type->data.generic_param;
7853 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7857 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7859 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
7860 data [0] = GUINT_TO_POINTER (rmb->nrefs);
7861 for (i = 0; i < rmb->nrefs; ++i)
7862 data [i + 1] = rmb->refs [i];
7867 /* Parameter info */
7870 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7871 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
7872 for (i = 0; i <= m->signature->param_count; ++i) {
7873 MonoReflectionParamBuilder *pb;
7874 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7875 if ((i > 0) && (pb->attrs)) {
7876 /* Make a copy since it might point to a shared type structure */
7877 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)));
7878 m->signature->params [i - 1]->attrs = pb->attrs;
7881 if (pb->def_value) {
7882 MonoDynamicImage *assembly;
7883 guint32 idx, def_type, len;
7887 if (!method_aux->param_defaults) {
7888 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7889 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
7891 assembly = (MonoDynamicImage*)klass->image;
7892 idx = encode_constant (assembly, pb->def_value, &def_type);
7893 /* Copy the data from the blob since it might get realloc-ed */
7894 p = assembly->blob.data + idx;
7895 len = mono_metadata_decode_blob_size (p, &p2);
7897 method_aux->param_defaults [i] = g_malloc (len);
7898 method_aux->param_default_types [i] = def_type;
7899 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7903 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7905 if (!method_aux->param_cattr)
7906 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7907 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7913 /* Parameter marshalling */
7916 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7917 MonoReflectionParamBuilder *pb;
7918 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7919 if (pb->marshal_info) {
7921 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7922 specs [pb->position] =
7923 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7927 if (specs != NULL) {
7929 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7930 method_aux->param_marshall = specs;
7933 if (klass->image->dynamic && method_aux)
7934 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7940 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7942 ReflectionMethodBuilder rmb;
7943 MonoMethodSignature *sig;
7945 sig = ctor_builder_to_signature (mb);
7947 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7949 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7950 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7952 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7953 /* ilgen is no longer needed */
7961 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7963 ReflectionMethodBuilder rmb;
7964 MonoMethodSignature *sig;
7966 sig = method_builder_to_signature (mb);
7968 reflection_methodbuilder_from_method_builder (&rmb, mb);
7970 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7971 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7973 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7974 /* ilgen is no longer needed */
7980 static MonoClassField*
7981 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7983 MonoClassField *field;
7990 field = g_new0 (MonoClassField, 1);
7992 field->name = mono_string_to_utf8 (fb->name);
7994 /* FIXME: handle type modifiers */
7995 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7996 field->type->attrs = fb->attrs;
7998 field->type = fb->type->type;
8000 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8001 field->data = mono_array_addr (fb->rva_data, char, 0);
8002 if (fb->offset != -1)
8003 field->offset = fb->offset;
8004 field->parent = klass;
8006 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8008 if (fb->def_value) {
8009 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8010 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8011 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8012 /* Copy the data from the blob since it might get realloc-ed */
8013 p = assembly->blob.data + idx;
8014 len = mono_metadata_decode_blob_size (p, &p2);
8016 field->data = g_malloc (len);
8017 memcpy ((gpointer)field->data, p, len);
8024 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8028 MonoReflectionTypeBuilder *tb = NULL;
8029 MonoGenericClass *gclass, *cached;
8030 MonoDynamicGenericClass *dgclass = NULL;
8031 gboolean is_dynamic = FALSE;
8036 klass = mono_class_from_mono_type (type->type);
8037 if (!klass->generic_container && !klass->generic_class &&
8038 !(klass->nested_in && klass->nested_in->generic_container))
8041 mono_loader_lock ();
8043 domain = mono_object_domain (type);
8045 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8046 tb = (MonoReflectionTypeBuilder *) type;
8048 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8050 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8051 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8052 MonoReflectionType *rgt = rgi->generic_type;
8054 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8055 tb = (MonoReflectionTypeBuilder *) rgt;
8057 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8060 icount = klass->interface_count;
8064 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8065 gclass = &dgclass->generic_class;
8066 gclass->is_dynamic = TRUE;
8068 gclass = g_new0 (MonoGenericClass, 1);
8070 gclass->inst = g_new0 (MonoGenericInst, 1);
8072 gclass->inst->type_argc = type_argc;
8073 gclass->inst->type_argv = types;
8074 gclass->inst->is_reference = 1;
8076 for (i = 0; i < gclass->inst->type_argc; ++i) {
8077 if (!gclass->inst->is_open)
8078 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8079 if (gclass->inst->is_reference)
8080 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8083 gclass->container_class = klass;
8085 if (klass->generic_class) {
8086 MonoGenericClass *kgclass = klass->generic_class;
8087 MonoGenericClass *ogclass = gclass;
8089 ogclass->context = g_new0 (MonoGenericContext, 1);
8090 ogclass->context->container = ogclass->container_class->generic_container;
8091 ogclass->context->gclass = ogclass;
8094 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8095 gclass = &dgclass->generic_class;
8096 gclass->is_dynamic = TRUE;
8098 gclass = g_new0 (MonoGenericClass, 1);
8100 gclass->inst = g_new0 (MonoGenericInst, 1);
8102 gclass->inst->type_argc = kgclass->inst->type_argc;
8103 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8104 gclass->inst->is_reference = 1;
8106 for (i = 0; i < gclass->inst->type_argc; i++) {
8107 MonoType *t = kgclass->inst->type_argv [i];
8109 t = mono_class_inflate_generic_type (t, ogclass->context);
8111 if (!gclass->inst->is_open)
8112 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8113 if (gclass->inst->is_reference)
8114 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8116 gclass->inst->type_argv [i] = t;
8119 gclass->container_class = kgclass->container_class;
8122 geninst = g_new0 (MonoType, 1);
8123 geninst->type = MONO_TYPE_GENERICINST;
8125 cached = mono_metadata_lookup_generic_class (gclass);
8128 mono_loader_unlock ();
8129 geninst->data.generic_class = cached;
8133 geninst->data.generic_class = gclass;
8135 gclass->parent = parent;
8137 gclass->context = g_new0 (MonoGenericContext, 1);
8138 gclass->context->container = gclass->container_class->generic_container;
8139 gclass->context->gclass = gclass;
8141 gclass->ifaces = g_new0 (MonoType *, icount);
8142 gclass->count_ifaces = icount;
8144 for (i = 0; i < icount; i++) {
8145 MonoReflectionType *itype;
8148 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8150 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8151 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8152 if (!gclass->ifaces [i])
8153 gclass->ifaces [i] = itype->type;
8156 mono_class_create_generic (gclass);
8158 mono_loader_unlock ();
8164 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8166 MonoClass *klass, *pklass = NULL;
8167 MonoReflectionType *parent = NULL;
8168 MonoType *the_parent = NULL, *geninst;
8169 MonoReflectionTypeBuilder *tb = NULL;
8170 MonoGenericClass *gclass;
8173 domain = mono_object_domain (type);
8174 klass = mono_class_from_mono_type (type->type);
8176 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8177 tb = (MonoReflectionTypeBuilder *) type;
8180 parent = tb->parent;
8181 pklass = mono_class_from_mono_type (parent->type);
8184 pklass = klass->parent;
8186 parent = mono_type_get_object (domain, &pklass->byval_arg);
8187 else if (klass->generic_class && klass->generic_class->parent) {
8188 parent = mono_type_get_object (domain, klass->generic_class->parent);
8189 pklass = mono_class_from_mono_type (klass->generic_class->parent);
8193 if (pklass && pklass->generic_class)
8194 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8196 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8200 gclass = geninst->data.generic_class;
8205 static inline MonoType*
8206 dup_type (const MonoType *original)
8208 MonoType *r = g_new0 (MonoType, 1);
8210 r->attrs = original->attrs;
8211 r->byref = original->byref;
8212 if (original->type == MONO_TYPE_PTR)
8213 r->data.type = dup_type (original->data.type);
8214 mono_stats.generics_metadata_size += sizeof (MonoType);
8218 MonoReflectionMethod*
8219 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8221 MonoMethod *method, *inflated;
8222 MonoReflectionMethodBuilder *mb = NULL;
8223 MonoGenericContainer *container;
8224 MonoGenericMethod *gmethod;
8225 MonoGenericContext *context;
8226 MonoGenericInst *ginst;
8229 MONO_ARCH_SAVE_REGS;
8230 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8231 MonoReflectionTypeBuilder *tb;
8234 mb = (MonoReflectionMethodBuilder *) rmethod;
8235 tb = (MonoReflectionTypeBuilder *) mb->type;
8236 klass = mono_class_from_mono_type (tb->type.type);
8238 method = methodbuilder_to_mono_method (klass, mb);
8240 method = rmethod->method;
8243 count = mono_method_signature (method)->generic_param_count;
8244 if (count != mono_array_length (types))
8247 container = ((MonoMethodNormal*) method)->generic_container;
8248 g_assert (container);
8250 if (!container->method_hash)
8251 container->method_hash = g_hash_table_new (
8252 (GHashFunc) mono_metadata_generic_method_hash,
8253 (GCompareFunc) mono_metadata_generic_method_equal);
8255 ginst = g_new0 (MonoGenericInst,1 );
8256 ginst->type_argc = count;
8257 ginst->type_argv = g_new0 (MonoType *, count);
8258 ginst->is_reference = 1;
8259 for (i = 0; i < count; i++) {
8260 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8261 ginst->type_argv [i] = dup_type (garg->type);
8263 if (!ginst->is_open)
8264 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8265 if (ginst->is_reference)
8266 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8268 ginst = mono_metadata_lookup_generic_inst (ginst);
8270 gmethod = g_new0 (MonoGenericMethod, 1);
8271 gmethod->container = container;
8272 gmethod->inst = ginst;
8274 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8278 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8281 gmethod->reflection_info = rmethod;
8283 context = g_new0 (MonoGenericContext, 1);
8284 context->container = container;
8285 context->gclass = method->klass->generic_class;
8286 context->gmethod = gmethod;
8288 inflated = mono_class_inflate_generic_method (method, context, NULL);
8289 g_hash_table_insert (container->method_hash, gmethod, inflated);
8291 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8295 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8297 MonoGenericMethod *gmethod;
8298 MonoGenericClass *gclass;
8299 MonoGenericContext *context;
8302 gclass = type->type.type->data.generic_class;
8304 gmethod = g_new0 (MonoGenericMethod, 1);
8305 gmethod->inst = g_new0 (MonoGenericInst, 1);
8306 gmethod->reflection_info = obj;
8308 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8309 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8311 for (i = 0; i < gmethod->inst->type_argc; i++) {
8312 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8313 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8315 g_assert (gparam->pklass);
8316 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8319 context = g_new0 (MonoGenericContext, 1);
8320 context->container = gclass->container_class->generic_container;
8321 context->gclass = gclass;
8322 context->gmethod = gmethod;
8324 return mono_class_inflate_generic_method (method, context, gclass->klass);
8328 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8333 klass = mono_class_from_mono_type (type->type.type);
8335 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8336 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8337 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8338 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8339 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8340 method = ((MonoReflectionMethod *) obj)->method;
8342 method = NULL; /* prevent compiler warning */
8343 g_assert_not_reached ();
8346 return inflate_mono_method (type, method, obj);
8350 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8351 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8354 MonoGenericClass *gclass;
8355 MonoDynamicGenericClass *dgclass;
8356 MonoClass *klass, *gklass, *pklass;
8359 MONO_ARCH_SAVE_REGS;
8361 klass = mono_class_from_mono_type (type->type.type);
8362 gclass = type->type.type->data.generic_class;
8364 g_assert (gclass->is_dynamic);
8365 dgclass = (MonoDynamicGenericClass *) gclass;
8367 if (dgclass->initialized)
8370 gklass = gclass->container_class;
8371 mono_class_init (gklass);
8374 pklass = mono_class_from_mono_type (gclass->parent);
8376 pklass = gklass->parent;
8378 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8379 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8380 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8381 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8382 dgclass->count_events = events ? mono_array_length (events) : 0;
8384 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8385 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8386 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8387 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8388 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8390 for (i = 0; i < dgclass->count_methods; i++) {
8391 MonoObject *obj = mono_array_get (methods, gpointer, i);
8393 dgclass->methods [i] = inflate_method (type, obj);
8396 for (i = 0; i < dgclass->count_ctors; i++) {
8397 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8399 dgclass->ctors [i] = inflate_method (type, obj);
8402 for (i = 0; i < dgclass->count_fields; i++) {
8403 MonoObject *obj = mono_array_get (fields, gpointer, i);
8404 MonoClassField *field;
8405 MonoInflatedField *ifield;
8407 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8408 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8409 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8410 field = ((MonoReflectionField *) obj)->field;
8412 field = NULL; /* prevent compiler warning */
8413 g_assert_not_reached ();
8416 ifield = g_new0 (MonoInflatedField, 1);
8417 ifield->generic_type = field->type;
8418 ifield->reflection_info = obj;
8420 dgclass->fields [i] = *field;
8421 dgclass->fields [i].generic_info = ifield;
8422 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8425 for (i = 0; i < dgclass->count_properties; i++) {
8426 MonoObject *obj = mono_array_get (properties, gpointer, i);
8427 MonoProperty *property = &dgclass->properties [i];
8429 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8430 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8432 property->parent = klass;
8433 property->attrs = pb->attrs;
8434 property->name = mono_string_to_utf8 (pb->name);
8436 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8438 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8439 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8440 *property = *((MonoReflectionProperty *) obj)->property;
8443 property->get = inflate_mono_method (type, property->get, NULL);
8445 property->set = inflate_mono_method (type, property->set, NULL);
8447 g_assert_not_reached ();
8450 for (i = 0; i < dgclass->count_events; i++) {
8451 MonoObject *obj = mono_array_get (events, gpointer, i);
8452 MonoEvent *event = &dgclass->events [i];
8454 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8455 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8457 event->parent = klass;
8458 event->attrs = eb->attrs;
8459 event->name = mono_string_to_utf8 (eb->name);
8461 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8462 if (eb->remove_method)
8463 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8464 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8465 *event = *((MonoReflectionEvent *) obj)->event;
8468 event->add = inflate_mono_method (type, event->add, NULL);
8470 event->remove = inflate_mono_method (type, event->remove, NULL);
8472 g_assert_not_reached ();
8475 dgclass->initialized = TRUE;
8479 ensure_runtime_vtable (MonoClass *klass)
8481 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8482 int i, num, j, onum;
8483 MonoMethod **overrides;
8485 if (!tb || klass->wastypebuilder)
8488 ensure_runtime_vtable (klass->parent);
8490 num = tb->ctors? mono_array_length (tb->ctors): 0;
8491 num += tb->num_methods;
8492 klass->method.count = num;
8493 klass->methods = g_new (MonoMethod*, num);
8494 num = tb->ctors? mono_array_length (tb->ctors): 0;
8495 for (i = 0; i < num; ++i)
8496 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8497 num = tb->num_methods;
8499 for (i = 0; i < num; ++i)
8500 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8502 if (tb->interfaces) {
8503 klass->interface_count = mono_array_length (tb->interfaces);
8504 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8505 for (i = 0; i < klass->interface_count; ++i) {
8506 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8507 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8511 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8512 for (i = 0; i < klass->method.count; ++i)
8513 klass->methods [i]->slot = i;
8515 if (!((MonoDynamicImage*)klass->image)->run)
8516 /* No need to create a generic vtable */
8522 for (i = 0; i < tb->num_methods; ++i) {
8523 MonoReflectionMethodBuilder *mb =
8524 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8525 if (mb->override_method)
8530 overrides = g_new0 (MonoMethod*, onum * 2);
8534 for (i = 0; i < tb->num_methods; ++i) {
8535 MonoReflectionMethodBuilder *mb =
8536 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8537 if (mb->override_method) {
8538 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8539 overrides [onum * 2] =
8540 mb->override_method->method;
8541 overrides [onum * 2 + 1] =
8544 g_assert (mb->mhandle);
8551 mono_class_setup_vtable_general (klass, overrides, onum);
8556 typebuilder_setup_fields (MonoClass *klass)
8558 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8559 MonoReflectionFieldBuilder *fb;
8560 MonoClassField *field;
8565 klass->field.count = tb->num_fields;
8566 klass->field.first = 0;
8567 klass->field.last = klass->field.count;
8569 if (!klass->field.count)
8572 klass->fields = g_new0 (MonoClassField, klass->field.count);
8574 for (i = 0; i < klass->field.count; ++i) {
8575 fb = mono_array_get (tb->fields, gpointer, i);
8576 field = &klass->fields [i];
8577 field->name = mono_string_to_utf8 (fb->name);
8579 /* FIXME: handle type modifiers */
8580 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8581 field->type->attrs = fb->attrs;
8583 field->type = fb->type->type;
8585 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8586 field->data = mono_array_addr (fb->rva_data, char, 0);
8587 if (fb->offset != -1)
8588 field->offset = fb->offset;
8589 field->parent = klass;
8591 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8593 if (fb->def_value) {
8594 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8595 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8596 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8597 /* Copy the data from the blob since it might get realloc-ed */
8598 p = assembly->blob.data + idx;
8599 len = mono_metadata_decode_blob_size (p, &p2);
8601 field->data = g_malloc (len);
8602 memcpy ((gpointer)field->data, p, len);
8605 mono_class_layout_fields (klass);
8609 typebuilder_setup_properties (MonoClass *klass)
8611 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8612 MonoReflectionPropertyBuilder *pb;
8615 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8616 klass->property.first = 0;
8617 klass->property.last = klass->property.count;
8619 klass->properties = g_new0 (MonoProperty, klass->property.count);
8620 for (i = 0; i < klass->property.count; ++i) {
8621 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8622 klass->properties [i].parent = klass;
8623 klass->properties [i].attrs = pb->attrs;
8624 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8626 klass->properties [i].get = pb->get_method->mhandle;
8628 klass->properties [i].set = pb->set_method->mhandle;
8632 MonoReflectionEvent *
8633 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8635 MonoEvent *event = g_new0 (MonoEvent, 1);
8639 klass = my_mono_class_from_mono_type (tb->type.type);
8641 event->parent = klass;
8642 event->attrs = eb->attrs;
8643 event->name = mono_string_to_utf8 (eb->name);
8645 event->add = eb->add_method->mhandle;
8646 if (eb->remove_method)
8647 event->remove = eb->remove_method->mhandle;
8648 if (eb->raise_method)
8649 event->raise = eb->raise_method->mhandle;
8651 if (eb->other_methods) {
8652 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8653 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8654 MonoReflectionMethodBuilder *mb =
8655 mono_array_get (eb->other_methods,
8656 MonoReflectionMethodBuilder*, j);
8657 event->other [j] = mb->mhandle;
8661 return mono_event_get_object (mono_object_domain (tb), klass, event);
8665 typebuilder_setup_events (MonoClass *klass)
8667 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8668 MonoReflectionEventBuilder *eb;
8671 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8672 klass->event.first = 0;
8673 klass->event.last = klass->event.count;
8675 klass->events = g_new0 (MonoEvent, klass->event.count);
8676 for (i = 0; i < klass->event.count; ++i) {
8677 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8678 klass->events [i].parent = klass;
8679 klass->events [i].attrs = eb->attrs;
8680 klass->events [i].name = mono_string_to_utf8 (eb->name);
8682 klass->events [i].add = eb->add_method->mhandle;
8683 if (eb->remove_method)
8684 klass->events [i].remove = eb->remove_method->mhandle;
8685 if (eb->raise_method)
8686 klass->events [i].raise = eb->raise_method->mhandle;
8688 if (eb->other_methods) {
8689 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8690 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8691 MonoReflectionMethodBuilder *mb =
8692 mono_array_get (eb->other_methods,
8693 MonoReflectionMethodBuilder*, j);
8694 klass->events [i].other [j] = mb->mhandle;
8701 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8704 MonoReflectionType* res;
8707 MONO_ARCH_SAVE_REGS;
8709 klass = my_mono_class_from_mono_type (tb->type.type);
8711 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8713 mono_loader_lock ();
8714 if (klass->wastypebuilder) {
8715 mono_loader_unlock ();
8716 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8719 * Fields to set in klass:
8720 * the various flags: delegate/unicode/contextbound etc.
8722 klass->flags = tb->attrs;
8723 klass->has_cctor = 1;
8724 klass->has_finalize = 1;
8726 if (!((MonoDynamicImage*)klass->image)->run) {
8727 if (klass->generic_container) {
8728 /* FIXME: The code below can't handle generic classes */
8729 klass->wastypebuilder = TRUE;
8730 mono_loader_unlock ();
8731 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8735 /* enums are done right away */
8736 if (!klass->enumtype)
8737 ensure_runtime_vtable (klass);
8740 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8741 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8742 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8746 /* fields and object layout */
8747 if (klass->parent) {
8748 if (!klass->parent->size_inited)
8749 mono_class_init (klass->parent);
8750 klass->instance_size += klass->parent->instance_size;
8751 klass->class_size += klass->parent->class_size;
8752 klass->min_align = klass->parent->min_align;
8753 /* if the type has no fields we won't call the field_setup
8754 * routine which sets up klass->has_references.
8756 klass->has_references |= klass->parent->has_references;
8758 klass->instance_size = sizeof (MonoObject);
8759 klass->min_align = 1;
8762 /* FIXME: handle packing_size and instance_size */
8763 typebuilder_setup_fields (klass);
8765 typebuilder_setup_properties (klass);
8767 typebuilder_setup_events (klass);
8769 klass->wastypebuilder = TRUE;
8770 mono_loader_unlock ();
8772 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8773 g_assert (res != (MonoReflectionType*)tb);
8778 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8780 MonoGenericParam *param;
8783 MONO_ARCH_SAVE_REGS;
8785 param = g_new0 (MonoGenericParam, 1);
8787 if (gparam->mbuilder) {
8788 if (!gparam->mbuilder->generic_container)
8789 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8790 param->owner = gparam->mbuilder->generic_container;
8791 } else if (gparam->tbuilder) {
8792 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8793 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8798 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8799 if (gparam->index >= count)
8802 container = nesting->generic_container;
8803 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8806 g_assert (container);
8807 param->owner = container;
8810 param->method = NULL;
8811 param->name = mono_string_to_utf8 (gparam->name);
8812 param->num = gparam->index;
8814 image = &gparam->tbuilder->module->dynamic_image->image;
8815 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8817 param->pklass->reflection_info = gparam;
8819 gparam->type.type = g_new0 (MonoType, 1);
8820 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8821 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8822 gparam->type.type->data.generic_param = param;
8826 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8828 MonoDynamicImage *assembly = sig->module->dynamic_image;
8829 guint32 na = mono_array_length (sig->arguments);
8834 MONO_ARCH_SAVE_REGS;
8836 p = buf = g_malloc (10 + na * 10);
8838 mono_metadata_encode_value (0x07, p, &p);
8839 mono_metadata_encode_value (na, p, &p);
8840 for (i = 0; i < na; ++i) {
8841 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8842 encode_reflection_type (assembly, type, p, &p);
8846 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8847 p = mono_array_addr (result, char, 0);
8848 memcpy (p, buf, buflen);
8855 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8857 MonoDynamicImage *assembly = sig->module->dynamic_image;
8858 guint32 na = mono_array_length (sig->arguments);
8863 MONO_ARCH_SAVE_REGS;
8865 p = buf = g_malloc (10 + na * 10);
8867 mono_metadata_encode_value (0x06, p, &p);
8868 for (i = 0; i < na; ++i) {
8869 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8870 encode_reflection_type (assembly, type, p, &p);
8874 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8875 p = mono_array_addr (result, char, 0);
8876 memcpy (p, buf, buflen);
8883 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8885 ReflectionMethodBuilder rmb;
8886 MonoMethodSignature *sig;
8889 sig = dynamic_method_to_signature (mb);
8891 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8894 * Resolve references.
8896 rmb.nrefs = mb->nrefs;
8897 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8898 for (i = 0; i < mb->nrefs; ++i) {
8899 MonoClass *handle_class;
8900 gpointer ref = resolve_object (mb->module->image,
8901 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
8904 mono_raise_exception (mono_get_exception_type_load (NULL));
8911 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8915 /* ilgen is no longer needed */
8920 * mono_reflection_lookup_dynamic_token:
8922 * Finish the Builder object pointed to by TOKEN and return the corresponding
8923 * runtime structure. HANDLE_CLASS is set to the class required by
8927 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
8929 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8932 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8935 return resolve_object (image, obj, handle_class);
8939 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
8941 gpointer result = NULL;
8943 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8944 result = mono_string_intern ((MonoString*)obj);
8945 *handle_class = NULL;
8947 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8948 MonoReflectionType *tb = (MonoReflectionType*)obj;
8949 result = mono_class_from_mono_type (tb->type);
8950 *handle_class = mono_defaults.typehandle_class;
8952 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8953 result = ((MonoReflectionMethod*)obj)->method;
8954 *handle_class = mono_defaults.methodhandle_class;
8956 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8957 result = ((MonoReflectionMethod*)obj)->method;
8958 *handle_class = mono_defaults.methodhandle_class;
8960 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8961 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8962 result = mb->mhandle;
8964 /* Type is not yet created */
8965 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8967 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8970 * Hopefully this has been filled in by calling CreateType() on the
8974 * TODO: This won't work if the application finishes another
8975 * TypeBuilder instance instead of this one.
8977 result = mb->mhandle;
8979 *handle_class = mono_defaults.methodhandle_class;
8980 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8981 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8983 result = cb->mhandle;
8985 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8987 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8988 result = cb->mhandle;
8990 *handle_class = mono_defaults.methodhandle_class;
8991 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8992 result = ((MonoReflectionField*)obj)->field;
8993 *handle_class = mono_defaults.fieldhandle_class;
8995 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8996 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8997 result = fb->handle;
9000 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9002 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9003 result = fb->handle;
9005 *handle_class = mono_defaults.fieldhandle_class;
9006 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9007 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9010 klass = tb->type.type->data.klass;
9011 if (klass->wastypebuilder) {
9012 /* Already created */
9016 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9017 result = tb->type.type->data.klass;
9020 *handle_class = mono_defaults.typehandle_class;
9021 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9022 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9023 MonoMethodSignature *sig;
9026 if (helper->arguments)
9027 nargs = mono_array_length (helper->arguments);
9031 sig = mono_metadata_signature_alloc (image, nargs);
9032 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9033 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9035 if (helper->call_conv == 0) /* unmanaged */
9036 sig->call_convention = helper->unmanaged_call_conv - 1;
9038 if (helper->call_conv & 0x02)
9039 sig->call_convention = MONO_CALL_VARARG;
9041 sig->call_convention = MONO_CALL_DEFAULT;
9043 sig->param_count = nargs;
9044 /* TODO: Copy type ? */
9045 sig->ret = helper->return_type->type;
9046 for (i = 0; i < nargs; ++i) {
9047 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9048 sig->params [i] = rt->type;
9052 *handle_class = NULL;
9054 g_print (obj->vtable->klass->name);
9055 g_assert_not_reached ();
9061 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9062 const static guint32 declsec_flags_map[] = {
9063 0x00000000, /* empty */
9064 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9065 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9066 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9067 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9068 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9069 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9070 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9071 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9072 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9073 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9074 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9075 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9076 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9077 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9078 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9079 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9080 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9081 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9085 * Returns flags that includes all available security action associated to the handle.
9086 * @token: metadata token (either for a class or a method)
9087 * @image: image where resides the metadata.
9090 mono_declsec_get_flags (MonoImage *image, guint32 token)
9092 guint32 index = mono_metadata_declsec_from_index (image, token);
9093 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9098 for (i = index; i < t->rows; i++) {
9099 guint32 cols [MONO_DECL_SECURITY_SIZE];
9101 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9102 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9105 action = cols [MONO_DECL_SECURITY_ACTION];
9106 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9107 result |= declsec_flags_map [action];
9109 g_assert_not_reached ();
9116 * Get the security actions (in the form of flags) associated with the specified method.
9118 * @method: The method for which we want the declarative security flags.
9119 * Return the declarative security flags for the method (only).
9121 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9122 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9125 mono_declsec_flags_from_method (MonoMethod *method)
9127 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9128 /* FIXME: No cache (for the moment) */
9129 guint32 idx = mono_method_get_index (method);
9130 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9131 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9132 return mono_declsec_get_flags (method->klass->image, idx);
9138 * Get the security actions (in the form of flags) associated with the specified class.
9140 * @klass: The class for which we want the declarative security flags.
9141 * Return the declarative security flags for the class.
9143 * Note: We cache the flags inside the MonoClass structure as this will get
9144 * called very often (at least for each method).
9147 mono_declsec_flags_from_class (MonoClass *klass)
9149 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9150 if (!klass->declsec_flags) {
9151 guint32 idx = mono_metadata_token_index (klass->type_token);
9152 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9153 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9154 /* we cache the flags on classes */
9155 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9157 return klass->declsec_flags;
9163 * Get the security actions (in the form of flags) associated with the specified assembly.
9165 * @assembly: The assembly for which we want the declarative security flags.
9166 * Return the declarative security flags for the assembly.
9169 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9171 guint32 idx = 1; /* there is only one assembly */
9172 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9173 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9174 return mono_declsec_get_flags (assembly->image, idx);
9179 * Fill actions for the specific index (which may either be an encoded class token or
9180 * an encoded method token) from the metadata image.
9181 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9184 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9185 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9187 MonoBoolean result = FALSE;
9189 guint32 cols [MONO_DECL_SECURITY_SIZE];
9190 int index = mono_metadata_declsec_from_index (image, token);
9193 t = &image->tables [MONO_TABLE_DECLSECURITY];
9194 for (i = index; i < t->rows; i++) {
9195 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9197 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9200 /* if present only replace (class) permissions with method permissions */
9201 /* if empty accept either class or method permissions */
9202 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9203 if (!actions->demand.blob) {
9204 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9205 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9206 actions->demand.blob = (char*) (blob + 2);
9207 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9210 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9211 if (!actions->noncasdemand.blob) {
9212 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9213 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9214 actions->noncasdemand.blob = (char*) (blob + 2);
9215 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9218 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9219 if (!actions->demandchoice.blob) {
9220 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9221 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9222 actions->demandchoice.blob = (char*) (blob + 2);
9223 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9233 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9234 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9236 guint32 idx = mono_metadata_token_index (klass->type_token);
9237 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9238 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9239 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9243 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9244 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9246 guint32 idx = mono_method_get_index (method);
9247 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9248 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9249 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9253 * Collect all actions (that requires to generate code in mini) assigned for
9254 * the specified method.
9255 * Note: Don't use the content of actions if the function return FALSE.
9258 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9260 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9261 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9262 MonoBoolean result = FALSE;
9265 /* quick exit if no declarative security is present in the metadata */
9266 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9269 /* we want the original as the wrapper is "free" of the security informations */
9270 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9271 method = mono_marshal_method_from_wrapper (method);
9276 /* First we look for method-level attributes */
9277 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9278 mono_class_init (method->klass);
9279 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9281 result = mono_declsec_get_method_demands_params (method, demands,
9282 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9285 /* Here we use (or create) the class declarative cache to look for demands */
9286 flags = mono_declsec_flags_from_class (method->klass);
9289 mono_class_init (method->klass);
9290 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9292 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9293 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9296 /* The boolean return value is used as a shortcut in case nothing needs to
9297 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9303 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9305 * Note: Don't use the content of actions if the function return FALSE.
9308 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9310 MonoBoolean result = FALSE;
9313 /* quick exit if no declarative security is present in the metadata */
9314 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9317 /* we want the original as the wrapper is "free" of the security informations */
9318 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9319 method = mono_marshal_method_from_wrapper (method);
9324 /* results are independant - zeroize both */
9325 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9326 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9328 /* First we look for method-level attributes */
9329 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9330 mono_class_init (method->klass);
9332 result = mono_declsec_get_method_demands_params (method, cmethod,
9333 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9336 /* Here we use (or create) the class declarative cache to look for demands */
9337 flags = mono_declsec_flags_from_class (method->klass);
9338 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9339 mono_class_init (method->klass);
9341 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9342 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9349 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9351 * @klass The inherited class - this is the class that provides the security check (attributes)
9353 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9355 * Note: Don't use the content of actions if the function return FALSE.
9358 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9360 MonoBoolean result = FALSE;
9363 /* quick exit if no declarative security is present in the metadata */
9364 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9367 /* Here we use (or create) the class declarative cache to look for demands */
9368 flags = mono_declsec_flags_from_class (klass);
9369 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9370 mono_class_init (klass);
9371 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9373 result |= mono_declsec_get_class_demands_params (klass, demands,
9374 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9381 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9383 * Note: Don't use the content of actions if the function return FALSE.
9386 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9388 /* quick exit if no declarative security is present in the metadata */
9389 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9392 /* we want the original as the wrapper is "free" of the security informations */
9393 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9394 method = mono_marshal_method_from_wrapper (method);
9399 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9400 mono_class_init (method->klass);
9401 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9403 return mono_declsec_get_method_demands_params (method, demands,
9404 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9411 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9413 guint32 cols [MONO_DECL_SECURITY_SIZE];
9417 int index = mono_metadata_declsec_from_index (image, token);
9421 t = &image->tables [MONO_TABLE_DECLSECURITY];
9422 for (i = index; i < t->rows; i++) {
9423 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9425 /* shortcut - index are ordered */
9426 if (token != cols [MONO_DECL_SECURITY_PARENT])
9429 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9430 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9431 entry->blob = (char*) (metadata + 2);
9432 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9441 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9443 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9444 guint32 idx = mono_method_get_index (method);
9445 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9446 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9447 return get_declsec_action (method->klass->image, idx, action, entry);
9453 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9456 guint32 flags = mono_declsec_flags_from_class (klass);
9457 if (declsec_flags_map [action] & flags) {
9458 guint32 idx = mono_metadata_token_index (klass->type_token);
9459 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9460 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9461 return get_declsec_action (klass->image, idx, action, entry);
9467 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9469 guint32 idx = 1; /* there is only one assembly */
9470 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9471 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9473 return get_declsec_action (assembly->image, idx, action, entry);
9477 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9479 MonoObject *res, *exc;
9481 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9482 static MonoMethod *method = NULL;
9484 if (!System_Reflection_Emit_TypeBuilder) {
9485 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
9486 g_assert (System_Reflection_Emit_TypeBuilder);
9488 if (method == NULL) {
9489 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
9494 * The result of mono_type_get_object () might be a System.MonoType but we
9495 * need a TypeBuilder so use klass->reflection_info.
9497 g_assert (klass->reflection_info);
9498 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
9500 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
9502 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
9506 return *(MonoBoolean*)mono_object_unbox (res);