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>
30 #include "rawbuffer.h"
31 #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 [64] = {
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,
126 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
127 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
128 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
129 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
130 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
131 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
132 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
133 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
134 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
135 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
136 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
137 static void ensure_runtime_vtable (MonoClass *klass);
138 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
139 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
140 static guint32 type_get_signature_size (MonoType *type);
141 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
142 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
146 alloc_table (MonoDynamicTable *table, guint nrows)
149 g_assert (table->columns);
150 if (nrows + 1 >= table->alloc_rows) {
151 while (nrows + 1 >= table->alloc_rows) {
152 if (table->alloc_rows == 0)
153 table->alloc_rows = 16;
155 table->alloc_rows *= 2;
158 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
163 make_room_in_stream (MonoDynamicStream *stream, int size)
165 if (size <= stream->alloc_size)
168 while (stream->alloc_size <= size) {
169 if (stream->alloc_size < 4096)
170 stream->alloc_size = 4096;
172 stream->alloc_size *= 2;
175 stream->data = g_realloc (stream->data, stream->alloc_size);
179 mono_dynamic_stream_reset (MonoDynamicStream* stream)
181 stream->alloc_size = stream->index = stream->offset = 0;
182 g_free (stream->data);
184 g_hash_table_destroy (stream->hash);
188 string_heap_insert (MonoDynamicStream *sh, const char *str)
192 gpointer oldkey, oldval;
194 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
195 return GPOINTER_TO_UINT (oldval);
197 len = strlen (str) + 1;
200 make_room_in_stream (sh, idx + len);
203 * We strdup the string even if we already copy them in sh->data
204 * so that the string pointers in the hash remain valid even if
205 * we need to realloc sh->data. We may want to avoid that later.
207 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
208 memcpy (sh->data + idx, str, len);
214 string_heap_init (MonoDynamicStream *sh)
217 sh->alloc_size = 4096;
218 sh->data = g_malloc (4096);
219 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
220 string_heap_insert (sh, "");
223 #if 0 /* never used */
225 string_heap_free (MonoDynamicStream *sh)
228 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
229 g_hash_table_destroy (sh->hash);
234 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
238 make_room_in_stream (stream, stream->index + len);
239 memcpy (stream->data + stream->index, data, len);
241 stream->index += len;
243 * align index? Not without adding an additional param that controls it since
244 * we may store a blob value in pieces.
250 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
254 make_room_in_stream (stream, stream->index + len);
255 memset (stream->data + stream->index, 0, len);
257 stream->index += len;
262 stream_data_align (MonoDynamicStream *stream)
265 guint32 count = stream->index % 4;
267 /* we assume the stream data will be aligned */
269 mono_image_add_stream_data (stream, buf, 4 - count);
273 mono_blob_entry_hash (const char* str)
277 len = mono_metadata_decode_blob_size (str, &str);
281 for (str += 1; str < end; str++)
282 h = (h << 5) - h + *str;
290 mono_blob_entry_equal (const char *str1, const char *str2) {
294 len = mono_metadata_decode_blob_size (str1, &end1);
295 len2 = mono_metadata_decode_blob_size (str2, &end2);
298 return memcmp (end1, end2, len) == 0;
302 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
306 gpointer oldkey, oldval;
308 copy = g_malloc (s1+s2);
309 memcpy (copy, b1, s1);
310 memcpy (copy + s1, b2, s2);
311 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
313 idx = GPOINTER_TO_UINT (oldval);
315 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
316 mono_image_add_stream_data (&assembly->blob, b2, s2);
317 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
323 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
324 * dest may be misaligned.
327 swap_with_size (char *dest, const char* val, int len, int nelem) {
328 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
331 for (elem = 0; elem < nelem; ++elem) {
357 g_assert_not_reached ();
363 memcpy (dest, val, len * nelem);
368 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
372 guint32 idx = 0, len;
374 len = str->length * 2;
375 mono_metadata_encode_value (len, b, &b);
376 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
378 char *swapped = g_malloc (2 * mono_string_length (str));
379 const char *p = (const char*)mono_string_chars (str);
381 swap_with_size (swapped, p, 2, mono_string_length (str));
382 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
386 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
391 /* modified version needed to handle building corlib */
393 my_mono_class_from_mono_type (MonoType *type) {
394 switch (type->type) {
395 case MONO_TYPE_ARRAY:
397 case MONO_TYPE_SZARRAY:
398 case MONO_TYPE_GENERICINST:
399 return mono_class_from_mono_type (type);
402 g_assert (type->data.generic_param->pklass);
403 return type->data.generic_param->pklass;
405 /* should be always valid when we reach this case... */
406 return type->data.klass;
411 default_class_from_mono_type (MonoType *type)
413 switch (type->type) {
414 case MONO_TYPE_OBJECT:
415 return mono_defaults.object_class;
417 return mono_defaults.void_class;
418 case MONO_TYPE_BOOLEAN:
419 return mono_defaults.boolean_class;
421 return mono_defaults.char_class;
423 return mono_defaults.sbyte_class;
425 return mono_defaults.byte_class;
427 return mono_defaults.int16_class;
429 return mono_defaults.uint16_class;
431 return mono_defaults.int32_class;
433 return mono_defaults.uint32_class;
435 return mono_defaults.int_class;
437 return mono_defaults.uint_class;
439 return mono_defaults.int64_class;
441 return mono_defaults.uint64_class;
443 return mono_defaults.single_class;
445 return mono_defaults.double_class;
446 case MONO_TYPE_STRING:
447 return mono_defaults.string_class;
449 g_warning ("implement me 0x%02x\n", type->type);
450 g_assert_not_reached ();
457 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
462 g_assert_not_reached ();
466 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
467 encode_type (assembly, gclass->generic_type, p, &p);
468 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
469 for (i = 0; i < gclass->inst->type_argc; ++i)
470 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
476 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
479 g_assert_not_reached ();
484 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
488 case MONO_TYPE_BOOLEAN:
502 case MONO_TYPE_STRING:
503 case MONO_TYPE_OBJECT:
504 case MONO_TYPE_TYPEDBYREF:
505 mono_metadata_encode_value (type->type, p, &p);
508 mono_metadata_encode_value (type->type, p, &p);
509 encode_type (assembly, type->data.type, p, &p);
511 case MONO_TYPE_SZARRAY:
512 mono_metadata_encode_value (type->type, p, &p);
513 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
515 case MONO_TYPE_VALUETYPE:
516 case MONO_TYPE_CLASS: {
517 MonoClass *k = mono_class_from_mono_type (type);
518 mono_metadata_encode_value (type->type, p, &p);
520 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
521 * otherwise two typerefs could point to the same type, leading to
522 * verification errors.
524 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
527 case MONO_TYPE_ARRAY:
528 mono_metadata_encode_value (type->type, p, &p);
529 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
530 mono_metadata_encode_value (type->data.array->rank, p, &p);
531 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
532 mono_metadata_encode_value (0, p, &p);
534 case MONO_TYPE_GENERICINST:
535 encode_generic_class (assembly, type->data.generic_class, p, &p);
539 mono_metadata_encode_value (type->type, p, &p);
540 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
543 g_error ("need to encode type %x", type->type);
549 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
552 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
556 encode_type (assembly, type->type, p, endbuf);
560 g_assert_not_reached ();
565 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
570 for (i = 0; i < mono_array_length (modreq); ++i) {
571 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
572 *p = MONO_TYPE_CMOD_REQD;
574 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
578 for (i = 0; i < mono_array_length (modopt); ++i) {
579 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
580 *p = MONO_TYPE_CMOD_OPT;
582 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
589 generic_class_get_signature_size (MonoGenericClass *gclass)
595 g_assert_not_reached ();
598 size += 1 + type_get_signature_size (gclass->generic_type);
600 for (i = 0; i < gclass->inst->type_argc; ++i)
601 size += type_get_signature_size (gclass->inst->type_argv [i]);
607 type_get_signature_size (MonoType *type)
612 g_assert_not_reached ();
620 case MONO_TYPE_BOOLEAN:
634 case MONO_TYPE_STRING:
635 case MONO_TYPE_OBJECT:
636 case MONO_TYPE_TYPEDBYREF:
639 return size + 1 + type_get_signature_size (type->data.type);
640 case MONO_TYPE_SZARRAY:
641 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
642 case MONO_TYPE_VALUETYPE:
643 case MONO_TYPE_CLASS:
645 case MONO_TYPE_ARRAY:
646 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
647 case MONO_TYPE_GENERICINST:
648 return size + generic_class_get_signature_size (type->data.generic_class);
653 g_error ("need to encode type %x", type->type);
659 method_get_signature_size (MonoMethodSignature *sig)
664 size = type_get_signature_size (sig->ret);
665 for (i = 0; i < sig->param_count; i++)
666 size += type_get_signature_size (sig->params [i]);
668 if (sig->generic_param_count)
670 if (sig->sentinelpos >= 0)
677 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
682 guint32 nparams = sig->param_count;
683 guint32 size = 11 + method_get_signature_size (sig);
691 p = buf = g_malloc (size);
693 * FIXME: vararg, explicit_this, differenc call_conv values...
695 *p = sig->call_convention;
697 *p |= 0x20; /* hasthis */
698 if (sig->generic_param_count)
699 *p |= 0x10; /* generic */
701 if (sig->generic_param_count)
702 mono_metadata_encode_value (sig->generic_param_count, p, &p);
703 mono_metadata_encode_value (nparams, p, &p);
704 encode_type (assembly, sig->ret, p, &p);
705 for (i = 0; i < nparams; ++i) {
706 if (i == sig->sentinelpos)
707 *p++ = MONO_TYPE_SENTINEL;
708 encode_type (assembly, sig->params [i], p, &p);
711 g_assert (p - buf < size);
712 mono_metadata_encode_value (p-buf, b, &b);
713 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
719 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
722 * FIXME: reuse code from method_encode_signature().
727 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
728 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
729 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
730 guint32 size = 21 + nparams * 20 + notypes * 20;
735 p = buf = g_malloc (size);
736 /* LAMESPEC: all the call conv spec is foobared */
737 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
738 if (mb->call_conv & 2)
739 *p |= 0x5; /* vararg */
740 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
741 *p |= 0x20; /* hasthis */
743 *p |= 0x10; /* generic */
746 mono_metadata_encode_value (ngparams, p, &p);
747 mono_metadata_encode_value (nparams + notypes, p, &p);
748 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
749 encode_reflection_type (assembly, mb->rtype, p, &p);
750 for (i = 0; i < nparams; ++i) {
751 MonoArray *modreq = NULL;
752 MonoArray *modopt = NULL;
753 MonoReflectionType *pt;
755 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
756 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
757 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
758 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
759 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
760 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
761 encode_reflection_type (assembly, pt, p, &p);
764 *p++ = MONO_TYPE_SENTINEL;
765 for (i = 0; i < notypes; ++i) {
766 MonoReflectionType *pt;
768 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
769 encode_reflection_type (assembly, pt, p, &p);
773 g_assert (p - buf < size);
774 mono_metadata_encode_value (p-buf, b, &b);
775 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
781 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
783 MonoDynamicTable *table;
786 guint32 idx, sig_idx, size;
787 guint nl = mono_array_length (ilgen->locals);
794 p = buf = g_malloc (size);
795 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
796 idx = table->next_idx ++;
798 alloc_table (table, table->rows);
799 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
801 mono_metadata_encode_value (0x07, p, &p);
802 mono_metadata_encode_value (nl, p, &p);
803 for (i = 0; i < nl; ++i) {
804 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
807 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
809 encode_reflection_type (assembly, lb->type, p, &p);
811 g_assert (p - buf < size);
812 mono_metadata_encode_value (p-buf, b, &b);
813 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
816 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
822 method_count_clauses (MonoReflectionILGen *ilgen)
824 guint32 num_clauses = 0;
827 MonoILExceptionInfo *ex_info;
828 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
829 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
830 if (ex_info->handlers)
831 num_clauses += mono_array_length (ex_info->handlers);
839 static MonoExceptionClause*
840 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
842 MonoExceptionClause *clauses;
843 MonoExceptionClause *clause;
844 MonoILExceptionInfo *ex_info;
845 MonoILExceptionBlock *ex_block;
846 guint32 finally_start;
847 int i, j, clause_index;;
849 clauses = g_new0 (MonoExceptionClause, num_clauses);
852 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
853 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
854 finally_start = ex_info->start + ex_info->len;
855 g_assert (ex_info->handlers);
856 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
857 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
858 clause = &(clauses [clause_index]);
860 clause->flags = ex_block->type;
861 clause->try_offset = ex_info->start;
863 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
864 clause->try_len = finally_start - ex_info->start;
866 clause->try_len = ex_info->len;
867 clause->handler_offset = ex_block->start;
868 clause->handler_len = ex_block->len;
869 if (ex_block->extype) {
870 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
872 /* FIXME: handle filters */
873 clause->data.filter_offset = 0;
875 finally_start = ex_block->start + ex_block->len;
885 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
891 gint32 num_locals = 0;
892 gint32 num_exception = 0;
895 char fat_header [12];
898 guint32 local_sig = 0;
899 guint32 header_size = 12;
902 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
903 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
907 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
909 code = mb->ilgen->code;
910 code_size = mb->ilgen->code_len;
911 max_stack = mb->ilgen->max_stack;
912 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
913 if (mb->ilgen->ex_handlers)
914 num_exception = method_count_clauses (mb->ilgen);
918 char *name = mono_string_to_utf8 (mb->name);
919 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
920 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
923 mono_raise_exception (exception);
926 code_size = mono_array_length (code);
927 max_stack = 8; /* we probably need to run a verifier on the code... */
930 stream_data_align (&assembly->code);
932 /* check for exceptions, maxstack, locals */
933 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
935 if (code_size < 64 && !(code_size & 1)) {
936 flags = (code_size << 2) | 0x2;
937 } else if (code_size < 32 && (code_size & 1)) {
938 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
942 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
943 /* add to the fixup todo list */
944 if (mb->ilgen && mb->ilgen->num_token_fixups)
945 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
946 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
947 return assembly->text_rva + idx;
951 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
953 * FIXME: need to set also the header size in fat_flags.
954 * (and more sects and init locals flags)
958 fat_flags |= METHOD_HEADER_MORE_SECTS;
960 fat_flags |= METHOD_HEADER_INIT_LOCALS;
961 fat_header [0] = fat_flags;
962 fat_header [1] = (header_size / 4 ) << 4;
963 shortp = (guint16*)(fat_header + 2);
964 *shortp = GUINT16_TO_LE (max_stack);
965 intp = (guint32*)(fat_header + 4);
966 *intp = GUINT32_TO_LE (code_size);
967 intp = (guint32*)(fat_header + 8);
968 *intp = GUINT32_TO_LE (local_sig);
969 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
970 /* add to the fixup todo list */
971 if (mb->ilgen && mb->ilgen->num_token_fixups)
972 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
974 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
976 unsigned char sheader [4];
977 MonoILExceptionInfo * ex_info;
978 MonoILExceptionBlock * ex_block;
981 stream_data_align (&assembly->code);
982 /* always use fat format for now */
983 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
984 num_exception *= 6 * sizeof (guint32);
985 num_exception += 4; /* include the size of the header */
986 sheader [1] = num_exception & 0xff;
987 sheader [2] = (num_exception >> 8) & 0xff;
988 sheader [3] = (num_exception >> 16) & 0xff;
989 mono_image_add_stream_data (&assembly->code, sheader, 4);
990 /* fat header, so we are already aligned */
992 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
993 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
994 if (ex_info->handlers) {
995 int finally_start = ex_info->start + ex_info->len;
996 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
998 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1000 val = GUINT32_TO_LE (ex_block->type);
1001 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1003 val = GUINT32_TO_LE (ex_info->start);
1004 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1005 /* need fault, too, probably */
1006 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1007 val = GUINT32_TO_LE (finally_start - ex_info->start);
1009 val = GUINT32_TO_LE (ex_info->len);
1010 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1011 /* handler offset */
1012 val = GUINT32_TO_LE (ex_block->start);
1013 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1015 val = GUINT32_TO_LE (ex_block->len);
1016 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1017 finally_start = ex_block->start + ex_block->len;
1018 if (ex_block->extype) {
1019 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1021 /* FIXME: handle filters */
1024 val = GUINT32_TO_LE (val);
1025 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1026 /*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",
1027 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);*/
1030 g_error ("No clauses for ex info block %d", i);
1034 return assembly->text_rva + idx;
1038 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1041 MonoDynamicTable *table;
1044 table = &assembly->tables [table_idx];
1046 g_assert (col < table->columns);
1048 values = table->values + table->columns;
1049 for (i = 1; i <= table->rows; ++i) {
1050 if (values [col] == token)
1052 values += table->columns;
1057 static GHashTable *dynamic_custom_attrs = NULL;
1059 static MonoCustomAttrInfo*
1060 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1063 MonoCustomAttrInfo *ainfo;
1064 MonoReflectionCustomAttr *cattr;
1068 /* FIXME: check in assembly the Run flag is set */
1070 count = mono_array_length (cattrs);
1072 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1074 ainfo->image = image;
1075 ainfo->num_attrs = count;
1076 for (i = 0; i < count; ++i) {
1077 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1078 ainfo->attrs [i].ctor = cattr->ctor->method;
1079 /* FIXME: might want to memdup the data here */
1080 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1081 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1088 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1090 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1095 if (!dynamic_custom_attrs)
1096 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1098 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1099 ainfo->cached = TRUE;
1103 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1105 /* they are cached, so we don't free them */
1106 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1112 * idx is the table index of the object
1113 * type is one of MONO_CUSTOM_ATTR_*
1116 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1118 MonoDynamicTable *table;
1119 MonoReflectionCustomAttr *cattr;
1121 guint32 count, i, token;
1123 char *p = blob_size;
1125 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1128 count = mono_array_length (cattrs);
1129 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1130 table->rows += count;
1131 alloc_table (table, table->rows);
1132 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1133 idx <<= MONO_CUSTOM_ATTR_BITS;
1135 for (i = 0; i < count; ++i) {
1136 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1137 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1138 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1139 type = mono_metadata_token_index (token);
1140 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1141 switch (mono_metadata_token_table (token)) {
1142 case MONO_TABLE_METHOD:
1143 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1145 case MONO_TABLE_MEMBERREF:
1146 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1149 g_warning ("got wrong token in custom attr");
1152 values [MONO_CUSTOM_ATTR_TYPE] = type;
1154 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1155 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1156 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1157 values += MONO_CUSTOM_ATTR_SIZE;
1163 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1165 MonoDynamicTable *table;
1167 guint32 count, i, idx;
1168 MonoReflectionPermissionSet *perm;
1173 count = mono_array_length (permissions);
1174 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1175 table->rows += count;
1176 alloc_table (table, table->rows);
1178 for (i = 0; i < mono_array_length (permissions); ++i) {
1179 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1181 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1183 idx = mono_metadata_token_index (parent_token);
1184 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1185 switch (mono_metadata_token_table (parent_token)) {
1186 case MONO_TABLE_TYPEDEF:
1187 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1189 case MONO_TABLE_METHOD:
1190 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1192 case MONO_TABLE_ASSEMBLY:
1193 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1196 g_assert_not_reached ();
1199 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1200 values [MONO_DECL_SECURITY_PARENT] = idx;
1201 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1208 * Fill in the MethodDef and ParamDef tables for a method.
1209 * This is used for both normal methods and constructors.
1212 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1214 MonoDynamicTable *table;
1219 /* room in this table is already allocated */
1220 table = &assembly->tables [MONO_TABLE_METHOD];
1221 *mb->table_idx = table->next_idx ++;
1222 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1223 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1224 name = mono_string_to_utf8 (mb->name);
1225 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1227 values [MONO_METHOD_FLAGS] = mb->attrs;
1228 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1229 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1230 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1232 table = &assembly->tables [MONO_TABLE_PARAM];
1233 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1235 mono_image_add_decl_security (assembly,
1236 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1239 MonoDynamicTable *mtable;
1242 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1243 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1246 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1247 if (mono_array_get (mb->pinfo, gpointer, i))
1250 table->rows += count;
1251 alloc_table (table, table->rows);
1252 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1253 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1254 MonoReflectionParamBuilder *pb;
1255 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1256 values [MONO_PARAM_FLAGS] = pb->attrs;
1257 values [MONO_PARAM_SEQUENCE] = i;
1258 if (pb->name != NULL) {
1259 name = mono_string_to_utf8 (pb->name);
1260 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1263 values [MONO_PARAM_NAME] = 0;
1265 values += MONO_PARAM_SIZE;
1266 if (pb->marshal_info) {
1268 alloc_table (mtable, mtable->rows);
1269 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1270 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1271 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1273 pb->table_idx = table->next_idx++;
1274 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1275 guint32 field_type = 0;
1276 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1278 alloc_table (mtable, mtable->rows);
1279 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1280 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1281 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1282 mvalues [MONO_CONSTANT_TYPE] = field_type;
1283 mvalues [MONO_CONSTANT_PADDING] = 0;
1291 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1293 rmb->ilgen = mb->ilgen;
1294 rmb->rtype = mb->rtype;
1295 rmb->parameters = mb->parameters;
1296 rmb->generic_params = mb->generic_params;
1297 rmb->generic_container = mb->generic_container;
1298 rmb->opt_types = NULL;
1299 rmb->pinfo = mb->pinfo;
1300 rmb->attrs = mb->attrs;
1301 rmb->iattrs = mb->iattrs;
1302 rmb->call_conv = mb->call_conv;
1303 rmb->code = mb->code;
1304 rmb->type = mb->type;
1305 rmb->name = mb->name;
1306 rmb->table_idx = &mb->table_idx;
1307 rmb->init_locals = mb->init_locals;
1308 rmb->return_modreq = mb->return_modreq;
1309 rmb->return_modopt = mb->return_modopt;
1310 rmb->param_modreq = mb->param_modreq;
1311 rmb->param_modopt = mb->param_modopt;
1312 rmb->permissions = mb->permissions;
1313 rmb->mhandle = mb->mhandle;
1318 rmb->charset = rmb->charset & 0xf;
1319 rmb->lasterr = rmb->charset & 0x40;
1320 rmb->native_cc = rmb->native_cc;
1321 rmb->dllentry = mb->dllentry;
1327 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1329 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1331 rmb->ilgen = mb->ilgen;
1332 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1333 rmb->parameters = mb->parameters;
1334 rmb->generic_params = NULL;
1335 rmb->generic_container = NULL;
1336 rmb->opt_types = NULL;
1337 rmb->pinfo = mb->pinfo;
1338 rmb->attrs = mb->attrs;
1339 rmb->iattrs = mb->iattrs;
1340 rmb->call_conv = mb->call_conv;
1342 rmb->type = mb->type;
1343 rmb->name = mono_string_new (mono_domain_get (), name);
1344 rmb->table_idx = &mb->table_idx;
1345 rmb->init_locals = mb->init_locals;
1346 rmb->return_modreq = NULL;
1347 rmb->return_modopt = NULL;
1348 rmb->param_modreq = mb->param_modreq;
1349 rmb->param_modopt = mb->param_modopt;
1350 rmb->permissions = mb->permissions;
1351 rmb->mhandle = mb->mhandle;
1357 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1359 rmb->ilgen = mb->ilgen;
1360 rmb->rtype = mb->rtype;
1361 rmb->parameters = mb->parameters;
1362 rmb->generic_params = NULL;
1363 rmb->generic_container = NULL;
1364 rmb->opt_types = NULL;
1366 rmb->attrs = mb->attrs;
1368 rmb->call_conv = mb->call_conv;
1371 rmb->name = mb->name;
1372 rmb->table_idx = NULL;
1373 rmb->init_locals = mb->init_locals;
1374 rmb->return_modreq = NULL;
1375 rmb->return_modopt = NULL;
1376 rmb->param_modreq = NULL;
1377 rmb->param_modopt = NULL;
1378 rmb->permissions = NULL;
1379 rmb->mhandle = mb->mhandle;
1385 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1387 MonoDynamicTable *table;
1390 ReflectionMethodBuilder rmb;
1393 reflection_methodbuilder_from_method_builder (&rmb, mb);
1395 mono_image_basic_method (&rmb, assembly);
1397 if (mb->dll) { /* It's a P/Invoke method */
1399 int charset = mb->charset & 0xf;
1400 int lasterr = mb->charset & 0x40;
1401 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1403 alloc_table (table, table->rows);
1404 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1405 /* map CharSet values to on-disk values */
1407 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1408 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1409 name = mono_string_to_utf8 (mb->dllentry);
1410 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1412 name = mono_string_to_utf8 (mb->dll);
1413 moduleref = string_heap_insert (&assembly->sheap, name);
1415 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1416 table = &assembly->tables [MONO_TABLE_MODULEREF];
1418 alloc_table (table, table->rows);
1419 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1420 values [MONO_IMPLMAP_SCOPE] = table->rows;
1424 if (mb->override_method) {
1425 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1427 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1429 alloc_table (table, table->rows);
1430 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1431 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1432 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1434 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1435 switch (mono_metadata_token_table (tok)) {
1436 case MONO_TABLE_MEMBERREF:
1437 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1439 case MONO_TABLE_METHOD:
1440 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1443 g_assert_not_reached ();
1445 values [MONO_METHODIMPL_DECLARATION] = tok;
1448 if (mb->generic_params) {
1449 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1450 table->rows += mono_array_length (mb->generic_params);
1451 alloc_table (table, table->rows);
1452 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1453 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1455 mono_image_get_generic_param_info (
1456 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1463 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1465 ReflectionMethodBuilder rmb;
1467 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1469 mono_image_basic_method (&rmb, assembly);
1473 type_get_fully_qualified_name (MonoType *type) {
1474 char *name, *result;
1478 name = mono_type_get_name (type);
1479 klass = my_mono_class_from_mono_type (type);
1480 ta = klass->image->assembly;
1482 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1483 name, ta->aname.name,
1484 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1485 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1486 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1492 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1496 klass = my_mono_class_from_mono_type (type);
1498 return mono_type_get_name (type);
1499 ta = klass->image->assembly;
1500 if (ta == ass || klass->image == mono_defaults.corlib)
1501 return mono_type_get_name (type);
1503 return type_get_fully_qualified_name (type);
1507 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1509 char blob_size [64];
1510 char *b = blob_size;
1515 if (!assembly->save)
1518 p = buf = g_malloc (64);
1520 mono_metadata_encode_value (0x06, p, &p);
1521 /* encode custom attributes before the type */
1522 encode_type (assembly, type, p, &p);
1523 g_assert (p-buf < 64);
1524 mono_metadata_encode_value (p-buf, b, &b);
1525 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1531 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1533 char blob_size [64];
1534 char *b = blob_size;
1539 p = buf = g_malloc (64);
1541 mono_metadata_encode_value (0x06, p, &p);
1542 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1543 /* encode custom attributes before the type */
1544 encode_reflection_type (assembly, fb->type, p, &p);
1545 g_assert (p-buf < 64);
1546 mono_metadata_encode_value (p-buf, b, &b);
1547 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1553 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1554 char blob_size [64];
1555 char *b = blob_size;
1558 guint32 idx = 0, len = 0, dummy = 0;
1560 p = buf = g_malloc (64);
1562 *ret_type = MONO_TYPE_CLASS;
1564 box_val = (char*)&dummy;
1566 box_val = ((char*)val) + sizeof (MonoObject);
1567 *ret_type = val->vtable->klass->byval_arg.type;
1570 switch (*ret_type) {
1571 case MONO_TYPE_BOOLEAN:
1576 case MONO_TYPE_CHAR:
1591 case MONO_TYPE_VALUETYPE:
1592 if (val->vtable->klass->enumtype) {
1593 *ret_type = val->vtable->klass->enum_basetype->type;
1596 g_error ("we can't encode valuetypes");
1597 case MONO_TYPE_CLASS:
1599 case MONO_TYPE_STRING: {
1600 MonoString *str = (MonoString*)val;
1601 /* there is no signature */
1602 len = str->length * 2;
1603 mono_metadata_encode_value (len, b, &b);
1604 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1606 char *swapped = g_malloc (2 * mono_string_length (str));
1607 const char *p = (const char*)mono_string_chars (str);
1609 swap_with_size (swapped, p, 2, mono_string_length (str));
1610 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1614 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1621 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1624 /* there is no signature */
1625 mono_metadata_encode_value (len, b, &b);
1626 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1627 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1628 swap_with_size (blob_size, box_val, len, 1);
1629 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1631 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1639 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1640 char blob_size [64];
1641 char *b = blob_size;
1642 char *p, *buf, *str;
1643 guint32 idx, len, bufsize = 256;
1645 p = buf = g_malloc (bufsize);
1647 switch (minfo->type) {
1648 case MONO_NATIVE_BYVALTSTR:
1649 case MONO_NATIVE_BYVALARRAY:
1650 mono_metadata_encode_value (minfo->type, p, &p);
1651 mono_metadata_encode_value (minfo->count, p, &p);
1653 case MONO_NATIVE_LPARRAY:
1654 mono_metadata_encode_value (minfo->type, p, &p);
1655 if (minfo->eltype || (minfo->count > 0)) {
1656 mono_metadata_encode_value (minfo->eltype, p, &p);
1657 if (minfo->count > 0) {
1658 mono_metadata_encode_value (0, p, &p);
1659 mono_metadata_encode_value (minfo->count, p, &p);
1663 case MONO_NATIVE_CUSTOM:
1664 mono_metadata_encode_value (minfo->type, p, &p);
1666 str = mono_string_to_utf8 (minfo->guid);
1668 mono_metadata_encode_value (len, p, &p);
1669 memcpy (p, str, len);
1673 mono_metadata_encode_value (0, p, &p);
1675 if (minfo->marshaltype) {
1676 str = mono_string_to_utf8 (minfo->marshaltype);
1678 mono_metadata_encode_value (len, p, &p);
1679 if (p + len >= buf + bufsize) {
1682 buf = g_realloc (buf, bufsize);
1685 memcpy (p, str, len);
1689 mono_metadata_encode_value (0, p, &p);
1691 if (minfo->marshaltyperef) {
1692 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1694 mono_metadata_encode_value (len, p, &p);
1695 if (p + len >= buf + bufsize) {
1698 buf = g_realloc (buf, bufsize);
1701 memcpy (p, str, len);
1705 mono_metadata_encode_value (0, p, &p);
1707 if (minfo->mcookie) {
1708 str = mono_string_to_utf8 (minfo->mcookie);
1710 mono_metadata_encode_value (len, p, &p);
1711 if (p + len >= buf + bufsize) {
1714 buf = g_realloc (buf, bufsize);
1717 memcpy (p, str, len);
1721 mono_metadata_encode_value (0, p, &p);
1725 mono_metadata_encode_value (minfo->type, p, &p);
1729 mono_metadata_encode_value (len, b, &b);
1730 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1736 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1738 MonoDynamicTable *table;
1742 /* maybe this fixup should be done in the C# code */
1743 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1744 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1745 table = &assembly->tables [MONO_TABLE_FIELD];
1746 fb->table_idx = table->next_idx ++;
1747 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1748 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1749 name = mono_string_to_utf8 (fb->name);
1750 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1752 values [MONO_FIELD_FLAGS] = fb->attrs;
1753 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1755 if (fb->offset != -1) {
1756 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1760 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1761 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1763 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1764 guint32 field_type = 0;
1765 table = &assembly->tables [MONO_TABLE_CONSTANT];
1767 alloc_table (table, table->rows);
1768 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1769 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1770 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1771 values [MONO_CONSTANT_TYPE] = field_type;
1772 values [MONO_CONSTANT_PADDING] = 0;
1774 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1776 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1778 alloc_table (table, table->rows);
1779 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1780 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1782 * We store it in the code section because it's simpler for now.
1785 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1787 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1788 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1790 if (fb->marshal_info) {
1791 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1793 alloc_table (table, table->rows);
1794 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1795 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1796 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1801 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1805 char *b = blob_size;
1806 guint32 nparams = 0;
1807 MonoReflectionMethodBuilder *mb = fb->get_method;
1808 MonoReflectionMethodBuilder *smb = fb->set_method;
1809 guint32 idx, i, size;
1811 if (mb && mb->parameters)
1812 nparams = mono_array_length (mb->parameters);
1813 if (!mb && smb && smb->parameters)
1814 nparams = mono_array_length (smb->parameters) - 1;
1815 size = 24 + nparams * 10;
1816 buf = p = g_malloc (size);
1819 mono_metadata_encode_value (nparams, p, &p);
1821 encode_reflection_type (assembly, mb->rtype, p, &p);
1822 for (i = 0; i < nparams; ++i) {
1823 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1824 encode_reflection_type (assembly, pt, p, &p);
1827 /* the property type is the last param */
1828 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1829 for (i = 0; i < nparams; ++i) {
1830 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1831 encode_reflection_type (assembly, pt, p, &p);
1835 g_assert (p - buf < size);
1836 mono_metadata_encode_value (p-buf, b, &b);
1837 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1843 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1845 MonoDynamicTable *table;
1848 guint num_methods = 0;
1852 * we need to set things in the following tables:
1853 * PROPERTYMAP (info already filled in _get_type_info ())
1854 * PROPERTY (rows already preallocated in _get_type_info ())
1855 * METHOD (method info already done with the generic method code)
1858 table = &assembly->tables [MONO_TABLE_PROPERTY];
1859 pb->table_idx = table->next_idx ++;
1860 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1861 name = mono_string_to_utf8 (pb->name);
1862 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1864 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1865 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1867 /* FIXME: we still don't handle 'other' methods */
1868 if (pb->get_method) num_methods ++;
1869 if (pb->set_method) num_methods ++;
1871 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1872 table->rows += num_methods;
1873 alloc_table (table, table->rows);
1875 if (pb->get_method) {
1876 semaidx = table->next_idx ++;
1877 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1878 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1879 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1880 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1882 if (pb->set_method) {
1883 semaidx = table->next_idx ++;
1884 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1885 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1886 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1887 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1892 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1894 MonoDynamicTable *table;
1897 guint num_methods = 0;
1901 * we need to set things in the following tables:
1902 * EVENTMAP (info already filled in _get_type_info ())
1903 * EVENT (rows already preallocated in _get_type_info ())
1904 * METHOD (method info already done with the generic method code)
1907 table = &assembly->tables [MONO_TABLE_EVENT];
1908 eb->table_idx = table->next_idx ++;
1909 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1910 name = mono_string_to_utf8 (eb->name);
1911 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1913 values [MONO_EVENT_FLAGS] = eb->attrs;
1914 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1917 * FIXME: we still don't handle 'other' methods
1919 if (eb->add_method) num_methods ++;
1920 if (eb->remove_method) num_methods ++;
1921 if (eb->raise_method) num_methods ++;
1923 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1924 table->rows += num_methods;
1925 alloc_table (table, table->rows);
1927 if (eb->add_method) {
1928 semaidx = table->next_idx ++;
1929 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1930 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1931 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1932 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1934 if (eb->remove_method) {
1935 semaidx = table->next_idx ++;
1936 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1937 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1938 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1939 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1941 if (eb->raise_method) {
1942 semaidx = table->next_idx ++;
1943 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1944 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1945 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1946 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1951 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1953 static MonoClass *NewConstraintAttr;
1954 static MonoMethod *NewConstraintAttr_ctor;
1955 MonoDynamicTable *table;
1957 guint32 token, type;
1958 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1961 if (!NewConstraintAttr)
1962 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1963 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1964 g_assert (NewConstraintAttr);
1966 if (!NewConstraintAttr_ctor) {
1969 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1970 MonoMethod *m = NewConstraintAttr->methods [i];
1972 if (strcmp (m->name, ".ctor"))
1975 NewConstraintAttr_ctor = m;
1979 g_assert (NewConstraintAttr_ctor);
1982 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1984 alloc_table (table, table->rows);
1986 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1987 owner <<= MONO_CUSTOM_ATTR_BITS;
1988 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1989 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1991 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1993 type = mono_metadata_token_index (token);
1994 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1995 switch (mono_metadata_token_table (token)) {
1996 case MONO_TABLE_METHOD:
1997 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1999 case MONO_TABLE_MEMBERREF:
2000 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
2003 g_warning ("got wrong token in custom attr");
2006 values [MONO_CUSTOM_ATTR_TYPE] = type;
2008 buf = p = g_malloc (1);
2009 mono_metadata_encode_value (4, p, &p);
2010 g_assert (p-buf == 1);
2012 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2014 values += MONO_CUSTOM_ATTR_SIZE;
2019 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2021 MonoDynamicTable *table;
2022 guint32 num_constraints, i;
2026 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2027 num_constraints = gparam->iface_constraints ?
2028 mono_array_length (gparam->iface_constraints) : 0;
2029 table->rows += num_constraints;
2030 if (gparam->base_type)
2032 alloc_table (table, table->rows);
2034 if (gparam->base_type) {
2035 table_idx = table->next_idx ++;
2036 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2038 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2039 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2040 assembly, gparam->base_type->type);
2043 for (i = 0; i < num_constraints; i++) {
2044 MonoReflectionType *constraint = mono_array_get (
2045 gparam->iface_constraints, gpointer, i);
2047 table_idx = table->next_idx ++;
2048 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2050 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2051 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2052 assembly, constraint->type);
2055 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2056 encode_new_constraint (assembly, owner);
2060 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2062 GenericParamTableEntry *entry;
2065 * The GenericParam table must be sorted according to the `owner' field.
2066 * We need to do this sorting prior to writing the GenericParamConstraint
2067 * table, since we have to use the final GenericParam table indices there
2068 * and they must also be sorted.
2071 entry = g_new0 (GenericParamTableEntry, 1);
2072 entry->owner = owner;
2073 entry->gparam = gparam;
2075 g_ptr_array_add (assembly->gen_params, entry);
2079 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2081 MonoDynamicTable *table;
2082 MonoGenericParam *param;
2086 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2087 table_idx = table->next_idx ++;
2088 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2090 param = entry->gparam->type.type->data.generic_param;
2092 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2093 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2094 values [MONO_GENERICPARAM_NUMBER] = param->num;
2095 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2096 values [MONO_GENERICPARAM_KIND] = 0;
2098 encode_constraints (entry->gparam, table_idx, assembly);
2102 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2104 MonoDynamicTable *table;
2107 guint32 cols [MONO_ASSEMBLY_SIZE];
2111 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2114 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2115 table = &assembly->tables [MONO_TABLE_MODULEREF];
2116 token = table->next_idx ++;
2118 alloc_table (table, table->rows);
2119 values = table->values + token * MONO_MODULEREF_SIZE;
2120 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2122 token <<= MONO_RESOLTION_SCOPE_BITS;
2123 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2124 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2129 if (image->assembly->dynamic)
2131 memset (cols, 0, sizeof (cols));
2133 /* image->assembly->image is the manifest module */
2134 image = image->assembly->image;
2135 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2138 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2139 token = table->next_idx ++;
2141 alloc_table (table, table->rows);
2142 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2143 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2144 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2145 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2146 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2147 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2148 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2149 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2150 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2152 if (strcmp ("", image->assembly->aname.culture)) {
2153 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2154 image->assembly->aname.culture);
2157 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2158 guchar pubtoken [9];
2160 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2161 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2163 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2165 token <<= MONO_RESOLTION_SCOPE_BITS;
2166 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2167 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2172 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2174 MonoDynamicTable *table;
2180 char *b = blob_size;
2182 switch (type->type) {
2183 case MONO_TYPE_FNPTR:
2185 case MONO_TYPE_SZARRAY:
2186 case MONO_TYPE_ARRAY:
2188 case MONO_TYPE_MVAR:
2189 case MONO_TYPE_GENERICINST:
2190 encode_type (assembly, type, p, &p);
2192 case MONO_TYPE_CLASS:
2193 case MONO_TYPE_VALUETYPE: {
2194 MonoClass *k = mono_class_from_mono_type (type);
2195 if (!k || !k->generic_class)
2197 encode_generic_class (assembly, k->generic_class, p, &p);
2204 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2205 if (assembly->save) {
2206 g_assert (p-sig < 128);
2207 mono_metadata_encode_value (p-sig, b, &b);
2208 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2209 alloc_table (table, table->rows + 1);
2210 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2211 values [MONO_TYPESPEC_SIGNATURE] = token;
2214 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2215 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2221 * Despite the name, we handle also TypeSpec (with the above helper).
2224 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2226 MonoDynamicTable *table;
2228 guint32 token, scope, enclosing;
2231 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2234 token = create_typespec (assembly, type);
2237 klass = my_mono_class_from_mono_type (type);
2239 klass = mono_class_from_mono_type (type);
2242 * If it's in the same module and not a generic type parameter:
2244 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2245 (type->type != MONO_TYPE_MVAR)) {
2246 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2247 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2248 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2252 if (klass->nested_in) {
2253 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2254 /* get the typeref idx of the enclosing type */
2255 enclosing >>= MONO_TYPEDEFORREF_BITS;
2256 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2258 scope = resolution_scope_from_image (assembly, klass->image);
2260 table = &assembly->tables [MONO_TABLE_TYPEREF];
2261 if (assembly->save) {
2262 alloc_table (table, table->rows + 1);
2263 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2264 values [MONO_TYPEREF_SCOPE] = scope;
2265 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2266 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2268 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2269 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2271 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2276 * Insert a memberef row into the metadata: the token that point to the memberref
2277 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2278 * mono_image_get_fieldref_token()).
2279 * The sig param is an index to an already built signature.
2282 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2284 MonoDynamicTable *table;
2286 guint32 token, pclass;
2289 parent = mono_image_typedef_or_ref (assembly, type);
2290 switch (parent & MONO_TYPEDEFORREF_MASK) {
2291 case MONO_TYPEDEFORREF_TYPEREF:
2292 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2294 case MONO_TYPEDEFORREF_TYPESPEC:
2295 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2297 case MONO_TYPEDEFORREF_TYPEDEF:
2298 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2301 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2304 /* extract the index */
2305 parent >>= MONO_TYPEDEFORREF_BITS;
2307 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2309 if (assembly->save) {
2310 alloc_table (table, table->rows + 1);
2311 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2312 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2313 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2314 values [MONO_MEMBERREF_SIGNATURE] = sig;
2317 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2324 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2327 MonoMethodSignature *sig;
2329 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2334 * A methodref signature can't contain an unmanaged calling convention.
2336 sig = mono_metadata_signature_dup (method->signature);
2337 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2338 sig->call_convention = MONO_CALL_DEFAULT;
2339 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2340 method->name, method_encode_signature (assembly, sig));
2342 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2347 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2348 const gchar *name, guint32 sig)
2350 MonoDynamicTable *table;
2354 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2356 if (assembly->save) {
2357 alloc_table (table, table->rows + 1);
2358 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2359 values [MONO_MEMBERREF_CLASS] = original;
2360 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2361 values [MONO_MEMBERREF_SIGNATURE] = sig;
2364 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2371 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2374 ReflectionMethodBuilder rmb;
2376 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2380 reflection_methodbuilder_from_method_builder (&rmb, mb);
2382 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2383 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2384 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2389 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2392 ReflectionMethodBuilder rmb;
2394 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2398 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2400 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2401 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2402 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2407 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2412 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2415 g_assert (f->field->parent);
2416 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2417 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2418 f->field->name, fieldref_encode_signature (assembly, type));
2419 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2424 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2429 guint32 nparams = gmethod->inst->type_argc;
2430 guint32 size = 10 + nparams * 10;
2433 char *b = blob_size;
2435 if (!assembly->save)
2438 p = buf = g_malloc (size);
2440 * FIXME: vararg, explicit_this, differenc call_conv values...
2442 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2443 mono_metadata_encode_value (nparams, p, &p);
2445 for (i = 0; i < nparams; i++)
2446 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2449 g_assert (p - buf < size);
2450 mono_metadata_encode_value (p-buf, b, &b);
2451 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2457 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2459 MonoDynamicTable *table;
2461 guint32 token, mtoken = 0, sig;
2462 MonoMethodInflated *imethod;
2463 MonoMethod *declaring;
2465 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2467 g_assert (method->signature->is_inflated);
2468 imethod = (MonoMethodInflated *) method;
2469 declaring = imethod->declaring;
2471 sig = method_encode_signature (assembly, declaring->signature);
2472 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2474 if (!declaring->signature->generic_param_count)
2477 switch (mono_metadata_token_table (mtoken)) {
2478 case MONO_TABLE_MEMBERREF:
2479 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2481 case MONO_TABLE_METHOD:
2482 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2485 g_assert_not_reached ();
2488 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2490 if (assembly->save) {
2491 alloc_table (table, table->rows + 1);
2492 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2493 values [MONO_METHODSPEC_METHOD] = mtoken;
2494 values [MONO_METHODSPEC_SIGNATURE] = sig;
2497 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2504 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2506 MonoMethodInflated *imethod;
2509 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2513 g_assert (m->signature->is_inflated);
2514 imethod = (MonoMethodInflated *) m;
2516 if (imethod->declaring->signature->generic_param_count) {
2517 token = method_encode_methodspec (assembly, m);
2519 guint32 sig = method_encode_signature (
2520 assembly, imethod->declaring->signature);
2521 token = mono_image_get_memberref_token (
2522 assembly, &m->klass->byval_arg, m->name, sig);
2525 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2530 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2532 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2535 sig = method_encode_signature (assembly, imethod->declaring->signature);
2536 token = mono_image_get_memberref_token (
2537 assembly, &m->klass->byval_arg, m->name, sig);
2543 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2545 MonoDynamicTable *table;
2552 char *b = blob_size;
2556 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2557 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2558 * Because of this, we must not insert it into the `typeref' hash table.
2561 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2565 g_assert (tb->generic_params);
2566 klass = mono_class_from_mono_type (tb->type.type);
2568 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2569 encode_type (assembly, &klass->byval_arg, p, &p);
2571 count = mono_array_length (tb->generic_params);
2572 mono_metadata_encode_value (count, p, &p);
2573 for (i = 0; i < count; i++) {
2574 MonoReflectionGenericParam *gparam;
2576 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2578 encode_type (assembly, gparam->type.type, p, &p);
2581 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2582 if (assembly->save) {
2583 g_assert (p-sig < 128);
2584 mono_metadata_encode_value (p-sig, b, &b);
2585 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2588 values [MONO_TYPESPEC_SIGNATURE] = token;
2591 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2592 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2598 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2600 MonoDynamicTable *table;
2603 guint32 token, pclass, parent, sig;
2606 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2610 klass = mono_class_from_mono_type (fb->typeb->type);
2611 name = mono_string_to_utf8 (fb->name);
2613 sig = fieldref_encode_signature (assembly, fb->type->type);
2615 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2616 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2618 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2619 parent >>= MONO_TYPEDEFORREF_BITS;
2621 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2623 if (assembly->save) {
2624 alloc_table (table, table->rows + 1);
2625 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2626 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2627 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2628 values [MONO_MEMBERREF_SIGNATURE] = sig;
2631 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2633 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2638 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2646 char *b = blob_size;
2648 if (!assembly->save)
2652 g_assert (helper->type == 2);
2654 if (helper->arguments)
2655 nargs = mono_array_length (helper->arguments);
2659 size = 10 + (nargs * 10);
2661 p = buf = g_malloc (size);
2663 /* Encode calling convention */
2664 /* Change Any to Standard */
2665 if ((helper->call_conv & 0x03) == 0x03)
2666 helper->call_conv = 0x01;
2667 /* explicit_this implies has_this */
2668 if (helper->call_conv & 0x40)
2669 helper->call_conv &= 0x20;
2671 if (helper->call_conv == 0) { /* Unmanaged */
2672 *p = helper->unmanaged_call_conv - 1;
2675 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2676 if (helper->call_conv & 0x02) /* varargs */
2681 mono_metadata_encode_value (nargs, p, &p);
2682 encode_reflection_type (assembly, helper->return_type, p, &p);
2683 for (i = 0; i < nargs; ++i) {
2684 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2685 encode_reflection_type (assembly, pt, p, &p);
2688 g_assert (p - buf < size);
2689 mono_metadata_encode_value (p-buf, b, &b);
2690 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2697 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2700 MonoDynamicTable *table;
2703 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2704 idx = table->next_idx ++;
2706 alloc_table (table, table->rows);
2707 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2709 values [MONO_STAND_ALONE_SIGNATURE] =
2710 mono_reflection_encode_sighelper (assembly, helper);
2716 reflection_cc_to_file (int call_conv) {
2717 switch (call_conv & 0x3) {
2719 case 1: return MONO_CALL_DEFAULT;
2720 case 2: return MONO_CALL_VARARG;
2722 g_assert_not_reached ();
2729 MonoMethodSignature *sig;
2735 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2740 MonoMethodSignature *sig;
2743 name = mono_string_to_utf8 (m->name);
2744 nparams = mono_array_length (m->parameters);
2745 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2747 sig->sentinelpos = -1;
2748 sig->call_convention = reflection_cc_to_file (m->call_conv);
2749 sig->param_count = nparams;
2750 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2751 for (i = 0; i < nparams; ++i) {
2752 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2753 sig->params [i] = t->type;
2756 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2758 if (strcmp (name, am->name) == 0 &&
2759 mono_metadata_type_equal (am->parent, m->parent->type) &&
2760 mono_metadata_signature_equal (am->sig, sig)) {
2763 m->table_idx = am->token & 0xffffff;
2767 am = g_new0 (ArrayMethod, 1);
2770 am->parent = m->parent->type;
2771 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2772 method_encode_signature (assembly, sig));
2773 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2774 m->table_idx = am->token & 0xffffff;
2779 * Insert into the metadata tables all the info about the TypeBuilder tb.
2780 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2783 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2785 MonoDynamicTable *table;
2787 int i, is_object = 0, is_system = 0;
2790 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2791 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2792 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2793 n = mono_string_to_utf8 (tb->name);
2794 if (strcmp (n, "Object") == 0)
2796 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2798 n = mono_string_to_utf8 (tb->nspace);
2799 if (strcmp (n, "System") == 0)
2801 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2803 if (tb->parent && !(is_system && is_object) &&
2804 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2805 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2807 values [MONO_TYPEDEF_EXTENDS] = 0;
2809 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2810 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2813 * if we have explicitlayout or sequentiallayouts, output data in the
2814 * ClassLayout table.
2816 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2817 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2818 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2820 alloc_table (table, table->rows);
2821 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2822 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2823 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2824 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2827 /* handle interfaces */
2828 if (tb->interfaces) {
2829 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2831 table->rows += mono_array_length (tb->interfaces);
2832 alloc_table (table, table->rows);
2833 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2834 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2835 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2836 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2837 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2838 values += MONO_INTERFACEIMPL_SIZE;
2844 table = &assembly->tables [MONO_TABLE_FIELD];
2845 table->rows += tb->num_fields;
2846 alloc_table (table, table->rows);
2847 for (i = 0; i < tb->num_fields; ++i)
2848 mono_image_get_field_info (
2849 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2852 /* handle constructors */
2854 table = &assembly->tables [MONO_TABLE_METHOD];
2855 table->rows += mono_array_length (tb->ctors);
2856 alloc_table (table, table->rows);
2857 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2858 mono_image_get_ctor_info (domain,
2859 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2862 /* handle methods */
2864 table = &assembly->tables [MONO_TABLE_METHOD];
2865 table->rows += tb->num_methods;
2866 alloc_table (table, table->rows);
2867 for (i = 0; i < tb->num_methods; ++i)
2868 mono_image_get_method_info (
2869 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2872 /* Do the same with properties etc.. */
2873 if (tb->events && mono_array_length (tb->events)) {
2874 table = &assembly->tables [MONO_TABLE_EVENT];
2875 table->rows += mono_array_length (tb->events);
2876 alloc_table (table, table->rows);
2877 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2879 alloc_table (table, table->rows);
2880 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2881 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2882 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2883 for (i = 0; i < mono_array_length (tb->events); ++i)
2884 mono_image_get_event_info (
2885 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2887 if (tb->properties && mono_array_length (tb->properties)) {
2888 table = &assembly->tables [MONO_TABLE_PROPERTY];
2889 table->rows += mono_array_length (tb->properties);
2890 alloc_table (table, table->rows);
2891 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2893 alloc_table (table, table->rows);
2894 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2895 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2896 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2897 for (i = 0; i < mono_array_length (tb->properties); ++i)
2898 mono_image_get_property_info (
2899 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2902 /* handle generic parameters */
2903 if (tb->generic_params) {
2904 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2905 table->rows += mono_array_length (tb->generic_params);
2906 alloc_table (table, table->rows);
2907 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2908 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2910 mono_image_get_generic_param_info (
2911 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2915 mono_image_add_decl_security (assembly,
2916 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2919 MonoDynamicTable *ntable;
2921 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2922 ntable->rows += mono_array_length (tb->subtypes);
2923 alloc_table (ntable, ntable->rows);
2924 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2926 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2927 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2929 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2930 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2931 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2932 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2933 mono_string_to_utf8 (tb->name), tb->table_idx,
2934 ntable->next_idx, ntable->rows);*/
2935 values += MONO_NESTED_CLASS_SIZE;
2942 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2946 g_ptr_array_add (types, type);
2948 if (!type->subtypes)
2951 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2952 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2953 collect_types (types, subtype);
2958 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2960 if ((*type1)->table_idx < (*type2)->table_idx)
2963 if ((*type1)->table_idx > (*type2)->table_idx)
2970 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2975 for (i = 0; i < mono_array_length (pinfo); ++i) {
2976 MonoReflectionParamBuilder *pb;
2977 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2980 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2985 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2988 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2990 for (i = 0; i < tb->num_fields; ++i) {
2991 MonoReflectionFieldBuilder* fb;
2992 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2993 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2997 for (i = 0; i < mono_array_length (tb->events); ++i) {
2998 MonoReflectionEventBuilder* eb;
2999 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3000 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3003 if (tb->properties) {
3004 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3005 MonoReflectionPropertyBuilder* pb;
3006 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3007 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3011 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3012 MonoReflectionCtorBuilder* cb;
3013 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3014 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3015 params_add_cattrs (assembly, cb->pinfo);
3020 for (i = 0; i < tb->num_methods; ++i) {
3021 MonoReflectionMethodBuilder* mb;
3022 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3023 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3024 params_add_cattrs (assembly, mb->pinfo);
3029 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3030 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3035 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3038 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3040 /* no types in the module */
3044 for (i = 0; i < mb->num_types; ++i)
3045 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3049 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3051 MonoDynamicTable *table;
3055 char *b = blob_size;
3058 table = &assembly->tables [MONO_TABLE_FILE];
3060 alloc_table (table, table->rows);
3061 values = table->values + table->next_idx * MONO_FILE_SIZE;
3062 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3063 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3064 if (module->image->dynamic) {
3065 /* This depends on the fact that the main module is emitted last */
3066 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3067 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3070 path = g_strdup (module->image->name);
3072 mono_sha1_get_digest_from_file (path, hash);
3075 mono_metadata_encode_value (20, b, &b);
3076 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3077 mono_image_add_stream_data (&assembly->blob, hash, 20);
3082 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3084 MonoDynamicTable *table;
3088 table = &assembly->tables [MONO_TABLE_MODULE];
3089 mb->table_idx = table->next_idx ++;
3090 name = mono_string_to_utf8 (mb->module.name);
3091 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3093 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3096 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3097 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3098 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3102 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3103 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3105 MonoDynamicTable *table;
3109 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3110 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3113 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3115 alloc_table (table, table->rows);
3116 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3118 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3119 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3120 if (klass->nested_in)
3121 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3123 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3124 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3125 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3127 res = table->next_idx;
3131 /* Emit nested types */
3132 if (klass->nested_classes) {
3135 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3136 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3143 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3144 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3149 klass = mono_class_from_mono_type (tb->type.type);
3151 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3153 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3154 parent_index, assembly);
3158 * We need to do this ourselves since klass->nested_classes is not set up.
3161 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3162 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3167 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3168 guint32 module_index, MonoDynamicImage *assembly)
3170 MonoImage *image = module->image;
3174 t = &image->tables [MONO_TABLE_TYPEDEF];
3176 for (i = 0; i < t->rows; ++i) {
3177 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3179 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3180 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3184 #define align_pointer(base,p)\
3186 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3188 (p) += 4 - (__diff & 3);\
3192 compare_semantics (const void *a, const void *b)
3194 const guint32 *a_values = a;
3195 const guint32 *b_values = b;
3196 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3199 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3203 compare_custom_attrs (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3208 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3212 compare_field_marshal (const void *a, const void *b)
3214 const guint32 *a_values = a;
3215 const guint32 *b_values = b;
3217 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3221 compare_nested (const void *a, const void *b)
3223 const guint32 *a_values = a;
3224 const guint32 *b_values = b;
3226 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3230 compare_genericparam (const void *a, const void *b)
3232 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3233 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3235 return (*b_entry)->owner - (*a_entry)->owner;
3239 compare_declsecurity_attrs (const void *a, const void *b)
3241 const guint32 *a_values = a;
3242 const guint32 *b_values = b;
3244 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3248 pad_heap (MonoDynamicStream *sh)
3250 if (sh->index & 3) {
3251 int sz = 4 - (sh->index & 3);
3252 memset (sh->data + sh->index, 0, sz);
3259 MonoDynamicStream *stream;
3263 * build_compressed_metadata() fills in the blob of data that represents the
3264 * raw metadata as it will be saved in the PE file. The five streams are output
3265 * and the metadata tables are comnpressed from the guint32 array representation,
3266 * to the compressed on-disk format.
3269 build_compressed_metadata (MonoDynamicImage *assembly)
3271 MonoDynamicTable *table;
3273 guint64 valid_mask = 0;
3274 guint64 sorted_mask;
3275 guint32 heapt_size = 0;
3276 guint32 meta_size = 256; /* allow for header and other stuff */
3277 guint32 table_offset;
3278 guint32 ntables = 0;
3284 struct StreamDesc stream_desc [5];
3286 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3287 for (i = 0; i < assembly->gen_params->len; i++){
3288 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3289 write_generic_param_entry (assembly, entry);
3292 stream_desc [0].name = "#~";
3293 stream_desc [0].stream = &assembly->tstream;
3294 stream_desc [1].name = "#Strings";
3295 stream_desc [1].stream = &assembly->sheap;
3296 stream_desc [2].name = "#US";
3297 stream_desc [2].stream = &assembly->us;
3298 stream_desc [3].name = "#Blob";
3299 stream_desc [3].stream = &assembly->blob;
3300 stream_desc [4].name = "#GUID";
3301 stream_desc [4].stream = &assembly->guid;
3303 /* tables that are sorted */
3304 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3305 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3306 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3307 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3308 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3309 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3311 /* Compute table sizes */
3312 /* the MonoImage has already been created in mono_image_basic_init() */
3313 meta = &assembly->image;
3315 /* sizes should be multiple of 4 */
3316 pad_heap (&assembly->blob);
3317 pad_heap (&assembly->guid);
3318 pad_heap (&assembly->sheap);
3319 pad_heap (&assembly->us);
3321 /* Setup the info used by compute_sizes () */
3322 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3323 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3324 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3326 meta_size += assembly->blob.index;
3327 meta_size += assembly->guid.index;
3328 meta_size += assembly->sheap.index;
3329 meta_size += assembly->us.index;
3331 for (i=0; i < 64; ++i)
3332 meta->tables [i].rows = assembly->tables [i].rows;
3334 for (i = 0; i < 64; i++){
3335 if (meta->tables [i].rows == 0)
3337 valid_mask |= (guint64)1 << i;
3339 meta->tables [i].row_size = mono_metadata_compute_size (
3340 meta, i, &meta->tables [i].size_bitfield);
3341 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3343 heapt_size += 24; /* #~ header size */
3344 heapt_size += ntables * 4;
3345 /* make multiple of 4 */
3348 meta_size += heapt_size;
3349 meta->raw_metadata = g_malloc0 (meta_size);
3350 p = meta->raw_metadata;
3351 /* the metadata signature */
3352 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3353 /* version numbers and 4 bytes reserved */
3354 int16val = (guint16*)p;
3355 *int16val++ = GUINT16_TO_LE (1);
3356 *int16val = GUINT16_TO_LE (1);
3358 /* version string */
3359 int32val = (guint32*)p;
3360 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3362 memcpy (p, meta->version, strlen (meta->version));
3363 p += GUINT32_FROM_LE (*int32val);
3364 align_pointer (meta->raw_metadata, p);
3365 int16val = (guint16*)p;
3366 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3367 *int16val = GUINT16_TO_LE (5); /* number of streams */
3371 * write the stream info.
3373 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3374 table_offset += 3; table_offset &= ~3;
3376 assembly->tstream.index = heapt_size;
3377 for (i = 0; i < 5; ++i) {
3378 int32val = (guint32*)p;
3379 stream_desc [i].stream->offset = table_offset;
3380 *int32val++ = GUINT32_TO_LE (table_offset);
3381 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3382 table_offset += GUINT32_FROM_LE (*int32val);
3383 table_offset += 3; table_offset &= ~3;
3385 strcpy (p, stream_desc [i].name);
3386 p += strlen (stream_desc [i].name) + 1;
3387 align_pointer (meta->raw_metadata, p);
3390 * now copy the data, the table stream header and contents goes first.
3392 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3393 p = meta->raw_metadata + assembly->tstream.offset;
3394 int32val = (guint32*)p;
3395 *int32val = GUINT32_TO_LE (0); /* reserved */
3398 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3399 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3400 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3401 *p++ = 1; /* version */
3404 *p++ = 1; /* version */
3408 if (meta->idx_string_wide)
3410 if (meta->idx_guid_wide)
3412 if (meta->idx_blob_wide)
3415 *p++ = 1; /* reserved */
3416 int64val = (guint64*)p;
3417 *int64val++ = GUINT64_TO_LE (valid_mask);
3418 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3420 int32val = (guint32*)p;
3421 for (i = 0; i < 64; i++){
3422 if (meta->tables [i].rows == 0)
3424 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3426 p = (unsigned char*)int32val;
3428 /* sort the tables that still need sorting */
3429 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3431 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3432 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3434 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3435 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3437 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3438 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3440 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3441 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3442 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3444 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3446 /* compress the tables */
3447 for (i = 0; i < 64; i++){
3450 guint32 bitfield = meta->tables [i].size_bitfield;
3451 if (!meta->tables [i].rows)
3453 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3454 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3455 meta->tables [i].base = p;
3456 for (row = 1; row <= meta->tables [i].rows; ++row) {
3457 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3458 for (col = 0; col < assembly->tables [i].columns; ++col) {
3459 switch (mono_metadata_table_size (bitfield, col)) {
3461 *p++ = values [col];
3464 *p++ = values [col] & 0xff;
3465 *p++ = (values [col] >> 8) & 0xff;
3468 *p++ = values [col] & 0xff;
3469 *p++ = (values [col] >> 8) & 0xff;
3470 *p++ = (values [col] >> 16) & 0xff;
3471 *p++ = (values [col] >> 24) & 0xff;
3474 g_assert_not_reached ();
3478 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3481 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3482 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3483 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3484 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3485 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3487 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3491 * Some tables in metadata need to be sorted according to some criteria, but
3492 * when methods and fields are first created with reflection, they may be assigned a token
3493 * that doesn't correspond to the final token they will get assigned after the sorting.
3494 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3495 * with the reflection objects that represent them. Once all the tables are set up, the
3496 * reflection objects will contains the correct table index. fixup_method() will fixup the
3497 * tokens for the method with ILGenerator @ilgen.
3500 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3501 guint32 code_idx = GPOINTER_TO_UINT (value);
3502 MonoReflectionILTokenInfo *iltoken;
3503 MonoReflectionFieldBuilder *field;
3504 MonoReflectionCtorBuilder *ctor;
3505 MonoReflectionMethodBuilder *method;
3506 MonoReflectionTypeBuilder *tb;
3507 MonoReflectionArrayMethod *am;
3509 unsigned char *target;
3511 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3512 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3513 target = assembly->code.data + code_idx + iltoken->code_pos;
3514 switch (target [3]) {
3515 case MONO_TABLE_FIELD:
3516 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3517 field = (MonoReflectionFieldBuilder *)iltoken->member;
3518 idx = field->table_idx;
3519 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3520 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3521 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3523 g_assert_not_reached ();
3526 case MONO_TABLE_METHOD:
3527 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3528 method = (MonoReflectionMethodBuilder *)iltoken->member;
3529 idx = method->table_idx;
3530 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3531 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3532 idx = ctor->table_idx;
3533 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3534 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3535 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3536 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3538 g_assert_not_reached ();
3541 case MONO_TABLE_TYPEDEF:
3542 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3543 g_assert_not_reached ();
3544 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3545 idx = tb->table_idx;
3547 case MONO_TABLE_MEMBERREF:
3548 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3549 am = (MonoReflectionArrayMethod*)iltoken->member;
3550 idx = am->table_idx;
3551 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3552 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3553 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3554 g_assert (m->klass->generic_class);
3556 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3558 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3559 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3560 g_assert (f->generic_info);
3562 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3565 g_assert_not_reached ();
3568 case MONO_TABLE_METHODSPEC:
3569 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3570 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3571 g_assert (m->signature->generic_param_count);
3574 g_assert_not_reached ();
3578 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3580 target [0] = idx & 0xff;
3581 target [1] = (idx >> 8) & 0xff;
3582 target [2] = (idx >> 16) & 0xff;
3589 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3590 * value is not known when the table is emitted.
3593 fixup_cattrs (MonoDynamicImage *assembly)
3595 MonoDynamicTable *table;
3597 guint32 type, i, idx, token;
3600 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3602 for (i = 0; i < table->rows; ++i) {
3603 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3605 type = values [MONO_CUSTOM_ATTR_TYPE];
3606 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3607 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3608 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3609 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3612 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3613 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3614 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3615 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3622 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3624 MonoDynamicTable *table;
3628 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3630 alloc_table (table, table->rows);
3631 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3632 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3633 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3634 name = mono_string_to_utf8 (rsrc->name);
3635 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3637 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3642 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3644 MonoDynamicTable *table;
3648 char *b = blob_size;
3650 guint32 idx, offset;
3652 if (rsrc->filename) {
3653 name = mono_string_to_utf8 (rsrc->filename);
3654 sname = g_path_get_basename (name);
3656 table = &assembly->tables [MONO_TABLE_FILE];
3658 alloc_table (table, table->rows);
3659 values = table->values + table->next_idx * MONO_FILE_SIZE;
3660 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3661 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3664 mono_sha1_get_digest_from_file (name, hash);
3665 mono_metadata_encode_value (20, b, &b);
3666 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3667 mono_image_add_stream_data (&assembly->blob, hash, 20);
3669 idx = table->next_idx++;
3671 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3674 offset = mono_array_length (rsrc->data);
3675 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3676 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3677 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3678 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3682 * The entry should be emitted into the MANIFESTRESOURCE table of
3683 * the main module, but that needs to reference the FILE table
3684 * which isn't emitted yet.
3691 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3695 set_version_from_string (MonoString *version, guint32 *values)
3697 gchar *ver, *p, *str;
3700 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3701 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3702 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3703 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3706 ver = str = mono_string_to_utf8 (version);
3707 for (i = 0; i < 4; ++i) {
3708 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3714 /* handle Revision and Build */
3724 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3728 char *b = blob_size;
3733 len = mono_array_length (pkey);
3734 mono_metadata_encode_value (len, b, &b);
3735 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3736 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3738 /* need to get the actual value from the key type... */
3739 assembly->strong_name_size = 128;
3740 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3746 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3748 MonoDynamicTable *table;
3749 MonoDynamicImage *assembly;
3750 MonoReflectionAssemblyBuilder *assemblyb;
3755 guint32 module_index;
3757 assemblyb = moduleb->assemblyb;
3758 assembly = moduleb->dynamic_image;
3759 domain = mono_object_domain (assemblyb);
3761 /* Emit ASSEMBLY table */
3762 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3763 alloc_table (table, 1);
3764 values = table->values + MONO_ASSEMBLY_SIZE;
3765 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3766 name = mono_string_to_utf8 (assemblyb->name);
3767 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3769 if (assemblyb->culture) {
3770 name = mono_string_to_utf8 (assemblyb->culture);
3771 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3774 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3776 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3777 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3778 set_version_from_string (assemblyb->version, values);
3780 /* Emit FILE + EXPORTED_TYPE table */
3782 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3784 MonoReflectionModuleBuilder *file_module =
3785 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3786 if (file_module != moduleb) {
3787 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3789 if (file_module->types) {
3790 for (j = 0; j < file_module->num_types; ++j) {
3791 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3792 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3797 if (assemblyb->loaded_modules) {
3798 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3799 MonoReflectionModule *file_module =
3800 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3801 mono_image_fill_file_table (domain, file_module, assembly);
3803 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3807 /* Emit MANIFESTRESOURCE table */
3809 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3811 MonoReflectionModuleBuilder *file_module =
3812 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3813 /* The table for the main module is emitted later */
3814 if (file_module != moduleb) {
3816 if (file_module->resources) {
3817 int len = mono_array_length (file_module->resources);
3818 for (j = 0; j < len; ++j) {
3819 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3820 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3828 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3829 * for the modulebuilder @moduleb.
3830 * At the end of the process, method and field tokens are fixed up and the
3831 * on-disk compressed metadata representation is created.
3834 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3836 MonoDynamicTable *table;
3837 MonoDynamicImage *assembly;
3838 MonoReflectionAssemblyBuilder *assemblyb;
3843 assemblyb = moduleb->assemblyb;
3844 assembly = moduleb->dynamic_image;
3845 domain = mono_object_domain (assemblyb);
3847 if (assembly->text_rva)
3850 assembly->text_rva = START_TEXT_RVA;
3852 if (moduleb->is_main) {
3853 mono_image_emit_manifest (moduleb);
3856 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3857 table->rows = 1; /* .<Module> */
3859 alloc_table (table, table->rows);
3861 * Set the first entry.
3863 values = table->values + table->columns;
3864 values [MONO_TYPEDEF_FLAGS] = 0;
3865 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3866 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3867 values [MONO_TYPEDEF_EXTENDS] = 0;
3868 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3869 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3872 * handle global methods
3873 * FIXME: test what to do when global methods are defined in multiple modules.
3875 if (moduleb->global_methods) {
3876 table = &assembly->tables [MONO_TABLE_METHOD];
3877 table->rows += mono_array_length (moduleb->global_methods);
3878 alloc_table (table, table->rows);
3879 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3880 mono_image_get_method_info (
3881 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3883 if (moduleb->global_fields) {
3884 table = &assembly->tables [MONO_TABLE_FIELD];
3885 table->rows += mono_array_length (moduleb->global_fields);
3886 alloc_table (table, table->rows);
3887 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3888 mono_image_get_field_info (
3889 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3892 table = &assembly->tables [MONO_TABLE_MODULE];
3893 alloc_table (table, 1);
3894 mono_image_fill_module_table (domain, moduleb, assembly);
3898 /* Collect all types into a list sorted by their table_idx */
3899 GPtrArray *types = g_ptr_array_new ();
3902 for (i = 0; i < moduleb->num_types; ++i) {
3903 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3904 collect_types (types, type);
3907 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3908 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3909 table->rows += types->len;
3910 alloc_table (table, table->rows);
3912 for (i = 0; i < types->len; ++i) {
3913 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3914 mono_image_get_type_info (domain, type, assembly);
3916 g_ptr_array_free (types, TRUE);
3920 * table->rows is already set above and in mono_image_fill_module_table.
3922 /* add all the custom attributes at the end, once all the indexes are stable */
3923 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3925 /* CAS assembly permissions */
3926 if (assemblyb->permissions_minimum)
3927 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3928 if (assemblyb->permissions_optional)
3929 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3930 if (assemblyb->permissions_refused)
3931 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3933 module_add_cattrs (assembly, moduleb);
3936 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3937 fixup_cattrs (assembly);
3941 * mono_image_insert_string:
3942 * @module: module builder object
3945 * Insert @str into the user string stream of @module.
3948 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3950 MonoDynamicImage *assembly;
3955 MONO_ARCH_SAVE_REGS;
3957 if (!module->dynamic_image)
3958 mono_image_module_basic_init (module);
3960 assembly = module->dynamic_image;
3962 if (assembly->save) {
3963 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3964 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3965 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3967 char *swapped = g_malloc (2 * mono_string_length (str));
3968 const char *p = (const char*)mono_string_chars (str);
3970 swap_with_size (swapped, p, 2, mono_string_length (str));
3971 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3975 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3977 mono_image_add_stream_data (&assembly->us, "", 1);
3979 idx = assembly->us.index ++;
3982 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3984 return MONO_TOKEN_STRING | idx;
3988 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3993 klass = obj->vtable->klass;
3994 if (strcmp (klass->name, "MonoMethod") == 0) {
3995 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3996 MonoMethodSignature *sig, *old;
3997 guint32 sig_token, parent;
4000 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4002 nargs = mono_array_length (opt_param_types);
4003 old = method->signature;
4004 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4006 sig->hasthis = old->hasthis;
4007 sig->explicit_this = old->explicit_this;
4008 sig->call_convention = old->call_convention;
4009 sig->generic_param_count = old->generic_param_count;
4010 sig->param_count = old->param_count + nargs;
4011 sig->sentinelpos = old->param_count;
4012 sig->ret = old->ret;
4014 for (i = 0; i < old->param_count; i++)
4015 sig->params [i] = old->params [i];
4017 for (i = 0; i < nargs; i++) {
4018 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4019 sig->params [old->param_count + i] = rt->type;
4022 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4023 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4024 parent >>= MONO_TYPEDEFORREF_BITS;
4026 parent <<= MONO_MEMBERREF_PARENT_BITS;
4027 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4029 sig_token = method_encode_signature (assembly, sig);
4030 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4031 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4032 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4033 ReflectionMethodBuilder rmb;
4034 guint32 parent, sig;
4036 reflection_methodbuilder_from_method_builder (&rmb, mb);
4037 rmb.opt_types = opt_param_types;
4039 sig = method_builder_encode_signature (assembly, &rmb);
4041 parent = mono_image_create_token (assembly, obj, TRUE);
4042 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4044 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4045 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4047 token = mono_image_get_varargs_method_token (
4048 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4050 g_error ("requested method token for %s\n", klass->name);
4057 * mono_image_create_token:
4058 * @assembly: a dynamic assembly
4061 * Get a token to insert in the IL code stream for the given MemberInfo.
4062 * @obj can be one of:
4063 * ConstructorBuilder
4073 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4078 klass = obj->vtable->klass;
4079 if (strcmp (klass->name, "MethodBuilder") == 0) {
4080 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4082 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4083 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4085 token = mono_image_get_methodbuilder_token (assembly, mb);
4086 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4087 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4088 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4090 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4091 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4093 token = mono_image_get_ctorbuilder_token (assembly, mb);
4094 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4095 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4096 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4097 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4098 if (tb->generic_params) {
4099 token = mono_image_get_generic_field_token (assembly, fb);
4101 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4103 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4104 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4105 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4106 } else if (strcmp (klass->name, "MonoType") == 0 ||
4107 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4108 MonoReflectionType *tb = (MonoReflectionType *)obj;
4109 token = mono_metadata_token_from_dor (
4110 mono_image_typedef_or_ref (assembly, tb->type));
4111 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4112 MonoReflectionType *tb = (MonoReflectionType *)obj;
4113 token = mono_metadata_token_from_dor (
4114 mono_image_typedef_or_ref (assembly, tb->type));
4115 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4116 strcmp (klass->name, "MonoMethod") == 0) {
4117 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4118 if (m->method->signature->is_inflated) {
4119 if (create_methodspec)
4120 token = mono_image_get_methodspec_token (assembly, m->method);
4122 token = mono_image_get_inflated_method_token (assembly, m->method);
4123 } else if ((m->method->klass->image == &assembly->image) &&
4124 !m->method->klass->generic_class) {
4125 static guint32 method_table_idx = 0xffffff;
4126 if (m->method->klass->wastypebuilder) {
4127 /* we use the same token as the one that was assigned
4128 * to the Methodbuilder.
4129 * FIXME: do the equivalent for Fields.
4131 token = m->method->token;
4134 * Each token should have a unique index, but the indexes are
4135 * assigned by managed code, so we don't know about them. An
4136 * easy solution is to count backwards...
4138 method_table_idx --;
4139 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4142 token = mono_image_get_methodref_token (assembly, m->method);
4144 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4145 } else if (strcmp (klass->name, "MonoField") == 0) {
4146 MonoReflectionField *f = (MonoReflectionField *)obj;
4147 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4148 static guint32 field_table_idx = 0xffffff;
4150 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4152 token = mono_image_get_fieldref_token (assembly, f);
4154 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4155 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4156 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4157 token = mono_image_get_array_token (assembly, m);
4158 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4159 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4160 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4162 g_error ("requested token for %s\n", klass->name);
4165 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4171 guint32 import_lookup_table;
4175 guint32 import_address_table_rva;
4183 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4185 static MonoDynamicImage*
4186 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4188 static const guchar entrycode [16] = {0xff, 0x25, 0};
4189 MonoDynamicImage *image;
4192 const char *version = mono_get_runtime_version ();
4195 image = GC_MALLOC (sizeof (MonoDynamicImage));
4197 image = g_new0 (MonoDynamicImage, 1);
4200 /* keep in sync with image.c */
4201 image->image.name = assembly_name;
4202 image->image.assembly_name = image->image.name; /* they may be different */
4203 image->image.module_name = module_name;
4204 image->image.version = g_strdup (version);
4205 image->image.dynamic = TRUE;
4207 image->image.references = g_new0 (MonoAssembly*, 1);
4208 image->image.references [0] = NULL;
4210 mono_image_init (&image->image);
4212 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4213 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4214 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4215 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4216 image->handleref = g_hash_table_new (NULL, NULL);
4217 image->tokens = mono_g_hash_table_new (NULL, NULL);
4218 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4219 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4220 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4221 image->gen_params = g_ptr_array_new ();
4223 string_heap_init (&image->sheap);
4224 mono_image_add_stream_data (&image->us, "", 1);
4225 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4226 /* import tables... */
4227 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4228 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4229 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4230 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4231 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4232 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4233 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4234 stream_data_align (&image->code);
4236 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4238 for (i=0; i < 64; ++i) {
4239 image->tables [i].next_idx = 1;
4240 image->tables [i].columns = table_sizes [i];
4243 image->image.assembly = (MonoAssembly*)assembly;
4244 image->run = assembly->run;
4245 image->save = assembly->save;
4246 image->pe_kind = 0x1; /* ILOnly */
4247 image->machine = 0x14c; /* I386 */
4253 * mono_image_basic_init:
4254 * @assembly: an assembly builder object
4256 * Create the MonoImage that represents the assembly builder and setup some
4257 * of the helper hash table and the basic metadata streams.
4260 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4262 MonoDynamicAssembly *assembly;
4263 MonoDynamicImage *image;
4265 MONO_ARCH_SAVE_REGS;
4267 if (assemblyb->dynamic_assembly)
4271 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4273 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4276 assembly->assembly.dynamic = TRUE;
4277 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4278 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4279 if (assemblyb->culture)
4280 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4282 assembly->assembly.aname.culture = g_strdup ("");
4284 assembly->run = assemblyb->access != 2;
4285 assembly->save = assemblyb->access != 1;
4287 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4288 image->initial_image = TRUE;
4289 assembly->assembly.aname.name = image->image.name;
4290 assembly->assembly.image = &image->image;
4292 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4293 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4297 calc_section_size (MonoDynamicImage *assembly)
4301 /* alignment constraints */
4302 assembly->code.index += 3;
4303 assembly->code.index &= ~3;
4304 assembly->meta_size += 3;
4305 assembly->meta_size &= ~3;
4306 assembly->resources.index += 3;
4307 assembly->resources.index &= ~3;
4309 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4310 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4313 if (assembly->win32_res) {
4314 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4316 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4317 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4321 assembly->sections [MONO_SECTION_RELOC].size = 12;
4322 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4332 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4336 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4338 ResTreeNode *t1 = (ResTreeNode*)a;
4339 ResTreeNode *t2 = (ResTreeNode*)b;
4341 return t1->id - t2->id;
4345 * resource_tree_create:
4347 * Organize the resources into a resource tree.
4349 static ResTreeNode *
4350 resource_tree_create (MonoArray *win32_resources)
4352 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4356 tree = g_new0 (ResTreeNode, 1);
4358 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4359 MonoReflectionWin32Resource *win32_res =
4360 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4364 lang_node = g_new0 (ResTreeNode, 1);
4365 lang_node->id = win32_res->lang_id;
4366 lang_node->win32_res = win32_res;
4368 /* Create type node if neccesary */
4370 for (l = tree->children; l; l = l->next)
4371 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4372 type_node = (ResTreeNode*)l->data;
4377 type_node = g_new0 (ResTreeNode, 1);
4378 type_node->id = win32_res->res_type;
4381 * The resource types have to be sorted otherwise
4382 * Windows Explorer can't display the version information.
4384 tree->children = g_slist_insert_sorted (tree->children,
4385 type_node, resource_tree_compare_by_id);
4388 /* Create res node if neccesary */
4390 for (l = type_node->children; l; l = l->next)
4391 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4392 res_node = (ResTreeNode*)l->data;
4397 res_node = g_new0 (ResTreeNode, 1);
4398 res_node->id = win32_res->res_id;
4399 type_node->children = g_slist_append (type_node->children, res_node);
4402 res_node->children = g_slist_append (res_node->children, lang_node);
4409 * resource_tree_encode:
4411 * Encode the resource tree into the format used in the PE file.
4414 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4417 MonoPEResourceDir dir;
4418 MonoPEResourceDirEntry dir_entry;
4419 MonoPEResourceDataEntry data_entry;
4423 * For the format of the resource directory, see the article
4424 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4428 memset (&dir, 0, sizeof (dir));
4429 memset (&dir_entry, 0, sizeof (dir_entry));
4430 memset (&data_entry, 0, sizeof (data_entry));
4432 g_assert (sizeof (dir) == 16);
4433 g_assert (sizeof (dir_entry) == 8);
4434 g_assert (sizeof (data_entry) == 16);
4436 node->offset = p - begin;
4438 /* IMAGE_RESOURCE_DIRECTORY */
4439 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4441 memcpy (p, &dir, sizeof (dir));
4444 /* Reserve space for entries */
4446 p += sizeof (dir_entry) * dir.res_id_entries;
4448 /* Write children */
4449 for (l = node->children; l; l = l->next) {
4450 ResTreeNode *child = (ResTreeNode*)l->data;
4452 if (child->win32_res) {
4454 child->offset = p - begin;
4456 /* IMAGE_RESOURCE_DATA_ENTRY */
4457 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4458 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4460 memcpy (p, &data_entry, sizeof (data_entry));
4461 p += sizeof (data_entry);
4463 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4464 p += data_entry.rde_size;
4466 resource_tree_encode (child, begin, p, &p);
4470 /* IMAGE_RESOURCE_ENTRY */
4471 for (l = node->children; l; l = l->next) {
4472 ResTreeNode *child = (ResTreeNode*)l->data;
4473 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4475 dir_entry.is_dir = child->win32_res ? 0 : 1;
4476 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4478 memcpy (entries, &dir_entry, sizeof (dir_entry));
4479 entries += sizeof (dir_entry);
4486 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4491 MonoReflectionWin32Resource *win32_res;
4494 if (!assemblyb->win32_resources)
4498 * Resources are stored in a three level tree inside the PE file.
4499 * - level one contains a node for each type of resource
4500 * - level two contains a node for each resource
4501 * - level three contains a node for each instance of a resource for a
4502 * specific language.
4505 tree = resource_tree_create (assemblyb->win32_resources);
4507 /* Estimate the size of the encoded tree */
4509 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4510 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4511 size += mono_array_length (win32_res->res_data);
4513 /* Directory structure */
4514 size += mono_array_length (assemblyb->win32_resources) * 256;
4515 p = buf = g_malloc (size);
4517 resource_tree_encode (tree, p, p, &p);
4519 g_assert (p - buf < size);
4521 assembly->win32_res = g_malloc (p - buf);
4522 assembly->win32_res_size = p - buf;
4523 memcpy (assembly->win32_res, buf, p - buf);
4529 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4531 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4534 p += sizeof (MonoPEResourceDir);
4535 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4536 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4537 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4538 if (dir_entry->is_dir) {
4539 fixup_resource_directory (res_section, child, rva);
4541 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4542 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4545 p += sizeof (MonoPEResourceDirEntry);
4550 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4553 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4554 g_error ("WriteFile returned %d\n", GetLastError ());
4558 * mono_image_create_pefile:
4559 * @mb: a module builder object
4561 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4562 * assembly->pefile where it can be easily retrieved later in chunks.
4565 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4566 MonoMSDOSHeader *msdos;
4567 MonoDotNetHeader *header;
4568 MonoSectionTable *section;
4569 MonoCLIHeader *cli_header;
4570 guint32 size, image_size, virtual_base, text_offset;
4571 guint32 header_start, section_start, file_offset, virtual_offset;
4572 MonoDynamicImage *assembly;
4573 MonoReflectionAssemblyBuilder *assemblyb;
4574 MonoDynamicStream pefile_stream = {0};
4575 MonoDynamicStream *pefile = &pefile_stream;
4577 guint32 *rva, value;
4579 static const unsigned char msheader[] = {
4580 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4581 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4584 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4585 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4586 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4587 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4590 assemblyb = mb->assemblyb;
4592 mono_image_basic_init (assemblyb);
4593 assembly = mb->dynamic_image;
4595 assembly->pe_kind = assemblyb->pe_kind;
4596 assembly->machine = assemblyb->machine;
4597 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4598 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4600 mono_image_build_metadata (mb);
4602 if (mb->is_main && assemblyb->resources) {
4603 int len = mono_array_length (assemblyb->resources);
4604 for (i = 0; i < len; ++i)
4605 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4608 if (mb->resources) {
4609 int len = mono_array_length (mb->resources);
4610 for (i = 0; i < len; ++i)
4611 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4614 build_compressed_metadata (assembly);
4617 assembly_add_win32_resources (assembly, assemblyb);
4619 nsections = calc_section_size (assembly);
4621 /* The DOS header and stub */
4622 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4623 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4625 /* the dotnet header */
4626 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4628 /* the section tables */
4629 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4631 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4632 virtual_offset = VIRT_ALIGN;
4635 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4636 if (!assembly->sections [i].size)
4639 file_offset += FILE_ALIGN - 1;
4640 file_offset &= ~(FILE_ALIGN - 1);
4641 virtual_offset += VIRT_ALIGN - 1;
4642 virtual_offset &= ~(VIRT_ALIGN - 1);
4644 assembly->sections [i].offset = file_offset;
4645 assembly->sections [i].rva = virtual_offset;
4647 file_offset += assembly->sections [i].size;
4648 virtual_offset += assembly->sections [i].size;
4649 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4652 file_offset += FILE_ALIGN - 1;
4653 file_offset &= ~(FILE_ALIGN - 1);
4655 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4657 /* back-patch info */
4658 msdos = (MonoMSDOSHeader*)pefile->data;
4659 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4660 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4661 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4663 header = (MonoDotNetHeader*)(pefile->data + header_start);
4664 header->pesig [0] = 'P';
4665 header->pesig [1] = 'E';
4667 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4668 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4669 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4670 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4671 if (assemblyb->pekind == 1) {
4673 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4676 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4679 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4681 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4682 header->pe.pe_major = 6;
4683 header->pe.pe_minor = 0;
4684 size = assembly->sections [MONO_SECTION_TEXT].size;
4685 size += FILE_ALIGN - 1;
4686 size &= ~(FILE_ALIGN - 1);
4687 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4688 size = assembly->sections [MONO_SECTION_RSRC].size;
4689 size += FILE_ALIGN - 1;
4690 size &= ~(FILE_ALIGN - 1);
4691 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4692 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4693 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4694 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4695 /* pe_rva_entry_point always at the beginning of the text section */
4696 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4698 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4699 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4700 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4701 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4702 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4703 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4704 size = section_start;
4705 size += FILE_ALIGN - 1;
4706 size &= ~(FILE_ALIGN - 1);
4707 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4709 size += VIRT_ALIGN - 1;
4710 size &= ~(VIRT_ALIGN - 1);
4711 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4714 // Translate the PEFileKind value to the value expected by the Windows loader
4720 // PEFileKinds.Dll == 1
4721 // PEFileKinds.ConsoleApplication == 2
4722 // PEFileKinds.WindowApplication == 3
4725 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4726 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4728 if (assemblyb->pekind == 3)
4733 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4735 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4736 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4737 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4738 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4739 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4740 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4742 /* fill data directory entries */
4744 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4745 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4747 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4748 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4750 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4751 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4752 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4753 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4754 /* patch entrypoint name */
4755 if (assemblyb->pekind == 1)
4756 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4758 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4759 /* patch imported function RVA name */
4760 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4761 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4763 /* the import table */
4764 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4765 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4766 /* patch imported dll RVA name and other entries in the dir */
4767 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4768 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4769 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4770 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4771 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4772 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4774 p = (assembly->code.data + assembly->ilt_offset);
4775 value = (assembly->text_rva + assembly->imp_names_offset);
4776 *p++ = (value) & 0xff;
4777 *p++ = (value >> 8) & (0xff);
4778 *p++ = (value >> 16) & (0xff);
4779 *p++ = (value >> 24) & (0xff);
4781 /* the CLI header info */
4782 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4783 cli_header->ch_size = GUINT32_FROM_LE (72);
4784 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4785 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4786 if (assemblyb->entry_point) {
4787 guint32 table_idx = 0;
4788 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4789 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4790 table_idx = methodb->table_idx;
4792 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4794 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4796 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4798 /* The embedded managed resources */
4799 text_offset = assembly->text_rva + assembly->code.index;
4800 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4801 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4802 text_offset += assembly->resources.index;
4803 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4804 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4805 text_offset += assembly->meta_size;
4806 if (assembly->strong_name_size) {
4807 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4808 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4809 text_offset += assembly->strong_name_size;
4812 /* write the section tables and section content */
4813 section = (MonoSectionTable*)(pefile->data + section_start);
4814 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4815 static const char *section_names [] = {
4816 ".text", ".rsrc", ".reloc"
4818 if (!assembly->sections [i].size)
4820 strcpy (section->st_name, section_names [i]);
4821 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4822 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4823 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4824 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4825 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4826 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4827 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4831 checked_write_file (file, pefile->data, pefile->index);
4833 mono_dynamic_stream_reset (pefile);
4835 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4836 if (!assembly->sections [i].size)
4839 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4840 g_error ("SetFilePointer returned %d\n", GetLastError ());
4843 case MONO_SECTION_TEXT:
4844 /* patch entry point */
4845 p = (assembly->code.data + 2);
4846 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4847 *p++ = (value) & 0xff;
4848 *p++ = (value >> 8) & 0xff;
4849 *p++ = (value >> 16) & 0xff;
4850 *p++ = (value >> 24) & 0xff;
4852 checked_write_file (file, assembly->code.data, assembly->code.index);
4853 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4854 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4855 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4858 g_free (assembly->image.raw_metadata);
4860 case MONO_SECTION_RELOC: {
4864 guint16 type_and_offset;
4868 g_assert (sizeof (reloc) == 12);
4870 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4871 reloc.block_size = GUINT32_FROM_LE (12);
4874 * the entrypoint is always at the start of the text section
4875 * 3 is IMAGE_REL_BASED_HIGHLOW
4876 * 2 is patch_size_rva - text_rva
4878 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4881 checked_write_file (file, &reloc, sizeof (reloc));
4885 case MONO_SECTION_RSRC:
4886 if (assembly->win32_res) {
4888 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4889 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4890 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4894 g_assert_not_reached ();
4898 /* check that the file is properly padded */
4899 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4900 g_error ("SetFilePointer returned %d\n", GetLastError ());
4901 if (! SetEndOfFile (file))
4902 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4904 mono_dynamic_stream_reset (&assembly->code);
4905 mono_dynamic_stream_reset (&assembly->us);
4906 mono_dynamic_stream_reset (&assembly->blob);
4907 mono_dynamic_stream_reset (&assembly->guid);
4908 mono_dynamic_stream_reset (&assembly->sheap);
4911 MonoReflectionModule *
4912 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4916 MonoImageOpenStatus status;
4917 MonoDynamicAssembly *assembly;
4918 guint32 module_count;
4919 MonoImage **new_modules;
4921 name = mono_string_to_utf8 (fileName);
4923 image = mono_image_open (name, &status);
4926 if (status == MONO_IMAGE_ERROR_ERRNO)
4927 exc = mono_get_exception_file_not_found (fileName);
4929 exc = mono_get_exception_bad_image_format (name);
4931 mono_raise_exception (exc);
4936 assembly = ab->dynamic_assembly;
4937 image->assembly = (MonoAssembly*)assembly;
4939 module_count = image->assembly->image->module_count;
4940 new_modules = g_new0 (MonoImage *, module_count + 1);
4942 if (image->assembly->image->modules)
4943 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4944 new_modules [module_count] = image;
4946 g_free (image->assembly->image->modules);
4947 image->assembly->image->modules = new_modules;
4948 image->assembly->image->module_count ++;
4950 mono_assembly_load_references (image, &status);
4952 mono_image_close (image);
4953 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4956 return mono_module_get_object (mono_domain_get (), image);
4960 * We need to return always the same object for MethodInfo, FieldInfo etc..
4961 * but we need to consider the reflected type.
4962 * type uses a different hash, since it uses custom hash/equal functions.
4967 MonoClass *refclass;
4971 reflected_equal (gconstpointer a, gconstpointer b) {
4972 const ReflectedEntry *ea = a;
4973 const ReflectedEntry *eb = b;
4975 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4979 reflected_hash (gconstpointer a) {
4980 const ReflectedEntry *ea = a;
4981 return GPOINTER_TO_UINT (ea->item);
4984 #define CHECK_OBJECT(t,p,k) \
4990 mono_domain_lock (domain); \
4991 if (!domain->refobject_hash) \
4992 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4993 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4994 mono_domain_unlock (domain); \
5000 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5002 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5005 #define CACHE_OBJECT(p,o,k) \
5007 ReflectedEntry *e = ALLOC_REFENTRY; \
5009 e->refclass = (k); \
5010 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5011 mono_domain_unlock (domain); \
5015 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5017 /* this is done only once */
5018 mono_domain_lock (domain);
5019 CACHE_OBJECT (assembly, res, NULL);
5023 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5025 /* this is done only once */
5026 mono_domain_lock (domain);
5027 CACHE_OBJECT (module, res, NULL);
5031 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5033 MonoDynamicImage *image = moduleb->dynamic_image;
5034 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5037 * FIXME: we already created an image in mono_image_basic_init (), but
5038 * we don't know which module it belongs to, since that is only
5039 * determined at assembly save time.
5041 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5042 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5044 moduleb->module.image = &image->image;
5045 moduleb->dynamic_image = image;
5046 register_module (mono_object_domain (moduleb), moduleb, image);
5051 * mono_assembly_get_object:
5052 * @domain: an app domain
5053 * @assembly: an assembly
5055 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5057 MonoReflectionAssembly*
5058 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5060 static MonoClass *System_Reflection_Assembly;
5061 MonoReflectionAssembly *res;
5063 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5064 if (!System_Reflection_Assembly)
5065 System_Reflection_Assembly = mono_class_from_name (
5066 mono_defaults.corlib, "System.Reflection", "Assembly");
5067 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5068 res->assembly = assembly;
5069 CACHE_OBJECT (assembly, res, NULL);
5075 MonoReflectionModule*
5076 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5078 static MonoClass *System_Reflection_Module;
5079 MonoReflectionModule *res;
5082 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5083 if (!System_Reflection_Module)
5084 System_Reflection_Module = mono_class_from_name (
5085 mono_defaults.corlib, "System.Reflection", "Module");
5086 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5089 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5091 res->fqname = mono_string_new (domain, image->name);
5092 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5093 res->scopename = mono_string_new (domain, image->module_name);
5097 if (image->assembly->image == image) {
5098 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5101 g_assert (image->assembly->image->modules);
5103 for (i = 0; i < image->assembly->image->module_count; i++) {
5104 if (image->assembly->image->modules [i] == image)
5105 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5107 g_assert (res->token);
5110 mono_image_addref (image);
5112 CACHE_OBJECT (image, res, NULL);
5116 MonoReflectionModule*
5117 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5119 static MonoClass *System_Reflection_Module;
5120 MonoReflectionModule *res;
5121 MonoTableInfo *table;
5122 guint32 cols [MONO_FILE_SIZE];
5124 guint32 i, name_idx;
5127 if (!System_Reflection_Module)
5128 System_Reflection_Module = mono_class_from_name (
5129 mono_defaults.corlib, "System.Reflection", "Module");
5130 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5132 table = &image->tables [MONO_TABLE_FILE];
5133 g_assert (table_index < table->rows);
5134 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5137 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5138 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5140 /* Check whenever the row has a corresponding row in the moduleref table */
5141 table = &image->tables [MONO_TABLE_MODULEREF];
5142 for (i = 0; i < table->rows; ++i) {
5143 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5144 val = mono_metadata_string_heap (image, name_idx);
5145 if (strcmp (val, name) == 0)
5146 res->image = image->modules [i];
5149 res->fqname = mono_string_new (domain, name);
5150 res->name = mono_string_new (domain, name);
5151 res->scopename = mono_string_new (domain, name);
5152 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5153 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5159 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5161 if ((t1->type != t2->type) ||
5162 (t1->byref != t2->byref))
5166 case MONO_TYPE_VOID:
5167 case MONO_TYPE_BOOLEAN:
5168 case MONO_TYPE_CHAR:
5179 case MONO_TYPE_STRING:
5182 case MONO_TYPE_OBJECT:
5183 case MONO_TYPE_TYPEDBYREF:
5185 case MONO_TYPE_VALUETYPE:
5186 case MONO_TYPE_CLASS:
5187 case MONO_TYPE_SZARRAY:
5188 return t1->data.klass == t2->data.klass;
5190 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5191 case MONO_TYPE_ARRAY:
5192 if (t1->data.array->rank != t2->data.array->rank)
5194 return t1->data.array->eklass == t2->data.array->eklass;
5195 case MONO_TYPE_GENERICINST: {
5197 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5199 if (!mono_metadata_type_equal (t1->data.generic_class->generic_type, t2->data.generic_class->generic_type))
5201 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5202 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5208 case MONO_TYPE_MVAR:
5209 return t1->data.generic_param == t2->data.generic_param;
5211 g_error ("implement type compare for %0x!", t1->type);
5219 mymono_metadata_type_hash (MonoType *t1)
5225 hash |= t1->byref << 6; /* do not collide with t1->type values */
5227 case MONO_TYPE_VALUETYPE:
5228 case MONO_TYPE_CLASS:
5229 case MONO_TYPE_SZARRAY:
5230 /* check if the distribution is good enough */
5231 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5233 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5238 static MonoReflectionGenericClass*
5239 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5241 static MonoClass *System_Reflection_MonoGenericClass;
5242 MonoReflectionGenericClass *res;
5243 MonoGenericClass *gclass;
5246 if (!System_Reflection_MonoGenericClass) {
5247 System_Reflection_MonoGenericClass = mono_class_from_name (
5248 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5249 g_assert (System_Reflection_MonoGenericClass);
5252 gclass = geninst->data.generic_class;
5253 gklass = mono_class_from_mono_type (gclass->generic_type);
5255 mono_class_init (gclass->klass);
5257 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5259 res->type.type = geninst;
5260 if (gklass->wastypebuilder && gklass->reflection_info)
5261 res->generic_type = gklass->reflection_info;
5263 res->generic_type = mono_type_get_object (domain, gclass->generic_type);
5269 * mono_type_get_object:
5270 * @domain: an app domain
5273 * Return an System.MonoType object representing the type @type.
5276 mono_type_get_object (MonoDomain *domain, MonoType *type)
5278 MonoReflectionType *res;
5279 MonoClass *klass = mono_class_from_mono_type (type);
5281 mono_domain_lock (domain);
5282 if (!domain->type_hash)
5283 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5284 (GCompareFunc)mymono_metadata_type_equal);
5285 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5286 mono_domain_unlock (domain);
5289 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5290 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5291 mono_g_hash_table_insert (domain->type_hash, type, res);
5292 mono_domain_unlock (domain);
5295 if (klass->reflection_info && !klass->wastypebuilder) {
5296 /* g_assert_not_reached (); */
5297 /* should this be considered an error condition? */
5299 mono_domain_unlock (domain);
5300 return klass->reflection_info;
5303 mono_class_init (klass);
5304 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5306 mono_g_hash_table_insert (domain->type_hash, type, res);
5307 mono_domain_unlock (domain);
5312 * mono_method_get_object:
5313 * @domain: an app domain
5315 * @refclass: the reflected type (can be NULL)
5317 * Return an System.Reflection.MonoMethod object representing the method @method.
5319 MonoReflectionMethod*
5320 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5323 * We use the same C representation for methods and constructors, but the type
5324 * name in C# is different.
5328 MonoReflectionMethod *ret;
5331 refclass = method->klass;
5333 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5334 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5335 cname = "MonoCMethod";
5337 cname = "MonoMethod";
5338 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5340 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5341 ret->method = method;
5342 ret->name = mono_string_new (domain, method->name);
5343 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5344 CACHE_OBJECT (method, ret, refclass);
5349 * mono_field_get_object:
5350 * @domain: an app domain
5354 * Return an System.Reflection.MonoField object representing the field @field
5357 MonoReflectionField*
5358 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5360 MonoReflectionField *res;
5363 CHECK_OBJECT (MonoReflectionField *, field, klass);
5364 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5365 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5368 res->name = mono_string_new (domain, field->name);
5369 if (field->generic_info)
5370 res->attrs = field->generic_info->generic_type->attrs;
5372 res->attrs = field->type->attrs;
5373 res->type = mono_type_get_object (domain, field->type);
5374 CACHE_OBJECT (field, res, klass);
5379 * mono_property_get_object:
5380 * @domain: an app domain
5382 * @property: a property
5384 * Return an System.Reflection.MonoProperty object representing the property @property
5387 MonoReflectionProperty*
5388 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5390 MonoReflectionProperty *res;
5393 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5394 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5395 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5397 res->property = property;
5398 CACHE_OBJECT (property, res, klass);
5403 * mono_event_get_object:
5404 * @domain: an app domain
5408 * Return an System.Reflection.MonoEvent object representing the event @event
5411 MonoReflectionEvent*
5412 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5414 MonoReflectionEvent *res;
5417 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5418 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5419 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5422 CACHE_OBJECT (event, res, klass);
5427 * mono_param_get_objects:
5428 * @domain: an app domain
5431 * Return an System.Reflection.ParameterInfo array object representing the parameters
5432 * in the method @method.
5435 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5437 static MonoClass *System_Reflection_ParameterInfo;
5438 MonoArray *res = NULL;
5439 MonoReflectionMethod *member = NULL;
5440 MonoReflectionParameter *param = NULL;
5441 char **names, **blobs = NULL;
5442 MonoObject *dbnull = mono_get_dbnull_object (domain);
5443 MonoMarshalSpec **mspecs;
5446 if (!System_Reflection_ParameterInfo)
5447 System_Reflection_ParameterInfo = mono_class_from_name (
5448 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5450 if (!method->signature->param_count)
5451 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5453 /* Note: the cache is based on the address of the signature into the method
5454 * since we already cache MethodInfos with the method as keys.
5456 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5458 member = mono_method_get_object (domain, method, NULL);
5459 names = g_new (char *, method->signature->param_count);
5460 mono_method_get_param_names (method, (const char **) names);
5462 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5463 mono_method_get_marshal_info (method, mspecs);
5465 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5466 for (i = 0; i < method->signature->param_count; ++i) {
5467 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5468 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5469 param->MemberImpl = (MonoObject*)member;
5470 param->NameImpl = mono_string_new (domain, names [i]);
5471 param->PositionImpl = i;
5472 param->AttrsImpl = method->signature->params [i]->attrs;
5474 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5475 param->DefaultValueImpl = dbnull;
5477 MonoType *type = param->ClassImpl->type;
5480 blobs = g_new0 (char *, method->signature->param_count);
5481 get_default_param_value_blobs (method, blobs);
5484 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5486 if (!param->DefaultValueImpl) {
5487 param->DefaultValueImpl = dbnull;
5492 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5494 mono_array_set (res, gpointer, i, param);
5499 for (i = method->signature->param_count; i >= 0; i--)
5501 mono_metadata_free_marshal_spec (mspecs [i]);
5504 CACHE_OBJECT (&(method->signature), res, NULL);
5509 * mono_method_body_get_object:
5510 * @domain: an app domain
5513 * Return an System.Reflection.MethodBody object representing the method @method.
5515 MonoReflectionMethodBody*
5516 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5518 static MonoClass *System_Reflection_MethodBody = NULL;
5519 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5520 MonoReflectionMethodBody *ret;
5521 MonoMethodNormal *mn;
5522 MonoMethodHeader *header;
5525 if (!System_Reflection_MethodBody)
5526 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5527 if (!System_Reflection_LocalVariableInfo)
5528 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5530 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5532 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5533 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5535 mn = (MonoMethodNormal *)method;
5536 header = mono_method_get_header (method);
5538 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5539 /* FIXME: Other fields */
5540 ret->init_locals = header->init_locals;
5541 ret->max_stack = header->max_stack;
5542 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5543 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5544 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5545 for (i = 0; i < header->num_locals; ++i) {
5546 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5547 info->local_type = mono_type_get_object (domain, header->locals [i]);
5548 info->is_pinned = header->locals [i]->pinned;
5549 info->local_index = 0;
5552 CACHE_OBJECT (method, ret, NULL);
5557 mono_get_dbnull_object (MonoDomain *domain)
5561 static MonoClassField *dbnull_value_field = NULL;
5563 if (!dbnull_value_field) {
5564 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5565 mono_class_init (klass);
5566 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5567 g_assert (dbnull_value_field);
5569 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5576 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5578 guint32 param_index, i, lastp, crow = 0;
5579 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5582 MonoClass *klass = method->klass;
5583 MonoImage *image = klass->image;
5584 MonoMethodSignature *methodsig = method->signature;
5586 MonoTableInfo *constt;
5587 MonoTableInfo *methodt;
5588 MonoTableInfo *paramt;
5590 if (!methodsig->param_count)
5593 if (klass->generic_class) {
5594 return; /* FIXME - ??? */
5597 mono_class_init (klass);
5599 if (klass->image->dynamic) {
5600 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5601 if (aux && aux->param_defaults)
5602 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5606 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5607 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5608 constt = &image->tables [MONO_TABLE_CONSTANT];
5610 for (i = 0; i < klass->method.count; ++i) {
5611 if (method == klass->methods [i]) {
5612 idx = klass->method.first + i;
5617 g_assert (idx != -1);
5619 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5620 if (idx + 1 < methodt->rows)
5621 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5623 lastp = paramt->rows + 1;
5625 for (i = param_index; i < lastp; ++i) {
5628 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5629 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5631 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5634 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5639 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5640 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5647 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5656 klass = mono_class_from_mono_type (type);
5657 if (klass->valuetype) {
5658 object = mono_object_new (domain, klass);
5659 retval = ((gchar *) object + sizeof (MonoObject));
5664 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5671 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5675 memset (assembly, 0, sizeof (MonoAssemblyName));
5677 assembly->culture = "";
5678 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5680 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5683 while (g_ascii_isspace (*p) || *p == ',') {
5692 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5694 assembly->major = strtoul (p, &s, 10);
5695 if (s == p || *s != '.')
5698 assembly->minor = strtoul (p, &s, 10);
5699 if (s == p || *s != '.')
5702 assembly->build = strtoul (p, &s, 10);
5703 if (s == p || *s != '.')
5706 assembly->revision = strtoul (p, &s, 10);
5710 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5712 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5713 assembly->culture = "";
5716 assembly->culture = p;
5717 while (*p && *p != ',') {
5721 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5723 if (strncmp (p, "null", 4) == 0) {
5728 while (*p && *p != ',') {
5731 len = (p - start + 1);
5732 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5733 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5734 g_strlcpy (assembly->public_key_token, start, len);
5737 while (*p && *p != ',')
5741 while (g_ascii_isspace (*p) || *p == ',') {
5755 * mono_reflection_parse_type:
5758 * Parse a type name as accepted by the GetType () method and output the info
5759 * extracted in the info structure.
5760 * the name param will be mangled, so, make a copy before passing it to this function.
5761 * The fields in info will be valid until the memory pointed to by name is valid.
5763 * See also mono_type_get_name () below.
5765 * Returns: 0 on parse error.
5768 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5770 char *start, *p, *w, *last_point, *startn;
5771 int in_modifiers = 0;
5772 int isbyref = 0, rank;
5774 start = p = w = name;
5776 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5777 info->name = info->name_space = NULL;
5778 info->nested = NULL;
5779 info->modifiers = NULL;
5781 /* last_point separates the namespace from the name */
5787 *p = 0; /* NULL terminate the name */
5789 info->nested = g_list_append (info->nested, startn);
5790 /* we have parsed the nesting namespace + name */
5794 info->name_space = start;
5796 info->name = last_point + 1;
5798 info->name_space = (char *)"";
5824 info->name_space = start;
5826 info->name = last_point + 1;
5828 info->name_space = (char *)"";
5835 if (isbyref) /* only one level allowed by the spec */
5838 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5842 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5853 else if (*p != '*') /* '*' means unknown lower bound */
5859 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5864 if (g_ascii_isspace (*p)) {
5871 return 0; /* missing assembly name */
5872 if (!assembly_name_to_aname (&info->assembly, p))
5879 if (info->assembly.name)
5882 *w = 0; /* terminate class name */
5883 if (!info->name || !*info->name)
5885 /* add other consistency checks */
5890 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5897 image = mono_defaults.corlib;
5900 klass = mono_class_from_name_case (image, info->name_space, info->name);
5902 klass = mono_class_from_name (image, info->name_space, info->name);
5905 for (mod = info->nested; mod; mod = mod->next) {
5908 mono_class_init (klass);
5909 nested = klass->nested_classes;
5912 klass = nested->data;
5914 if (g_strcasecmp (klass->name, mod->data) == 0)
5917 if (strcmp (klass->name, mod->data) == 0)
5921 nested = nested->next;
5928 mono_class_init (klass);
5929 for (mod = info->modifiers; mod; mod = mod->next) {
5930 modval = GPOINTER_TO_UINT (mod->data);
5931 if (!modval) { /* byref: must be last modifier */
5932 return &klass->this_arg;
5933 } else if (modval == -1) {
5934 klass = mono_ptr_class_get (&klass->byval_arg);
5935 } else { /* array rank */
5936 klass = mono_array_class_get (klass, modval);
5938 mono_class_init (klass);
5941 return &klass->byval_arg;
5945 * mono_reflection_get_type:
5946 * @image: a metadata context
5947 * @info: type description structure
5948 * @ignorecase: flag for case-insensitive string compares
5949 * @type_resolve: whenever type resolve was already tried
5951 * Build a MonoType from the type description in @info.
5956 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5959 MonoReflectionAssembly *assembly;
5963 type = mono_reflection_get_type_internal (image, info, ignorecase);
5966 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5973 *type_resolve = TRUE;
5976 /* Reconstruct the type name */
5977 fullName = g_string_new ("");
5978 if (info->name_space && (info->name_space [0] != '\0'))
5979 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5981 g_string_printf (fullName, info->name);
5982 for (mod = info->nested; mod; mod = mod->next)
5983 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5985 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5987 if (assembly->assembly->dynamic) {
5988 /* Enumerate all modules */
5989 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5993 if (abuilder->modules) {
5994 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5995 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5996 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6002 if (!type && abuilder->loaded_modules) {
6003 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6004 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6005 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6012 type = mono_reflection_get_type_internal (assembly->assembly->image,
6015 g_string_free (fullName, TRUE);
6020 * mono_reflection_type_from_name:
6022 * @image: a metadata context (can be NULL).
6024 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6025 * it defaults to get the type from @image or, if @image is NULL or loading
6026 * from it fails, uses corlib.
6030 mono_reflection_type_from_name (char *name, MonoImage *image)
6033 MonoTypeNameParse info;
6034 MonoAssembly *assembly;
6036 gboolean type_resolve = FALSE;
6038 /* Make a copy since parse_type modifies its argument */
6039 tmp = g_strdup (name);
6041 /*g_print ("requested type %s\n", str);*/
6042 if (!mono_reflection_parse_type (tmp, &info)) {
6044 g_list_free (info.modifiers);
6045 g_list_free (info.nested);
6049 if (info.assembly.name) {
6050 assembly = mono_assembly_loaded (&info.assembly);
6052 /* then we must load the assembly ourselve - see #60439 */
6053 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6056 g_list_free (info.modifiers);
6057 g_list_free (info.nested);
6061 image = assembly->image;
6062 } else if (image == NULL) {
6063 image = mono_defaults.corlib;
6066 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6067 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6068 image = mono_defaults.corlib;
6069 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6073 g_list_free (info.modifiers);
6074 g_list_free (info.nested);
6079 * mono_reflection_get_token:
6081 * Return the metadata token of OBJ which should be an object
6082 * representing a metadata element.
6085 mono_reflection_get_token (MonoObject *obj)
6090 klass = obj->vtable->klass;
6092 if (strcmp (klass->name, "MethodBuilder") == 0) {
6093 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6095 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6096 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6097 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6099 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6100 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6101 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6102 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6103 if (tb->generic_params) {
6104 g_assert_not_reached ();
6106 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6108 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6109 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6110 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6111 } else if (strcmp (klass->name, "MonoType") == 0) {
6112 MonoReflectionType *tb = (MonoReflectionType *)obj;
6113 token = mono_class_from_mono_type (tb->type)->type_token;
6114 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6115 strcmp (klass->name, "MonoMethod") == 0) {
6116 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6117 if (m->method->signature->is_inflated) {
6118 g_assert_not_reached ();
6119 } else if (m->method->signature->generic_param_count) {
6120 g_assert_not_reached ();
6121 } else if (m->method->klass->generic_class) {
6122 g_assert_not_reached ();
6124 token = m->method->token;
6126 } else if (strcmp (klass->name, "MonoField") == 0) {
6127 MonoReflectionField *f = (MonoReflectionField*)obj;
6129 token = mono_class_get_field_token (f->field);
6130 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6131 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6133 token = mono_class_get_property_token (p->property);
6134 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6135 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6137 token = mono_class_get_event_token (p->event);
6138 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6139 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6141 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6142 } else if (strcmp (klass->name, "Module") == 0) {
6143 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6146 } else if (strcmp (klass->name, "Assembly") == 0) {
6147 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6149 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6150 MonoException *ex = mono_get_exception_not_implemented (msg);
6152 mono_raise_exception (ex);
6159 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6161 int slen, type = t->type;
6166 case MONO_TYPE_BOOLEAN: {
6167 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6172 case MONO_TYPE_CHAR:
6174 case MONO_TYPE_I2: {
6175 guint16 *val = g_malloc (sizeof (guint16));
6180 #if SIZEOF_VOID_P == 4
6186 case MONO_TYPE_I4: {
6187 guint32 *val = g_malloc (sizeof (guint32));
6192 #if SIZEOF_VOID_P == 8
6193 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6198 case MONO_TYPE_I8: {
6199 guint64 *val = g_malloc (sizeof (guint64));
6204 case MONO_TYPE_VALUETYPE:
6205 if (t->data.klass->enumtype) {
6206 type = t->data.klass->enum_basetype->type;
6209 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6212 case MONO_TYPE_STRING:
6213 if (*p == (char)0xFF) {
6217 slen = mono_metadata_decode_value (p, &p);
6219 return mono_string_new_len (mono_domain_get (), p, slen);
6220 case MONO_TYPE_CLASS: {
6223 if (*p == (char)0xFF) {
6228 slen = mono_metadata_decode_value (p, &p);
6229 n = g_memdup (p, slen + 1);
6231 t = mono_reflection_type_from_name (n, image);
6233 g_warning ("Cannot load type '%s'", n);
6237 return mono_type_get_object (mono_domain_get (), t);
6241 case MONO_TYPE_OBJECT: {
6244 MonoClass *subc = NULL;
6249 } else if (subt == 0x0E) {
6250 type = MONO_TYPE_STRING;
6252 } else if (subt == 0x55) {
6255 slen = mono_metadata_decode_value (p, &p);
6256 n = g_memdup (p, slen + 1);
6258 t = mono_reflection_type_from_name (n, image);
6260 g_warning ("Cannot load type '%s'", n);
6263 subc = mono_class_from_mono_type (t);
6264 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6265 MonoType simple_type = {{0}};
6266 simple_type.type = subt;
6267 subc = mono_class_from_mono_type (&simple_type);
6269 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6271 val = load_cattr_value (image, &subc->byval_arg, p, end);
6272 obj = mono_object_new (mono_domain_get (), subc);
6273 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6277 case MONO_TYPE_SZARRAY: {
6279 guint32 i, alen, basetype;
6282 if (alen == 0xffffffff) {
6286 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6287 basetype = t->data.klass->byval_arg.type;
6292 case MONO_TYPE_BOOLEAN:
6293 for (i = 0; i < alen; i++) {
6294 MonoBoolean val = *p++;
6295 mono_array_set (arr, MonoBoolean, i, val);
6298 case MONO_TYPE_CHAR:
6301 for (i = 0; i < alen; i++) {
6302 guint16 val = read16 (p);
6303 mono_array_set (arr, guint16, i, val);
6310 for (i = 0; i < alen; i++) {
6311 guint32 val = read32 (p);
6312 mono_array_set (arr, guint32, i, val);
6319 for (i = 0; i < alen; i++) {
6320 guint64 val = read64 (p);
6321 mono_array_set (arr, guint64, i, val);
6325 case MONO_TYPE_CLASS:
6326 case MONO_TYPE_OBJECT:
6327 case MONO_TYPE_STRING:
6328 for (i = 0; i < alen; i++) {
6329 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6330 mono_array_set (arr, gpointer, i, item);
6334 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6340 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6346 type_is_reference (MonoType *type)
6348 switch (type->type) {
6349 case MONO_TYPE_BOOLEAN:
6350 case MONO_TYPE_CHAR:
6363 case MONO_TYPE_VALUETYPE:
6371 free_param_data (MonoMethodSignature *sig, void **params) {
6373 for (i = 0; i < sig->param_count; ++i) {
6374 if (!type_is_reference (sig->params [i]))
6375 g_free (params [i]);
6380 * Find the method index in the metadata methodDef table.
6381 * Later put these three helper methods in metadata and export them.
6384 find_method_index (MonoMethod *method) {
6385 MonoClass *klass = method->klass;
6388 for (i = 0; i < klass->method.count; ++i) {
6389 if (method == klass->methods [i])
6390 return klass->method.first + 1 + i;
6396 * Find the field index in the metadata FieldDef table.
6399 find_field_index (MonoClass *klass, MonoClassField *field) {
6402 for (i = 0; i < klass->field.count; ++i) {
6403 if (field == &klass->fields [i])
6404 return klass->field.first + 1 + i;
6410 * Find the property index in the metadata Property table.
6413 find_property_index (MonoClass *klass, MonoProperty *property) {
6416 for (i = 0; i < klass->property.count; ++i) {
6417 if (property == &klass->properties [i])
6418 return klass->property.first + 1 + i;
6424 * Find the event index in the metadata Event table.
6427 find_event_index (MonoClass *klass, MonoEvent *event) {
6430 for (i = 0; i < klass->event.count; ++i) {
6431 if (event == &klass->events [i])
6432 return klass->event.first + 1 + i;
6438 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6440 const char *p = data;
6442 guint32 i, j, num_named;
6446 mono_class_init (method->klass);
6449 attr = mono_object_new (mono_domain_get (), method->klass);
6450 mono_runtime_invoke (method, attr, NULL, NULL);
6454 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6457 /*g_print ("got attr %s\n", method->klass->name);*/
6459 params = g_new (void*, method->signature->param_count);
6463 for (i = 0; i < method->signature->param_count; ++i) {
6464 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6468 attr = mono_object_new (mono_domain_get (), method->klass);
6469 mono_runtime_invoke (method, attr, params, NULL);
6470 free_param_data (method->signature, params);
6472 num_named = read16 (named);
6474 for (j = 0; j < num_named; j++) {
6476 char *name, named_type, data_type;
6477 named_type = *named++;
6478 data_type = *named++; /* type of data */
6479 if (data_type == 0x55) {
6482 type_len = mono_metadata_decode_blob_size (named, &named);
6483 type_name = g_malloc (type_len + 1);
6484 memcpy (type_name, named, type_len);
6485 type_name [type_len] = 0;
6487 /* FIXME: lookup the type and check type consistency */
6488 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6489 /* this seems to be the type of the element of the array */
6490 /* g_print ("skipping 0x%02x after prop\n", *named); */
6493 name_len = mono_metadata_decode_blob_size (named, &named);
6494 name = g_malloc (name_len + 1);
6495 memcpy (name, named, name_len);
6496 name [name_len] = 0;
6498 if (named_type == 0x53) {
6499 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6500 void *val = load_cattr_value (image, field->type, named, &named);
6501 mono_field_set_value (attr, field, val);
6502 if (!type_is_reference (field->type))
6504 } else if (named_type == 0x54) {
6507 MonoType *prop_type;
6509 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6510 /* can we have more that 1 arg in a custom attr named property? */
6511 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6512 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6513 mono_property_set_value (prop, attr, pparams, NULL);
6514 if (!type_is_reference (prop_type))
6515 g_free (pparams [0]);
6524 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6531 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6532 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6533 for (i = 0; i < cinfo->num_attrs; ++i) {
6534 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6535 mono_array_set (result, gpointer, i, attr);
6541 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6543 guint32 mtoken, i, len;
6544 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6546 MonoCustomAttrInfo *ainfo;
6547 GList *tmp, *list = NULL;
6550 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6552 i = mono_metadata_custom_attrs_from_index (image, idx);
6556 while (i < ca->rows) {
6557 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6559 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6562 len = g_list_length (list);
6565 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6566 ainfo->num_attrs = len;
6567 ainfo->image = image;
6568 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6569 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6570 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6571 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6572 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6573 mtoken |= MONO_TOKEN_METHOD_DEF;
6575 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6576 mtoken |= MONO_TOKEN_MEMBER_REF;
6579 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6582 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6583 if (!ainfo->attrs [i].ctor)
6584 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6585 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6586 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6587 ainfo->attrs [i].data = data;
6595 mono_custom_attrs_from_method (MonoMethod *method)
6597 MonoCustomAttrInfo *cinfo;
6600 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6602 idx = find_method_index (method);
6603 idx <<= MONO_CUSTOM_ATTR_BITS;
6604 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6605 return mono_custom_attrs_from_index (method->klass->image, idx);
6609 mono_custom_attrs_from_class (MonoClass *klass)
6611 MonoCustomAttrInfo *cinfo;
6614 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6616 idx = mono_metadata_token_index (klass->type_token);
6617 idx <<= MONO_CUSTOM_ATTR_BITS;
6618 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6619 return mono_custom_attrs_from_index (klass->image, idx);
6623 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6625 MonoCustomAttrInfo *cinfo;
6628 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6630 idx = 1; /* there is only one assembly */
6631 idx <<= MONO_CUSTOM_ATTR_BITS;
6632 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6633 return mono_custom_attrs_from_index (assembly->image, idx);
6636 static MonoCustomAttrInfo*
6637 mono_custom_attrs_from_module (MonoImage *image)
6639 MonoCustomAttrInfo *cinfo;
6642 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6644 idx = 1; /* there is only one module */
6645 idx <<= MONO_CUSTOM_ATTR_BITS;
6646 idx |= MONO_CUSTOM_ATTR_MODULE;
6647 return mono_custom_attrs_from_index (image, idx);
6651 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6653 MonoCustomAttrInfo *cinfo;
6656 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6658 idx = find_property_index (klass, property);
6659 idx <<= MONO_CUSTOM_ATTR_BITS;
6660 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6661 return mono_custom_attrs_from_index (klass->image, idx);
6665 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6667 MonoCustomAttrInfo *cinfo;
6670 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6672 idx = find_event_index (klass, event);
6673 idx <<= MONO_CUSTOM_ATTR_BITS;
6674 idx |= MONO_CUSTOM_ATTR_EVENT;
6675 return mono_custom_attrs_from_index (klass->image, idx);
6679 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6681 MonoCustomAttrInfo *cinfo;
6684 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6686 idx = find_field_index (klass, field);
6687 idx <<= MONO_CUSTOM_ATTR_BITS;
6688 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6689 return mono_custom_attrs_from_index (klass->image, idx);
6693 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6696 guint32 i, idx, method_index;
6697 guint32 param_list, param_last, param_pos, found;
6699 MonoReflectionMethodAux *aux;
6701 if (method->klass->image->dynamic) {
6702 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6703 if (!aux || !aux->param_cattr)
6705 return aux->param_cattr [param];
6708 image = method->klass->image;
6709 method_index = find_method_index (method);
6710 ca = &image->tables [MONO_TABLE_METHOD];
6712 if (method->klass->generic_class || method->klass->generic_container ||
6713 method->signature->generic_param_count) {
6714 /* FIXME FIXME FIXME */
6718 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6719 if (method_index == ca->rows) {
6720 ca = &image->tables [MONO_TABLE_PARAM];
6721 param_last = ca->rows + 1;
6723 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6724 ca = &image->tables [MONO_TABLE_PARAM];
6727 for (i = param_list; i < param_last; ++i) {
6728 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6729 if (param_pos == param) {
6737 idx <<= MONO_CUSTOM_ATTR_BITS;
6738 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6739 return mono_custom_attrs_from_index (image, idx);
6743 * mono_reflection_get_custom_attrs:
6744 * @obj: a reflection object handle
6746 * Return an array with all the custom attributes defined of the
6747 * reflection handle @obj. The objects are fully build.
6750 mono_reflection_get_custom_attrs (MonoObject *obj)
6754 MonoCustomAttrInfo *cinfo = NULL;
6756 MONO_ARCH_SAVE_REGS;
6758 klass = obj->vtable->klass;
6759 if (klass == mono_defaults.monotype_class) {
6760 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6761 klass = mono_class_from_mono_type (rtype->type);
6762 cinfo = mono_custom_attrs_from_class (klass);
6763 } else if (strcmp ("Assembly", klass->name) == 0) {
6764 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6765 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6766 } else if (strcmp ("Module", klass->name) == 0) {
6767 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6768 cinfo = mono_custom_attrs_from_module (module->image);
6769 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6770 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6771 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6772 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6773 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6774 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6775 } else if (strcmp ("MonoField", klass->name) == 0) {
6776 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6777 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6778 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6779 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6780 cinfo = mono_custom_attrs_from_method (rmethod->method);
6781 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6782 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6783 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6784 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6785 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6786 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6787 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6788 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6789 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6790 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6791 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6792 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6793 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6794 } else { /* handle other types here... */
6795 g_error ("get custom attrs not yet supported for %s", klass->name);
6799 result = mono_custom_attrs_construct (cinfo);
6801 mono_custom_attrs_free (cinfo);
6803 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6804 result = mono_array_new (mono_domain_get (), klass, 0);
6810 static MonoMethodSignature*
6811 parameters_to_signature (MonoArray *parameters) {
6812 MonoMethodSignature *sig;
6815 count = parameters? mono_array_length (parameters): 0;
6817 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6818 sig->param_count = count;
6819 sig->sentinelpos = -1; /* FIXME */
6820 for (i = 0; i < count; ++i) {
6821 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6822 sig->params [i] = pt->type;
6827 static MonoMethodSignature*
6828 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6829 MonoMethodSignature *sig;
6831 sig = parameters_to_signature (ctor->parameters);
6832 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6833 sig->ret = &mono_defaults.void_class->byval_arg;
6837 static MonoMethodSignature*
6838 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6839 MonoMethodSignature *sig;
6841 sig = parameters_to_signature (method->parameters);
6842 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6843 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6844 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6848 static MonoMethodSignature*
6849 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6850 MonoMethodSignature *sig;
6852 sig = parameters_to_signature (method->parameters);
6853 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6854 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6855 sig->generic_param_count = 0;
6860 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6862 MonoClass *klass = mono_object_class (prop);
6863 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6864 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6865 *name = mono_string_to_utf8 (pb->name);
6866 *type = pb->type->type;
6868 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6869 *name = g_strdup (p->property->name);
6870 if (p->property->get)
6871 *type = p->property->get->signature->ret;
6873 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6878 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6880 MonoClass *klass = mono_object_class (field);
6881 if (strcmp (klass->name, "FieldBuilder") == 0) {
6882 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6883 *name = mono_string_to_utf8 (fb->name);
6884 *type = fb->type->type;
6886 MonoReflectionField *f = (MonoReflectionField *)field;
6887 *name = g_strdup (f->field->name);
6888 *type = f->field->type;
6893 * Encode a value in a custom attribute stream of bytes.
6894 * The value to encode is either supplied as an object in argument val
6895 * (valuetypes are boxed), or as a pointer to the data in the
6897 * @type represents the type of the value
6898 * @buffer is the start of the buffer
6899 * @p the current position in the buffer
6900 * @buflen contains the size of the buffer and is used to return the new buffer size
6901 * if this needs to be realloced.
6902 * @retbuffer and @retp return the start and the position of the buffer
6905 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6907 MonoTypeEnum simple_type;
6909 if ((p-buffer) + 10 >= *buflen) {
6912 newbuf = g_realloc (buffer, *buflen);
6913 p = newbuf + (p-buffer);
6917 argval = ((char*)arg + sizeof (MonoObject));
6918 simple_type = type->type;
6920 switch (simple_type) {
6921 case MONO_TYPE_BOOLEAN:
6926 case MONO_TYPE_CHAR:
6929 swap_with_size (p, argval, 2, 1);
6935 swap_with_size (p, argval, 4, 1);
6941 swap_with_size (p, argval, 8, 1);
6944 case MONO_TYPE_VALUETYPE:
6945 if (type->data.klass->enumtype) {
6946 simple_type = type->data.klass->enum_basetype->type;
6949 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6952 case MONO_TYPE_STRING: {
6959 str = mono_string_to_utf8 ((MonoString*)arg);
6960 slen = strlen (str);
6961 if ((p-buffer) + 10 + slen >= *buflen) {
6965 newbuf = g_realloc (buffer, *buflen);
6966 p = newbuf + (p-buffer);
6969 mono_metadata_encode_value (slen, p, &p);
6970 memcpy (p, str, slen);
6975 case MONO_TYPE_CLASS: {
6983 k = mono_object_class (arg);
6984 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6985 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6986 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6988 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6989 slen = strlen (str);
6990 if ((p-buffer) + 10 + slen >= *buflen) {
6994 newbuf = g_realloc (buffer, *buflen);
6995 p = newbuf + (p-buffer);
6998 mono_metadata_encode_value (slen, p, &p);
6999 memcpy (p, str, slen);
7004 case MONO_TYPE_SZARRAY: {
7006 MonoClass *eclass, *arg_eclass;
7009 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7012 len = mono_array_length ((MonoArray*)arg);
7014 *p++ = (len >> 8) & 0xff;
7015 *p++ = (len >> 16) & 0xff;
7016 *p++ = (len >> 24) & 0xff;
7018 *retbuffer = buffer;
7019 eclass = type->data.klass;
7020 arg_eclass = mono_object_class (arg)->element_class;
7021 if (eclass->valuetype && arg_eclass->valuetype) {
7022 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7023 int elsize = mono_class_array_element_size (eclass);
7024 for (i = 0; i < len; ++i) {
7025 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7029 for (i = 0; i < len; ++i) {
7030 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7035 /* it may be a boxed value or a Type */
7036 case MONO_TYPE_OBJECT: {
7037 MonoClass *klass = mono_object_class (arg);
7041 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7044 } else if (klass->enumtype) {
7046 } else if (klass == mono_defaults.string_class) {
7047 simple_type = MONO_TYPE_STRING;
7050 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7051 *p++ = simple_type = klass->byval_arg.type;
7054 g_error ("unhandled type in custom attr");
7056 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7057 slen = strlen (str);
7058 if ((p-buffer) + 10 + slen >= *buflen) {
7062 newbuf = g_realloc (buffer, *buflen);
7063 p = newbuf + (p-buffer);
7066 mono_metadata_encode_value (slen, p, &p);
7067 memcpy (p, str, slen);
7070 simple_type = klass->enum_basetype->type;
7074 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7077 *retbuffer = buffer;
7081 * mono_reflection_get_custom_attrs_blob:
7082 * @ctor: custom attribute constructor
7083 * @ctorArgs: arguments o the constructor
7089 * Creates the blob of data that needs to be saved in the metadata and that represents
7090 * the custom attributed described by @ctor, @ctorArgs etc.
7091 * Returns: a Byte array representing the blob of data.
7094 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7097 MonoMethodSignature *sig;
7102 MONO_ARCH_SAVE_REGS;
7104 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7105 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7107 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7109 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7111 p = buffer = g_malloc (buflen);
7112 /* write the prolog */
7115 for (i = 0; i < sig->param_count; ++i) {
7116 arg = mono_array_get (ctorArgs, MonoObject*, i);
7117 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7121 i += mono_array_length (properties);
7123 i += mono_array_length (fields);
7125 *p++ = (i >> 8) & 0xff;
7128 for (i = 0; i < mono_array_length (properties); ++i) {
7133 prop = mono_array_get (properties, gpointer, i);
7134 get_prop_name_and_type (prop, &pname, &ptype);
7135 *p++ = 0x54; /* PROPERTY signature */
7137 /* Preallocate a large enough buffer */
7138 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7139 char *str = type_get_qualified_name (ptype, NULL);
7145 len += strlen (pname);
7147 if ((p-buffer) + 20 + len >= buflen) {
7151 newbuf = g_realloc (buffer, buflen);
7152 p = newbuf + (p-buffer);
7156 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7157 char *str = type_get_qualified_name (ptype, NULL);
7158 int slen = strlen (str);
7162 * This seems to be optional...
7165 mono_metadata_encode_value (slen, p, &p);
7166 memcpy (p, str, slen);
7170 mono_metadata_encode_value (ptype->type, p, &p);
7171 if (ptype->type == MONO_TYPE_SZARRAY)
7172 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7174 len = strlen (pname);
7175 mono_metadata_encode_value (len, p, &p);
7176 memcpy (p, pname, len);
7178 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7185 for (i = 0; i < mono_array_length (fields); ++i) {
7190 field = mono_array_get (fields, gpointer, i);
7191 get_field_name_and_type (field, &fname, &ftype);
7192 *p++ = 0x53; /* FIELD signature */
7193 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7194 char *str = type_get_qualified_name (ftype, NULL);
7195 int slen = strlen (str);
7196 if ((p-buffer) + 10 + slen >= buflen) {
7200 newbuf = g_realloc (buffer, buflen);
7201 p = newbuf + (p-buffer);
7206 * This seems to be optional...
7209 mono_metadata_encode_value (slen, p, &p);
7210 memcpy (p, str, slen);
7214 mono_metadata_encode_value (ftype->type, p, &p);
7215 if (ftype->type == MONO_TYPE_SZARRAY)
7216 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7218 len = strlen (fname);
7219 mono_metadata_encode_value (len, p, &p);
7220 memcpy (p, fname, len);
7222 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7227 g_assert (p - buffer <= buflen);
7228 buflen = p - buffer;
7229 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7230 p = mono_array_addr (result, char, 0);
7231 memcpy (p, buffer, buflen);
7233 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7239 * mono_reflection_setup_internal_class:
7240 * @tb: a TypeBuilder object
7242 * Creates a MonoClass that represents the TypeBuilder.
7243 * This is a trick that lets us simplify a lot of reflection code
7244 * (and will allow us to support Build and Run assemblies easier).
7247 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7249 MonoClass *klass, *parent;
7251 MONO_ARCH_SAVE_REGS;
7254 /* check so we can compile corlib correctly */
7255 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7256 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7257 parent = tb->parent->type->data.klass;
7259 parent = my_mono_class_from_mono_type (tb->parent->type);
7265 /* the type has already being created: it means we just have to change the parent */
7266 if (tb->type.type) {
7267 klass = mono_class_from_mono_type (tb->type.type);
7268 klass->parent = NULL;
7269 /* fool mono_class_setup_parent */
7270 g_free (klass->supertypes);
7271 klass->supertypes = NULL;
7272 mono_class_setup_parent (klass, parent);
7273 mono_class_setup_mono_type (klass);
7277 klass = g_new0 (MonoClass, 1);
7279 klass->image = &tb->module->dynamic_image->image;
7281 klass->inited = 1; /* we lie to the runtime */
7282 klass->name = mono_string_to_utf8 (tb->name);
7283 klass->name_space = mono_string_to_utf8 (tb->nspace);
7284 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7285 klass->flags = tb->attrs;
7287 klass->element_class = klass;
7288 klass->reflection_info = tb; /* need to pin. */
7290 /* Put into cache so mono_class_get () will find it */
7291 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7293 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7294 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7296 if (parent != NULL) {
7297 mono_class_setup_parent (klass, parent);
7298 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7299 const char *old_n = klass->name;
7300 /* trick to get relative numbering right when compiling corlib */
7301 klass->name = "BuildingObject";
7302 mono_class_setup_parent (klass, mono_defaults.object_class);
7303 klass->name = old_n;
7306 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7307 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7308 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7309 klass->instance_size = sizeof (MonoObject);
7310 klass->size_inited = 1;
7311 mono_class_setup_vtable (klass, NULL, 0);
7314 mono_class_setup_mono_type (klass);
7316 mono_class_setup_supertypes (klass);
7319 * FIXME: handle interfaces.
7322 tb->type.type = &klass->byval_arg;
7324 if (tb->nesting_type) {
7325 g_assert (tb->nesting_type->type);
7326 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7329 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7333 * mono_reflection_setup_generic_class:
7334 * @tb: a TypeBuilder object
7336 * Setup the generic class before adding the first generic parameter.
7339 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7343 MONO_ARCH_SAVE_REGS;
7345 klass = my_mono_class_from_mono_type (tb->type.type);
7346 if (tb->generic_container)
7349 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7350 tb->generic_container->klass = klass;
7352 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7353 tb->generic_container->context->container = tb->generic_container;
7357 * mono_reflection_create_generic_class:
7358 * @tb: a TypeBuilder object
7360 * Creates the generic class after all generic parameters have been added.
7363 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7368 MONO_ARCH_SAVE_REGS;
7370 klass = my_mono_class_from_mono_type (tb->type.type);
7372 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7374 if (klass->generic_container || (count == 0))
7377 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7379 klass->generic_container = tb->generic_container;
7381 klass->generic_container->type_argc = count;
7382 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7384 for (i = 0; i < count; i++) {
7385 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7386 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7387 g_assert (klass->generic_container->type_params [i].owner);
7392 * mono_reflection_create_internal_class:
7393 * @tb: a TypeBuilder object
7395 * Actually create the MonoClass that is associated with the TypeBuilder.
7398 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7402 MONO_ARCH_SAVE_REGS;
7404 klass = my_mono_class_from_mono_type (tb->type.type);
7406 if (klass->enumtype && klass->enum_basetype == NULL) {
7407 MonoReflectionFieldBuilder *fb;
7410 g_assert (tb->fields != NULL);
7411 g_assert (mono_array_length (tb->fields) >= 1);
7413 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7415 klass->enum_basetype = fb->type->type;
7416 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7417 if (!klass->element_class)
7418 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7421 * get the element_class from the current corlib.
7423 ec = default_class_from_mono_type (klass->enum_basetype);
7424 klass->instance_size = ec->instance_size;
7425 klass->size_inited = 1;
7427 * this is almost safe to do with enums and it's needed to be able
7428 * to create objects of the enum type (for use in SetConstant).
7430 /* FIXME: Does this mean enums can't have method overrides ? */
7431 mono_class_setup_vtable (klass, NULL, 0);
7435 static MonoMarshalSpec*
7436 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7437 MonoReflectionMarshal *minfo)
7439 MonoMarshalSpec *res;
7441 res = g_new0 (MonoMarshalSpec, 1);
7442 res->native = minfo->type;
7444 switch (minfo->type) {
7445 case MONO_NATIVE_LPARRAY:
7446 res->data.array_data.elem_type = minfo->eltype;
7447 res->data.array_data.param_num = 0; /* Not yet */
7448 res->data.array_data.num_elem = minfo->count;
7451 case MONO_NATIVE_BYVALTSTR:
7452 case MONO_NATIVE_BYVALARRAY:
7453 res->data.array_data.num_elem = minfo->count;
7456 case MONO_NATIVE_CUSTOM:
7457 if (minfo->marshaltyperef)
7458 res->data.custom_data.custom_name =
7459 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7461 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7471 MonoReflectionMarshal*
7472 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7473 MonoMarshalSpec *spec)
7475 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7476 MonoReflectionMarshal *minfo;
7479 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7480 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7481 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7482 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7485 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7486 minfo->type = spec->native;
7488 switch (minfo->type) {
7489 case MONO_NATIVE_LPARRAY:
7490 minfo->eltype = spec->data.array_data.elem_type;
7491 minfo->count = spec->data.array_data.num_elem;
7494 case MONO_NATIVE_BYVALTSTR:
7495 case MONO_NATIVE_BYVALARRAY:
7496 minfo->count = spec->data.array_data.num_elem;
7499 case MONO_NATIVE_CUSTOM:
7500 if (spec->data.custom_data.custom_name) {
7501 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7503 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7505 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7507 if (spec->data.custom_data.cookie)
7508 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7519 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7520 ReflectionMethodBuilder *rmb,
7521 MonoMethodSignature *sig)
7524 MonoMethodNormal *pm;
7525 MonoMarshalSpec **specs;
7526 MonoReflectionMethodAux *method_aux;
7529 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7530 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7531 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7533 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7535 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7537 pm = (MonoMethodNormal*)m;
7540 m->flags = rmb->attrs;
7541 m->iflags = rmb->iattrs;
7542 m->name = mono_string_to_utf8 (rmb->name);
7546 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7548 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7549 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7552 m->signature->pinvoke = 1;
7553 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7554 m->signature->pinvoke = 1;
7556 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7558 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7559 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7561 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7563 if (klass->image->dynamic)
7564 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7567 } else if (!m->klass->dummy &&
7568 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7569 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7570 MonoMethodHeader *header;
7572 gint32 max_stack, i;
7573 gint32 num_locals = 0;
7574 gint32 num_clauses = 0;
7578 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7579 code_size = rmb->ilgen->code_len;
7580 max_stack = rmb->ilgen->max_stack;
7581 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7582 if (rmb->ilgen->ex_handlers)
7583 num_clauses = method_count_clauses (rmb->ilgen);
7586 code = mono_array_addr (rmb->code, guint8, 0);
7587 code_size = mono_array_length (rmb->code);
7588 /* we probably need to run a verifier on the code... */
7598 header = g_malloc0 (sizeof (MonoMethodHeader) +
7599 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7600 header->code_size = code_size;
7601 header->code = g_malloc (code_size);
7602 memcpy ((char*)header->code, code, code_size);
7603 header->max_stack = max_stack;
7604 header->init_locals = rmb->init_locals;
7605 header->num_locals = num_locals;
7607 for (i = 0; i < num_locals; ++i) {
7608 MonoReflectionLocalBuilder *lb =
7609 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7611 header->locals [i] = g_new0 (MonoType, 1);
7612 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7615 header->num_clauses = num_clauses;
7617 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7618 rmb->ilgen, num_clauses);
7621 pm->header = header;
7624 if (rmb->generic_params) {
7625 int count = mono_array_length (rmb->generic_params);
7626 MonoGenericContainer *container;
7628 pm->generic_container = container = rmb->generic_container;
7629 container->type_argc = count;
7630 container->type_params = g_new0 (MonoGenericParam, count);
7632 for (i = 0; i < count; i++) {
7633 MonoReflectionGenericParam *gp =
7634 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7636 container->type_params [i] = *gp->type.type->data.generic_param;
7641 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7644 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7646 for (i = 0; i < rmb->nrefs; ++i)
7647 mw->data = g_list_append (mw->data, rmb->refs [i]);
7652 /* Parameter info */
7655 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7656 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7657 for (i = 0; i <= m->signature->param_count; ++i) {
7658 MonoReflectionParamBuilder *pb;
7659 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7661 m->signature->params [i - 1]->attrs = pb->attrs;
7663 if (pb->def_value) {
7664 MonoDynamicImage *assembly;
7665 guint32 idx, def_type, len;
7669 if (!method_aux->param_defaults)
7670 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7671 assembly = (MonoDynamicImage*)klass->image;
7672 idx = encode_constant (assembly, pb->def_value, &def_type);
7673 /* Copy the data from the blob since it might get realloc-ed */
7674 p = assembly->blob.data + idx;
7675 len = mono_metadata_decode_blob_size (p, &p2);
7677 method_aux->param_defaults [i] = g_malloc (len);
7678 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7682 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7684 if (!method_aux->param_cattr)
7685 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7686 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7692 /* Parameter marshalling */
7695 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7696 MonoReflectionParamBuilder *pb;
7697 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7698 if (pb->marshal_info) {
7700 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7701 specs [pb->position] =
7702 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7706 if (specs != NULL) {
7708 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7709 method_aux->param_marshall = specs;
7712 if (klass->image->dynamic && method_aux)
7713 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7719 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7721 ReflectionMethodBuilder rmb;
7722 MonoMethodSignature *sig;
7724 sig = ctor_builder_to_signature (mb);
7726 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7728 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7729 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7731 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7732 /* ilgen is no longer needed */
7740 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7742 ReflectionMethodBuilder rmb;
7743 MonoMethodSignature *sig;
7745 sig = method_builder_to_signature (mb);
7747 reflection_methodbuilder_from_method_builder (&rmb, mb);
7749 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7750 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7752 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7753 /* ilgen is no longer needed */
7759 static MonoClassField*
7760 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7762 MonoClassField *field;
7769 field = g_new0 (MonoClassField, 1);
7771 field->name = mono_string_to_utf8 (fb->name);
7773 /* FIXME: handle type modifiers */
7774 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7775 field->type->attrs = fb->attrs;
7777 field->type = fb->type->type;
7779 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7780 field->data = mono_array_addr (fb->rva_data, char, 0);
7781 if (fb->offset != -1)
7782 field->offset = fb->offset;
7783 field->parent = klass;
7785 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7787 if (fb->def_value) {
7788 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7789 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7790 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7791 /* Copy the data from the blob since it might get realloc-ed */
7792 p = assembly->blob.data + idx;
7793 len = mono_metadata_decode_blob_size (p, &p2);
7795 field->data = g_malloc (len);
7796 memcpy ((gpointer)field->data, p, len);
7803 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7806 MonoClass *klass, *gklass;
7807 MonoReflectionTypeBuilder *tb = NULL;
7808 MonoGenericClass *gclass, *cached;
7813 klass = mono_class_from_mono_type (type->type);
7814 if (!klass->generic_container && !klass->generic_class &&
7815 !(klass->nested_in && klass->nested_in->generic_container))
7818 mono_loader_lock ();
7820 domain = mono_object_domain (type);
7822 gclass = g_new0 (MonoGenericClass, 1);
7823 gclass->inst = g_new0 (MonoGenericInst, 1);
7825 gclass->inst->type_argc = type_argc;
7826 gclass->inst->type_argv = types;
7828 for (i = 0; i < gclass->inst->type_argc; ++i) {
7829 if (!gclass->inst->is_open)
7830 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7833 gclass->generic_type = &klass->byval_arg;
7835 if (klass->generic_class) {
7836 MonoGenericClass *kgclass = klass->generic_class;
7837 MonoGenericClass *ogclass = gclass;
7839 ogclass->context = g_new0 (MonoGenericContext, 1);
7840 ogclass->context->gclass = ogclass;
7842 gclass = g_new0 (MonoGenericClass, 1);
7843 gclass->inst = g_new0 (MonoGenericInst, 1);
7845 gclass->inst->type_argc = kgclass->inst->type_argc;
7846 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7848 for (i = 0; i < gclass->inst->type_argc; i++) {
7849 MonoType *t = kgclass->inst->type_argv [i];
7851 t = mono_class_inflate_generic_type (t, ogclass->context);
7853 if (!gclass->inst->is_open)
7854 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
7856 gclass->inst->type_argv [i] = t;
7859 gclass->generic_type = kgclass->generic_type;
7862 geninst = g_new0 (MonoType, 1);
7863 geninst->type = MONO_TYPE_GENERICINST;
7865 cached = g_hash_table_lookup (klass->image->generic_class_cache, gclass);
7868 mono_loader_unlock ();
7869 geninst->data.generic_class = cached;
7873 gklass = mono_class_from_mono_type (gclass->generic_type);
7874 g_assert ((gclass->container = gklass->generic_container) != NULL);
7876 geninst->data.generic_class = gclass;
7878 gclass->parent = parent;
7880 gclass->context = g_new0 (MonoGenericContext, 1);
7881 gclass->context->gclass = gclass;
7883 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7884 tb = (MonoReflectionTypeBuilder *) type;
7886 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7887 gclass->is_dynamic = TRUE;
7888 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7889 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7890 MonoReflectionType *rgt = rgi->generic_type;
7892 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7893 tb = (MonoReflectionTypeBuilder *) rgt;
7895 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7896 gclass->is_dynamic = TRUE;
7898 icount = klass->interface_count;
7901 gclass->ifaces = g_new0 (MonoType *, icount);
7902 gclass->count_ifaces = icount;
7904 for (i = 0; i < icount; i++) {
7905 MonoReflectionType *itype;
7908 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7910 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7911 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7912 if (!gclass->ifaces [i])
7913 gclass->ifaces [i] = itype->type;
7916 mono_class_create_generic (gclass);
7917 mono_class_create_generic_2 (gclass);
7919 g_hash_table_insert (klass->image->generic_class_cache, gclass, gclass);
7921 mono_loader_unlock ();
7927 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7929 MonoClass *klass, *pklass = NULL;
7930 MonoReflectionType *parent = NULL;
7931 MonoType *the_parent = NULL, *geninst;
7932 MonoReflectionTypeBuilder *tb = NULL;
7933 MonoGenericClass *gclass;
7936 domain = mono_object_domain (type);
7937 klass = mono_class_from_mono_type (type->type);
7939 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7940 tb = (MonoReflectionTypeBuilder *) type;
7943 parent = tb->parent;
7944 pklass = mono_class_from_mono_type (parent->type);
7947 pklass = klass->parent;
7949 parent = mono_type_get_object (domain, &pklass->byval_arg);
7950 else if (klass->generic_class && klass->generic_class->parent) {
7951 parent = mono_type_get_object (domain, klass->generic_class->parent);
7952 pklass = mono_class_from_mono_type (klass->generic_class->parent);
7956 if (pklass && pklass->generic_class)
7957 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7959 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7963 gclass = geninst->data.generic_class;
7968 MonoReflectionMethod*
7969 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7971 MonoMethod *method, *inflated;
7972 MonoReflectionMethodBuilder *mb = NULL;
7973 MonoGenericContainer *container;
7974 MonoGenericMethod *gmethod;
7975 MonoGenericContext *context;
7978 MONO_ARCH_SAVE_REGS;
7979 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7980 MonoReflectionTypeBuilder *tb;
7983 mb = (MonoReflectionMethodBuilder *) rmethod;
7984 tb = (MonoReflectionTypeBuilder *) mb->type;
7985 klass = mono_class_from_mono_type (tb->type.type);
7987 method = methodbuilder_to_mono_method (klass, mb);
7989 method = rmethod->method;
7992 count = method->signature->generic_param_count;
7993 if (count != mono_array_length (types))
7996 container = ((MonoMethodNormal*) method)->generic_container;
7997 g_assert (container);
7999 if (!container->method_hash)
8000 container->method_hash = g_hash_table_new (
8001 mono_metadata_generic_method_hash, mono_metadata_generic_method_equal);
8003 gmethod = g_new0 (MonoGenericMethod, 1);
8004 gmethod->inst = g_new0 (MonoGenericInst, 1);
8005 gmethod->inst->type_argc = count;
8006 gmethod->inst->type_argv = g_new0 (MonoType *, count);
8007 for (i = 0; i < count; i++) {
8008 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8009 gmethod->inst->type_argv [i] = garg->type;
8012 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8014 g_free (gmethod->inst->type_argv);
8017 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8020 gmethod->reflection_info = rmethod;
8022 context = g_new0 (MonoGenericContext, 1);
8023 context->gclass = method->klass->generic_class;
8024 context->gmethod = gmethod;
8026 inflated = mono_class_inflate_generic_method (method, context, NULL);
8027 g_hash_table_insert (container->method_hash, gmethod, inflated);
8029 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8033 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8035 MonoGenericMethod *gmethod;
8036 MonoGenericClass *gclass;
8037 MonoGenericContext *context;
8040 gclass = type->type.type->data.generic_class;
8042 gmethod = g_new0 (MonoGenericMethod, 1);
8043 gmethod->inst = g_new0 (MonoGenericInst, 1);
8044 gmethod->reflection_info = obj;
8046 gmethod->inst->type_argc = method->signature->generic_param_count;
8047 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8049 for (i = 0; i < gmethod->inst->type_argc; i++) {
8050 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8051 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8053 g_assert (gparam->pklass);
8054 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8057 context = g_new0 (MonoGenericContext, 1);
8058 context->gclass = gclass;
8059 context->gmethod = gmethod;
8061 return mono_class_inflate_generic_method (method, context, gclass->klass);
8065 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8070 klass = mono_class_from_mono_type (type->type.type);
8072 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8073 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8074 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8075 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8076 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8077 method = ((MonoReflectionMethod *) obj)->method;
8079 method = NULL; /* prevent compiler warning */
8080 g_assert_not_reached ();
8083 return inflate_mono_method (type, method, obj);
8087 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8088 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8091 MonoGenericClass *gclass;
8092 MonoDynamicGenericClass *dgclass;
8093 MonoClass *klass, *gklass, *pklass;
8096 MONO_ARCH_SAVE_REGS;
8098 klass = mono_class_from_mono_type (type->type.type);
8099 gclass = type->type.type->data.generic_class;
8101 if (gclass->initialized)
8104 dgclass = gclass->dynamic_info = g_new0 (MonoDynamicGenericClass, 1);
8106 gklass = mono_class_from_mono_type (gclass->generic_type);
8107 mono_class_init (gklass);
8110 pklass = mono_class_from_mono_type (gclass->parent);
8112 pklass = gklass->parent;
8114 mono_class_setup_parent (klass, pklass);
8116 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8117 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8118 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8119 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8120 dgclass->count_events = events ? mono_array_length (events) : 0;
8122 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8123 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8124 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8125 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8126 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8128 for (i = 0; i < dgclass->count_methods; i++) {
8129 MonoObject *obj = mono_array_get (methods, gpointer, i);
8131 dgclass->methods [i] = inflate_method (type, obj);
8134 for (i = 0; i < dgclass->count_ctors; i++) {
8135 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8137 dgclass->ctors [i] = inflate_method (type, obj);
8140 for (i = 0; i < dgclass->count_fields; i++) {
8141 MonoObject *obj = mono_array_get (fields, gpointer, i);
8142 MonoClassField *field;
8143 MonoInflatedField *ifield;
8145 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8146 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8147 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8148 field = ((MonoReflectionField *) obj)->field;
8150 field = NULL; /* prevent compiler warning */
8151 g_assert_not_reached ();
8154 ifield = g_new0 (MonoInflatedField, 1);
8155 ifield->generic_type = field->type;
8156 ifield->reflection_info = obj;
8158 dgclass->fields [i] = *field;
8159 dgclass->fields [i].generic_info = ifield;
8160 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8163 for (i = 0; i < dgclass->count_properties; i++) {
8164 MonoObject *obj = mono_array_get (properties, gpointer, i);
8165 MonoProperty *property = &dgclass->properties [i];
8167 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8168 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8170 property->parent = klass;
8171 property->attrs = pb->attrs;
8172 property->name = mono_string_to_utf8 (pb->name);
8174 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8176 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8177 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8178 *property = *((MonoReflectionProperty *) obj)->property;
8181 property->get = inflate_mono_method (type, property->get, NULL);
8183 property->set = inflate_mono_method (type, property->set, NULL);
8185 g_assert_not_reached ();
8188 for (i = 0; i < dgclass->count_events; i++) {
8189 MonoObject *obj = mono_array_get (events, gpointer, i);
8190 MonoEvent *event = &dgclass->events [i];
8192 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8193 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8195 event->parent = klass;
8196 event->attrs = eb->attrs;
8197 event->name = mono_string_to_utf8 (eb->name);
8199 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8200 if (eb->remove_method)
8201 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8202 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8203 *event = *((MonoReflectionEvent *) obj)->event;
8206 event->add = inflate_mono_method (type, event->add, NULL);
8208 event->remove = inflate_mono_method (type, event->remove, NULL);
8210 g_assert_not_reached ();
8213 gclass->initialized = TRUE;
8217 ensure_runtime_vtable (MonoClass *klass)
8219 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8220 int i, num, j, onum;
8221 MonoMethod **overrides;
8223 if (!tb || klass->wastypebuilder)
8226 ensure_runtime_vtable (klass->parent);
8228 num = tb->ctors? mono_array_length (tb->ctors): 0;
8229 num += tb->num_methods;
8230 klass->method.count = num;
8231 klass->methods = g_new (MonoMethod*, num);
8232 num = tb->ctors? mono_array_length (tb->ctors): 0;
8233 for (i = 0; i < num; ++i)
8234 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8235 num = tb->num_methods;
8237 for (i = 0; i < num; ++i)
8238 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8240 if (tb->interfaces) {
8241 klass->interface_count = mono_array_length (tb->interfaces);
8242 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8243 for (i = 0; i < klass->interface_count; ++i) {
8244 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8245 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8249 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8250 for (i = 0; i < klass->method.count; ++i)
8251 klass->methods [i]->slot = i;
8256 for (i = 0; i < tb->num_methods; ++i) {
8257 MonoReflectionMethodBuilder *mb =
8258 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8259 if (mb->override_method)
8264 overrides = g_new0 (MonoMethod*, onum * 2);
8268 for (i = 0; i < tb->num_methods; ++i) {
8269 MonoReflectionMethodBuilder *mb =
8270 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8271 if (mb->override_method) {
8272 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8273 overrides [onum * 2] =
8274 mb->override_method->method;
8275 overrides [onum * 2 + 1] =
8278 g_assert (mb->mhandle);
8285 mono_class_setup_vtable (klass, overrides, onum);
8290 typebuilder_setup_fields (MonoClass *klass)
8292 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8293 MonoReflectionFieldBuilder *fb;
8294 MonoClassField *field;
8299 klass->field.count = tb->num_fields;
8300 klass->field.first = 0;
8301 klass->field.last = klass->field.count;
8303 if (!klass->field.count)
8306 klass->fields = g_new0 (MonoClassField, klass->field.count);
8308 for (i = 0; i < klass->field.count; ++i) {
8309 fb = mono_array_get (tb->fields, gpointer, i);
8310 field = &klass->fields [i];
8311 field->name = mono_string_to_utf8 (fb->name);
8313 /* FIXME: handle type modifiers */
8314 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8315 field->type->attrs = fb->attrs;
8317 field->type = fb->type->type;
8319 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8320 field->data = mono_array_addr (fb->rva_data, char, 0);
8321 if (fb->offset != -1)
8322 field->offset = fb->offset;
8323 field->parent = klass;
8325 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8327 if (fb->def_value) {
8328 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8329 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8330 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8331 /* Copy the data from the blob since it might get realloc-ed */
8332 p = assembly->blob.data + idx;
8333 len = mono_metadata_decode_blob_size (p, &p2);
8335 field->data = g_malloc (len);
8336 memcpy ((gpointer)field->data, p, len);
8339 mono_class_layout_fields (klass);
8343 typebuilder_setup_properties (MonoClass *klass)
8345 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8346 MonoReflectionPropertyBuilder *pb;
8349 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8350 klass->property.first = 0;
8351 klass->property.last = klass->property.count;
8353 klass->properties = g_new0 (MonoProperty, klass->property.count);
8354 for (i = 0; i < klass->property.count; ++i) {
8355 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8356 klass->properties [i].parent = klass;
8357 klass->properties [i].attrs = pb->attrs;
8358 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8360 klass->properties [i].get = pb->get_method->mhandle;
8362 klass->properties [i].set = pb->set_method->mhandle;
8366 MonoReflectionEvent *
8367 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8369 MonoEvent *event = g_new0 (MonoEvent, 1);
8373 klass = my_mono_class_from_mono_type (tb->type.type);
8375 event->parent = klass;
8376 event->attrs = eb->attrs;
8377 event->name = mono_string_to_utf8 (eb->name);
8379 event->add = eb->add_method->mhandle;
8380 if (eb->remove_method)
8381 event->remove = eb->remove_method->mhandle;
8382 if (eb->raise_method)
8383 event->raise = eb->raise_method->mhandle;
8385 if (eb->other_methods) {
8386 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8387 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8388 MonoReflectionMethodBuilder *mb =
8389 mono_array_get (eb->other_methods,
8390 MonoReflectionMethodBuilder*, j);
8391 event->other [j] = mb->mhandle;
8395 return mono_event_get_object (mono_object_domain (tb), klass, event);
8399 typebuilder_setup_events (MonoClass *klass)
8401 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8402 MonoReflectionEventBuilder *eb;
8405 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8406 klass->event.first = 0;
8407 klass->event.last = klass->event.count;
8409 klass->events = g_new0 (MonoEvent, klass->event.count);
8410 for (i = 0; i < klass->event.count; ++i) {
8411 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8412 klass->events [i].parent = klass;
8413 klass->events [i].attrs = eb->attrs;
8414 klass->events [i].name = mono_string_to_utf8 (eb->name);
8416 klass->events [i].add = eb->add_method->mhandle;
8417 if (eb->remove_method)
8418 klass->events [i].remove = eb->remove_method->mhandle;
8419 if (eb->raise_method)
8420 klass->events [i].raise = eb->raise_method->mhandle;
8422 if (eb->other_methods) {
8423 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8424 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8425 MonoReflectionMethodBuilder *mb =
8426 mono_array_get (eb->other_methods,
8427 MonoReflectionMethodBuilder*, j);
8428 klass->events [i].other [j] = mb->mhandle;
8435 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8438 MonoReflectionType* res;
8441 MONO_ARCH_SAVE_REGS;
8443 klass = my_mono_class_from_mono_type (tb->type.type);
8445 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8448 * Fields to set in klass:
8449 * the various flags: delegate/unicode/contextbound etc.
8451 klass->flags = tb->attrs;
8453 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8454 /* No need to fully construct the type */
8455 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8457 /* enums are done right away */
8458 if (!klass->enumtype)
8459 ensure_runtime_vtable (klass);
8462 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8463 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8464 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8468 /* fields and object layout */
8469 if (klass->parent) {
8470 if (!klass->parent->size_inited)
8471 mono_class_init (klass->parent);
8472 klass->instance_size += klass->parent->instance_size;
8473 klass->class_size += klass->parent->class_size;
8474 klass->min_align = klass->parent->min_align;
8476 klass->instance_size = sizeof (MonoObject);
8477 klass->min_align = 1;
8480 /* FIXME: handle packing_size and instance_size */
8481 typebuilder_setup_fields (klass);
8483 typebuilder_setup_properties (klass);
8485 typebuilder_setup_events (klass);
8487 klass->wastypebuilder = TRUE;
8489 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8490 g_assert (res != (MonoReflectionType*)tb);
8495 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8497 MonoGenericParam *param;
8500 MONO_ARCH_SAVE_REGS;
8502 param = g_new0 (MonoGenericParam, 1);
8504 if (gparam->mbuilder) {
8505 if (!gparam->mbuilder->generic_container)
8506 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8507 param->owner = gparam->mbuilder->generic_container;
8508 } else if (gparam->tbuilder) {
8509 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8510 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8515 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8516 if (gparam->index >= count)
8519 container = nesting->generic_container;
8520 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8523 g_assert (container);
8524 param->owner = container;
8527 param->method = NULL;
8528 param->name = mono_string_to_utf8 (gparam->name);
8529 param->num = gparam->index;
8531 image = &gparam->tbuilder->module->dynamic_image->image;
8532 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8534 param->pklass->reflection_info = gparam;
8536 gparam->type.type = g_new0 (MonoType, 1);
8537 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8538 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8539 gparam->type.type->data.generic_param = param;
8543 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8545 MonoDynamicImage *assembly = sig->module->dynamic_image;
8546 guint32 na = mono_array_length (sig->arguments);
8551 MONO_ARCH_SAVE_REGS;
8553 p = buf = g_malloc (10 + na * 10);
8555 mono_metadata_encode_value (0x07, p, &p);
8556 mono_metadata_encode_value (na, p, &p);
8557 for (i = 0; i < na; ++i) {
8558 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8559 encode_reflection_type (assembly, type, p, &p);
8563 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8564 p = mono_array_addr (result, char, 0);
8565 memcpy (p, buf, buflen);
8572 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8574 MonoDynamicImage *assembly = sig->module->dynamic_image;
8575 guint32 na = mono_array_length (sig->arguments);
8580 MONO_ARCH_SAVE_REGS;
8582 p = buf = g_malloc (10 + na * 10);
8584 mono_metadata_encode_value (0x06, p, &p);
8585 for (i = 0; i < na; ++i) {
8586 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8587 encode_reflection_type (assembly, type, p, &p);
8591 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8592 p = mono_array_addr (result, char, 0);
8593 memcpy (p, buf, buflen);
8600 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8602 ReflectionMethodBuilder rmb;
8603 MonoMethodSignature *sig;
8606 sig = dynamic_method_to_signature (mb);
8608 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8611 * Resolve references.
8613 rmb.nrefs = mb->nrefs;
8614 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8615 for (i = 0; i < mb->nrefs; ++i) {
8616 gpointer ref = resolve_object (mb->module->image,
8617 mono_array_get (mb->refs, MonoObject*, i));
8620 mono_raise_exception (mono_get_exception_type_load (NULL));
8627 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8631 /* ilgen is no longer needed */
8636 * mono_reflection_lookup_dynamic_token:
8638 * Finish the Builder object pointed to by TOKEN and return the corresponding
8639 * runtime structure.
8642 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8644 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8647 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8650 return resolve_object (image, obj);
8654 resolve_object (MonoImage *image, MonoObject *obj)
8656 gpointer result = NULL;
8658 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8659 result = mono_string_intern ((MonoString*)obj);
8661 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8662 MonoReflectionType *tb = (MonoReflectionType*)obj;
8663 result = mono_class_from_mono_type (tb->type);
8665 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8666 result = ((MonoReflectionMethod*)obj)->method;
8668 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8669 result = ((MonoReflectionMethod*)obj)->method;
8671 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8672 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8673 result = mb->mhandle;
8675 /* Type is not yet created */
8676 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8678 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8681 * Hopefully this has been filled in by calling CreateType() on the
8685 * TODO: This won't work if the application finishes another
8686 * TypeBuilder instance instead of this one.
8688 result = mb->mhandle;
8690 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8691 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8693 result = cb->mhandle;
8695 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8697 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8698 result = cb->mhandle;
8700 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8701 result = ((MonoReflectionField*)obj)->field;
8703 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8704 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8705 result = fb->handle;
8708 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8710 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8711 result = fb->handle;
8713 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8714 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8717 klass = tb->type.type->data.klass;
8718 if (klass->wastypebuilder) {
8719 /* Already created */
8723 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8724 result = tb->type.type->data.klass;
8727 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8728 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8729 MonoMethodSignature *sig;
8732 if (helper->arguments)
8733 nargs = mono_array_length (helper->arguments);
8737 sig = mono_metadata_signature_alloc (image, nargs);
8738 sig->explicit_this = helper->call_conv & 64;
8739 sig->hasthis = helper->call_conv & 32;
8741 if (helper->call_conv == 0) /* unmanaged */
8742 sig->call_convention = helper->unmanaged_call_conv - 1;
8744 if (helper->call_conv & 0x02)
8745 sig->call_convention = MONO_CALL_VARARG;
8747 sig->call_convention = MONO_CALL_DEFAULT;
8749 sig->param_count = nargs;
8750 /* TODO: Copy type ? */
8751 sig->ret = helper->return_type->type;
8752 for (i = 0; i < nargs; ++i) {
8753 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8754 sig->params [i] = rt->type;
8759 g_print (obj->vtable->klass->name);
8760 g_assert_not_reached ();
8766 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8767 const static guint32 declsec_flags_map[] = {
8768 0x00000000, /* empty */
8769 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8770 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8771 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8772 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8773 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8774 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8775 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8776 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8777 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8778 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8779 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8780 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8781 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8782 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8783 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8784 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8785 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8786 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8790 * Returns flags that includes all available security action associated to the handle.
8791 * @token: metadata token (either for a class or a method)
8792 * @image: image where resides the metadata.
8795 mono_declsec_get_flags (MonoImage *image, guint32 token)
8797 guint32 index = mono_metadata_declsec_from_index (image, token);
8798 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8803 for (i = index; i < t->rows; i++) {
8804 guint32 cols [MONO_DECL_SECURITY_SIZE];
8806 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8807 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8810 action = cols [MONO_DECL_SECURITY_ACTION];
8811 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8812 result |= declsec_flags_map [action];
8814 g_assert_not_reached ();
8821 * Get the security actions (in the form of flags) associated with the specified method.
8823 * @method: The method for which we want the declarative security flags.
8824 * Return the declarative security flags for the method (only).
8826 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8827 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8830 mono_declsec_flags_from_method (MonoMethod *method)
8832 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8833 /* FIXME: No cache (for the moment) */
8834 guint32 idx = find_method_index (method);
8835 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8836 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8837 return mono_declsec_get_flags (method->klass->image, idx);
8843 * Get the security actions (in the form of flags) associated with the specified class.
8845 * @klass: The class for which we want the declarative security flags.
8846 * Return the declarative security flags for the class.
8848 * Note: We cache the flags inside the MonoClass structure as this will get
8849 * called very often (at least for each method).
8852 mono_declsec_flags_from_class (MonoClass *klass)
8854 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
8855 if (!klass->declsec_flags) {
8856 guint32 idx = mono_metadata_token_index (klass->type_token);
8857 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8858 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
8859 /* we cache the flags on classes */
8860 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
8862 return klass->declsec_flags;
8868 * Get the security actions (in the form of flags) associated with the specified assembly.
8870 * @assembly: The assembly for which we want the declarative security flags.
8871 * Return the declarative security flags for the assembly.
8874 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
8876 guint32 idx = 1; /* there is only one assembly */
8877 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8878 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
8879 return mono_declsec_get_flags (assembly->image, idx);