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_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
462 g_assert_not_reached ();
466 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
467 encode_type (assembly, ginst->generic_type, p, &p);
468 mono_metadata_encode_value (ginst->type_argc, p, &p);
469 for (i = 0; i < ginst->type_argc; ++i)
470 encode_type (assembly, ginst->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_inst (assembly, type->data.generic_inst, 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_inst_get_signature_size (MonoGenericInst *ginst)
595 g_assert_not_reached ();
598 size += 1 + type_get_signature_size (ginst->generic_type);
600 for (i = 0; i < ginst->type_argc; ++i)
601 size += type_get_signature_size (ginst->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_inst_get_signature_size (type->data.generic_inst);
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_inst)
2197 encode_generic_inst (assembly, k->generic_inst, 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->mtype_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->mtype_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_inst);
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, "MonoGenericInst") == 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_inst) {
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_inst->type_argc != t2->data.generic_inst->type_argc)
5199 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5201 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5202 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_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 MonoReflectionGenericInst*
5239 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5241 static MonoClass *System_Reflection_MonoGenericInst;
5242 MonoReflectionGenericInst *res;
5243 MonoGenericInst *ginst;
5246 if (!System_Reflection_MonoGenericInst) {
5247 System_Reflection_MonoGenericInst = mono_class_from_name (
5248 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5249 g_assert (System_Reflection_MonoGenericInst);
5252 ginst = geninst->data.generic_inst;
5253 gklass = mono_class_from_mono_type (ginst->generic_type);
5255 mono_class_init (ginst->klass);
5257 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
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, ginst->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_inst->is_dynamic) {
5290 res = (MonoReflectionType *)mono_generic_inst_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_inst) {
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.
5762 * Returns 0 on parse error.
5763 * See also mono_type_get_name () below.
5766 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5768 char *start, *p, *w, *last_point, *startn;
5769 int in_modifiers = 0;
5770 int isbyref = 0, rank;
5772 start = p = w = name;
5774 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5775 info->name = info->name_space = NULL;
5776 info->nested = NULL;
5777 info->modifiers = NULL;
5779 /* last_point separates the namespace from the name */
5785 *p = 0; /* NULL terminate the name */
5787 info->nested = g_list_append (info->nested, startn);
5788 /* we have parsed the nesting namespace + name */
5792 info->name_space = start;
5794 info->name = last_point + 1;
5796 info->name_space = (char *)"";
5822 info->name_space = start;
5824 info->name = last_point + 1;
5826 info->name_space = (char *)"";
5833 if (isbyref) /* only one level allowed by the spec */
5836 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5840 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5851 else if (*p != '*') /* '*' means unknown lower bound */
5857 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5862 if (g_ascii_isspace (*p)) {
5869 return 0; /* missing assembly name */
5870 if (!assembly_name_to_aname (&info->assembly, p))
5877 if (info->assembly.name)
5880 *w = 0; /* terminate class name */
5881 if (!info->name || !*info->name)
5883 /* add other consistency checks */
5888 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5895 image = mono_defaults.corlib;
5898 klass = mono_class_from_name_case (image, info->name_space, info->name);
5900 klass = mono_class_from_name (image, info->name_space, info->name);
5903 for (mod = info->nested; mod; mod = mod->next) {
5906 mono_class_init (klass);
5907 nested = klass->nested_classes;
5910 klass = nested->data;
5912 if (g_strcasecmp (klass->name, mod->data) == 0)
5915 if (strcmp (klass->name, mod->data) == 0)
5919 nested = nested->next;
5926 mono_class_init (klass);
5927 for (mod = info->modifiers; mod; mod = mod->next) {
5928 modval = GPOINTER_TO_UINT (mod->data);
5929 if (!modval) { /* byref: must be last modifier */
5930 return &klass->this_arg;
5931 } else if (modval == -1) {
5932 klass = mono_ptr_class_get (&klass->byval_arg);
5933 } else { /* array rank */
5934 klass = mono_array_class_get (klass, modval);
5936 mono_class_init (klass);
5939 return &klass->byval_arg;
5943 * mono_reflection_get_type:
5944 * @image: a metadata context
5945 * @info: type description structure
5946 * @ignorecase: flag for case-insensitive string compares
5947 * @type_resolve: whenever type resolve was already tried
5949 * Build a MonoType from the type description in @info.
5954 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5957 MonoReflectionAssembly *assembly;
5961 type = mono_reflection_get_type_internal (image, info, ignorecase);
5964 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5971 *type_resolve = TRUE;
5974 /* Reconstruct the type name */
5975 fullName = g_string_new ("");
5976 if (info->name_space && (info->name_space [0] != '\0'))
5977 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5979 g_string_printf (fullName, info->name);
5980 for (mod = info->nested; mod; mod = mod->next)
5981 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5983 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5985 if (assembly->assembly->dynamic) {
5986 /* Enumerate all modules */
5987 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5991 if (abuilder->modules) {
5992 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5993 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5994 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6000 if (!type && abuilder->loaded_modules) {
6001 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6002 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6003 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6010 type = mono_reflection_get_type_internal (assembly->assembly->image,
6013 g_string_free (fullName, TRUE);
6018 * mono_reflection_type_from_name:
6020 * @image: a metadata context (can be NULL).
6022 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6023 * it defaults to get the type from @image or, if @image is NULL or loading
6024 * from it fails, uses corlib.
6028 mono_reflection_type_from_name (char *name, MonoImage *image)
6031 MonoTypeNameParse info;
6032 MonoAssembly *assembly;
6034 gboolean type_resolve = FALSE;
6036 /* Make a copy since parse_type modifies its argument */
6037 tmp = g_strdup (name);
6039 /*g_print ("requested type %s\n", str);*/
6040 if (!mono_reflection_parse_type (tmp, &info)) {
6042 g_list_free (info.modifiers);
6043 g_list_free (info.nested);
6047 if (info.assembly.name) {
6048 assembly = mono_assembly_loaded (&info.assembly);
6050 /* then we must load the assembly ourselve - see #60439 */
6051 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6054 g_list_free (info.modifiers);
6055 g_list_free (info.nested);
6059 image = assembly->image;
6060 } else if (image == NULL) {
6061 image = mono_defaults.corlib;
6064 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6065 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6066 image = mono_defaults.corlib;
6067 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6071 g_list_free (info.modifiers);
6072 g_list_free (info.nested);
6077 * mono_reflection_get_token:
6079 * Return the metadata token of OBJ which should be an object
6080 * representing a metadata element.
6083 mono_reflection_get_token (MonoObject *obj)
6088 klass = obj->vtable->klass;
6090 if (strcmp (klass->name, "MethodBuilder") == 0) {
6091 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6093 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6094 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6095 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6097 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6098 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6099 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6100 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6101 if (tb->generic_params) {
6102 g_assert_not_reached ();
6104 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6106 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6107 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6108 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6109 } else if (strcmp (klass->name, "MonoType") == 0) {
6110 MonoReflectionType *tb = (MonoReflectionType *)obj;
6111 token = mono_class_from_mono_type (tb->type)->type_token;
6112 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6113 strcmp (klass->name, "MonoMethod") == 0) {
6114 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6115 if (m->method->signature->is_inflated) {
6116 g_assert_not_reached ();
6117 } else if (m->method->signature->generic_param_count) {
6118 g_assert_not_reached ();
6119 } else if (m->method->klass->generic_inst) {
6120 g_assert_not_reached ();
6122 token = m->method->token;
6124 } else if (strcmp (klass->name, "MonoField") == 0) {
6125 MonoReflectionField *f = (MonoReflectionField*)obj;
6127 token = mono_class_get_field_token (f->field);
6128 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6129 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6131 token = mono_class_get_property_token (p->property);
6132 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6133 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6135 token = mono_class_get_event_token (p->event);
6136 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6137 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6139 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6140 } else if (strcmp (klass->name, "Module") == 0) {
6141 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6144 } else if (strcmp (klass->name, "Assembly") == 0) {
6145 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6147 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6148 MonoException *ex = mono_get_exception_not_implemented (msg);
6150 mono_raise_exception (ex);
6157 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6159 int slen, type = t->type;
6164 case MONO_TYPE_BOOLEAN: {
6165 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6170 case MONO_TYPE_CHAR:
6172 case MONO_TYPE_I2: {
6173 guint16 *val = g_malloc (sizeof (guint16));
6178 #if SIZEOF_VOID_P == 4
6184 case MONO_TYPE_I4: {
6185 guint32 *val = g_malloc (sizeof (guint32));
6190 #if SIZEOF_VOID_P == 8
6191 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6196 case MONO_TYPE_I8: {
6197 guint64 *val = g_malloc (sizeof (guint64));
6202 case MONO_TYPE_VALUETYPE:
6203 if (t->data.klass->enumtype) {
6204 type = t->data.klass->enum_basetype->type;
6207 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6210 case MONO_TYPE_STRING:
6211 if (*p == (char)0xFF) {
6215 slen = mono_metadata_decode_value (p, &p);
6217 return mono_string_new_len (mono_domain_get (), p, slen);
6218 case MONO_TYPE_CLASS: {
6221 if (*p == (char)0xFF) {
6226 slen = mono_metadata_decode_value (p, &p);
6227 n = g_memdup (p, slen + 1);
6229 t = mono_reflection_type_from_name (n, image);
6231 g_warning ("Cannot load type '%s'", n);
6235 return mono_type_get_object (mono_domain_get (), t);
6239 case MONO_TYPE_OBJECT: {
6242 MonoClass *subc = NULL;
6247 } else if (subt == 0x0E) {
6248 type = MONO_TYPE_STRING;
6250 } else if (subt == 0x55) {
6253 slen = mono_metadata_decode_value (p, &p);
6254 n = g_memdup (p, slen + 1);
6256 t = mono_reflection_type_from_name (n, image);
6258 g_warning ("Cannot load type '%s'", n);
6261 subc = mono_class_from_mono_type (t);
6262 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6263 MonoType simple_type = {{0}};
6264 simple_type.type = subt;
6265 subc = mono_class_from_mono_type (&simple_type);
6267 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6269 val = load_cattr_value (image, &subc->byval_arg, p, end);
6270 obj = mono_object_new (mono_domain_get (), subc);
6271 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6275 case MONO_TYPE_SZARRAY: {
6277 guint32 i, alen, basetype;
6280 if (alen == 0xffffffff) {
6284 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6285 basetype = t->data.klass->byval_arg.type;
6290 case MONO_TYPE_BOOLEAN:
6291 for (i = 0; i < alen; i++) {
6292 MonoBoolean val = *p++;
6293 mono_array_set (arr, MonoBoolean, i, val);
6296 case MONO_TYPE_CHAR:
6299 for (i = 0; i < alen; i++) {
6300 guint16 val = read16 (p);
6301 mono_array_set (arr, guint16, i, val);
6308 for (i = 0; i < alen; i++) {
6309 guint32 val = read32 (p);
6310 mono_array_set (arr, guint32, i, val);
6317 for (i = 0; i < alen; i++) {
6318 guint64 val = read64 (p);
6319 mono_array_set (arr, guint64, i, val);
6323 case MONO_TYPE_CLASS:
6324 case MONO_TYPE_OBJECT:
6325 case MONO_TYPE_STRING:
6326 for (i = 0; i < alen; i++) {
6327 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6328 mono_array_set (arr, gpointer, i, item);
6332 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6338 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6344 type_is_reference (MonoType *type)
6346 switch (type->type) {
6347 case MONO_TYPE_BOOLEAN:
6348 case MONO_TYPE_CHAR:
6361 case MONO_TYPE_VALUETYPE:
6369 free_param_data (MonoMethodSignature *sig, void **params) {
6371 for (i = 0; i < sig->param_count; ++i) {
6372 if (!type_is_reference (sig->params [i]))
6373 g_free (params [i]);
6378 * Find the method index in the metadata methodDef table.
6379 * Later put these three helper methods in metadata and export them.
6382 find_method_index (MonoMethod *method) {
6383 MonoClass *klass = method->klass;
6386 for (i = 0; i < klass->method.count; ++i) {
6387 if (method == klass->methods [i])
6388 return klass->method.first + 1 + i;
6394 * Find the field index in the metadata FieldDef table.
6397 find_field_index (MonoClass *klass, MonoClassField *field) {
6400 for (i = 0; i < klass->field.count; ++i) {
6401 if (field == &klass->fields [i])
6402 return klass->field.first + 1 + i;
6408 * Find the property index in the metadata Property table.
6411 find_property_index (MonoClass *klass, MonoProperty *property) {
6414 for (i = 0; i < klass->property.count; ++i) {
6415 if (property == &klass->properties [i])
6416 return klass->property.first + 1 + i;
6422 * Find the event index in the metadata Event table.
6425 find_event_index (MonoClass *klass, MonoEvent *event) {
6428 for (i = 0; i < klass->event.count; ++i) {
6429 if (event == &klass->events [i])
6430 return klass->event.first + 1 + i;
6436 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6438 const char *p = data;
6440 guint32 i, j, num_named;
6444 mono_class_init (method->klass);
6447 attr = mono_object_new (mono_domain_get (), method->klass);
6448 mono_runtime_invoke (method, attr, NULL, NULL);
6452 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6455 /*g_print ("got attr %s\n", method->klass->name);*/
6457 params = g_new (void*, method->signature->param_count);
6461 for (i = 0; i < method->signature->param_count; ++i) {
6462 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6466 attr = mono_object_new (mono_domain_get (), method->klass);
6467 mono_runtime_invoke (method, attr, params, NULL);
6468 free_param_data (method->signature, params);
6470 num_named = read16 (named);
6472 for (j = 0; j < num_named; j++) {
6474 char *name, named_type, data_type;
6475 named_type = *named++;
6476 data_type = *named++; /* type of data */
6477 if (data_type == 0x55) {
6480 type_len = mono_metadata_decode_blob_size (named, &named);
6481 type_name = g_malloc (type_len + 1);
6482 memcpy (type_name, named, type_len);
6483 type_name [type_len] = 0;
6485 /* FIXME: lookup the type and check type consistency */
6486 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6487 /* this seems to be the type of the element of the array */
6488 /* g_print ("skipping 0x%02x after prop\n", *named); */
6491 name_len = mono_metadata_decode_blob_size (named, &named);
6492 name = g_malloc (name_len + 1);
6493 memcpy (name, named, name_len);
6494 name [name_len] = 0;
6496 if (named_type == 0x53) {
6497 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6498 void *val = load_cattr_value (image, field->type, named, &named);
6499 mono_field_set_value (attr, field, val);
6500 if (!type_is_reference (field->type))
6502 } else if (named_type == 0x54) {
6505 MonoType *prop_type;
6507 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6508 /* can we have more that 1 arg in a custom attr named property? */
6509 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6510 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6511 mono_property_set_value (prop, attr, pparams, NULL);
6512 if (!type_is_reference (prop_type))
6513 g_free (pparams [0]);
6522 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6529 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6530 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6531 for (i = 0; i < cinfo->num_attrs; ++i) {
6532 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6533 mono_array_set (result, gpointer, i, attr);
6539 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6541 guint32 mtoken, i, len;
6542 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6544 MonoCustomAttrInfo *ainfo;
6545 GList *tmp, *list = NULL;
6548 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6550 i = mono_metadata_custom_attrs_from_index (image, idx);
6554 while (i < ca->rows) {
6555 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6557 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6560 len = g_list_length (list);
6563 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6564 ainfo->num_attrs = len;
6565 ainfo->image = image;
6566 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6567 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6568 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6569 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6570 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6571 mtoken |= MONO_TOKEN_METHOD_DEF;
6573 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6574 mtoken |= MONO_TOKEN_MEMBER_REF;
6577 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6580 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6581 if (!ainfo->attrs [i].ctor)
6582 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6583 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6584 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6585 ainfo->attrs [i].data = data;
6593 mono_custom_attrs_from_method (MonoMethod *method)
6595 MonoCustomAttrInfo *cinfo;
6598 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6600 idx = find_method_index (method);
6601 idx <<= MONO_CUSTOM_ATTR_BITS;
6602 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6603 return mono_custom_attrs_from_index (method->klass->image, idx);
6607 mono_custom_attrs_from_class (MonoClass *klass)
6609 MonoCustomAttrInfo *cinfo;
6612 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6614 idx = mono_metadata_token_index (klass->type_token);
6615 idx <<= MONO_CUSTOM_ATTR_BITS;
6616 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6617 return mono_custom_attrs_from_index (klass->image, idx);
6621 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6623 MonoCustomAttrInfo *cinfo;
6626 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6628 idx = 1; /* there is only one assembly */
6629 idx <<= MONO_CUSTOM_ATTR_BITS;
6630 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6631 return mono_custom_attrs_from_index (assembly->image, idx);
6634 static MonoCustomAttrInfo*
6635 mono_custom_attrs_from_module (MonoImage *image)
6637 MonoCustomAttrInfo *cinfo;
6640 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6642 idx = 1; /* there is only one module */
6643 idx <<= MONO_CUSTOM_ATTR_BITS;
6644 idx |= MONO_CUSTOM_ATTR_MODULE;
6645 return mono_custom_attrs_from_index (image, idx);
6649 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6651 MonoCustomAttrInfo *cinfo;
6654 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6656 idx = find_property_index (klass, property);
6657 idx <<= MONO_CUSTOM_ATTR_BITS;
6658 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6659 return mono_custom_attrs_from_index (klass->image, idx);
6663 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6665 MonoCustomAttrInfo *cinfo;
6668 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6670 idx = find_event_index (klass, event);
6671 idx <<= MONO_CUSTOM_ATTR_BITS;
6672 idx |= MONO_CUSTOM_ATTR_EVENT;
6673 return mono_custom_attrs_from_index (klass->image, idx);
6677 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6679 MonoCustomAttrInfo *cinfo;
6682 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6684 idx = find_field_index (klass, field);
6685 idx <<= MONO_CUSTOM_ATTR_BITS;
6686 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6687 return mono_custom_attrs_from_index (klass->image, idx);
6691 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6694 guint32 i, idx, method_index;
6695 guint32 param_list, param_last, param_pos, found;
6697 MonoReflectionMethodAux *aux;
6699 if (method->klass->image->dynamic) {
6700 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6701 if (!aux || !aux->param_cattr)
6703 return aux->param_cattr [param];
6706 image = method->klass->image;
6707 method_index = find_method_index (method);
6708 ca = &image->tables [MONO_TABLE_METHOD];
6710 if (method->klass->generic_inst || method->klass->generic_container ||
6711 method->signature->generic_param_count) {
6712 /* FIXME FIXME FIXME */
6716 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6717 if (method_index == ca->rows) {
6718 ca = &image->tables [MONO_TABLE_PARAM];
6719 param_last = ca->rows + 1;
6721 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6722 ca = &image->tables [MONO_TABLE_PARAM];
6725 for (i = param_list; i < param_last; ++i) {
6726 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6727 if (param_pos == param) {
6735 idx <<= MONO_CUSTOM_ATTR_BITS;
6736 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6737 return mono_custom_attrs_from_index (image, idx);
6741 * mono_reflection_get_custom_attrs:
6742 * @obj: a reflection object handle
6744 * Return an array with all the custom attributes defined of the
6745 * reflection handle @obj. The objects are fully build.
6748 mono_reflection_get_custom_attrs (MonoObject *obj)
6752 MonoCustomAttrInfo *cinfo = NULL;
6754 MONO_ARCH_SAVE_REGS;
6756 klass = obj->vtable->klass;
6757 if (klass == mono_defaults.monotype_class) {
6758 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6759 klass = mono_class_from_mono_type (rtype->type);
6760 cinfo = mono_custom_attrs_from_class (klass);
6761 } else if (strcmp ("Assembly", klass->name) == 0) {
6762 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6763 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6764 } else if (strcmp ("Module", klass->name) == 0) {
6765 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6766 cinfo = mono_custom_attrs_from_module (module->image);
6767 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6768 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6769 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6770 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6771 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6772 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6773 } else if (strcmp ("MonoField", klass->name) == 0) {
6774 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6775 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6776 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6777 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6778 cinfo = mono_custom_attrs_from_method (rmethod->method);
6779 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6780 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6781 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6782 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6783 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6784 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6785 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6786 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6787 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6788 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6789 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6790 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6791 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6792 } else { /* handle other types here... */
6793 g_error ("get custom attrs not yet supported for %s", klass->name);
6797 result = mono_custom_attrs_construct (cinfo);
6799 mono_custom_attrs_free (cinfo);
6801 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6802 result = mono_array_new (mono_domain_get (), klass, 0);
6808 static MonoMethodSignature*
6809 parameters_to_signature (MonoArray *parameters) {
6810 MonoMethodSignature *sig;
6813 count = parameters? mono_array_length (parameters): 0;
6815 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6816 sig->param_count = count;
6817 sig->sentinelpos = -1; /* FIXME */
6818 for (i = 0; i < count; ++i) {
6819 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6820 sig->params [i] = pt->type;
6825 static MonoMethodSignature*
6826 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6827 MonoMethodSignature *sig;
6829 sig = parameters_to_signature (ctor->parameters);
6830 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6831 sig->ret = &mono_defaults.void_class->byval_arg;
6835 static MonoMethodSignature*
6836 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6837 MonoMethodSignature *sig;
6839 sig = parameters_to_signature (method->parameters);
6840 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6841 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6842 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6846 static MonoMethodSignature*
6847 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6848 MonoMethodSignature *sig;
6850 sig = parameters_to_signature (method->parameters);
6851 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6852 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6853 sig->generic_param_count = 0;
6858 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6860 MonoClass *klass = mono_object_class (prop);
6861 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6862 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6863 *name = mono_string_to_utf8 (pb->name);
6864 *type = pb->type->type;
6866 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6867 *name = g_strdup (p->property->name);
6868 if (p->property->get)
6869 *type = p->property->get->signature->ret;
6871 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6876 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6878 MonoClass *klass = mono_object_class (field);
6879 if (strcmp (klass->name, "FieldBuilder") == 0) {
6880 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6881 *name = mono_string_to_utf8 (fb->name);
6882 *type = fb->type->type;
6884 MonoReflectionField *f = (MonoReflectionField *)field;
6885 *name = g_strdup (f->field->name);
6886 *type = f->field->type;
6891 * Encode a value in a custom attribute stream of bytes.
6892 * The value to encode is either supplied as an object in argument val
6893 * (valuetypes are boxed), or as a pointer to the data in the
6895 * @type represents the type of the value
6896 * @buffer is the start of the buffer
6897 * @p the current position in the buffer
6898 * @buflen contains the size of the buffer and is used to return the new buffer size
6899 * if this needs to be realloced.
6900 * @retbuffer and @retp return the start and the position of the buffer
6903 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6905 MonoTypeEnum simple_type;
6907 if ((p-buffer) + 10 >= *buflen) {
6910 newbuf = g_realloc (buffer, *buflen);
6911 p = newbuf + (p-buffer);
6915 argval = ((char*)arg + sizeof (MonoObject));
6916 simple_type = type->type;
6918 switch (simple_type) {
6919 case MONO_TYPE_BOOLEAN:
6924 case MONO_TYPE_CHAR:
6927 swap_with_size (p, argval, 2, 1);
6933 swap_with_size (p, argval, 4, 1);
6939 swap_with_size (p, argval, 8, 1);
6942 case MONO_TYPE_VALUETYPE:
6943 if (type->data.klass->enumtype) {
6944 simple_type = type->data.klass->enum_basetype->type;
6947 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6950 case MONO_TYPE_STRING: {
6957 str = mono_string_to_utf8 ((MonoString*)arg);
6958 slen = strlen (str);
6959 if ((p-buffer) + 10 + slen >= *buflen) {
6963 newbuf = g_realloc (buffer, *buflen);
6964 p = newbuf + (p-buffer);
6967 mono_metadata_encode_value (slen, p, &p);
6968 memcpy (p, str, slen);
6973 case MONO_TYPE_CLASS: {
6981 k = mono_object_class (arg);
6982 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6983 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6984 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6986 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6987 slen = strlen (str);
6988 if ((p-buffer) + 10 + slen >= *buflen) {
6992 newbuf = g_realloc (buffer, *buflen);
6993 p = newbuf + (p-buffer);
6996 mono_metadata_encode_value (slen, p, &p);
6997 memcpy (p, str, slen);
7002 case MONO_TYPE_SZARRAY: {
7004 MonoClass *eclass, *arg_eclass;
7007 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7010 len = mono_array_length ((MonoArray*)arg);
7012 *p++ = (len >> 8) & 0xff;
7013 *p++ = (len >> 16) & 0xff;
7014 *p++ = (len >> 24) & 0xff;
7016 *retbuffer = buffer;
7017 eclass = type->data.klass;
7018 arg_eclass = mono_object_class (arg)->element_class;
7019 if (eclass->valuetype && arg_eclass->valuetype) {
7020 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7021 int elsize = mono_class_array_element_size (eclass);
7022 for (i = 0; i < len; ++i) {
7023 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7027 for (i = 0; i < len; ++i) {
7028 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7033 /* it may be a boxed value or a Type */
7034 case MONO_TYPE_OBJECT: {
7035 MonoClass *klass = mono_object_class (arg);
7039 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7042 } else if (klass->enumtype) {
7044 } else if (klass == mono_defaults.string_class) {
7045 simple_type = MONO_TYPE_STRING;
7048 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7049 *p++ = simple_type = klass->byval_arg.type;
7052 g_error ("unhandled type in custom attr");
7054 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7055 slen = strlen (str);
7056 if ((p-buffer) + 10 + slen >= *buflen) {
7060 newbuf = g_realloc (buffer, *buflen);
7061 p = newbuf + (p-buffer);
7064 mono_metadata_encode_value (slen, p, &p);
7065 memcpy (p, str, slen);
7068 simple_type = klass->enum_basetype->type;
7072 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7075 *retbuffer = buffer;
7079 * mono_reflection_get_custom_attrs_blob:
7080 * @ctor: custom attribute constructor
7081 * @ctorArgs: arguments o the constructor
7087 * Creates the blob of data that needs to be saved in the metadata and that represents
7088 * the custom attributed described by @ctor, @ctorArgs etc.
7089 * Returns: a Byte array representing the blob of data.
7092 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7095 MonoMethodSignature *sig;
7100 MONO_ARCH_SAVE_REGS;
7102 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7103 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7105 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7107 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7109 p = buffer = g_malloc (buflen);
7110 /* write the prolog */
7113 for (i = 0; i < sig->param_count; ++i) {
7114 arg = mono_array_get (ctorArgs, MonoObject*, i);
7115 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7119 i += mono_array_length (properties);
7121 i += mono_array_length (fields);
7123 *p++ = (i >> 8) & 0xff;
7126 for (i = 0; i < mono_array_length (properties); ++i) {
7131 prop = mono_array_get (properties, gpointer, i);
7132 get_prop_name_and_type (prop, &pname, &ptype);
7133 *p++ = 0x54; /* PROPERTY signature */
7135 /* Preallocate a large enough buffer */
7136 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7137 char *str = type_get_qualified_name (ptype, NULL);
7143 len += strlen (pname);
7145 if ((p-buffer) + 20 + len >= buflen) {
7149 newbuf = g_realloc (buffer, buflen);
7150 p = newbuf + (p-buffer);
7154 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7155 char *str = type_get_qualified_name (ptype, NULL);
7156 int slen = strlen (str);
7160 * This seems to be optional...
7163 mono_metadata_encode_value (slen, p, &p);
7164 memcpy (p, str, slen);
7168 mono_metadata_encode_value (ptype->type, p, &p);
7169 if (ptype->type == MONO_TYPE_SZARRAY)
7170 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7172 len = strlen (pname);
7173 mono_metadata_encode_value (len, p, &p);
7174 memcpy (p, pname, len);
7176 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7183 for (i = 0; i < mono_array_length (fields); ++i) {
7188 field = mono_array_get (fields, gpointer, i);
7189 get_field_name_and_type (field, &fname, &ftype);
7190 *p++ = 0x53; /* FIELD signature */
7191 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7192 char *str = type_get_qualified_name (ftype, NULL);
7193 int slen = strlen (str);
7194 if ((p-buffer) + 10 + slen >= buflen) {
7198 newbuf = g_realloc (buffer, buflen);
7199 p = newbuf + (p-buffer);
7204 * This seems to be optional...
7207 mono_metadata_encode_value (slen, p, &p);
7208 memcpy (p, str, slen);
7212 mono_metadata_encode_value (ftype->type, p, &p);
7213 if (ftype->type == MONO_TYPE_SZARRAY)
7214 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7216 len = strlen (fname);
7217 mono_metadata_encode_value (len, p, &p);
7218 memcpy (p, fname, len);
7220 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7225 g_assert (p - buffer <= buflen);
7226 buflen = p - buffer;
7227 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7228 p = mono_array_addr (result, char, 0);
7229 memcpy (p, buffer, buflen);
7231 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7237 * mono_reflection_setup_internal_class:
7238 * @tb: a TypeBuilder object
7240 * Creates a MonoClass that represents the TypeBuilder.
7241 * This is a trick that lets us simplify a lot of reflection code
7242 * (and will allow us to support Build and Run assemblies easier).
7245 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7247 MonoClass *klass, *parent;
7249 MONO_ARCH_SAVE_REGS;
7252 /* check so we can compile corlib correctly */
7253 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7254 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7255 parent = tb->parent->type->data.klass;
7257 parent = my_mono_class_from_mono_type (tb->parent->type);
7263 /* the type has already being created: it means we just have to change the parent */
7264 if (tb->type.type) {
7265 klass = mono_class_from_mono_type (tb->type.type);
7266 klass->parent = NULL;
7267 /* fool mono_class_setup_parent */
7268 g_free (klass->supertypes);
7269 klass->supertypes = NULL;
7270 mono_class_setup_parent (klass, parent);
7271 mono_class_setup_mono_type (klass);
7275 klass = g_new0 (MonoClass, 1);
7277 klass->image = &tb->module->dynamic_image->image;
7279 klass->inited = 1; /* we lie to the runtime */
7280 klass->name = mono_string_to_utf8 (tb->name);
7281 klass->name_space = mono_string_to_utf8 (tb->nspace);
7282 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7283 klass->flags = tb->attrs;
7285 klass->element_class = klass;
7286 klass->reflection_info = tb; /* need to pin. */
7288 /* Put into cache so mono_class_get () will find it */
7289 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7291 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7292 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7294 if (parent != NULL) {
7295 mono_class_setup_parent (klass, parent);
7296 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7297 const char *old_n = klass->name;
7298 /* trick to get relative numbering right when compiling corlib */
7299 klass->name = "BuildingObject";
7300 mono_class_setup_parent (klass, mono_defaults.object_class);
7301 klass->name = old_n;
7304 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7305 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7306 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7307 klass->instance_size = sizeof (MonoObject);
7308 klass->size_inited = 1;
7309 mono_class_setup_vtable (klass, NULL, 0);
7312 mono_class_setup_mono_type (klass);
7314 mono_class_setup_supertypes (klass);
7317 * FIXME: handle interfaces.
7320 tb->type.type = &klass->byval_arg;
7322 if (tb->nesting_type) {
7323 g_assert (tb->nesting_type->type);
7324 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7327 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7331 * mono_reflection_setup_generic_class:
7332 * @tb: a TypeBuilder object
7334 * Setup the generic class before adding the first generic parameter.
7337 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7341 MONO_ARCH_SAVE_REGS;
7343 klass = my_mono_class_from_mono_type (tb->type.type);
7344 if (tb->generic_container)
7347 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7348 tb->generic_container->klass = klass;
7350 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7351 tb->generic_container->context->container = tb->generic_container;
7355 * mono_reflection_create_generic_class:
7356 * @tb: a TypeBuilder object
7358 * Creates the generic class after all generic parameters have been added.
7361 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7366 MONO_ARCH_SAVE_REGS;
7368 klass = my_mono_class_from_mono_type (tb->type.type);
7370 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7372 if (klass->generic_container || (count == 0))
7375 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7377 klass->generic_container = tb->generic_container;
7379 klass->generic_container->type_argc = count;
7380 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7382 for (i = 0; i < count; i++) {
7383 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7384 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7385 g_assert (klass->generic_container->type_params [i].owner);
7390 * mono_reflection_create_internal_class:
7391 * @tb: a TypeBuilder object
7393 * Actually create the MonoClass that is associated with the TypeBuilder.
7396 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7400 MONO_ARCH_SAVE_REGS;
7402 klass = my_mono_class_from_mono_type (tb->type.type);
7404 if (klass->enumtype && klass->enum_basetype == NULL) {
7405 MonoReflectionFieldBuilder *fb;
7408 g_assert (tb->fields != NULL);
7409 g_assert (mono_array_length (tb->fields) >= 1);
7411 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7413 klass->enum_basetype = fb->type->type;
7414 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7415 if (!klass->element_class)
7416 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7419 * get the element_class from the current corlib.
7421 ec = default_class_from_mono_type (klass->enum_basetype);
7422 klass->instance_size = ec->instance_size;
7423 klass->size_inited = 1;
7425 * this is almost safe to do with enums and it's needed to be able
7426 * to create objects of the enum type (for use in SetConstant).
7428 /* FIXME: Does this mean enums can't have method overrides ? */
7429 mono_class_setup_vtable (klass, NULL, 0);
7433 static MonoMarshalSpec*
7434 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7435 MonoReflectionMarshal *minfo)
7437 MonoMarshalSpec *res;
7439 res = g_new0 (MonoMarshalSpec, 1);
7440 res->native = minfo->type;
7442 switch (minfo->type) {
7443 case MONO_NATIVE_LPARRAY:
7444 res->data.array_data.elem_type = minfo->eltype;
7445 res->data.array_data.param_num = 0; /* Not yet */
7446 res->data.array_data.num_elem = minfo->count;
7449 case MONO_NATIVE_BYVALTSTR:
7450 case MONO_NATIVE_BYVALARRAY:
7451 res->data.array_data.num_elem = minfo->count;
7454 case MONO_NATIVE_CUSTOM:
7455 if (minfo->marshaltyperef)
7456 res->data.custom_data.custom_name =
7457 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7459 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7469 MonoReflectionMarshal*
7470 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7471 MonoMarshalSpec *spec)
7473 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7474 MonoReflectionMarshal *minfo;
7477 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7478 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7479 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7480 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7483 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7484 minfo->type = spec->native;
7486 switch (minfo->type) {
7487 case MONO_NATIVE_LPARRAY:
7488 minfo->eltype = spec->data.array_data.elem_type;
7489 minfo->count = spec->data.array_data.num_elem;
7492 case MONO_NATIVE_BYVALTSTR:
7493 case MONO_NATIVE_BYVALARRAY:
7494 minfo->count = spec->data.array_data.num_elem;
7497 case MONO_NATIVE_CUSTOM:
7498 if (spec->data.custom_data.custom_name) {
7499 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7501 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7503 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7505 if (spec->data.custom_data.cookie)
7506 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7517 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7518 ReflectionMethodBuilder *rmb,
7519 MonoMethodSignature *sig)
7522 MonoMethodNormal *pm;
7523 MonoMarshalSpec **specs;
7524 MonoReflectionMethodAux *method_aux;
7527 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7528 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7529 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7531 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7533 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7535 pm = (MonoMethodNormal*)m;
7538 m->flags = rmb->attrs;
7539 m->iflags = rmb->iattrs;
7540 m->name = mono_string_to_utf8 (rmb->name);
7544 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7546 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7547 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7550 m->signature->pinvoke = 1;
7551 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7552 m->signature->pinvoke = 1;
7554 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7556 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7557 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7559 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7561 if (klass->image->dynamic)
7562 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7565 } else if (!m->klass->dummy &&
7566 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7567 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7568 MonoMethodHeader *header;
7570 gint32 max_stack, i;
7571 gint32 num_locals = 0;
7572 gint32 num_clauses = 0;
7576 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7577 code_size = rmb->ilgen->code_len;
7578 max_stack = rmb->ilgen->max_stack;
7579 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7580 if (rmb->ilgen->ex_handlers)
7581 num_clauses = method_count_clauses (rmb->ilgen);
7584 code = mono_array_addr (rmb->code, guint8, 0);
7585 code_size = mono_array_length (rmb->code);
7586 /* we probably need to run a verifier on the code... */
7596 header = g_malloc0 (sizeof (MonoMethodHeader) +
7597 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7598 header->code_size = code_size;
7599 header->code = g_malloc (code_size);
7600 memcpy ((char*)header->code, code, code_size);
7601 header->max_stack = max_stack;
7602 header->init_locals = rmb->init_locals;
7603 header->num_locals = num_locals;
7605 for (i = 0; i < num_locals; ++i) {
7606 MonoReflectionLocalBuilder *lb =
7607 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7609 header->locals [i] = g_new0 (MonoType, 1);
7610 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7613 header->num_clauses = num_clauses;
7615 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7616 rmb->ilgen, num_clauses);
7619 pm->header = header;
7622 if (rmb->generic_params) {
7623 int count = mono_array_length (rmb->generic_params);
7624 MonoGenericContainer *container;
7626 pm->generic_container = container = rmb->generic_container;
7627 container->type_argc = count;
7628 container->type_params = g_new0 (MonoGenericParam, count);
7630 for (i = 0; i < count; i++) {
7631 MonoReflectionGenericParam *gp =
7632 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7634 container->type_params [i] = *gp->type.type->data.generic_param;
7639 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7642 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7644 for (i = 0; i < rmb->nrefs; ++i)
7645 mw->data = g_list_append (mw->data, rmb->refs [i]);
7650 /* Parameter info */
7653 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7654 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7655 for (i = 0; i <= m->signature->param_count; ++i) {
7656 MonoReflectionParamBuilder *pb;
7657 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7659 m->signature->params [i - 1]->attrs = pb->attrs;
7661 if (pb->def_value) {
7662 MonoDynamicImage *assembly;
7663 guint32 idx, def_type, len;
7667 if (!method_aux->param_defaults)
7668 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7669 assembly = (MonoDynamicImage*)klass->image;
7670 idx = encode_constant (assembly, pb->def_value, &def_type);
7671 /* Copy the data from the blob since it might get realloc-ed */
7672 p = assembly->blob.data + idx;
7673 len = mono_metadata_decode_blob_size (p, &p2);
7675 method_aux->param_defaults [i] = g_malloc (len);
7676 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7680 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7682 if (!method_aux->param_cattr)
7683 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7684 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7690 /* Parameter marshalling */
7693 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7694 MonoReflectionParamBuilder *pb;
7695 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7696 if (pb->marshal_info) {
7698 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7699 specs [pb->position] =
7700 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7704 if (specs != NULL) {
7706 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7707 method_aux->param_marshall = specs;
7710 if (klass->image->dynamic && method_aux)
7711 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7717 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7719 ReflectionMethodBuilder rmb;
7720 MonoMethodSignature *sig;
7722 sig = ctor_builder_to_signature (mb);
7724 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7726 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7727 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7729 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7730 /* ilgen is no longer needed */
7738 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7740 ReflectionMethodBuilder rmb;
7741 MonoMethodSignature *sig;
7743 sig = method_builder_to_signature (mb);
7745 reflection_methodbuilder_from_method_builder (&rmb, mb);
7747 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7748 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7750 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7751 /* ilgen is no longer needed */
7757 static MonoClassField*
7758 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7760 MonoClassField *field;
7767 field = g_new0 (MonoClassField, 1);
7769 field->name = mono_string_to_utf8 (fb->name);
7771 /* FIXME: handle type modifiers */
7772 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7773 field->type->attrs = fb->attrs;
7775 field->type = fb->type->type;
7777 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7778 field->data = mono_array_addr (fb->rva_data, char, 0);
7779 if (fb->offset != -1)
7780 field->offset = fb->offset;
7781 field->parent = klass;
7783 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7785 if (fb->def_value) {
7786 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7787 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7788 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7789 /* Copy the data from the blob since it might get realloc-ed */
7790 p = assembly->blob.data + idx;
7791 len = mono_metadata_decode_blob_size (p, &p2);
7793 field->data = g_malloc (len);
7794 memcpy ((gpointer)field->data, p, len);
7801 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7804 MonoClass *klass, *gklass;
7805 MonoReflectionTypeBuilder *tb = NULL;
7806 MonoGenericInst *ginst, *cached;
7811 klass = mono_class_from_mono_type (type->type);
7812 if (!klass->generic_container && !klass->generic_inst &&
7813 !(klass->nested_in && klass->nested_in->generic_container))
7816 mono_loader_lock ();
7818 domain = mono_object_domain (type);
7820 ginst = g_new0 (MonoGenericInst, 1);
7822 ginst->type_argc = type_argc;
7823 ginst->type_argv = types;
7825 for (i = 0; i < ginst->type_argc; ++i) {
7826 if (!ginst->is_open)
7827 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7830 ginst->generic_type = &klass->byval_arg;
7832 if (klass->generic_inst) {
7833 MonoGenericInst *kginst = klass->generic_inst;
7834 MonoGenericInst *oginst = ginst;
7836 oginst->context = g_new0 (MonoGenericContext, 1);
7837 oginst->context->ginst = oginst;
7839 ginst = g_new0 (MonoGenericInst, 1);
7841 ginst->type_argc = kginst->type_argc;
7842 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7844 for (i = 0; i < ginst->type_argc; i++) {
7845 MonoType *t = kginst->type_argv [i];
7847 t = mono_class_inflate_generic_type (t, oginst->context);
7849 if (!ginst->is_open)
7850 ginst->is_open = mono_class_is_open_constructed_type (t);
7852 ginst->type_argv [i] = t;
7855 ginst->generic_type = kginst->generic_type;
7858 geninst = g_new0 (MonoType, 1);
7859 geninst->type = MONO_TYPE_GENERICINST;
7861 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7864 mono_loader_unlock ();
7865 geninst->data.generic_inst = cached;
7869 gklass = mono_class_from_mono_type (ginst->generic_type);
7870 g_assert ((ginst->container = gklass->generic_container) != NULL);
7872 geninst->data.generic_inst = ginst;
7874 ginst->parent = parent;
7876 ginst->context = g_new0 (MonoGenericContext, 1);
7877 ginst->context->ginst = ginst;
7879 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7880 tb = (MonoReflectionTypeBuilder *) type;
7882 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7883 ginst->is_dynamic = TRUE;
7884 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7885 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7886 MonoReflectionType *rgt = rgi->generic_type;
7888 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7889 tb = (MonoReflectionTypeBuilder *) rgt;
7891 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7892 ginst->is_dynamic = TRUE;
7894 icount = klass->interface_count;
7897 ginst->ifaces = g_new0 (MonoType *, icount);
7898 ginst->count_ifaces = icount;
7900 for (i = 0; i < icount; i++) {
7901 MonoReflectionType *itype;
7904 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7906 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7907 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7908 if (!ginst->ifaces [i])
7909 ginst->ifaces [i] = itype->type;
7912 mono_class_create_generic (ginst);
7913 mono_class_create_generic_2 (ginst);
7915 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7917 mono_loader_unlock ();
7923 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7925 MonoClass *klass, *pklass = NULL;
7926 MonoReflectionType *parent = NULL;
7927 MonoType *the_parent = NULL, *geninst;
7928 MonoReflectionTypeBuilder *tb = NULL;
7929 MonoGenericInst *ginst;
7932 domain = mono_object_domain (type);
7933 klass = mono_class_from_mono_type (type->type);
7935 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7936 tb = (MonoReflectionTypeBuilder *) type;
7939 parent = tb->parent;
7940 pklass = mono_class_from_mono_type (parent->type);
7943 pklass = klass->parent;
7945 parent = mono_type_get_object (domain, &pklass->byval_arg);
7946 else if (klass->generic_inst && klass->generic_inst->parent) {
7947 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7948 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7952 if (pklass && pklass->generic_inst)
7953 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7955 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
7959 ginst = geninst->data.generic_inst;
7964 MonoReflectionMethod*
7965 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7967 MonoMethod *method, *inflated;
7968 MonoReflectionMethodBuilder *mb = NULL;
7969 MonoGenericContainer *container;
7970 MonoGenericMethod *gmethod;
7971 MonoGenericContext *context;
7974 MONO_ARCH_SAVE_REGS;
7975 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7976 MonoReflectionTypeBuilder *tb;
7979 mb = (MonoReflectionMethodBuilder *) rmethod;
7980 tb = (MonoReflectionTypeBuilder *) mb->type;
7981 klass = mono_class_from_mono_type (tb->type.type);
7983 method = methodbuilder_to_mono_method (klass, mb);
7985 method = rmethod->method;
7988 count = method->signature->generic_param_count;
7989 if (count != mono_array_length (types))
7992 container = ((MonoMethodNormal*) method)->generic_container;
7993 g_assert (container);
7995 if (!container->method_hash)
7996 container->method_hash = g_hash_table_new (
7997 mono_metadata_generic_method_hash, mono_metadata_generic_method_equal);
7999 gmethod = g_new0 (MonoGenericMethod, 1);
8000 gmethod->mtype_argc = count;
8001 gmethod->mtype_argv = g_new0 (MonoType *, count);
8002 for (i = 0; i < count; i++) {
8003 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8004 gmethod->mtype_argv [i] = garg->type;
8007 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8009 g_free (gmethod->mtype_argv);
8012 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8015 gmethod->reflection_info = rmethod;
8017 context = g_new0 (MonoGenericContext, 1);
8018 context->ginst = method->klass->generic_inst;
8019 context->gmethod = gmethod;
8021 inflated = mono_class_inflate_generic_method (method, context, NULL);
8022 g_hash_table_insert (container->method_hash, gmethod, inflated);
8024 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8028 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
8030 MonoGenericMethod *gmethod;
8031 MonoGenericInst *ginst;
8032 MonoGenericContext *context;
8035 ginst = type->type.type->data.generic_inst;
8037 gmethod = g_new0 (MonoGenericMethod, 1);
8038 gmethod->reflection_info = obj;
8040 gmethod->mtype_argc = method->signature->generic_param_count;
8041 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
8043 for (i = 0; i < gmethod->mtype_argc; i++) {
8044 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8045 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8047 g_assert (gparam->pklass);
8048 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8051 context = g_new0 (MonoGenericContext, 1);
8052 context->ginst = ginst;
8053 context->gmethod = gmethod;
8055 return mono_class_inflate_generic_method (method, context, ginst->klass);
8059 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8064 klass = mono_class_from_mono_type (type->type.type);
8066 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8067 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8068 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8069 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8070 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8071 method = ((MonoReflectionMethod *) obj)->method;
8073 method = NULL; /* prevent compiler warning */
8074 g_assert_not_reached ();
8077 return inflate_mono_method (type, method, obj);
8081 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8082 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8084 MonoGenericInst *ginst;
8085 MonoDynamicGenericInst *dginst;
8086 MonoClass *klass, *gklass, *pklass;
8089 MONO_ARCH_SAVE_REGS;
8091 klass = mono_class_from_mono_type (type->type.type);
8092 ginst = type->type.type->data.generic_inst;
8094 if (ginst->initialized)
8097 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8099 gklass = mono_class_from_mono_type (ginst->generic_type);
8100 mono_class_init (gklass);
8103 pklass = mono_class_from_mono_type (ginst->parent);
8105 pklass = gklass->parent;
8107 mono_class_setup_parent (klass, pklass);
8109 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8110 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8111 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8112 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8113 dginst->count_events = events ? mono_array_length (events) : 0;
8115 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8116 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8117 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8118 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8119 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8121 for (i = 0; i < dginst->count_methods; i++) {
8122 MonoObject *obj = mono_array_get (methods, gpointer, i);
8124 dginst->methods [i] = inflate_method (type, obj);
8127 for (i = 0; i < dginst->count_ctors; i++) {
8128 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8130 dginst->ctors [i] = inflate_method (type, obj);
8133 for (i = 0; i < dginst->count_fields; i++) {
8134 MonoObject *obj = mono_array_get (fields, gpointer, i);
8135 MonoClassField *field;
8136 MonoInflatedField *ifield;
8138 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8139 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8140 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8141 field = ((MonoReflectionField *) obj)->field;
8143 field = NULL; /* prevent compiler warning */
8144 g_assert_not_reached ();
8147 ifield = g_new0 (MonoInflatedField, 1);
8148 ifield->generic_type = field->type;
8149 ifield->reflection_info = obj;
8151 dginst->fields [i] = *field;
8152 dginst->fields [i].generic_info = ifield;
8153 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8156 for (i = 0; i < dginst->count_properties; i++) {
8157 MonoObject *obj = mono_array_get (properties, gpointer, i);
8158 MonoProperty *property = &dginst->properties [i];
8160 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8161 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8163 property->parent = klass;
8164 property->attrs = pb->attrs;
8165 property->name = mono_string_to_utf8 (pb->name);
8167 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8169 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8170 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8171 *property = *((MonoReflectionProperty *) obj)->property;
8174 property->get = inflate_mono_method (type, property->get, NULL);
8176 property->set = inflate_mono_method (type, property->set, NULL);
8178 g_assert_not_reached ();
8181 for (i = 0; i < dginst->count_events; i++) {
8182 MonoObject *obj = mono_array_get (events, gpointer, i);
8183 MonoEvent *event = &dginst->events [i];
8185 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8186 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8188 event->parent = klass;
8189 event->attrs = eb->attrs;
8190 event->name = mono_string_to_utf8 (eb->name);
8192 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8193 if (eb->remove_method)
8194 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8195 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8196 *event = *((MonoReflectionEvent *) obj)->event;
8199 event->add = inflate_mono_method (type, event->add, NULL);
8201 event->remove = inflate_mono_method (type, event->remove, NULL);
8203 g_assert_not_reached ();
8206 ginst->initialized = TRUE;
8210 ensure_runtime_vtable (MonoClass *klass)
8212 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8213 int i, num, j, onum;
8214 MonoMethod **overrides;
8216 if (!tb || klass->wastypebuilder)
8219 ensure_runtime_vtable (klass->parent);
8221 num = tb->ctors? mono_array_length (tb->ctors): 0;
8222 num += tb->num_methods;
8223 klass->method.count = num;
8224 klass->methods = g_new (MonoMethod*, num);
8225 num = tb->ctors? mono_array_length (tb->ctors): 0;
8226 for (i = 0; i < num; ++i)
8227 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8228 num = tb->num_methods;
8230 for (i = 0; i < num; ++i)
8231 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8233 if (tb->interfaces) {
8234 klass->interface_count = mono_array_length (tb->interfaces);
8235 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8236 for (i = 0; i < klass->interface_count; ++i) {
8237 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8238 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8242 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8243 for (i = 0; i < klass->method.count; ++i)
8244 klass->methods [i]->slot = i;
8249 for (i = 0; i < tb->num_methods; ++i) {
8250 MonoReflectionMethodBuilder *mb =
8251 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8252 if (mb->override_method)
8257 overrides = g_new0 (MonoMethod*, onum * 2);
8261 for (i = 0; i < tb->num_methods; ++i) {
8262 MonoReflectionMethodBuilder *mb =
8263 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8264 if (mb->override_method) {
8265 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8266 overrides [onum * 2] =
8267 mb->override_method->method;
8268 overrides [onum * 2 + 1] =
8271 g_assert (mb->mhandle);
8278 mono_class_setup_vtable (klass, overrides, onum);
8283 typebuilder_setup_fields (MonoClass *klass)
8285 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8286 MonoReflectionFieldBuilder *fb;
8287 MonoClassField *field;
8292 klass->field.count = tb->num_fields;
8293 klass->field.first = 0;
8294 klass->field.last = klass->field.count;
8296 if (!klass->field.count)
8299 klass->fields = g_new0 (MonoClassField, klass->field.count);
8301 for (i = 0; i < klass->field.count; ++i) {
8302 fb = mono_array_get (tb->fields, gpointer, i);
8303 field = &klass->fields [i];
8304 field->name = mono_string_to_utf8 (fb->name);
8306 /* FIXME: handle type modifiers */
8307 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8308 field->type->attrs = fb->attrs;
8310 field->type = fb->type->type;
8312 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8313 field->data = mono_array_addr (fb->rva_data, char, 0);
8314 if (fb->offset != -1)
8315 field->offset = fb->offset;
8316 field->parent = klass;
8318 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8320 if (fb->def_value) {
8321 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8322 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8323 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8324 /* Copy the data from the blob since it might get realloc-ed */
8325 p = assembly->blob.data + idx;
8326 len = mono_metadata_decode_blob_size (p, &p2);
8328 field->data = g_malloc (len);
8329 memcpy ((gpointer)field->data, p, len);
8332 mono_class_layout_fields (klass);
8336 typebuilder_setup_properties (MonoClass *klass)
8338 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8339 MonoReflectionPropertyBuilder *pb;
8342 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8343 klass->property.first = 0;
8344 klass->property.last = klass->property.count;
8346 klass->properties = g_new0 (MonoProperty, klass->property.count);
8347 for (i = 0; i < klass->property.count; ++i) {
8348 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8349 klass->properties [i].parent = klass;
8350 klass->properties [i].attrs = pb->attrs;
8351 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8353 klass->properties [i].get = pb->get_method->mhandle;
8355 klass->properties [i].set = pb->set_method->mhandle;
8359 MonoReflectionEvent *
8360 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8362 MonoEvent *event = g_new0 (MonoEvent, 1);
8366 klass = my_mono_class_from_mono_type (tb->type.type);
8368 event->parent = klass;
8369 event->attrs = eb->attrs;
8370 event->name = mono_string_to_utf8 (eb->name);
8372 event->add = eb->add_method->mhandle;
8373 if (eb->remove_method)
8374 event->remove = eb->remove_method->mhandle;
8375 if (eb->raise_method)
8376 event->raise = eb->raise_method->mhandle;
8378 if (eb->other_methods) {
8379 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8380 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8381 MonoReflectionMethodBuilder *mb =
8382 mono_array_get (eb->other_methods,
8383 MonoReflectionMethodBuilder*, j);
8384 event->other [j] = mb->mhandle;
8388 return mono_event_get_object (mono_object_domain (tb), klass, event);
8392 typebuilder_setup_events (MonoClass *klass)
8394 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8395 MonoReflectionEventBuilder *eb;
8398 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8399 klass->event.first = 0;
8400 klass->event.last = klass->event.count;
8402 klass->events = g_new0 (MonoEvent, klass->event.count);
8403 for (i = 0; i < klass->event.count; ++i) {
8404 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8405 klass->events [i].parent = klass;
8406 klass->events [i].attrs = eb->attrs;
8407 klass->events [i].name = mono_string_to_utf8 (eb->name);
8409 klass->events [i].add = eb->add_method->mhandle;
8410 if (eb->remove_method)
8411 klass->events [i].remove = eb->remove_method->mhandle;
8412 if (eb->raise_method)
8413 klass->events [i].raise = eb->raise_method->mhandle;
8415 if (eb->other_methods) {
8416 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8417 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8418 MonoReflectionMethodBuilder *mb =
8419 mono_array_get (eb->other_methods,
8420 MonoReflectionMethodBuilder*, j);
8421 klass->events [i].other [j] = mb->mhandle;
8428 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8431 MonoReflectionType* res;
8434 MONO_ARCH_SAVE_REGS;
8436 klass = my_mono_class_from_mono_type (tb->type.type);
8438 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8441 * Fields to set in klass:
8442 * the various flags: delegate/unicode/contextbound etc.
8444 klass->flags = tb->attrs;
8446 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8447 /* No need to fully construct the type */
8448 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8450 /* enums are done right away */
8451 if (!klass->enumtype)
8452 ensure_runtime_vtable (klass);
8455 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8456 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8457 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8461 /* fields and object layout */
8462 if (klass->parent) {
8463 if (!klass->parent->size_inited)
8464 mono_class_init (klass->parent);
8465 klass->instance_size += klass->parent->instance_size;
8466 klass->class_size += klass->parent->class_size;
8467 klass->min_align = klass->parent->min_align;
8469 klass->instance_size = sizeof (MonoObject);
8470 klass->min_align = 1;
8473 /* FIXME: handle packing_size and instance_size */
8474 typebuilder_setup_fields (klass);
8476 typebuilder_setup_properties (klass);
8478 typebuilder_setup_events (klass);
8480 klass->wastypebuilder = TRUE;
8482 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8483 g_assert (res != (MonoReflectionType*)tb);
8488 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8490 MonoGenericParam *param;
8493 MONO_ARCH_SAVE_REGS;
8495 param = g_new0 (MonoGenericParam, 1);
8497 if (gparam->mbuilder) {
8498 if (!gparam->mbuilder->generic_container)
8499 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8500 param->owner = gparam->mbuilder->generic_container;
8501 } else if (gparam->tbuilder) {
8502 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8503 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8508 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8509 if (gparam->index >= count)
8512 container = nesting->generic_container;
8513 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8516 g_assert (container);
8517 param->owner = container;
8520 param->method = NULL;
8521 param->name = mono_string_to_utf8 (gparam->name);
8522 param->num = gparam->index;
8524 image = &gparam->tbuilder->module->dynamic_image->image;
8525 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8527 param->pklass->reflection_info = gparam;
8529 gparam->type.type = g_new0 (MonoType, 1);
8530 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8531 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8532 gparam->type.type->data.generic_param = param;
8536 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8538 MonoDynamicImage *assembly = sig->module->dynamic_image;
8539 guint32 na = mono_array_length (sig->arguments);
8544 MONO_ARCH_SAVE_REGS;
8546 p = buf = g_malloc (10 + na * 10);
8548 mono_metadata_encode_value (0x07, p, &p);
8549 mono_metadata_encode_value (na, p, &p);
8550 for (i = 0; i < na; ++i) {
8551 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8552 encode_reflection_type (assembly, type, p, &p);
8556 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8557 p = mono_array_addr (result, char, 0);
8558 memcpy (p, buf, buflen);
8565 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8567 MonoDynamicImage *assembly = sig->module->dynamic_image;
8568 guint32 na = mono_array_length (sig->arguments);
8573 MONO_ARCH_SAVE_REGS;
8575 p = buf = g_malloc (10 + na * 10);
8577 mono_metadata_encode_value (0x06, p, &p);
8578 for (i = 0; i < na; ++i) {
8579 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8580 encode_reflection_type (assembly, type, p, &p);
8584 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8585 p = mono_array_addr (result, char, 0);
8586 memcpy (p, buf, buflen);
8593 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8595 ReflectionMethodBuilder rmb;
8596 MonoMethodSignature *sig;
8599 sig = dynamic_method_to_signature (mb);
8601 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8604 * Resolve references.
8606 rmb.nrefs = mb->nrefs;
8607 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8608 for (i = 0; i < mb->nrefs; ++i) {
8609 gpointer ref = resolve_object (mb->module->image,
8610 mono_array_get (mb->refs, MonoObject*, i));
8613 mono_raise_exception (mono_get_exception_type_load (NULL));
8620 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8624 /* ilgen is no longer needed */
8629 * mono_reflection_lookup_dynamic_token:
8631 * Finish the Builder object pointed to by TOKEN and return the corresponding
8632 * runtime structure.
8635 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8637 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8640 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8643 return resolve_object (image, obj);
8647 resolve_object (MonoImage *image, MonoObject *obj)
8649 gpointer result = NULL;
8651 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8652 result = mono_string_intern ((MonoString*)obj);
8654 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8655 MonoReflectionType *tb = (MonoReflectionType*)obj;
8656 result = mono_class_from_mono_type (tb->type);
8658 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8659 result = ((MonoReflectionMethod*)obj)->method;
8661 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8662 result = ((MonoReflectionMethod*)obj)->method;
8664 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8665 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8666 result = mb->mhandle;
8668 /* Type is not yet created */
8669 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8671 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8674 * Hopefully this has been filled in by calling CreateType() on the
8678 * TODO: This won't work if the application finishes another
8679 * TypeBuilder instance instead of this one.
8681 result = mb->mhandle;
8683 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8684 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8686 result = cb->mhandle;
8688 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8690 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8691 result = cb->mhandle;
8693 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8694 result = ((MonoReflectionField*)obj)->field;
8696 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8697 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8698 result = fb->handle;
8701 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8703 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8704 result = fb->handle;
8706 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8707 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8710 klass = tb->type.type->data.klass;
8711 if (klass->wastypebuilder) {
8712 /* Already created */
8716 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8717 result = tb->type.type->data.klass;
8720 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8721 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8722 MonoMethodSignature *sig;
8725 if (helper->arguments)
8726 nargs = mono_array_length (helper->arguments);
8730 sig = mono_metadata_signature_alloc (image, nargs);
8731 sig->explicit_this = helper->call_conv & 64;
8732 sig->hasthis = helper->call_conv & 32;
8734 if (helper->call_conv == 0) /* unmanaged */
8735 sig->call_convention = helper->unmanaged_call_conv - 1;
8737 if (helper->call_conv & 0x02)
8738 sig->call_convention = MONO_CALL_VARARG;
8740 sig->call_convention = MONO_CALL_DEFAULT;
8742 sig->param_count = nargs;
8743 /* TODO: Copy type ? */
8744 sig->ret = helper->return_type->type;
8745 for (i = 0; i < nargs; ++i) {
8746 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8747 sig->params [i] = rt->type;
8752 g_print (obj->vtable->klass->name);
8753 g_assert_not_reached ();