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;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
160 alloc_table (MonoDynamicTable *table, guint nrows)
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows) {
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
169 table->alloc_rows *= 2;
173 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
175 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
180 make_room_in_stream (MonoDynamicStream *stream, int size)
182 while (stream->alloc_size <= size) {
183 if (stream->alloc_size < 4096)
184 stream->alloc_size = 4096;
186 stream->alloc_size *= 2;
189 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
191 stream->data = ALLOC_ATOMIC (stream->alloc_size);
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
199 gpointer oldkey, oldval;
201 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202 return GPOINTER_TO_UINT (oldval);
204 len = strlen (str) + 1;
206 if (idx + len > sh->alloc_size)
207 make_room_in_stream (sh, idx + len);
210 * We strdup the string even if we already copy them in sh->data
211 * so that the string pointers in the hash remain valid even if
212 * we need to realloc sh->data. We may want to avoid that later.
214 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215 memcpy (sh->data + idx, str, len);
221 string_heap_init (MonoDynamicStream *sh)
224 sh->alloc_size = 4096;
225 sh->data = ALLOC_ATOMIC (4096);
226 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227 string_heap_insert (sh, "");
230 #if 0 /* never used */
232 string_heap_free (MonoDynamicStream *sh)
234 FREE_ATOMIC (sh->data);
235 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236 g_hash_table_destroy (sh->hash);
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memcpy (stream->data + stream->index, data, len);
248 stream->index += len;
250 * align index? Not without adding an additional param that controls it since
251 * we may store a blob value in pieces.
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
260 if (stream->alloc_size < stream->index + len)
261 make_room_in_stream (stream, stream->index + len);
262 memset (stream->data + stream->index, 0, len);
264 stream->index += len;
269 stream_data_align (MonoDynamicStream *stream)
272 guint32 count = stream->index % 4;
274 /* we assume the stream data will be aligned */
276 mono_image_add_stream_data (stream, buf, 4 - count);
280 mono_blob_entry_hash (const char* str)
284 len = mono_metadata_decode_blob_size (str, &str);
288 for (str += 1; str < end; str++)
289 h = (h << 5) - h + *str;
297 mono_blob_entry_equal (const char *str1, const char *str2) {
301 len = mono_metadata_decode_blob_size (str1, &end1);
302 len2 = mono_metadata_decode_blob_size (str2, &end2);
305 return memcmp (end1, end2, len) == 0;
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
313 gpointer oldkey, oldval;
315 copy = ALLOC_ATOMIC (s1+s2);
316 memcpy (copy, b1, s1);
317 memcpy (copy + s1, b2, s2);
318 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
320 idx = GPOINTER_TO_UINT (oldval);
322 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323 mono_image_add_stream_data (&assembly->blob, b2, s2);
324 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
330 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331 * dest may be misaligned.
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
338 for (elem = 0; elem < nelem; ++elem) {
364 g_assert_not_reached ();
370 memcpy (dest, val, len * nelem);
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
379 guint32 idx = 0, len;
381 len = str->length * 2;
382 mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
385 char *swapped = g_malloc (2 * mono_string_length (str));
386 const char *p = (const char*)mono_string_chars (str);
388 swap_with_size (swapped, p, 2, mono_string_length (str));
389 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
393 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
398 /* modified version needed to handle building corlib */
400 my_mono_class_from_mono_type (MonoType *type) {
401 switch (type->type) {
402 case MONO_TYPE_ARRAY:
404 case MONO_TYPE_SZARRAY:
405 case MONO_TYPE_GENERICINST:
406 return mono_class_from_mono_type (type);
409 g_assert (type->data.generic_param->pklass);
410 return type->data.generic_param->pklass;
412 /* should be always valid when we reach this case... */
413 return type->data.klass;
418 default_class_from_mono_type (MonoType *type)
420 switch (type->type) {
421 case MONO_TYPE_OBJECT:
422 return mono_defaults.object_class;
424 return mono_defaults.void_class;
425 case MONO_TYPE_BOOLEAN:
426 return mono_defaults.boolean_class;
428 return mono_defaults.char_class;
430 return mono_defaults.sbyte_class;
432 return mono_defaults.byte_class;
434 return mono_defaults.int16_class;
436 return mono_defaults.uint16_class;
438 return mono_defaults.int32_class;
440 return mono_defaults.uint32_class;
442 return mono_defaults.int_class;
444 return mono_defaults.uint_class;
446 return mono_defaults.int64_class;
448 return mono_defaults.uint64_class;
450 return mono_defaults.single_class;
452 return mono_defaults.double_class;
453 case MONO_TYPE_STRING:
454 return mono_defaults.string_class;
456 g_warning ("implement me 0x%02x\n", type->type);
457 g_assert_not_reached ();
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
469 g_assert_not_reached ();
473 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474 encode_type (assembly, ginst->generic_type, p, &p);
475 mono_metadata_encode_value (ginst->type_argc, p, &p);
476 for (i = 0; i < ginst->type_argc; ++i)
477 encode_type (assembly, ginst->type_argv [i], p, &p);
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
486 g_assert_not_reached ();
491 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
495 case MONO_TYPE_BOOLEAN:
509 case MONO_TYPE_STRING:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_TYPEDBYREF:
512 mono_metadata_encode_value (type->type, p, &p);
515 mono_metadata_encode_value (type->type, p, &p);
516 encode_type (assembly, type->data.type, p, &p);
518 case MONO_TYPE_SZARRAY:
519 mono_metadata_encode_value (type->type, p, &p);
520 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
522 case MONO_TYPE_VALUETYPE:
523 case MONO_TYPE_CLASS: {
524 MonoClass *k = mono_class_from_mono_type (type);
525 mono_metadata_encode_value (type->type, p, &p);
527 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528 * otherwise two typerefs could point to the same type, leading to
529 * verification errors.
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
534 case MONO_TYPE_ARRAY:
535 mono_metadata_encode_value (type->type, p, &p);
536 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537 mono_metadata_encode_value (type->data.array->rank, p, &p);
538 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539 mono_metadata_encode_value (0, p, &p);
541 case MONO_TYPE_GENERICINST:
542 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
546 mono_metadata_encode_value (type->type, p, &p);
547 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
550 g_error ("need to encode type %x", type->type);
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
559 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
563 encode_type (assembly, type->type, p, endbuf);
567 g_assert_not_reached ();
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
577 for (i = 0; i < mono_array_length (modreq); ++i) {
578 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_REQD;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
585 for (i = 0; i < mono_array_length (modopt); ++i) {
586 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587 *p = MONO_TYPE_CMOD_OPT;
589 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
602 g_assert_not_reached ();
605 size += 1 + type_get_signature_size (ginst->generic_type);
607 for (i = 0; i < ginst->type_argc; ++i)
608 size += type_get_signature_size (ginst->type_argv [i]);
614 type_get_signature_size (MonoType *type)
619 g_assert_not_reached ();
627 case MONO_TYPE_BOOLEAN:
641 case MONO_TYPE_STRING:
642 case MONO_TYPE_OBJECT:
643 case MONO_TYPE_TYPEDBYREF:
646 return size + 1 + type_get_signature_size (type->data.type);
647 case MONO_TYPE_SZARRAY:
648 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS:
652 case MONO_TYPE_ARRAY:
653 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654 case MONO_TYPE_GENERICINST:
655 return size + generic_inst_get_signature_size (type->data.generic_inst);
660 g_error ("need to encode type %x", type->type);
666 method_get_signature_size (MonoMethodSignature *sig)
671 size = type_get_signature_size (sig->ret);
672 for (i = 0; i < sig->param_count; i++)
673 size += type_get_signature_size (sig->params [i]);
675 if (sig->generic_param_count)
677 if (sig->sentinelpos >= 0)
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
689 guint32 nparams = sig->param_count;
690 guint32 size = 11 + method_get_signature_size (sig);
698 p = buf = g_malloc (size);
700 * FIXME: vararg, explicit_this, differenc call_conv values...
702 *p = sig->call_convention;
704 *p |= 0x20; /* hasthis */
705 if (sig->generic_param_count)
706 *p |= 0x10; /* generic */
708 if (sig->generic_param_count)
709 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710 mono_metadata_encode_value (nparams, p, &p);
711 encode_type (assembly, sig->ret, p, &p);
712 for (i = 0; i < nparams; ++i) {
713 if (i == sig->sentinelpos)
714 *p++ = MONO_TYPE_SENTINEL;
715 encode_type (assembly, sig->params [i], p, &p);
718 g_assert (p - buf < size);
719 mono_metadata_encode_value (p-buf, b, &b);
720 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
729 * FIXME: reuse code from method_encode_signature().
734 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
735 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737 guint32 size = 21 + nparams * 20 + notypes * 20;
742 p = buf = g_malloc (size);
743 /* LAMESPEC: all the call conv spec is foobared */
744 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745 if (mb->call_conv & 2)
746 *p |= 0x5; /* vararg */
747 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748 *p |= 0x20; /* hasthis */
750 *p |= 0x10; /* generic */
753 mono_metadata_encode_value (ngparams, p, &p);
754 mono_metadata_encode_value (nparams + notypes, p, &p);
755 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756 encode_reflection_type (assembly, mb->rtype, p, &p);
757 for (i = 0; i < nparams; ++i) {
758 MonoArray *modreq = NULL;
759 MonoArray *modopt = NULL;
760 MonoReflectionType *pt;
762 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
771 *p++ = MONO_TYPE_SENTINEL;
772 for (i = 0; i < notypes; ++i) {
773 MonoReflectionType *pt;
775 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776 encode_reflection_type (assembly, pt, p, &p);
780 g_assert (p - buf < size);
781 mono_metadata_encode_value (p-buf, b, &b);
782 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
790 MonoDynamicTable *table;
793 guint32 idx, sig_idx, size;
794 guint nl = mono_array_length (ilgen->locals);
801 p = buf = g_malloc (size);
802 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803 idx = table->next_idx ++;
805 alloc_table (table, table->rows);
806 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
808 mono_metadata_encode_value (0x07, p, &p);
809 mono_metadata_encode_value (nl, p, &p);
810 for (i = 0; i < nl; ++i) {
811 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
814 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
816 encode_reflection_type (assembly, lb->type, p, &p);
818 g_assert (p - buf < size);
819 mono_metadata_encode_value (p-buf, b, &b);
820 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
823 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
829 method_count_clauses (MonoReflectionILGen *ilgen)
831 guint32 num_clauses = 0;
834 MonoILExceptionInfo *ex_info;
835 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 if (ex_info->handlers)
838 num_clauses += mono_array_length (ex_info->handlers);
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
849 MonoExceptionClause *clauses;
850 MonoExceptionClause *clause;
851 MonoILExceptionInfo *ex_info;
852 MonoILExceptionBlock *ex_block;
853 guint32 finally_start;
854 int i, j, clause_index;;
856 clauses = g_new0 (MonoExceptionClause, num_clauses);
859 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861 finally_start = ex_info->start + ex_info->len;
862 g_assert (ex_info->handlers);
863 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865 clause = &(clauses [clause_index]);
867 clause->flags = ex_block->type;
868 clause->try_offset = ex_info->start;
870 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871 clause->try_len = finally_start - ex_info->start;
873 clause->try_len = ex_info->len;
874 clause->handler_offset = ex_block->start;
875 clause->handler_len = ex_block->len;
876 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878 if (ex_block->extype) {
879 mono_g_hash_table_insert (assembly->tokens,
880 GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
882 finally_start = ex_block->start + ex_block->len;
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
898 gint32 num_locals = 0;
899 gint32 num_exception = 0;
902 char fat_header [12];
905 guint32 local_sig = 0;
906 guint32 header_size = 12;
909 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
914 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
916 code = mb->ilgen->code;
917 code_size = mb->ilgen->code_len;
918 max_stack = mb->ilgen->max_stack;
919 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920 if (mb->ilgen->ex_handlers)
921 num_exception = method_count_clauses (mb->ilgen);
925 char *name = mono_string_to_utf8 (mb->name);
926 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
930 mono_raise_exception (exception);
933 code_size = mono_array_length (code);
934 max_stack = 8; /* we probably need to run a verifier on the code... */
937 /* check for exceptions, maxstack, locals */
938 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
940 if (code_size < 64 && !(code_size & 1)) {
941 flags = (code_size << 2) | 0x2;
942 } else if (code_size < 32 && (code_size & 1)) {
943 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
947 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
948 /* add to the fixup todo list */
949 if (mb->ilgen && mb->ilgen->num_token_fixups)
950 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
951 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
952 return assembly->text_rva + idx;
956 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
958 * FIXME: need to set also the header size in fat_flags.
959 * (and more sects and init locals flags)
963 fat_flags |= METHOD_HEADER_MORE_SECTS;
965 fat_flags |= METHOD_HEADER_INIT_LOCALS;
966 fat_header [0] = fat_flags;
967 fat_header [1] = (header_size / 4 ) << 4;
968 shortp = (guint16*)(fat_header + 2);
969 *shortp = GUINT16_TO_LE (max_stack);
970 intp = (guint32*)(fat_header + 4);
971 *intp = GUINT32_TO_LE (code_size);
972 intp = (guint32*)(fat_header + 8);
973 *intp = GUINT32_TO_LE (local_sig);
974 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
975 /* add to the fixup todo list */
976 if (mb->ilgen && mb->ilgen->num_token_fixups)
977 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
979 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
981 unsigned char sheader [4];
982 MonoExceptionClause clause;
983 MonoILExceptionInfo * ex_info;
984 MonoILExceptionBlock * ex_block;
987 stream_data_align (&assembly->code);
988 /* always use fat format for now */
989 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
990 num_exception *= sizeof (MonoExceptionClause);
991 num_exception += 4; /* include the size of the header */
992 sheader [1] = num_exception & 0xff;
993 sheader [2] = (num_exception >> 8) & 0xff;
994 sheader [3] = (num_exception >> 16) & 0xff;
995 mono_image_add_stream_data (&assembly->code, sheader, 4);
996 /* fat header, so we are already aligned */
998 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
999 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1000 if (ex_info->handlers) {
1001 int finally_start = ex_info->start + ex_info->len;
1002 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1003 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1004 clause.flags = GUINT32_TO_LE (ex_block->type);
1005 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1006 /* need fault, too, probably */
1007 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1008 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1010 clause.try_len = GUINT32_TO_LE (ex_info->len);
1011 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1012 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1013 finally_start = ex_block->start + ex_block->len;
1014 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1015 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1016 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1017 /*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",
1018 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);*/
1019 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1022 g_error ("No clauses for ex info block %d", i);
1026 return assembly->text_rva + idx;
1030 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1033 MonoDynamicTable *table;
1036 table = &assembly->tables [table_idx];
1038 g_assert (col < table->columns);
1040 values = table->values + table->columns;
1041 for (i = 1; i <= table->rows; ++i) {
1042 if (values [col] == token)
1044 values += table->columns;
1049 static GHashTable *dynamic_custom_attrs = NULL;
1051 static MonoCustomAttrInfo*
1052 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1055 MonoCustomAttrInfo *ainfo;
1056 MonoReflectionCustomAttr *cattr;
1060 /* FIXME: check in assembly the Run flag is set */
1062 count = mono_array_length (cattrs);
1064 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1066 ainfo->image = image;
1067 ainfo->num_attrs = count;
1068 for (i = 0; i < count; ++i) {
1069 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1070 ainfo->attrs [i].ctor = cattr->ctor->method;
1071 /* FIXME: might want to memdup the data here */
1072 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1073 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1080 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1082 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1087 if (!dynamic_custom_attrs)
1088 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1090 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1091 ainfo->cached = TRUE;
1095 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1097 /* they are cached, so we don't free them */
1098 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1104 * idx is the table index of the object
1105 * type is one of MONO_CUSTOM_ATTR_*
1108 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1110 MonoDynamicTable *table;
1111 MonoReflectionCustomAttr *cattr;
1113 guint32 count, i, token;
1115 char *p = blob_size;
1117 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1120 count = mono_array_length (cattrs);
1121 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1122 table->rows += count;
1123 alloc_table (table, table->rows);
1124 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1125 idx <<= MONO_CUSTOM_ATTR_BITS;
1127 for (i = 0; i < count; ++i) {
1128 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1129 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1130 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1131 type = mono_metadata_token_index (token);
1132 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1133 switch (mono_metadata_token_table (token)) {
1134 case MONO_TABLE_METHOD:
1135 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1137 case MONO_TABLE_MEMBERREF:
1138 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1141 g_warning ("got wrong token in custom attr");
1144 values [MONO_CUSTOM_ATTR_TYPE] = type;
1146 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1147 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1148 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1149 values += MONO_CUSTOM_ATTR_SIZE;
1155 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1157 MonoDynamicTable *table;
1159 guint32 count, i, idx;
1160 MonoReflectionPermissionSet *perm;
1165 count = mono_array_length (permissions);
1166 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1167 table->rows += count;
1168 alloc_table (table, table->rows);
1170 for (i = 0; i < mono_array_length (permissions); ++i) {
1171 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1173 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1175 idx = mono_metadata_token_index (parent_token);
1176 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1177 switch (mono_metadata_token_table (parent_token)) {
1178 case MONO_TABLE_TYPEDEF:
1179 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1181 case MONO_TABLE_METHOD:
1182 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1184 case MONO_TABLE_ASSEMBLY:
1185 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1188 g_assert_not_reached ();
1191 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1192 values [MONO_DECL_SECURITY_PARENT] = idx;
1193 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1200 * Fill in the MethodDef and ParamDef tables for a method.
1201 * This is used for both normal methods and constructors.
1204 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1206 MonoDynamicTable *table;
1211 /* room in this table is already allocated */
1212 table = &assembly->tables [MONO_TABLE_METHOD];
1213 *mb->table_idx = table->next_idx ++;
1214 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1215 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1216 name = mono_string_to_utf8 (mb->name);
1217 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1219 values [MONO_METHOD_FLAGS] = mb->attrs;
1220 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1221 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1222 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1224 table = &assembly->tables [MONO_TABLE_PARAM];
1225 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1227 mono_image_add_decl_security (assembly,
1228 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1231 MonoDynamicTable *mtable;
1234 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1235 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1238 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1239 if (mono_array_get (mb->pinfo, gpointer, i))
1242 table->rows += count;
1243 alloc_table (table, table->rows);
1244 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1245 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1246 MonoReflectionParamBuilder *pb;
1247 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1248 values [MONO_PARAM_FLAGS] = pb->attrs;
1249 values [MONO_PARAM_SEQUENCE] = i;
1250 if (pb->name != NULL) {
1251 name = mono_string_to_utf8 (pb->name);
1252 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1255 values [MONO_PARAM_NAME] = 0;
1257 values += MONO_PARAM_SIZE;
1258 if (pb->marshal_info) {
1260 alloc_table (mtable, mtable->rows);
1261 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1262 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1263 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1265 pb->table_idx = table->next_idx++;
1266 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1267 guint32 field_type = 0;
1268 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1270 alloc_table (mtable, mtable->rows);
1271 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1272 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1273 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1274 mvalues [MONO_CONSTANT_TYPE] = field_type;
1275 mvalues [MONO_CONSTANT_PADDING] = 0;
1283 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1285 rmb->ilgen = mb->ilgen;
1286 rmb->rtype = mb->rtype;
1287 rmb->parameters = mb->parameters;
1288 rmb->generic_params = mb->generic_params;
1289 rmb->opt_types = NULL;
1290 rmb->pinfo = mb->pinfo;
1291 rmb->attrs = mb->attrs;
1292 rmb->iattrs = mb->iattrs;
1293 rmb->call_conv = mb->call_conv;
1294 rmb->code = mb->code;
1295 rmb->type = mb->type;
1296 rmb->name = mb->name;
1297 rmb->table_idx = &mb->table_idx;
1298 rmb->init_locals = mb->init_locals;
1299 rmb->return_modreq = mb->return_modreq;
1300 rmb->return_modopt = mb->return_modopt;
1301 rmb->param_modreq = mb->param_modreq;
1302 rmb->param_modopt = mb->param_modopt;
1303 rmb->permissions = mb->permissions;
1304 rmb->mhandle = mb->mhandle;
1309 rmb->charset = rmb->charset & 0xf;
1310 rmb->lasterr = rmb->charset & 0x40;
1311 rmb->native_cc = rmb->native_cc;
1312 rmb->dllentry = mb->dllentry;
1318 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1320 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1322 rmb->ilgen = mb->ilgen;
1323 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1324 rmb->parameters = mb->parameters;
1325 rmb->generic_params = NULL;
1326 rmb->opt_types = NULL;
1327 rmb->pinfo = mb->pinfo;
1328 rmb->attrs = mb->attrs;
1329 rmb->iattrs = mb->iattrs;
1330 rmb->call_conv = mb->call_conv;
1332 rmb->type = mb->type;
1333 rmb->name = mono_string_new (mono_domain_get (), name);
1334 rmb->table_idx = &mb->table_idx;
1335 rmb->init_locals = mb->init_locals;
1336 rmb->return_modreq = NULL;
1337 rmb->return_modopt = NULL;
1338 rmb->param_modreq = mb->param_modreq;
1339 rmb->param_modopt = mb->param_modopt;
1340 rmb->permissions = mb->permissions;
1341 rmb->mhandle = mb->mhandle;
1347 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1349 rmb->ilgen = mb->ilgen;
1350 rmb->rtype = mb->rtype;
1351 rmb->parameters = mb->parameters;
1352 rmb->generic_params = NULL;
1353 rmb->opt_types = NULL;
1355 rmb->attrs = mb->attrs;
1357 rmb->call_conv = mb->call_conv;
1360 rmb->name = mb->name;
1361 rmb->table_idx = NULL;
1362 rmb->init_locals = mb->init_locals;
1363 rmb->return_modreq = NULL;
1364 rmb->return_modopt = NULL;
1365 rmb->param_modreq = NULL;
1366 rmb->param_modopt = NULL;
1367 rmb->permissions = NULL;
1368 rmb->mhandle = mb->mhandle;
1374 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1376 MonoDynamicTable *table;
1379 ReflectionMethodBuilder rmb;
1382 reflection_methodbuilder_from_method_builder (&rmb, mb);
1384 mono_image_basic_method (&rmb, assembly);
1386 if (mb->dll) { /* It's a P/Invoke method */
1388 int charset = mb->charset & 0xf;
1389 int lasterr = mb->charset & 0x40;
1390 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1392 alloc_table (table, table->rows);
1393 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1394 /* map CharSet values to on-disk values */
1396 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1397 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1398 name = mono_string_to_utf8 (mb->dllentry);
1399 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1401 name = mono_string_to_utf8 (mb->dll);
1402 moduleref = string_heap_insert (&assembly->sheap, name);
1404 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1405 table = &assembly->tables [MONO_TABLE_MODULEREF];
1407 alloc_table (table, table->rows);
1408 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1409 values [MONO_IMPLMAP_SCOPE] = table->rows;
1413 if (mb->override_method) {
1414 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1416 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1418 alloc_table (table, table->rows);
1419 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1420 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1421 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1423 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1424 switch (mono_metadata_token_table (tok)) {
1425 case MONO_TABLE_MEMBERREF:
1426 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1428 case MONO_TABLE_METHOD:
1429 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1432 g_assert_not_reached ();
1434 values [MONO_METHODIMPL_DECLARATION] = tok;
1437 if (mb->generic_params) {
1438 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1439 table->rows += mono_array_length (mb->generic_params);
1440 alloc_table (table, table->rows);
1441 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1442 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1444 mono_image_get_generic_param_info (
1445 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1452 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1454 ReflectionMethodBuilder rmb;
1456 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1458 mono_image_basic_method (&rmb, assembly);
1462 type_get_fully_qualified_name (MonoType *type) {
1463 char *name, *result;
1467 name = mono_type_get_name (type);
1468 klass = my_mono_class_from_mono_type (type);
1469 ta = klass->image->assembly;
1471 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1472 name, ta->aname.name,
1473 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1474 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1475 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1481 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1485 klass = my_mono_class_from_mono_type (type);
1487 return mono_type_get_name (type);
1488 ta = klass->image->assembly;
1489 if (ta == ass || klass->image == mono_defaults.corlib)
1490 return mono_type_get_name (type);
1492 return type_get_fully_qualified_name (type);
1496 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1498 char blob_size [64];
1499 char *b = blob_size;
1504 if (!assembly->save)
1507 p = buf = g_malloc (64);
1509 mono_metadata_encode_value (0x06, p, &p);
1510 /* encode custom attributes before the type */
1511 encode_type (assembly, type, p, &p);
1512 g_assert (p-buf < 64);
1513 mono_metadata_encode_value (p-buf, b, &b);
1514 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1520 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1522 char blob_size [64];
1523 char *b = blob_size;
1528 p = buf = g_malloc (64);
1530 mono_metadata_encode_value (0x06, p, &p);
1531 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1532 /* encode custom attributes before the type */
1533 encode_reflection_type (assembly, fb->type, p, &p);
1534 g_assert (p-buf < 64);
1535 mono_metadata_encode_value (p-buf, b, &b);
1536 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1542 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1543 char blob_size [64];
1544 char *b = blob_size;
1547 guint32 idx = 0, len = 0, dummy = 0;
1549 p = buf = g_malloc (64);
1551 *ret_type = MONO_TYPE_CLASS;
1553 box_val = (char*)&dummy;
1555 box_val = ((char*)val) + sizeof (MonoObject);
1556 *ret_type = val->vtable->klass->byval_arg.type;
1559 switch (*ret_type) {
1560 case MONO_TYPE_BOOLEAN:
1565 case MONO_TYPE_CHAR:
1580 case MONO_TYPE_VALUETYPE:
1581 if (val->vtable->klass->enumtype) {
1582 *ret_type = val->vtable->klass->enum_basetype->type;
1585 g_error ("we can't encode valuetypes");
1586 case MONO_TYPE_CLASS:
1588 case MONO_TYPE_STRING: {
1589 MonoString *str = (MonoString*)val;
1590 /* there is no signature */
1591 len = str->length * 2;
1592 mono_metadata_encode_value (len, b, &b);
1593 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1595 char *swapped = g_malloc (2 * mono_string_length (str));
1596 const char *p = (const char*)mono_string_chars (str);
1598 swap_with_size (swapped, p, 2, mono_string_length (str));
1599 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1603 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1610 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1613 /* there is no signature */
1614 mono_metadata_encode_value (len, b, &b);
1615 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1616 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1617 swap_with_size (blob_size, box_val, len, 1);
1618 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1620 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1628 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1629 char blob_size [64];
1630 char *b = blob_size;
1631 char *p, *buf, *str;
1632 guint32 idx, len, bufsize = 256;
1634 p = buf = g_malloc (bufsize);
1636 switch (minfo->type) {
1637 case MONO_NATIVE_BYVALTSTR:
1638 case MONO_NATIVE_BYVALARRAY:
1639 mono_metadata_encode_value (minfo->type, p, &p);
1640 mono_metadata_encode_value (minfo->count, p, &p);
1642 case MONO_NATIVE_LPARRAY:
1643 mono_metadata_encode_value (minfo->type, p, &p);
1644 if (minfo->eltype || (minfo->count > 0)) {
1645 mono_metadata_encode_value (minfo->eltype, p, &p);
1646 if (minfo->count > 0) {
1647 mono_metadata_encode_value (0, p, &p);
1648 mono_metadata_encode_value (minfo->count, p, &p);
1652 case MONO_NATIVE_CUSTOM:
1653 mono_metadata_encode_value (minfo->type, p, &p);
1655 str = mono_string_to_utf8 (minfo->guid);
1657 mono_metadata_encode_value (len, p, &p);
1658 memcpy (p, str, len);
1662 mono_metadata_encode_value (0, p, &p);
1664 if (minfo->marshaltype) {
1665 str = mono_string_to_utf8 (minfo->marshaltype);
1667 mono_metadata_encode_value (len, p, &p);
1668 if (p + len >= buf + bufsize) {
1671 buf = g_realloc (buf, bufsize);
1674 memcpy (p, str, len);
1678 mono_metadata_encode_value (0, p, &p);
1680 if (minfo->marshaltyperef) {
1681 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1683 mono_metadata_encode_value (len, p, &p);
1684 if (p + len >= buf + bufsize) {
1687 buf = g_realloc (buf, bufsize);
1690 memcpy (p, str, len);
1694 mono_metadata_encode_value (0, p, &p);
1696 if (minfo->mcookie) {
1697 str = mono_string_to_utf8 (minfo->mcookie);
1699 mono_metadata_encode_value (len, p, &p);
1700 if (p + len >= buf + bufsize) {
1703 buf = g_realloc (buf, bufsize);
1706 memcpy (p, str, len);
1710 mono_metadata_encode_value (0, p, &p);
1714 mono_metadata_encode_value (minfo->type, p, &p);
1718 mono_metadata_encode_value (len, b, &b);
1719 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1725 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1727 MonoDynamicTable *table;
1731 /* maybe this fixup should be done in the C# code */
1732 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1733 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1734 table = &assembly->tables [MONO_TABLE_FIELD];
1735 fb->table_idx = table->next_idx ++;
1736 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1737 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1738 name = mono_string_to_utf8 (fb->name);
1739 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1741 values [MONO_FIELD_FLAGS] = fb->attrs;
1742 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1744 if (fb->offset != -1) {
1745 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1747 alloc_table (table, table->rows);
1748 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1749 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1750 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1752 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1753 guint32 field_type = 0;
1754 table = &assembly->tables [MONO_TABLE_CONSTANT];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1758 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1759 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1760 values [MONO_CONSTANT_TYPE] = field_type;
1761 values [MONO_CONSTANT_PADDING] = 0;
1763 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1765 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1767 alloc_table (table, table->rows);
1768 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1769 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1771 * We store it in the code section because it's simpler for now.
1774 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1776 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1777 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1779 if (fb->marshal_info) {
1780 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1782 alloc_table (table, table->rows);
1783 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1784 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1785 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1790 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1794 char *b = blob_size;
1795 guint32 nparams = 0;
1796 MonoReflectionMethodBuilder *mb = fb->get_method;
1797 MonoReflectionMethodBuilder *smb = fb->set_method;
1798 guint32 idx, i, size;
1800 if (mb && mb->parameters)
1801 nparams = mono_array_length (mb->parameters);
1802 if (!mb && smb && smb->parameters)
1803 nparams = mono_array_length (smb->parameters) - 1;
1804 size = 24 + nparams * 10;
1805 buf = p = g_malloc (size);
1808 mono_metadata_encode_value (nparams, p, &p);
1810 encode_reflection_type (assembly, mb->rtype, p, &p);
1811 for (i = 0; i < nparams; ++i) {
1812 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1813 encode_reflection_type (assembly, pt, p, &p);
1816 /* the property type is the last param */
1817 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1818 for (i = 0; i < nparams; ++i) {
1819 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1820 encode_reflection_type (assembly, pt, p, &p);
1824 g_assert (p - buf < size);
1825 mono_metadata_encode_value (p-buf, b, &b);
1826 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1832 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1834 MonoDynamicTable *table;
1837 guint num_methods = 0;
1841 * we need to set things in the following tables:
1842 * PROPERTYMAP (info already filled in _get_type_info ())
1843 * PROPERTY (rows already preallocated in _get_type_info ())
1844 * METHOD (method info already done with the generic method code)
1847 table = &assembly->tables [MONO_TABLE_PROPERTY];
1848 pb->table_idx = table->next_idx ++;
1849 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1850 name = mono_string_to_utf8 (pb->name);
1851 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1853 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1854 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1856 /* FIXME: we still don't handle 'other' methods */
1857 if (pb->get_method) num_methods ++;
1858 if (pb->set_method) num_methods ++;
1860 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1861 table->rows += num_methods;
1862 alloc_table (table, table->rows);
1864 if (pb->get_method) {
1865 semaidx = table->next_idx ++;
1866 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1867 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1868 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1869 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1871 if (pb->set_method) {
1872 semaidx = table->next_idx ++;
1873 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1874 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1875 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1876 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1881 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1883 MonoDynamicTable *table;
1886 guint num_methods = 0;
1890 * we need to set things in the following tables:
1891 * EVENTMAP (info already filled in _get_type_info ())
1892 * EVENT (rows already preallocated in _get_type_info ())
1893 * METHOD (method info already done with the generic method code)
1896 table = &assembly->tables [MONO_TABLE_EVENT];
1897 eb->table_idx = table->next_idx ++;
1898 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1899 name = mono_string_to_utf8 (eb->name);
1900 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1902 values [MONO_EVENT_FLAGS] = eb->attrs;
1903 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1906 * FIXME: we still don't handle 'other' methods
1908 if (eb->add_method) num_methods ++;
1909 if (eb->remove_method) num_methods ++;
1910 if (eb->raise_method) num_methods ++;
1912 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1913 table->rows += num_methods;
1914 alloc_table (table, table->rows);
1916 if (eb->add_method) {
1917 semaidx = table->next_idx ++;
1918 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1919 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1920 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1921 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1923 if (eb->remove_method) {
1924 semaidx = table->next_idx ++;
1925 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1926 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1927 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1928 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1930 if (eb->raise_method) {
1931 semaidx = table->next_idx ++;
1932 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1933 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1934 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1935 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1940 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1942 static MonoClass *NewConstraintAttr;
1943 static MonoMethod *NewConstraintAttr_ctor;
1944 MonoDynamicTable *table;
1946 guint32 token, type;
1947 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1950 if (!NewConstraintAttr)
1951 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1952 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1953 g_assert (NewConstraintAttr);
1955 if (!NewConstraintAttr_ctor) {
1958 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1959 MonoMethod *m = NewConstraintAttr->methods [i];
1961 if (strcmp (m->name, ".ctor"))
1964 NewConstraintAttr_ctor = m;
1968 g_assert (NewConstraintAttr_ctor);
1971 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1973 alloc_table (table, table->rows);
1975 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1976 owner <<= MONO_CUSTOM_ATTR_BITS;
1977 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1978 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1980 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1982 type = mono_metadata_token_index (token);
1983 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1984 switch (mono_metadata_token_table (token)) {
1985 case MONO_TABLE_METHOD:
1986 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1988 case MONO_TABLE_MEMBERREF:
1989 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1992 g_warning ("got wrong token in custom attr");
1995 values [MONO_CUSTOM_ATTR_TYPE] = type;
1997 buf = p = g_malloc (1);
1998 mono_metadata_encode_value (4, p, &p);
1999 g_assert (p-buf == 1);
2001 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2003 values += MONO_CUSTOM_ATTR_SIZE;
2008 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2010 MonoDynamicTable *table;
2011 guint32 num_constraints, i;
2015 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2016 num_constraints = gparam->iface_constraints ?
2017 mono_array_length (gparam->iface_constraints) : 0;
2018 table->rows += num_constraints;
2019 if (gparam->base_type)
2021 alloc_table (table, table->rows);
2023 if (gparam->base_type) {
2024 table_idx = table->next_idx ++;
2025 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2027 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2028 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2029 assembly, gparam->base_type->type);
2032 for (i = 0; i < num_constraints; i++) {
2033 MonoReflectionType *constraint = mono_array_get (
2034 gparam->iface_constraints, gpointer, i);
2036 table_idx = table->next_idx ++;
2037 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2039 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2040 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2041 assembly, constraint->type);
2044 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2045 encode_new_constraint (assembly, owner);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2062 entry->gparam = gparam;
2064 g_ptr_array_add (assembly->gen_params, entry);
2068 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2070 MonoDynamicTable *table;
2071 MonoGenericParam *param;
2075 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2076 table_idx = table->next_idx ++;
2077 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2079 param = entry->gparam->type.type->data.generic_param;
2081 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2082 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2083 values [MONO_GENERICPARAM_NUMBER] = param->num;
2084 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2085 values [MONO_GENERICPARAM_KIND] = 0;
2087 encode_constraints (entry->gparam, table_idx, assembly);
2091 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2093 MonoDynamicTable *table;
2096 guint32 cols [MONO_ASSEMBLY_SIZE];
2100 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2103 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2104 table = &assembly->tables [MONO_TABLE_MODULEREF];
2105 token = table->next_idx ++;
2107 alloc_table (table, table->rows);
2108 values = table->values + token * MONO_MODULEREF_SIZE;
2109 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2111 token <<= MONO_RESOLTION_SCOPE_BITS;
2112 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2113 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2118 if (image->assembly->dynamic)
2120 memset (cols, 0, sizeof (cols));
2122 /* image->assembly->image is the manifest module */
2123 image = image->assembly->image;
2124 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2127 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2128 token = table->next_idx ++;
2130 alloc_table (table, table->rows);
2131 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2132 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2133 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2134 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2135 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2136 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2137 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2138 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2139 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2141 if (strcmp ("", image->assembly->aname.culture)) {
2142 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2143 image->assembly->aname.culture);
2146 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2147 guchar pubtoken [9];
2149 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2150 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2152 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2154 token <<= MONO_RESOLTION_SCOPE_BITS;
2155 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2156 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2161 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2163 MonoDynamicTable *table;
2169 char *b = blob_size;
2171 switch (type->type) {
2172 case MONO_TYPE_FNPTR:
2174 case MONO_TYPE_SZARRAY:
2175 case MONO_TYPE_ARRAY:
2177 case MONO_TYPE_MVAR:
2178 case MONO_TYPE_GENERICINST:
2179 encode_type (assembly, type, p, &p);
2181 case MONO_TYPE_CLASS:
2182 case MONO_TYPE_VALUETYPE: {
2183 MonoClass *k = mono_class_from_mono_type (type);
2184 if (!k || !k->generic_inst)
2186 encode_generic_inst (assembly, k->generic_inst, p, &p);
2193 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2194 if (assembly->save) {
2195 g_assert (p-sig < 128);
2196 mono_metadata_encode_value (p-sig, b, &b);
2197 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2198 alloc_table (table, table->rows + 1);
2199 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2200 values [MONO_TYPESPEC_SIGNATURE] = token;
2203 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2204 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2210 * Despite the name, we handle also TypeSpec (with the above helper).
2213 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2215 MonoDynamicTable *table;
2217 guint32 token, scope, enclosing;
2220 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2223 token = create_typespec (assembly, type);
2226 klass = my_mono_class_from_mono_type (type);
2228 klass = mono_class_from_mono_type (type);
2231 * If it's in the same module and not a generic type parameter:
2233 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2234 (type->type != MONO_TYPE_MVAR)) {
2235 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2236 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2237 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2241 if (klass->nested_in) {
2242 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2243 /* get the typeref idx of the enclosing type */
2244 enclosing >>= MONO_TYPEDEFORREF_BITS;
2245 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2247 scope = resolution_scope_from_image (assembly, klass->image);
2249 table = &assembly->tables [MONO_TABLE_TYPEREF];
2250 if (assembly->save) {
2251 alloc_table (table, table->rows + 1);
2252 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2253 values [MONO_TYPEREF_SCOPE] = scope;
2254 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2255 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2257 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2258 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2260 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2265 * Insert a memberef row into the metadata: the token that point to the memberref
2266 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2267 * mono_image_get_fieldref_token()).
2268 * The sig param is an index to an already built signature.
2271 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2273 MonoDynamicTable *table;
2275 guint32 token, pclass;
2278 parent = mono_image_typedef_or_ref (assembly, type);
2279 switch (parent & MONO_TYPEDEFORREF_MASK) {
2280 case MONO_TYPEDEFORREF_TYPEREF:
2281 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2283 case MONO_TYPEDEFORREF_TYPESPEC:
2284 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2286 case MONO_TYPEDEFORREF_TYPEDEF:
2287 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2290 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2293 /* extract the index */
2294 parent >>= MONO_TYPEDEFORREF_BITS;
2296 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2298 if (assembly->save) {
2299 alloc_table (table, table->rows + 1);
2300 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2301 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2302 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2303 values [MONO_MEMBERREF_SIGNATURE] = sig;
2306 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2313 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2316 MonoMethodSignature *sig;
2318 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2323 * A methodref signature can't contain an unmanaged calling convention.
2325 sig = mono_metadata_signature_dup (method->signature);
2326 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2327 sig->call_convention = MONO_CALL_DEFAULT;
2328 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2329 method->name, method_encode_signature (assembly, sig));
2331 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2336 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2337 const gchar *name, guint32 sig)
2339 MonoDynamicTable *table;
2343 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2345 if (assembly->save) {
2346 alloc_table (table, table->rows + 1);
2347 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2348 values [MONO_MEMBERREF_CLASS] = original;
2349 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2350 values [MONO_MEMBERREF_SIGNATURE] = sig;
2353 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2360 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2363 ReflectionMethodBuilder rmb;
2365 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2369 reflection_methodbuilder_from_method_builder (&rmb, mb);
2371 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2372 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2373 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2378 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2381 ReflectionMethodBuilder rmb;
2383 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2387 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2389 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2390 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2391 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2396 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2401 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2404 g_assert (f->field->parent);
2405 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2406 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2407 f->field->name, fieldref_encode_signature (assembly, type));
2408 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2413 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2418 guint32 nparams = gmethod->mtype_argc;
2419 guint32 size = 10 + nparams * 10;
2422 char *b = blob_size;
2424 if (!assembly->save)
2427 p = buf = g_malloc (size);
2429 * FIXME: vararg, explicit_this, differenc call_conv values...
2431 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2432 mono_metadata_encode_value (nparams, p, &p);
2434 for (i = 0; i < nparams; i++)
2435 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2438 g_assert (p - buf < size);
2439 mono_metadata_encode_value (p-buf, b, &b);
2440 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2446 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2448 MonoDynamicTable *table;
2450 guint32 token, mtoken = 0, sig;
2451 MonoMethodInflated *imethod;
2452 MonoMethod *declaring;
2454 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2456 g_assert (method->signature->is_inflated);
2457 imethod = (MonoMethodInflated *) method;
2458 declaring = imethod->declaring;
2460 sig = method_encode_signature (assembly, declaring->signature);
2461 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2463 if (!declaring->signature->generic_param_count)
2466 switch (mono_metadata_token_table (mtoken)) {
2467 case MONO_TABLE_MEMBERREF:
2468 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2470 case MONO_TABLE_METHOD:
2471 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2474 g_assert_not_reached ();
2477 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2479 if (assembly->save) {
2480 alloc_table (table, table->rows + 1);
2481 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2482 values [MONO_METHODSPEC_METHOD] = mtoken;
2483 values [MONO_METHODSPEC_SIGNATURE] = sig;
2486 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2493 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2495 MonoMethodInflated *imethod;
2498 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2502 g_assert (m->signature->is_inflated);
2503 imethod = (MonoMethodInflated *) m;
2505 if (imethod->declaring->signature->generic_param_count) {
2506 token = method_encode_methodspec (assembly, m);
2508 guint32 sig = method_encode_signature (
2509 assembly, imethod->declaring->signature);
2510 token = mono_image_get_memberref_token (
2511 assembly, &m->klass->byval_arg, m->name, sig);
2514 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2519 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2521 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2524 sig = method_encode_signature (assembly, imethod->declaring->signature);
2525 token = mono_image_get_memberref_token (
2526 assembly, &m->klass->byval_arg, m->name, sig);
2532 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2534 MonoDynamicTable *table;
2541 char *b = blob_size;
2545 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2546 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2547 * Because of this, we must not insert it into the `typeref' hash table.
2550 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2554 g_assert (tb->generic_params);
2555 klass = mono_class_from_mono_type (tb->type.type);
2557 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2558 encode_type (assembly, &klass->byval_arg, p, &p);
2560 count = mono_array_length (tb->generic_params);
2561 mono_metadata_encode_value (count, p, &p);
2562 for (i = 0; i < count; i++) {
2563 MonoReflectionGenericParam *gparam;
2565 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2567 encode_type (assembly, gparam->type.type, p, &p);
2570 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2571 if (assembly->save) {
2572 g_assert (p-sig < 128);
2573 mono_metadata_encode_value (p-sig, b, &b);
2574 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2575 alloc_table (table, table->rows + 1);
2576 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2577 values [MONO_TYPESPEC_SIGNATURE] = token;
2580 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2581 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2587 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2589 MonoDynamicTable *table;
2592 guint32 token, pclass, parent, sig;
2595 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2599 klass = mono_class_from_mono_type (fb->typeb->type);
2600 name = mono_string_to_utf8 (fb->name);
2602 sig = fieldref_encode_signature (assembly, fb->type->type);
2604 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2605 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2607 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2608 parent >>= MONO_TYPEDEFORREF_BITS;
2610 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2612 if (assembly->save) {
2613 alloc_table (table, table->rows + 1);
2614 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2615 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2616 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2617 values [MONO_MEMBERREF_SIGNATURE] = sig;
2620 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2622 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2627 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2635 char *b = blob_size;
2637 if (!assembly->save)
2641 g_assert (helper->type == 2);
2643 if (helper->arguments)
2644 nargs = mono_array_length (helper->arguments);
2648 size = 10 + (nargs * 10);
2650 p = buf = g_malloc (size);
2652 /* Encode calling convention */
2653 /* Change Any to Standard */
2654 if ((helper->call_conv & 0x03) == 0x03)
2655 helper->call_conv = 0x01;
2656 /* explicit_this implies has_this */
2657 if (helper->call_conv & 0x40)
2658 helper->call_conv &= 0x20;
2660 if (helper->call_conv == 0) { /* Unmanaged */
2661 *p = helper->unmanaged_call_conv - 1;
2664 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2665 if (helper->call_conv & 0x02) /* varargs */
2670 mono_metadata_encode_value (nargs, p, &p);
2671 encode_reflection_type (assembly, helper->return_type, p, &p);
2672 for (i = 0; i < nargs; ++i) {
2673 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2674 encode_reflection_type (assembly, pt, p, &p);
2677 g_assert (p - buf < size);
2678 mono_metadata_encode_value (p-buf, b, &b);
2679 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2686 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2689 MonoDynamicTable *table;
2692 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2693 idx = table->next_idx ++;
2695 alloc_table (table, table->rows);
2696 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2698 values [MONO_STAND_ALONE_SIGNATURE] =
2699 mono_reflection_encode_sighelper (assembly, helper);
2705 reflection_cc_to_file (int call_conv) {
2706 switch (call_conv & 0x3) {
2708 case 1: return MONO_CALL_DEFAULT;
2709 case 2: return MONO_CALL_VARARG;
2711 g_assert_not_reached ();
2718 MonoMethodSignature *sig;
2724 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2729 MonoMethodSignature *sig;
2732 name = mono_string_to_utf8 (m->name);
2733 nparams = mono_array_length (m->parameters);
2734 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2736 sig->sentinelpos = -1;
2737 sig->call_convention = reflection_cc_to_file (m->call_conv);
2738 sig->param_count = nparams;
2739 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2740 for (i = 0; i < nparams; ++i) {
2741 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2742 sig->params [i] = t->type;
2745 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2747 if (strcmp (name, am->name) == 0 &&
2748 mono_metadata_type_equal (am->parent, m->parent->type) &&
2749 mono_metadata_signature_equal (am->sig, sig)) {
2752 m->table_idx = am->token & 0xffffff;
2756 am = g_new0 (ArrayMethod, 1);
2759 am->parent = m->parent->type;
2760 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2761 method_encode_signature (assembly, sig));
2762 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2763 m->table_idx = am->token & 0xffffff;
2768 * Insert into the metadata tables all the info about the TypeBuilder tb.
2769 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2772 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2774 MonoDynamicTable *table;
2776 int i, is_object = 0, is_system = 0;
2779 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2780 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2781 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2782 n = mono_string_to_utf8 (tb->name);
2783 if (strcmp (n, "Object") == 0)
2785 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2787 n = mono_string_to_utf8 (tb->nspace);
2788 if (strcmp (n, "System") == 0)
2790 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2792 if (tb->parent && !(is_system && is_object) &&
2793 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2794 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2796 values [MONO_TYPEDEF_EXTENDS] = 0;
2798 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2799 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2802 * if we have explicitlayout or sequentiallayouts, output data in the
2803 * ClassLayout table.
2805 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2806 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2807 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2809 alloc_table (table, table->rows);
2810 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2811 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2812 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2813 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2816 /* handle interfaces */
2817 if (tb->interfaces) {
2818 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2820 table->rows += mono_array_length (tb->interfaces);
2821 alloc_table (table, table->rows);
2822 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2823 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2824 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2825 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2826 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2827 values += MONO_INTERFACEIMPL_SIZE;
2833 table = &assembly->tables [MONO_TABLE_FIELD];
2834 table->rows += tb->num_fields;
2835 alloc_table (table, table->rows);
2836 for (i = 0; i < tb->num_fields; ++i)
2837 mono_image_get_field_info (
2838 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2841 /* handle constructors */
2843 table = &assembly->tables [MONO_TABLE_METHOD];
2844 table->rows += mono_array_length (tb->ctors);
2845 alloc_table (table, table->rows);
2846 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2847 mono_image_get_ctor_info (domain,
2848 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2851 /* handle methods */
2853 table = &assembly->tables [MONO_TABLE_METHOD];
2854 table->rows += tb->num_methods;
2855 alloc_table (table, table->rows);
2856 for (i = 0; i < tb->num_methods; ++i)
2857 mono_image_get_method_info (
2858 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2861 /* Do the same with properties etc.. */
2862 if (tb->events && mono_array_length (tb->events)) {
2863 table = &assembly->tables [MONO_TABLE_EVENT];
2864 table->rows += mono_array_length (tb->events);
2865 alloc_table (table, table->rows);
2866 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2868 alloc_table (table, table->rows);
2869 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2870 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2871 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2872 for (i = 0; i < mono_array_length (tb->events); ++i)
2873 mono_image_get_event_info (
2874 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2876 if (tb->properties && mono_array_length (tb->properties)) {
2877 table = &assembly->tables [MONO_TABLE_PROPERTY];
2878 table->rows += mono_array_length (tb->properties);
2879 alloc_table (table, table->rows);
2880 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2882 alloc_table (table, table->rows);
2883 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2884 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2885 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2886 for (i = 0; i < mono_array_length (tb->properties); ++i)
2887 mono_image_get_property_info (
2888 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2891 /* handle generic parameters */
2892 if (tb->generic_params) {
2893 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2894 table->rows += mono_array_length (tb->generic_params);
2895 alloc_table (table, table->rows);
2896 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2897 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2899 mono_image_get_generic_param_info (
2900 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2904 mono_image_add_decl_security (assembly,
2905 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2908 MonoDynamicTable *ntable;
2910 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2911 ntable->rows += mono_array_length (tb->subtypes);
2912 alloc_table (ntable, ntable->rows);
2913 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2915 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2916 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2918 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2919 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2920 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2921 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2922 mono_string_to_utf8 (tb->name), tb->table_idx,
2923 ntable->next_idx, ntable->rows);*/
2924 values += MONO_NESTED_CLASS_SIZE;
2931 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2935 g_ptr_array_add (types, type);
2937 if (!type->subtypes)
2940 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2941 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2942 collect_types (types, subtype);
2947 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2949 if ((*type1)->table_idx < (*type2)->table_idx)
2952 if ((*type1)->table_idx > (*type2)->table_idx)
2959 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2964 for (i = 0; i < mono_array_length (pinfo); ++i) {
2965 MonoReflectionParamBuilder *pb;
2966 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2969 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2974 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2977 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2979 for (i = 0; i < tb->num_fields; ++i) {
2980 MonoReflectionFieldBuilder* fb;
2981 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2982 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2986 for (i = 0; i < mono_array_length (tb->events); ++i) {
2987 MonoReflectionEventBuilder* eb;
2988 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2989 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2992 if (tb->properties) {
2993 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2994 MonoReflectionPropertyBuilder* pb;
2995 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2996 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3000 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3001 MonoReflectionCtorBuilder* cb;
3002 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3003 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3004 params_add_cattrs (assembly, cb->pinfo);
3009 for (i = 0; i < tb->num_methods; ++i) {
3010 MonoReflectionMethodBuilder* mb;
3011 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3012 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3013 params_add_cattrs (assembly, mb->pinfo);
3018 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3019 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3024 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3027 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3029 /* no types in the module */
3033 for (i = 0; i < mb->num_types; ++i)
3034 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3038 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3040 MonoDynamicTable *table;
3044 char *b = blob_size;
3047 table = &assembly->tables [MONO_TABLE_FILE];
3049 alloc_table (table, table->rows);
3050 values = table->values + table->next_idx * MONO_FILE_SIZE;
3051 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3052 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3053 if (module->image->dynamic) {
3054 /* This depends on the fact that the main module is emitted last */
3055 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3056 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3059 path = g_strdup (module->image->name);
3061 mono_sha1_get_digest_from_file (path, hash);
3064 mono_metadata_encode_value (20, b, &b);
3065 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3066 mono_image_add_stream_data (&assembly->blob, hash, 20);
3071 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3073 MonoDynamicTable *table;
3077 table = &assembly->tables [MONO_TABLE_MODULE];
3078 mb->table_idx = table->next_idx ++;
3079 name = mono_string_to_utf8 (mb->module.name);
3080 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3082 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3085 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3086 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3091 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3092 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3094 MonoDynamicTable *table;
3098 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3099 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3102 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3104 alloc_table (table, table->rows);
3105 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3107 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3108 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3109 if (klass->nested_in)
3110 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3113 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3114 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3116 res = table->next_idx;
3120 /* Emit nested types */
3121 if (klass->nested_classes) {
3124 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3125 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3132 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3133 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3138 klass = mono_class_from_mono_type (tb->type.type);
3140 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3142 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3143 parent_index, assembly);
3147 * We need to do this ourselves since klass->nested_classes is not set up.
3150 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3151 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3156 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3157 guint32 module_index, MonoDynamicImage *assembly)
3159 MonoImage *image = module->image;
3163 t = &image->tables [MONO_TABLE_TYPEDEF];
3165 for (i = 0; i < t->rows; ++i) {
3166 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3168 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3169 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3173 #define align_pointer(base,p)\
3175 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3177 (p) += 4 - (__diff & 3);\
3181 compare_semantics (const void *a, const void *b)
3183 const guint32 *a_values = a;
3184 const guint32 *b_values = b;
3185 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3188 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3192 compare_custom_attrs (const void *a, const void *b)
3194 const guint32 *a_values = a;
3195 const guint32 *b_values = b;
3197 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3201 compare_field_marshal (const void *a, const void *b)
3203 const guint32 *a_values = a;
3204 const guint32 *b_values = b;
3206 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3210 compare_nested (const void *a, const void *b)
3212 const guint32 *a_values = a;
3213 const guint32 *b_values = b;
3215 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3219 compare_genericparam (const void *a, const void *b)
3221 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3222 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3224 return (*a_entry)->owner - (*b_entry)->owner;
3228 compare_declsecurity_attrs (const void *a, const void *b)
3230 const guint32 *a_values = a;
3231 const guint32 *b_values = b;
3233 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3237 pad_heap (MonoDynamicStream *sh)
3239 if (sh->index & 3) {
3240 int sz = 4 - (sh->index & 3);
3241 memset (sh->data + sh->index, 0, sz);
3248 MonoDynamicStream *stream;
3252 * build_compressed_metadata() fills in the blob of data that represents the
3253 * raw metadata as it will be saved in the PE file. The five streams are output
3254 * and the metadata tables are comnpressed from the guint32 array representation,
3255 * to the compressed on-disk format.
3258 build_compressed_metadata (MonoDynamicImage *assembly)
3260 MonoDynamicTable *table;
3262 guint64 valid_mask = 0;
3263 guint64 sorted_mask;
3264 guint32 heapt_size = 0;
3265 guint32 meta_size = 256; /* allow for header and other stuff */
3266 guint32 table_offset;
3267 guint32 ntables = 0;
3273 struct StreamDesc stream_desc [5];
3275 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3276 for (i = 0; i < assembly->gen_params->len; i++){
3277 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3278 write_generic_param_entry (assembly, entry);
3281 stream_desc [0].name = "#~";
3282 stream_desc [0].stream = &assembly->tstream;
3283 stream_desc [1].name = "#Strings";
3284 stream_desc [1].stream = &assembly->sheap;
3285 stream_desc [2].name = "#US";
3286 stream_desc [2].stream = &assembly->us;
3287 stream_desc [3].name = "#Blob";
3288 stream_desc [3].stream = &assembly->blob;
3289 stream_desc [4].name = "#GUID";
3290 stream_desc [4].stream = &assembly->guid;
3292 /* tables that are sorted */
3293 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3294 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3295 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3296 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3297 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3298 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3300 /* Compute table sizes */
3301 /* the MonoImage has already been created in mono_image_basic_init() */
3302 meta = &assembly->image;
3304 /* sizes should be multiple of 4 */
3305 pad_heap (&assembly->blob);
3306 pad_heap (&assembly->guid);
3307 pad_heap (&assembly->sheap);
3308 pad_heap (&assembly->us);
3310 /* Setup the info used by compute_sizes () */
3311 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3312 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3313 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3315 meta_size += assembly->blob.index;
3316 meta_size += assembly->guid.index;
3317 meta_size += assembly->sheap.index;
3318 meta_size += assembly->us.index;
3320 for (i=0; i < 64; ++i)
3321 meta->tables [i].rows = assembly->tables [i].rows;
3323 for (i = 0; i < 64; i++){
3324 if (meta->tables [i].rows == 0)
3326 valid_mask |= (guint64)1 << i;
3328 meta->tables [i].row_size = mono_metadata_compute_size (
3329 meta, i, &meta->tables [i].size_bitfield);
3330 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3332 heapt_size += 24; /* #~ header size */
3333 heapt_size += ntables * 4;
3334 /* make multiple of 4 */
3337 meta_size += heapt_size;
3338 meta->raw_metadata = g_malloc0 (meta_size);
3339 p = meta->raw_metadata;
3340 /* the metadata signature */
3341 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3342 /* version numbers and 4 bytes reserved */
3343 int16val = (guint16*)p;
3344 *int16val++ = GUINT16_TO_LE (1);
3345 *int16val = GUINT16_TO_LE (1);
3347 /* version string */
3348 int32val = (guint32*)p;
3349 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3351 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3352 p += GUINT32_FROM_LE (*int32val);
3353 align_pointer (meta->raw_metadata, p);
3354 int16val = (guint16*)p;
3355 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3356 *int16val = GUINT16_TO_LE (5); /* number of streams */
3360 * write the stream info.
3362 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3363 table_offset += 3; table_offset &= ~3;
3365 assembly->tstream.index = heapt_size;
3366 for (i = 0; i < 5; ++i) {
3367 int32val = (guint32*)p;
3368 stream_desc [i].stream->offset = table_offset;
3369 *int32val++ = GUINT32_TO_LE (table_offset);
3370 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3371 table_offset += GUINT32_FROM_LE (*int32val);
3372 table_offset += 3; table_offset &= ~3;
3374 strcpy (p, stream_desc [i].name);
3375 p += strlen (stream_desc [i].name) + 1;
3376 align_pointer (meta->raw_metadata, p);
3379 * now copy the data, the table stream header and contents goes first.
3381 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3382 p = meta->raw_metadata + assembly->tstream.offset;
3383 int32val = (guint32*)p;
3384 *int32val = GUINT32_TO_LE (0); /* reserved */
3387 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3388 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3389 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3390 *p++ = 1; /* version */
3393 *p++ = 1; /* version */
3397 if (meta->idx_string_wide)
3399 if (meta->idx_guid_wide)
3401 if (meta->idx_blob_wide)
3404 *p++ = 0; /* reserved */
3405 int64val = (guint64*)p;
3406 *int64val++ = GUINT64_TO_LE (valid_mask);
3407 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3409 int32val = (guint32*)p;
3410 for (i = 0; i < 64; i++){
3411 if (meta->tables [i].rows == 0)
3413 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3415 p = (unsigned char*)int32val;
3417 /* sort the tables that still need sorting */
3418 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3420 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3421 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3423 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3424 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3426 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3427 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3429 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3430 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3431 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3433 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3435 /* compress the tables */
3436 for (i = 0; i < 64; i++){
3439 guint32 bitfield = meta->tables [i].size_bitfield;
3440 if (!meta->tables [i].rows)
3442 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3443 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3444 meta->tables [i].base = p;
3445 for (row = 1; row <= meta->tables [i].rows; ++row) {
3446 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3447 for (col = 0; col < assembly->tables [i].columns; ++col) {
3448 switch (mono_metadata_table_size (bitfield, col)) {
3450 *p++ = values [col];
3453 *p++ = values [col] & 0xff;
3454 *p++ = (values [col] >> 8) & 0xff;
3457 *p++ = values [col] & 0xff;
3458 *p++ = (values [col] >> 8) & 0xff;
3459 *p++ = (values [col] >> 16) & 0xff;
3460 *p++ = (values [col] >> 24) & 0xff;
3463 g_assert_not_reached ();
3467 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3470 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3471 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3472 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3473 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3474 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3476 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3480 * Some tables in metadata need to be sorted according to some criteria, but
3481 * when methods and fields are first created with reflection, they may be assigned a token
3482 * that doesn't correspond to the final token they will get assigned after the sorting.
3483 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3484 * with the reflection objects that represent them. Once all the tables are set up, the
3485 * reflection objects will contains the correct table index. fixup_method() will fixup the
3486 * tokens for the method with ILGenerator @ilgen.
3489 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3490 guint32 code_idx = GPOINTER_TO_UINT (value);
3491 MonoReflectionILTokenInfo *iltoken;
3492 MonoReflectionFieldBuilder *field;
3493 MonoReflectionCtorBuilder *ctor;
3494 MonoReflectionMethodBuilder *method;
3495 MonoReflectionTypeBuilder *tb;
3496 MonoReflectionArrayMethod *am;
3498 unsigned char *target;
3500 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3501 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3502 target = assembly->code.data + code_idx + iltoken->code_pos;
3503 switch (target [3]) {
3504 case MONO_TABLE_FIELD:
3505 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3506 field = (MonoReflectionFieldBuilder *)iltoken->member;
3507 idx = field->table_idx;
3508 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3509 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3510 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3512 g_assert_not_reached ();
3515 case MONO_TABLE_METHOD:
3516 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3517 method = (MonoReflectionMethodBuilder *)iltoken->member;
3518 idx = method->table_idx;
3519 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3520 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3521 idx = ctor->table_idx;
3522 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3523 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3524 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3525 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3527 g_assert_not_reached ();
3530 case MONO_TABLE_TYPEDEF:
3531 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3532 g_assert_not_reached ();
3533 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3534 idx = tb->table_idx;
3536 case MONO_TABLE_MEMBERREF:
3537 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3538 am = (MonoReflectionArrayMethod*)iltoken->member;
3539 idx = am->table_idx;
3540 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3541 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3542 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3543 g_assert (m->klass->generic_inst);
3545 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3548 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3549 g_assert (f->generic_info);
3551 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3554 g_assert_not_reached ();
3557 case MONO_TABLE_METHODSPEC:
3558 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3559 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3560 g_assert (m->signature->generic_param_count);
3563 g_assert_not_reached ();
3567 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3569 target [0] = idx & 0xff;
3570 target [1] = (idx >> 8) & 0xff;
3571 target [2] = (idx >> 16) & 0xff;
3578 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3579 * value is not known when the table is emitted.
3582 fixup_cattrs (MonoDynamicImage *assembly)
3584 MonoDynamicTable *table;
3586 guint32 type, i, idx, token;
3589 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3591 for (i = 0; i < table->rows; ++i) {
3592 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3594 type = values [MONO_CUSTOM_ATTR_TYPE];
3595 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3596 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3597 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3598 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3601 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3602 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3603 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3604 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3611 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3613 MonoDynamicTable *table;
3617 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3619 alloc_table (table, table->rows);
3620 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3621 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3622 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3623 name = mono_string_to_utf8 (rsrc->name);
3624 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3626 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3631 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3633 MonoDynamicTable *table;
3637 char *b = blob_size;
3639 guint32 idx, offset;
3641 if (rsrc->filename) {
3642 name = mono_string_to_utf8 (rsrc->filename);
3643 sname = g_path_get_basename (name);
3645 table = &assembly->tables [MONO_TABLE_FILE];
3647 alloc_table (table, table->rows);
3648 values = table->values + table->next_idx * MONO_FILE_SIZE;
3649 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3650 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3653 mono_sha1_get_digest_from_file (name, hash);
3654 mono_metadata_encode_value (20, b, &b);
3655 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3656 mono_image_add_stream_data (&assembly->blob, hash, 20);
3658 idx = table->next_idx++;
3660 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3663 offset = mono_array_length (rsrc->data);
3664 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3665 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3666 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3667 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3671 * The entry should be emitted into the MANIFESTRESOURCE table of
3672 * the main module, but that needs to reference the FILE table
3673 * which isn't emitted yet.
3680 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3684 set_version_from_string (MonoString *version, guint32 *values)
3686 gchar *ver, *p, *str;
3689 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3690 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3691 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3692 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3695 ver = str = mono_string_to_utf8 (version);
3696 for (i = 0; i < 4; ++i) {
3697 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3703 /* handle Revision and Build */
3713 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3717 char *b = blob_size;
3722 len = mono_array_length (pkey);
3723 mono_metadata_encode_value (len, b, &b);
3724 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3725 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3727 /* need to get the actual value from the key type... */
3728 assembly->strong_name_size = 128;
3729 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3735 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3737 MonoDynamicTable *table;
3738 MonoDynamicImage *assembly;
3739 MonoReflectionAssemblyBuilder *assemblyb;
3744 guint32 module_index;
3746 assemblyb = moduleb->assemblyb;
3747 assembly = moduleb->dynamic_image;
3748 domain = mono_object_domain (assemblyb);
3750 /* Emit ASSEMBLY table */
3751 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3752 alloc_table (table, 1);
3753 values = table->values + MONO_ASSEMBLY_SIZE;
3754 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3755 name = mono_string_to_utf8 (assemblyb->name);
3756 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3758 if (assemblyb->culture) {
3759 name = mono_string_to_utf8 (assemblyb->culture);
3760 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3763 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3765 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3766 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3767 set_version_from_string (assemblyb->version, values);
3769 /* Emit FILE + EXPORTED_TYPE table */
3771 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3773 MonoReflectionModuleBuilder *file_module =
3774 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3775 if (file_module != moduleb) {
3776 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3778 if (file_module->types) {
3779 for (j = 0; j < file_module->num_types; ++j) {
3780 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3781 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3786 if (assemblyb->loaded_modules) {
3787 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3788 MonoReflectionModule *file_module =
3789 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3790 mono_image_fill_file_table (domain, file_module, assembly);
3792 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3796 /* Emit MANIFESTRESOURCE table */
3798 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3800 MonoReflectionModuleBuilder *file_module =
3801 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3802 /* The table for the main module is emitted later */
3803 if (file_module != moduleb) {
3805 if (file_module->resources) {
3806 int len = mono_array_length (file_module->resources);
3807 for (j = 0; j < len; ++j) {
3808 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3809 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3817 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3818 * for the modulebuilder @moduleb.
3819 * At the end of the process, method and field tokens are fixed up and the
3820 * on-disk compressed metadata representation is created.
3823 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3825 MonoDynamicTable *table;
3826 MonoDynamicImage *assembly;
3827 MonoReflectionAssemblyBuilder *assemblyb;
3832 assemblyb = moduleb->assemblyb;
3833 assembly = moduleb->dynamic_image;
3834 domain = mono_object_domain (assemblyb);
3836 if (assembly->text_rva)
3839 assembly->text_rva = START_TEXT_RVA;
3841 if (moduleb->is_main) {
3842 mono_image_emit_manifest (moduleb);
3845 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3846 table->rows = 1; /* .<Module> */
3848 alloc_table (table, table->rows);
3850 * Set the first entry.
3852 values = table->values + table->columns;
3853 values [MONO_TYPEDEF_FLAGS] = 0;
3854 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3855 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3856 values [MONO_TYPEDEF_EXTENDS] = 0;
3857 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3858 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3861 * handle global methods
3862 * FIXME: test what to do when global methods are defined in multiple modules.
3864 if (moduleb->global_methods) {
3865 table = &assembly->tables [MONO_TABLE_METHOD];
3866 table->rows += mono_array_length (moduleb->global_methods);
3867 alloc_table (table, table->rows);
3868 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3869 mono_image_get_method_info (
3870 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3872 if (moduleb->global_fields) {
3873 table = &assembly->tables [MONO_TABLE_FIELD];
3874 table->rows += mono_array_length (moduleb->global_fields);
3875 alloc_table (table, table->rows);
3876 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3877 mono_image_get_field_info (
3878 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3881 table = &assembly->tables [MONO_TABLE_MODULE];
3882 alloc_table (table, 1);
3883 mono_image_fill_module_table (domain, moduleb, assembly);
3887 /* Collect all types into a list sorted by their table_idx */
3888 GPtrArray *types = g_ptr_array_new ();
3891 for (i = 0; i < moduleb->num_types; ++i) {
3892 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3893 collect_types (types, type);
3896 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3897 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3898 table->rows += types->len;
3899 alloc_table (table, table->rows);
3901 for (i = 0; i < types->len; ++i) {
3902 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3903 mono_image_get_type_info (domain, type, assembly);
3905 g_ptr_array_free (types, TRUE);
3909 * table->rows is already set above and in mono_image_fill_module_table.
3911 /* add all the custom attributes at the end, once all the indexes are stable */
3912 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3914 /* CAS assembly permissions */
3915 if (assemblyb->permissions_minimum)
3916 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3917 if (assemblyb->permissions_optional)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3919 if (assemblyb->permissions_refused)
3920 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3922 module_add_cattrs (assembly, moduleb);
3925 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3926 fixup_cattrs (assembly);
3930 * mono_image_insert_string:
3931 * @module: module builder object
3934 * Insert @str into the user string stream of @module.
3937 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3939 MonoDynamicImage *assembly;
3944 MONO_ARCH_SAVE_REGS;
3946 if (!module->dynamic_image)
3947 mono_image_module_basic_init (module);
3949 assembly = module->dynamic_image;
3951 if (assembly->save) {
3952 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3953 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3954 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3956 char *swapped = g_malloc (2 * mono_string_length (str));
3957 const char *p = (const char*)mono_string_chars (str);
3959 swap_with_size (swapped, p, 2, mono_string_length (str));
3960 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3964 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3966 mono_image_add_stream_data (&assembly->us, "", 1);
3968 idx = assembly->us.index ++;
3971 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3973 return MONO_TOKEN_STRING | idx;
3977 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3982 klass = obj->vtable->klass;
3983 if (strcmp (klass->name, "MonoMethod") == 0) {
3984 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3985 MonoMethodSignature *sig, *old;
3986 guint32 sig_token, parent;
3989 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3991 nargs = mono_array_length (opt_param_types);
3992 old = method->signature;
3993 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3995 sig->hasthis = old->hasthis;
3996 sig->explicit_this = old->explicit_this;
3997 sig->call_convention = old->call_convention;
3998 sig->generic_param_count = old->generic_param_count;
3999 sig->param_count = old->param_count + nargs;
4000 sig->sentinelpos = old->param_count;
4001 sig->ret = old->ret;
4003 for (i = 0; i < old->param_count; i++)
4004 sig->params [i] = old->params [i];
4006 for (i = 0; i < nargs; i++) {
4007 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4008 sig->params [old->param_count + i] = rt->type;
4011 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4012 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4013 parent >>= MONO_TYPEDEFORREF_BITS;
4015 parent <<= MONO_MEMBERREF_PARENT_BITS;
4016 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4018 sig_token = method_encode_signature (assembly, sig);
4019 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4020 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4021 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4022 ReflectionMethodBuilder rmb;
4023 guint32 parent, sig;
4025 reflection_methodbuilder_from_method_builder (&rmb, mb);
4026 rmb.opt_types = opt_param_types;
4028 sig = method_builder_encode_signature (assembly, &rmb);
4030 parent = mono_image_create_token (assembly, obj, TRUE);
4031 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4033 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4034 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4036 token = mono_image_get_varargs_method_token (
4037 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4039 g_error ("requested method token for %s\n", klass->name);
4046 * mono_image_create_token:
4047 * @assembly: a dynamic assembly
4050 * Get a token to insert in the IL code stream for the given MemberInfo.
4051 * @obj can be one of:
4052 * ConstructorBuilder
4062 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4067 klass = obj->vtable->klass;
4068 if (strcmp (klass->name, "MethodBuilder") == 0) {
4069 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4071 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4072 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4074 token = mono_image_get_methodbuilder_token (assembly, mb);
4075 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4076 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4077 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4079 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4080 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4082 token = mono_image_get_ctorbuilder_token (assembly, mb);
4083 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4084 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4085 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4086 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4087 if (tb->generic_params) {
4088 token = mono_image_get_generic_field_token (assembly, fb);
4090 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4092 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4093 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4094 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4095 } else if (strcmp (klass->name, "MonoType") == 0 ||
4096 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4097 MonoReflectionType *tb = (MonoReflectionType *)obj;
4098 token = mono_metadata_token_from_dor (
4099 mono_image_typedef_or_ref (assembly, tb->type));
4100 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4101 MonoReflectionType *tb = (MonoReflectionType *)obj;
4102 token = mono_metadata_token_from_dor (
4103 mono_image_typedef_or_ref (assembly, tb->type));
4104 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4105 strcmp (klass->name, "MonoMethod") == 0) {
4106 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4107 if (m->method->signature->is_inflated) {
4108 if (create_methodspec)
4109 token = mono_image_get_methodspec_token (assembly, m->method);
4111 token = mono_image_get_inflated_method_token (assembly, m->method);
4112 } else if (m->method->signature->generic_param_count) {
4113 g_assert_not_reached ();
4114 } else if ((m->method->klass->image == &assembly->image) &&
4115 !m->method->klass->generic_inst) {
4116 static guint32 method_table_idx = 0xffffff;
4117 if (m->method->klass->wastypebuilder) {
4118 /* we use the same token as the one that was assigned
4119 * to the Methodbuilder.
4120 * FIXME: do the equivalent for Fields.
4122 token = m->method->token;
4125 * Each token should have a unique index, but the indexes are
4126 * assigned by managed code, so we don't know about them. An
4127 * easy solution is to count backwards...
4129 method_table_idx --;
4130 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4133 token = mono_image_get_methodref_token (assembly, m->method);
4135 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4136 } else if (strcmp (klass->name, "MonoField") == 0) {
4137 MonoReflectionField *f = (MonoReflectionField *)obj;
4138 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4139 static guint32 field_table_idx = 0xffffff;
4141 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4143 token = mono_image_get_fieldref_token (assembly, f);
4145 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4146 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4147 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4148 token = mono_image_get_array_token (assembly, m);
4149 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4150 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4151 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4153 g_error ("requested token for %s\n", klass->name);
4156 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4162 guint32 import_lookup_table;
4166 guint32 import_address_table_rva;
4174 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4176 static MonoDynamicImage*
4177 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4179 static const guchar entrycode [16] = {0xff, 0x25, 0};
4180 MonoDynamicImage *image;
4183 const char *version = mono_get_runtime_version ();
4186 image = GC_MALLOC (sizeof (MonoDynamicImage));
4188 image = g_new0 (MonoDynamicImage, 1);
4191 /* keep in sync with image.c */
4192 image->image.name = assembly_name;
4193 image->image.assembly_name = image->image.name; /* they may be different */
4194 image->image.module_name = module_name;
4195 image->image.version = g_strdup (version);
4196 image->image.dynamic = TRUE;
4198 image->image.references = g_new0 (MonoAssembly*, 1);
4199 image->image.references [0] = NULL;
4201 mono_image_init (&image->image);
4203 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4204 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4205 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4206 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4207 image->handleref = g_hash_table_new (NULL, NULL);
4208 image->tokens = mono_g_hash_table_new (NULL, NULL);
4209 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4210 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4211 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4212 image->gen_params = g_ptr_array_new ();
4214 string_heap_init (&image->sheap);
4215 mono_image_add_stream_data (&image->us, "", 1);
4216 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4217 /* import tables... */
4218 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4219 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4220 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4221 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4222 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4223 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4224 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4225 stream_data_align (&image->code);
4227 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4229 for (i=0; i < 64; ++i) {
4230 image->tables [i].next_idx = 1;
4231 image->tables [i].columns = table_sizes [i];
4234 image->image.assembly = (MonoAssembly*)assembly;
4235 image->run = assembly->run;
4236 image->save = assembly->save;
4242 * mono_image_basic_init:
4243 * @assembly: an assembly builder object
4245 * Create the MonoImage that represents the assembly builder and setup some
4246 * of the helper hash table and the basic metadata streams.
4249 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4251 MonoDynamicAssembly *assembly;
4252 MonoDynamicImage *image;
4254 MONO_ARCH_SAVE_REGS;
4256 if (assemblyb->dynamic_assembly)
4260 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4262 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4265 assembly->assembly.dynamic = TRUE;
4266 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4267 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4268 if (assemblyb->culture)
4269 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4271 assembly->assembly.aname.culture = g_strdup ("");
4273 assembly->run = assemblyb->access != 2;
4274 assembly->save = assemblyb->access != 1;
4276 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4277 assembly->assembly.aname.name = image->image.name;
4278 assembly->assembly.image = &image->image;
4280 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4281 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4285 calc_section_size (MonoDynamicImage *assembly)
4289 /* alignment constraints */
4290 assembly->code.index += 3;
4291 assembly->code.index &= ~3;
4292 assembly->meta_size += 3;
4293 assembly->meta_size &= ~3;
4294 assembly->resources.index += 3;
4295 assembly->resources.index &= ~3;
4297 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4298 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4301 if (assembly->win32_res) {
4302 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4304 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4305 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4309 assembly->sections [MONO_SECTION_RELOC].size = 12;
4310 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4320 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4324 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4326 ResTreeNode *t1 = (ResTreeNode*)a;
4327 ResTreeNode *t2 = (ResTreeNode*)b;
4329 return t1->id - t2->id;
4333 * resource_tree_create:
4335 * Organize the resources into a resource tree.
4337 static ResTreeNode *
4338 resource_tree_create (MonoArray *win32_resources)
4340 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4344 tree = g_new0 (ResTreeNode, 1);
4346 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4347 MonoReflectionWin32Resource *win32_res =
4348 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4352 lang_node = g_new0 (ResTreeNode, 1);
4353 lang_node->id = win32_res->lang_id;
4354 lang_node->win32_res = win32_res;
4356 /* Create type node if neccesary */
4358 for (l = tree->children; l; l = l->next)
4359 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4360 type_node = (ResTreeNode*)l->data;
4365 type_node = g_new0 (ResTreeNode, 1);
4366 type_node->id = win32_res->res_type;
4369 * The resource types have to be sorted otherwise
4370 * Windows Explorer can't display the version information.
4372 tree->children = g_slist_insert_sorted (tree->children,
4373 type_node, resource_tree_compare_by_id);
4376 /* Create res node if neccesary */
4378 for (l = type_node->children; l; l = l->next)
4379 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4380 res_node = (ResTreeNode*)l->data;
4385 res_node = g_new0 (ResTreeNode, 1);
4386 res_node->id = win32_res->res_id;
4387 type_node->children = g_slist_append (type_node->children, res_node);
4390 res_node->children = g_slist_append (res_node->children, lang_node);
4397 * resource_tree_encode:
4399 * Encode the resource tree into the format used in the PE file.
4402 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4405 MonoPEResourceDir dir;
4406 MonoPEResourceDirEntry dir_entry;
4407 MonoPEResourceDataEntry data_entry;
4411 * For the format of the resource directory, see the article
4412 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4416 memset (&dir, 0, sizeof (dir));
4417 memset (&dir_entry, 0, sizeof (dir_entry));
4418 memset (&data_entry, 0, sizeof (data_entry));
4420 g_assert (sizeof (dir) == 16);
4421 g_assert (sizeof (dir_entry) == 8);
4422 g_assert (sizeof (data_entry) == 16);
4424 node->offset = p - begin;
4426 /* IMAGE_RESOURCE_DIRECTORY */
4427 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4429 memcpy (p, &dir, sizeof (dir));
4432 /* Reserve space for entries */
4434 p += sizeof (dir_entry) * dir.res_id_entries;
4436 /* Write children */
4437 for (l = node->children; l; l = l->next) {
4438 ResTreeNode *child = (ResTreeNode*)l->data;
4440 if (child->win32_res) {
4442 child->offset = p - begin;
4444 /* IMAGE_RESOURCE_DATA_ENTRY */
4445 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4446 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4448 memcpy (p, &data_entry, sizeof (data_entry));
4449 p += sizeof (data_entry);
4451 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4452 p += data_entry.rde_size;
4454 resource_tree_encode (child, begin, p, &p);
4458 /* IMAGE_RESOURCE_ENTRY */
4459 for (l = node->children; l; l = l->next) {
4460 ResTreeNode *child = (ResTreeNode*)l->data;
4461 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4463 dir_entry.is_dir = child->win32_res ? 0 : 1;
4464 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4466 memcpy (entries, &dir_entry, sizeof (dir_entry));
4467 entries += sizeof (dir_entry);
4474 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4479 MonoReflectionWin32Resource *win32_res;
4482 if (!assemblyb->win32_resources)
4486 * Resources are stored in a three level tree inside the PE file.
4487 * - level one contains a node for each type of resource
4488 * - level two contains a node for each resource
4489 * - level three contains a node for each instance of a resource for a
4490 * specific language.
4493 tree = resource_tree_create (assemblyb->win32_resources);
4495 /* Estimate the size of the encoded tree */
4497 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4498 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4499 size += mono_array_length (win32_res->res_data);
4501 /* Directory structure */
4502 size += mono_array_length (assemblyb->win32_resources) * 256;
4503 p = buf = g_malloc (size);
4505 resource_tree_encode (tree, p, p, &p);
4507 g_assert (p - buf < size);
4509 assembly->win32_res = g_malloc (p - buf);
4510 assembly->win32_res_size = p - buf;
4511 memcpy (assembly->win32_res, buf, p - buf);
4517 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4519 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4522 p += sizeof (MonoPEResourceDir);
4523 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4524 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4525 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4526 if (dir_entry->is_dir) {
4527 fixup_resource_directory (res_section, child, rva);
4529 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4530 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4533 p += sizeof (MonoPEResourceDirEntry);
4538 * mono_image_create_pefile:
4539 * @mb: a module builder object
4541 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4542 * assembly->pefile where it can be easily retrieved later in chunks.
4545 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4546 MonoMSDOSHeader *msdos;
4547 MonoDotNetHeader *header;
4548 MonoSectionTable *section;
4549 MonoCLIHeader *cli_header;
4550 guint32 size, image_size, virtual_base, text_offset;
4551 guint32 header_start, section_start, file_offset, virtual_offset;
4552 MonoDynamicImage *assembly;
4553 MonoReflectionAssemblyBuilder *assemblyb;
4554 MonoDynamicStream *pefile;
4556 guint32 *rva, value;
4559 static const unsigned char msheader[] = {
4560 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4561 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4564 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4565 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4566 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4567 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4570 assemblyb = mb->assemblyb;
4572 mono_image_basic_init (assemblyb);
4573 assembly = mb->dynamic_image;
4575 /* already created */
4576 if (assembly->pefile.index)
4579 mono_image_build_metadata (mb);
4581 if (mb->is_main && assemblyb->resources) {
4582 int len = mono_array_length (assemblyb->resources);
4583 for (i = 0; i < len; ++i)
4584 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4587 if (mb->resources) {
4588 int len = mono_array_length (mb->resources);
4589 for (i = 0; i < len; ++i)
4590 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4593 build_compressed_metadata (assembly);
4596 assembly_add_win32_resources (assembly, assemblyb);
4598 nsections = calc_section_size (assembly);
4600 pefile = &assembly->pefile;
4602 /* The DOS header and stub */
4603 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4604 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4606 /* the dotnet header */
4607 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4609 /* the section tables */
4610 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4612 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4613 virtual_offset = VIRT_ALIGN;
4616 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4617 if (!assembly->sections [i].size)
4620 file_offset += FILE_ALIGN - 1;
4621 file_offset &= ~(FILE_ALIGN - 1);
4622 virtual_offset += VIRT_ALIGN - 1;
4623 virtual_offset &= ~(VIRT_ALIGN - 1);
4625 assembly->sections [i].offset = file_offset;
4626 assembly->sections [i].rva = virtual_offset;
4628 file_offset += assembly->sections [i].size;
4629 virtual_offset += assembly->sections [i].size;
4630 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4633 file_offset += FILE_ALIGN - 1;
4634 file_offset &= ~(FILE_ALIGN - 1);
4635 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4637 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4639 /* back-patch info */
4640 msdos = (MonoMSDOSHeader*)pefile->data;
4641 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4642 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4643 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4645 header = (MonoDotNetHeader*)(pefile->data + header_start);
4646 header->pesig [0] = 'P';
4647 header->pesig [1] = 'E';
4649 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4650 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4651 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4652 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4653 if (assemblyb->pekind == 1) {
4655 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4658 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4661 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4663 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4664 header->pe.pe_major = 6;
4665 header->pe.pe_minor = 0;
4666 size = assembly->sections [MONO_SECTION_TEXT].size;
4667 size += FILE_ALIGN - 1;
4668 size &= ~(FILE_ALIGN - 1);
4669 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4670 size = assembly->sections [MONO_SECTION_RSRC].size;
4671 size += FILE_ALIGN - 1;
4672 size &= ~(FILE_ALIGN - 1);
4673 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4674 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4675 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4676 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4677 /* pe_rva_entry_point always at the beginning of the text section */
4678 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4680 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4681 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4682 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4683 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4684 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4685 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4686 size = section_start;
4687 size += FILE_ALIGN - 1;
4688 size &= ~(FILE_ALIGN - 1);
4689 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4691 size += VIRT_ALIGN - 1;
4692 size &= ~(VIRT_ALIGN - 1);
4693 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4696 // Translate the PEFileKind value to the value expected by the Windows loader
4702 // PEFileKinds.Dll == 1
4703 // PEFileKinds.ConsoleApplication == 2
4704 // PEFileKinds.WindowApplication == 3
4707 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4708 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4710 if (assemblyb->pekind == 3)
4715 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4717 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4718 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4719 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4720 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4721 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4722 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4724 /* fill data directory entries */
4726 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4727 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4729 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4730 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4732 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4733 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4734 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4735 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4736 /* patch imported function RVA name */
4737 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4738 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4740 /* the import table */
4741 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4742 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4743 /* patch imported dll RVA name and other entries in the dir */
4744 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4745 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4746 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4747 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4748 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4749 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4751 p = (assembly->code.data + assembly->ilt_offset);
4752 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4753 *p++ = (value) & 0xff;
4754 *p++ = (value >> 8) & (0xff);
4755 *p++ = (value >> 16) & (0xff);
4756 *p++ = (value >> 24) & (0xff);
4758 /* the CLI header info */
4759 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4760 cli_header->ch_size = GUINT32_FROM_LE (72);
4761 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4762 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4763 if (assemblyb->entry_point) {
4764 guint32 table_idx = 0;
4765 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4766 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4767 table_idx = methodb->table_idx;
4769 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4771 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4773 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4775 /* The embedded managed resources */
4776 text_offset = assembly->text_rva + assembly->code.index;
4777 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4778 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4779 text_offset += assembly->resources.index;
4780 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4781 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4782 text_offset += assembly->meta_size;
4783 if (assembly->strong_name_size) {
4784 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4785 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4786 text_offset += assembly->strong_name_size;
4789 /* write the section tables and section content */
4790 section = (MonoSectionTable*)(pefile->data + section_start);
4791 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4792 static const char *section_names [] = {
4793 ".text", ".rsrc", ".reloc"
4795 if (!assembly->sections [i].size)
4797 strcpy (section->st_name, section_names [i]);
4798 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4799 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4800 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4801 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4802 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4803 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4804 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4806 case MONO_SECTION_TEXT:
4807 /* patch entry point */
4808 p = (assembly->code.data + 2);
4809 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4810 *p++ = (value) & 0xff;
4811 *p++ = (value >> 8) & 0xff;
4812 *p++ = (value >> 16) & 0xff;
4813 *p++ = (value >> 24) & 0xff;
4815 text_offset = assembly->sections [i].offset;
4816 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4817 text_offset += assembly->code.index;
4818 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4819 text_offset += assembly->resources.index;
4820 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4821 text_offset += assembly->meta_size;
4822 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4824 g_free (assembly->image.raw_metadata);
4826 case MONO_SECTION_RELOC:
4827 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4828 *rva = GUINT32_FROM_LE (assembly->text_rva);
4830 *rva = GUINT32_FROM_LE (12);
4832 data16 = (guint16*)rva;
4834 * the entrypoint is always at the start of the text section
4835 * 3 is IMAGE_REL_BASED_HIGHLOW
4836 * 2 is patch_size_rva - text_rva
4838 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4840 *data16 = 0; /* terminate */
4842 case MONO_SECTION_RSRC:
4843 if (assembly->win32_res) {
4844 text_offset = assembly->sections [i].offset;
4846 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4847 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4849 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4853 g_assert_not_reached ();
4858 /* check that the file is properly padded */
4861 FILE *f = fopen ("mypetest.exe", "w");
4862 fwrite (pefile->data, pefile->index, 1, f);
4868 MonoReflectionModule *
4869 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4873 MonoImageOpenStatus status;
4874 MonoDynamicAssembly *assembly;
4876 name = mono_string_to_utf8 (fileName);
4878 image = mono_image_open (name, &status);
4881 if (status == MONO_IMAGE_ERROR_ERRNO)
4882 exc = mono_get_exception_file_not_found (fileName);
4884 exc = mono_get_exception_bad_image_format (name);
4886 mono_raise_exception (exc);
4891 assembly = ab->dynamic_assembly;
4892 image->assembly = (MonoAssembly*)assembly;
4894 mono_assembly_load_references (image, &status);
4896 mono_image_close (image);
4897 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4900 return mono_module_get_object (mono_domain_get (), image);
4904 * We need to return always the same object for MethodInfo, FieldInfo etc..
4905 * but we need to consider the reflected type.
4906 * type uses a different hash, since it uses custom hash/equal functions.
4911 MonoClass *refclass;
4915 reflected_equal (gconstpointer a, gconstpointer b) {
4916 const ReflectedEntry *ea = a;
4917 const ReflectedEntry *eb = b;
4919 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4923 reflected_hash (gconstpointer a) {
4924 const ReflectedEntry *ea = a;
4925 return GPOINTER_TO_UINT (ea->item);
4928 #define CHECK_OBJECT(t,p,k) \
4934 mono_domain_lock (domain); \
4935 if (!domain->refobject_hash) \
4936 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4937 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4938 mono_domain_unlock (domain); \
4944 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4946 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4949 #define CACHE_OBJECT(p,o,k) \
4951 ReflectedEntry *e = ALLOC_REFENTRY; \
4953 e->refclass = (k); \
4954 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4955 mono_domain_unlock (domain); \
4959 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4961 /* this is done only once */
4962 mono_domain_lock (domain);
4963 CACHE_OBJECT (assembly, res, NULL);
4967 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4969 /* this is done only once */
4970 mono_domain_lock (domain);
4971 CACHE_OBJECT (module, res, NULL);
4975 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4977 MonoDynamicImage *image = moduleb->dynamic_image;
4978 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4981 * FIXME: we already created an image in mono_image_basic_init (), but
4982 * we don't know which module it belongs to, since that is only
4983 * determined at assembly save time.
4985 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4986 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4988 moduleb->module.image = &image->image;
4989 moduleb->dynamic_image = image;
4990 register_module (mono_object_domain (moduleb), moduleb, image);
4995 * mono_assembly_get_object:
4996 * @domain: an app domain
4997 * @assembly: an assembly
4999 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5001 MonoReflectionAssembly*
5002 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5004 static MonoClass *System_Reflection_Assembly;
5005 MonoReflectionAssembly *res;
5007 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5008 if (!System_Reflection_Assembly)
5009 System_Reflection_Assembly = mono_class_from_name (
5010 mono_defaults.corlib, "System.Reflection", "Assembly");
5011 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5012 res->assembly = assembly;
5013 CACHE_OBJECT (assembly, res, NULL);
5019 MonoReflectionModule*
5020 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5022 static MonoClass *System_Reflection_Module;
5023 MonoReflectionModule *res;
5025 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5026 if (!System_Reflection_Module)
5027 System_Reflection_Module = mono_class_from_name (
5028 mono_defaults.corlib, "System.Reflection", "Module");
5029 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5032 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5034 res->fqname = mono_string_new (domain, image->name);
5035 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5036 res->scopename = mono_string_new (domain, image->module_name);
5038 if (image->assembly->image == image) {
5039 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5042 g_assert (image->assembly->image->modules);
5044 while (image->assembly->image->modules [i]) {
5045 if (image->assembly->image->modules [i] == image)
5046 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5048 g_assert (res->token);
5051 mono_image_addref (image);
5053 CACHE_OBJECT (image, res, NULL);
5057 MonoReflectionModule*
5058 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5060 static MonoClass *System_Reflection_Module;
5061 MonoReflectionModule *res;
5062 MonoTableInfo *table;
5063 guint32 cols [MONO_FILE_SIZE];
5065 guint32 i, name_idx;
5068 if (!System_Reflection_Module)
5069 System_Reflection_Module = mono_class_from_name (
5070 mono_defaults.corlib, "System.Reflection", "Module");
5071 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5073 table = &image->tables [MONO_TABLE_FILE];
5074 g_assert (table_index < table->rows);
5075 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5078 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5079 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5081 /* Check whenever the row has a corresponding row in the moduleref table */
5082 table = &image->tables [MONO_TABLE_MODULEREF];
5083 for (i = 0; i < table->rows; ++i) {
5084 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5085 val = mono_metadata_string_heap (image, name_idx);
5086 if (strcmp (val, name) == 0)
5087 res->image = image->modules [i];
5090 res->fqname = mono_string_new (domain, name);
5091 res->name = mono_string_new (domain, name);
5092 res->scopename = mono_string_new (domain, name);
5093 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5094 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5100 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5102 if ((t1->type != t2->type) ||
5103 (t1->byref != t2->byref))
5107 case MONO_TYPE_VOID:
5108 case MONO_TYPE_BOOLEAN:
5109 case MONO_TYPE_CHAR:
5120 case MONO_TYPE_STRING:
5123 case MONO_TYPE_OBJECT:
5124 case MONO_TYPE_TYPEDBYREF:
5126 case MONO_TYPE_VALUETYPE:
5127 case MONO_TYPE_CLASS:
5128 case MONO_TYPE_SZARRAY:
5129 return t1->data.klass == t2->data.klass;
5131 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5132 case MONO_TYPE_ARRAY:
5133 if (t1->data.array->rank != t2->data.array->rank)
5135 return t1->data.array->eklass == t2->data.array->eklass;
5136 case MONO_TYPE_GENERICINST: {
5138 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5140 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5142 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5143 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5149 case MONO_TYPE_MVAR:
5150 return t1->data.generic_param == t2->data.generic_param;
5152 g_error ("implement type compare for %0x!", t1->type);
5160 mymono_metadata_type_hash (MonoType *t1)
5166 hash |= t1->byref << 6; /* do not collide with t1->type values */
5168 case MONO_TYPE_VALUETYPE:
5169 case MONO_TYPE_CLASS:
5170 case MONO_TYPE_SZARRAY:
5171 /* check if the distribution is good enough */
5172 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5174 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5179 static MonoReflectionGenericInst*
5180 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5182 static MonoClass *System_Reflection_MonoGenericInst;
5183 MonoReflectionGenericInst *res;
5184 MonoGenericInst *ginst;
5187 if (!System_Reflection_MonoGenericInst) {
5188 System_Reflection_MonoGenericInst = mono_class_from_name (
5189 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5190 g_assert (System_Reflection_MonoGenericInst);
5193 ginst = geninst->data.generic_inst;
5194 gklass = mono_class_from_mono_type (ginst->generic_type);
5196 mono_class_init (ginst->klass);
5198 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5200 res->type.type = geninst;
5201 if (gklass->wastypebuilder && gklass->reflection_info)
5202 res->generic_type = gklass->reflection_info;
5204 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5210 * mono_type_get_object:
5211 * @domain: an app domain
5214 * Return an System.MonoType object representing the type @type.
5217 mono_type_get_object (MonoDomain *domain, MonoType *type)
5219 MonoReflectionType *res;
5220 MonoClass *klass = mono_class_from_mono_type (type);
5222 mono_domain_lock (domain);
5223 if (!domain->type_hash)
5224 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5225 (GCompareFunc)mymono_metadata_type_equal);
5226 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5227 mono_domain_unlock (domain);
5230 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5231 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5232 mono_g_hash_table_insert (domain->type_hash, type, res);
5233 mono_domain_unlock (domain);
5236 if (klass->reflection_info && !klass->wastypebuilder) {
5237 /* g_assert_not_reached (); */
5238 /* should this be considered an error condition? */
5240 mono_domain_unlock (domain);
5241 return klass->reflection_info;
5244 mono_class_init (klass);
5245 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5247 mono_g_hash_table_insert (domain->type_hash, type, res);
5248 mono_domain_unlock (domain);
5253 * mono_method_get_object:
5254 * @domain: an app domain
5256 * @refclass: the reflected type (can be NULL)
5258 * Return an System.Reflection.MonoMethod object representing the method @method.
5260 MonoReflectionMethod*
5261 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5264 * We use the same C representation for methods and constructors, but the type
5265 * name in C# is different.
5269 MonoReflectionMethod *ret;
5272 refclass = method->klass;
5274 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5275 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5276 cname = "MonoCMethod";
5278 cname = "MonoMethod";
5279 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5281 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5282 ret->method = method;
5283 ret->name = mono_string_new (domain, method->name);
5284 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5285 CACHE_OBJECT (method, ret, refclass);
5290 * mono_field_get_object:
5291 * @domain: an app domain
5295 * Return an System.Reflection.MonoField object representing the field @field
5298 MonoReflectionField*
5299 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5301 MonoReflectionField *res;
5304 CHECK_OBJECT (MonoReflectionField *, field, klass);
5305 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5306 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5309 res->name = mono_string_new (domain, field->name);
5310 if (field->generic_info)
5311 res->attrs = field->generic_info->generic_type->attrs;
5313 res->attrs = field->type->attrs;
5314 res->type = mono_type_get_object (domain, field->type);
5315 CACHE_OBJECT (field, res, klass);
5320 * mono_property_get_object:
5321 * @domain: an app domain
5323 * @property: a property
5325 * Return an System.Reflection.MonoProperty object representing the property @property
5328 MonoReflectionProperty*
5329 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5331 MonoReflectionProperty *res;
5334 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5335 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5336 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5338 res->property = property;
5339 CACHE_OBJECT (property, res, klass);
5344 * mono_event_get_object:
5345 * @domain: an app domain
5349 * Return an System.Reflection.MonoEvent object representing the event @event
5352 MonoReflectionEvent*
5353 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5355 MonoReflectionEvent *res;
5358 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5359 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5360 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5363 CACHE_OBJECT (event, res, klass);
5368 * mono_param_get_objects:
5369 * @domain: an app domain
5372 * Return an System.Reflection.ParameterInfo array object representing the parameters
5373 * in the method @method.
5376 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5378 static MonoClass *System_Reflection_ParameterInfo;
5380 MonoArray *res = NULL;
5381 MonoReflectionMethod *member = NULL;
5382 MonoReflectionParameter *param = NULL;
5383 char **names, **blobs = NULL;
5384 MonoObject *dbnull = mono_get_dbnull_object (domain);
5387 if (!System_Reflection_ParameterInfo)
5388 System_Reflection_ParameterInfo = mono_class_from_name (
5389 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5391 if (!method->signature->param_count)
5392 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5394 /* Note: the cache is based on the address of the signature into the method
5395 * since we already cache MethodInfos with the method as keys.
5397 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5399 member = mono_method_get_object (domain, method, NULL);
5400 names = g_new (char *, method->signature->param_count);
5401 mono_method_get_param_names (method, (const char **) names);
5403 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5404 for (i = 0; i < method->signature->param_count; ++i) {
5405 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5406 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5407 param->MemberImpl = (MonoObject*)member;
5408 param->NameImpl = mono_string_new (domain, names [i]);
5409 param->PositionImpl = i;
5410 param->AttrsImpl = method->signature->params [i]->attrs;
5412 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5413 param->DefaultValueImpl = dbnull;
5415 MonoType *type = param->ClassImpl->type;
5418 blobs = g_new0 (char *, method->signature->param_count);
5419 get_default_param_value_blobs (method, blobs);
5422 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5424 if (!param->DefaultValueImpl) {
5425 param->DefaultValueImpl = dbnull;
5429 mono_array_set (res, gpointer, i, param);
5434 CACHE_OBJECT (&(method->signature), res, NULL);
5439 mono_get_dbnull_object (MonoDomain *domain)
5443 static MonoClassField *dbnull_value_field = NULL;
5445 if (!dbnull_value_field) {
5446 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5447 mono_class_init (klass);
5448 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5449 g_assert (dbnull_value_field);
5451 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5458 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5460 guint32 param_index, i, lastp, crow = 0;
5461 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5464 MonoClass *klass = method->klass;
5465 MonoImage *image = klass->image;
5466 MonoDomain *domain = mono_domain_get ();
5467 MonoMethodSignature *methodsig = method->signature;
5469 MonoTableInfo *constt;
5470 MonoTableInfo *methodt;
5471 MonoTableInfo *paramt;
5473 if (!methodsig->param_count)
5476 if (klass->generic_inst) {
5477 return; /* FIXME - ??? */
5480 mono_class_init (klass);
5482 if (klass->image->dynamic) {
5486 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5487 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5488 constt = &image->tables [MONO_TABLE_CONSTANT];
5490 for (i = 0; i < klass->method.count; ++i) {
5491 if (method == klass->methods [i]) {
5492 idx = klass->method.first + i;
5497 g_assert (idx != -1);
5499 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5500 if (idx + 1 < methodt->rows)
5501 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5503 lastp = paramt->rows + 1;
5505 for (i = param_index; i < lastp; ++i) {
5508 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5509 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5511 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5514 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5519 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5520 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5527 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5536 klass = mono_class_from_mono_type (type);
5537 if (klass->valuetype) {
5538 object = mono_object_new (domain, klass);
5539 retval = ((gchar *) object + sizeof (MonoObject));
5544 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5551 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5555 memset (assembly, 0, sizeof (MonoAssemblyName));
5557 assembly->culture = "";
5558 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5560 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5563 while (*p == ' ' || *p == ',') {
5572 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5574 assembly->major = strtoul (p, &s, 10);
5575 if (s == p || *s != '.')
5578 assembly->minor = strtoul (p, &s, 10);
5579 if (s == p || *s != '.')
5582 assembly->build = strtoul (p, &s, 10);
5583 if (s == p || *s != '.')
5586 assembly->revision = strtoul (p, &s, 10);
5590 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5592 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5593 assembly->culture = "";
5596 assembly->culture = p;
5597 while (*p && *p != ',') {
5601 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5603 if (strncmp (p, "null", 4) == 0) {
5608 while (*p && *p != ',') {
5611 len = (p - start + 1);
5612 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5613 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5614 g_strlcpy (assembly->public_key_token, start, len);
5617 while (*p && *p != ',')
5621 while (*p == ' ' || *p == ',') {
5635 * mono_reflection_parse_type:
5638 * Parse a type name as accepted by the GetType () method and output the info
5639 * extracted in the info structure.
5640 * the name param will be mangled, so, make a copy before passing it to this function.
5641 * The fields in info will be valid until the memory pointed to by name is valid.
5642 * Returns 0 on parse error.
5643 * See also mono_type_get_name () below.
5646 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5648 char *start, *p, *w, *last_point, *startn;
5649 int in_modifiers = 0;
5650 int isbyref = 0, rank;
5652 start = p = w = name;
5654 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5655 info->name = info->name_space = NULL;
5656 info->nested = NULL;
5657 info->modifiers = NULL;
5659 /* last_point separates the namespace from the name */
5665 *p = 0; /* NULL terminate the name */
5667 info->nested = g_list_append (info->nested, startn);
5668 /* we have parsed the nesting namespace + name */
5672 info->name_space = start;
5674 info->name = last_point + 1;
5676 info->name_space = (char *)"";
5702 info->name_space = start;
5704 info->name = last_point + 1;
5706 info->name_space = (char *)"";
5713 if (isbyref) /* only one level allowed by the spec */
5716 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5720 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5731 else if (*p != '*') /* '*' means unknown lower bound */
5737 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5749 return 0; /* missing assembly name */
5750 if (!assembly_name_to_aname (&info->assembly, p))
5757 if (info->assembly.name)
5760 *w = 0; /* terminate class name */
5761 if (!info->name || !*info->name)
5763 /* add other consistency checks */
5768 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5775 image = mono_defaults.corlib;
5778 klass = mono_class_from_name_case (image, info->name_space, info->name);
5780 klass = mono_class_from_name (image, info->name_space, info->name);
5783 for (mod = info->nested; mod; mod = mod->next) {
5786 mono_class_init (klass);
5787 nested = klass->nested_classes;
5790 klass = nested->data;
5792 if (g_strcasecmp (klass->name, mod->data) == 0)
5795 if (strcmp (klass->name, mod->data) == 0)
5799 nested = nested->next;
5806 mono_class_init (klass);
5807 for (mod = info->modifiers; mod; mod = mod->next) {
5808 modval = GPOINTER_TO_UINT (mod->data);
5809 if (!modval) { /* byref: must be last modifier */
5810 return &klass->this_arg;
5811 } else if (modval == -1) {
5812 klass = mono_ptr_class_get (&klass->byval_arg);
5813 } else { /* array rank */
5814 klass = mono_array_class_get (klass, modval);
5816 mono_class_init (klass);
5819 return &klass->byval_arg;
5823 * mono_reflection_get_type:
5824 * @image: a metadata context
5825 * @info: type description structure
5826 * @ignorecase: flag for case-insensitive string compares
5827 * @type_resolve: whenever type resolve was already tried
5829 * Build a MonoType from the type description in @info.
5834 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5837 MonoReflectionAssembly *assembly;
5841 type = mono_reflection_get_type_internal (image, info, ignorecase);
5844 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5847 /* FIXME: Enabling this causes regressions (#65577) */
5853 *type_resolve = TRUE;
5857 /* Reconstruct the type name */
5858 fullName = g_string_new ("");
5859 if (info->name_space && (info->name_space [0] != '\0'))
5860 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5862 g_string_printf (fullName, info->name);
5863 for (mod = info->nested; mod; mod = mod->next)
5864 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5866 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5867 if (assembly && (!image || (assembly->assembly->image == image))) {
5869 if (assembly->assembly->dynamic) {
5870 /* Enumerate all modules */
5871 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5875 if (abuilder->modules) {
5876 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5877 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5878 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5884 if (!type && abuilder->loaded_modules) {
5885 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5886 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5887 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5894 type = mono_reflection_get_type_internal (assembly->assembly->image,
5897 g_string_free (fullName, TRUE);
5902 * mono_reflection_type_from_name:
5904 * @image: a metadata context (can be NULL).
5906 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5907 * it defaults to get the type from @image or, if @image is NULL or loading
5908 * from it fails, uses corlib.
5912 mono_reflection_type_from_name (char *name, MonoImage *image)
5915 MonoTypeNameParse info;
5916 MonoAssembly *assembly;
5918 gboolean type_resolve = FALSE;
5920 /* Make a copy since parse_type modifies its argument */
5921 tmp = g_strdup (name);
5923 /*g_print ("requested type %s\n", str);*/
5924 if (!mono_reflection_parse_type (tmp, &info)) {
5926 g_list_free (info.modifiers);
5927 g_list_free (info.nested);
5931 if (info.assembly.name) {
5932 assembly = mono_assembly_loaded (&info.assembly);
5934 /* then we must load the assembly ourselve - see #60439 */
5935 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5938 g_list_free (info.modifiers);
5939 g_list_free (info.nested);
5943 image = assembly->image;
5944 } else if (image == NULL) {
5945 image = mono_defaults.corlib;
5948 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5949 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5950 image = mono_defaults.corlib;
5951 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5955 g_list_free (info.modifiers);
5956 g_list_free (info.nested);
5961 * mono_reflection_get_token:
5963 * Return the metadata token of OBJ which should be an object
5964 * representing a metadata element.
5967 mono_reflection_get_token (MonoObject *obj)
5972 klass = obj->vtable->klass;
5974 if (strcmp (klass->name, "MethodBuilder") == 0) {
5975 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5977 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5978 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5979 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5981 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5982 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5983 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5984 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5985 if (tb->generic_params) {
5986 g_assert_not_reached ();
5988 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5990 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5991 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5992 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5993 } else if (strcmp (klass->name, "MonoType") == 0) {
5994 MonoReflectionType *tb = (MonoReflectionType *)obj;
5995 token = mono_class_from_mono_type (tb->type)->type_token;
5996 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5997 strcmp (klass->name, "MonoMethod") == 0) {
5998 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5999 if (m->method->signature->is_inflated) {
6000 g_assert_not_reached ();
6001 } else if (m->method->signature->generic_param_count) {
6002 g_assert_not_reached ();
6003 } else if (m->method->klass->generic_inst) {
6004 g_assert_not_reached ();
6006 token = m->method->token;
6008 } else if (strcmp (klass->name, "MonoField") == 0) {
6009 MonoReflectionField *f = (MonoReflectionField*)obj;
6011 token = mono_class_get_field_token (f->field);
6012 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6013 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6015 token = mono_class_get_property_token (p->property);
6016 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6017 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6019 token = mono_class_get_event_token (p->event);
6020 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6021 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6023 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6024 } else if (strcmp (klass->name, "Module") == 0) {
6025 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6028 } else if (strcmp (klass->name, "Assembly") == 0) {
6029 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6031 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6032 MonoException *ex = mono_get_exception_not_implemented (msg);
6034 mono_raise_exception (ex);
6041 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6043 int slen, type = t->type;
6048 case MONO_TYPE_BOOLEAN: {
6049 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6054 case MONO_TYPE_CHAR:
6056 case MONO_TYPE_I2: {
6057 guint16 *val = g_malloc (sizeof (guint16));
6062 #if SIZEOF_VOID_P == 4
6068 case MONO_TYPE_I4: {
6069 guint32 *val = g_malloc (sizeof (guint32));
6074 #if SIZEOF_VOID_P == 8
6075 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6080 case MONO_TYPE_I8: {
6081 guint64 *val = g_malloc (sizeof (guint64));
6086 case MONO_TYPE_VALUETYPE:
6087 if (t->data.klass->enumtype) {
6088 type = t->data.klass->enum_basetype->type;
6091 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6094 case MONO_TYPE_STRING:
6095 if (*p == (char)0xFF) {
6099 slen = mono_metadata_decode_value (p, &p);
6101 return mono_string_new_len (mono_domain_get (), p, slen);
6102 case MONO_TYPE_CLASS: {
6105 if (*p == (char)0xFF) {
6110 slen = mono_metadata_decode_value (p, &p);
6111 n = g_memdup (p, slen + 1);
6113 t = mono_reflection_type_from_name (n, image);
6115 g_warning ("Cannot load type '%s'", n);
6119 return mono_type_get_object (mono_domain_get (), t);
6123 case MONO_TYPE_OBJECT: {
6126 MonoClass *subc = NULL;
6131 } else if (subt == 0x0E) {
6132 type = MONO_TYPE_STRING;
6134 } else if (subt == 0x55) {
6137 slen = mono_metadata_decode_value (p, &p);
6138 n = g_memdup (p, slen + 1);
6140 t = mono_reflection_type_from_name (n, image);
6142 g_warning ("Cannot load type '%s'", n);
6145 subc = mono_class_from_mono_type (t);
6146 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6147 MonoType simple_type = {{0}};
6148 simple_type.type = subt;
6149 subc = mono_class_from_mono_type (&simple_type);
6151 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6153 val = load_cattr_value (image, &subc->byval_arg, p, end);
6154 obj = mono_object_new (mono_domain_get (), subc);
6155 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6159 case MONO_TYPE_SZARRAY: {
6161 guint32 i, alen, basetype;
6164 if (alen == 0xffffffff) {
6168 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6169 basetype = t->data.klass->byval_arg.type;
6174 case MONO_TYPE_BOOLEAN:
6175 for (i = 0; i < alen; i++) {
6176 MonoBoolean val = *p++;
6177 mono_array_set (arr, MonoBoolean, i, val);
6180 case MONO_TYPE_CHAR:
6183 for (i = 0; i < alen; i++) {
6184 guint16 val = read16 (p);
6185 mono_array_set (arr, guint16, i, val);
6192 for (i = 0; i < alen; i++) {
6193 guint32 val = read32 (p);
6194 mono_array_set (arr, guint32, i, val);
6201 for (i = 0; i < alen; i++) {
6202 guint64 val = read64 (p);
6203 mono_array_set (arr, guint64, i, val);
6207 case MONO_TYPE_CLASS:
6208 case MONO_TYPE_OBJECT:
6209 case MONO_TYPE_STRING:
6210 for (i = 0; i < alen; i++) {
6211 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6212 mono_array_set (arr, gpointer, i, item);
6216 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6222 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6228 type_is_reference (MonoType *type)
6230 switch (type->type) {
6231 case MONO_TYPE_BOOLEAN:
6232 case MONO_TYPE_CHAR:
6245 case MONO_TYPE_VALUETYPE:
6253 free_param_data (MonoMethodSignature *sig, void **params) {
6255 for (i = 0; i < sig->param_count; ++i) {
6256 if (!type_is_reference (sig->params [i]))
6257 g_free (params [i]);
6262 * Find the method index in the metadata methodDef table.
6263 * Later put these three helper methods in metadata and export them.
6266 find_method_index (MonoMethod *method) {
6267 MonoClass *klass = method->klass;
6270 for (i = 0; i < klass->method.count; ++i) {
6271 if (method == klass->methods [i])
6272 return klass->method.first + 1 + i;
6278 * Find the field index in the metadata FieldDef table.
6281 find_field_index (MonoClass *klass, MonoClassField *field) {
6284 for (i = 0; i < klass->field.count; ++i) {
6285 if (field == &klass->fields [i])
6286 return klass->field.first + 1 + i;
6292 * Find the property index in the metadata Property table.
6295 find_property_index (MonoClass *klass, MonoProperty *property) {
6298 for (i = 0; i < klass->property.count; ++i) {
6299 if (property == &klass->properties [i])
6300 return klass->property.first + 1 + i;
6306 * Find the event index in the metadata Event table.
6309 find_event_index (MonoClass *klass, MonoEvent *event) {
6312 for (i = 0; i < klass->event.count; ++i) {
6313 if (event == &klass->events [i])
6314 return klass->event.first + 1 + i;
6320 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6322 const char *p = data;
6324 guint32 i, j, num_named;
6328 mono_class_init (method->klass);
6331 attr = mono_object_new (mono_domain_get (), method->klass);
6332 mono_runtime_invoke (method, attr, NULL, NULL);
6336 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6339 /*g_print ("got attr %s\n", method->klass->name);*/
6341 params = g_new (void*, method->signature->param_count);
6345 for (i = 0; i < method->signature->param_count; ++i) {
6346 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6350 attr = mono_object_new (mono_domain_get (), method->klass);
6351 mono_runtime_invoke (method, attr, params, NULL);
6352 free_param_data (method->signature, params);
6354 num_named = read16 (named);
6356 for (j = 0; j < num_named; j++) {
6358 char *name, named_type, data_type;
6359 named_type = *named++;
6360 data_type = *named++; /* type of data */
6361 if (data_type == 0x55) {
6364 type_len = mono_metadata_decode_blob_size (named, &named);
6365 type_name = g_malloc (type_len + 1);
6366 memcpy (type_name, named, type_len);
6367 type_name [type_len] = 0;
6369 /* FIXME: lookup the type and check type consistency */
6370 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6371 /* this seems to be the type of the element of the array */
6372 /* g_print ("skipping 0x%02x after prop\n", *named); */
6375 name_len = mono_metadata_decode_blob_size (named, &named);
6376 name = g_malloc (name_len + 1);
6377 memcpy (name, named, name_len);
6378 name [name_len] = 0;
6380 if (named_type == 0x53) {
6381 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6382 void *val = load_cattr_value (image, field->type, named, &named);
6383 mono_field_set_value (attr, field, val);
6384 if (!type_is_reference (field->type))
6386 } else if (named_type == 0x54) {
6389 MonoType *prop_type;
6391 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6392 /* can we have more that 1 arg in a custom attr named property? */
6393 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6394 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6395 mono_property_set_value (prop, attr, pparams, NULL);
6396 if (!type_is_reference (prop_type))
6397 g_free (pparams [0]);
6406 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6413 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6414 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6415 for (i = 0; i < cinfo->num_attrs; ++i) {
6416 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6417 mono_array_set (result, gpointer, i, attr);
6423 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6425 guint32 mtoken, i, len;
6426 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6428 MonoCustomAttrInfo *ainfo;
6429 GList *tmp, *list = NULL;
6432 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6434 i = mono_metadata_custom_attrs_from_index (image, idx);
6438 while (i < ca->rows) {
6439 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6441 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6444 len = g_list_length (list);
6447 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6448 ainfo->num_attrs = len;
6449 ainfo->image = image;
6450 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6451 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6452 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6453 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6454 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6455 mtoken |= MONO_TOKEN_METHOD_DEF;
6457 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6458 mtoken |= MONO_TOKEN_MEMBER_REF;
6461 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6464 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6465 if (!ainfo->attrs [i].ctor)
6466 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6467 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6468 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6469 ainfo->attrs [i].data = data;
6477 mono_custom_attrs_from_method (MonoMethod *method)
6479 MonoCustomAttrInfo *cinfo;
6482 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6484 idx = find_method_index (method);
6485 idx <<= MONO_CUSTOM_ATTR_BITS;
6486 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6487 return mono_custom_attrs_from_index (method->klass->image, idx);
6491 mono_custom_attrs_from_class (MonoClass *klass)
6493 MonoCustomAttrInfo *cinfo;
6496 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6498 idx = mono_metadata_token_index (klass->type_token);
6499 idx <<= MONO_CUSTOM_ATTR_BITS;
6500 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6501 return mono_custom_attrs_from_index (klass->image, idx);
6505 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6507 MonoCustomAttrInfo *cinfo;
6510 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6512 idx = 1; /* there is only one assembly */
6513 idx <<= MONO_CUSTOM_ATTR_BITS;
6514 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6515 return mono_custom_attrs_from_index (assembly->image, idx);
6518 static MonoCustomAttrInfo*
6519 mono_custom_attrs_from_module (MonoImage *image)
6521 MonoCustomAttrInfo *cinfo;
6524 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6526 idx = 1; /* there is only one module */
6527 idx <<= MONO_CUSTOM_ATTR_BITS;
6528 idx |= MONO_CUSTOM_ATTR_MODULE;
6529 return mono_custom_attrs_from_index (image, idx);
6533 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6535 MonoCustomAttrInfo *cinfo;
6538 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6540 idx = find_property_index (klass, property);
6541 idx <<= MONO_CUSTOM_ATTR_BITS;
6542 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6543 return mono_custom_attrs_from_index (klass->image, idx);
6547 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6549 MonoCustomAttrInfo *cinfo;
6552 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6554 idx = find_event_index (klass, event);
6555 idx <<= MONO_CUSTOM_ATTR_BITS;
6556 idx |= MONO_CUSTOM_ATTR_EVENT;
6557 return mono_custom_attrs_from_index (klass->image, idx);
6561 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6563 MonoCustomAttrInfo *cinfo;
6566 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6568 idx = find_field_index (klass, field);
6569 idx <<= MONO_CUSTOM_ATTR_BITS;
6570 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6571 return mono_custom_attrs_from_index (klass->image, idx);
6575 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6578 guint32 i, idx, method_index;
6579 guint32 param_list, param_last, param_pos, found;
6581 MonoReflectionMethodAux *aux;
6583 if (method->klass->image->dynamic) {
6584 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6585 if (!aux || !aux->param_cattr)
6587 return aux->param_cattr [param];
6590 image = method->klass->image;
6591 method_index = find_method_index (method);
6592 ca = &image->tables [MONO_TABLE_METHOD];
6594 if (method->klass->generic_inst || method->klass->gen_params ||
6595 method->signature->generic_param_count) {
6596 /* FIXME FIXME FIXME */
6600 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6601 if (method_index == ca->rows) {
6602 ca = &image->tables [MONO_TABLE_PARAM];
6603 param_last = ca->rows + 1;
6605 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6606 ca = &image->tables [MONO_TABLE_PARAM];
6609 for (i = param_list; i < param_last; ++i) {
6610 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6611 if (param_pos == param) {
6619 idx <<= MONO_CUSTOM_ATTR_BITS;
6620 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6621 return mono_custom_attrs_from_index (image, idx);
6625 * mono_reflection_get_custom_attrs:
6626 * @obj: a reflection object handle
6627 * @pseudo_attrs: whenever to return pseudo attributes
6629 * Return an array with all the custom attributes defined of the
6630 * reflection handle @obj. The objects are fully build.
6633 mono_reflection_get_custom_attrs (MonoObject *obj, gboolean pseudo_attrs)
6637 MonoCustomAttrInfo *cinfo = NULL;
6639 MONO_ARCH_SAVE_REGS;
6641 klass = obj->vtable->klass;
6642 if (klass == mono_defaults.monotype_class) {
6643 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6644 klass = mono_class_from_mono_type (rtype->type);
6645 cinfo = mono_custom_attrs_from_class (klass);
6646 } else if (strcmp ("Assembly", klass->name) == 0) {
6647 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6648 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6649 } else if (strcmp ("Module", klass->name) == 0) {
6650 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6651 cinfo = mono_custom_attrs_from_module (module->image);
6652 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6653 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6654 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6655 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6656 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6657 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6658 } else if (strcmp ("MonoField", klass->name) == 0) {
6659 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6660 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6661 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6662 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6663 cinfo = mono_custom_attrs_from_method (rmethod->method);
6664 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6665 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6666 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6667 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6668 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6669 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6670 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6671 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6672 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6673 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6674 } else { /* handle other types here... */
6675 g_error ("get custom attrs not yet supported for %s", klass->name);
6679 result = mono_custom_attrs_construct (cinfo);
6681 mono_custom_attrs_free (cinfo);
6683 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6684 result = mono_array_new (mono_domain_get (), klass, 0);
6690 static MonoMethodSignature*
6691 parameters_to_signature (MonoArray *parameters) {
6692 MonoMethodSignature *sig;
6695 count = parameters? mono_array_length (parameters): 0;
6697 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6698 sig->param_count = count;
6699 sig->sentinelpos = -1; /* FIXME */
6700 for (i = 0; i < count; ++i) {
6701 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6702 sig->params [i] = pt->type;
6707 static MonoMethodSignature*
6708 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6709 MonoMethodSignature *sig;
6711 sig = parameters_to_signature (ctor->parameters);
6712 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6713 sig->ret = &mono_defaults.void_class->byval_arg;
6717 static MonoMethodSignature*
6718 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6719 MonoMethodSignature *sig;
6721 sig = parameters_to_signature (method->parameters);
6722 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6723 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6724 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6728 static MonoMethodSignature*
6729 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6730 MonoMethodSignature *sig;
6732 sig = parameters_to_signature (method->parameters);
6733 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6734 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6735 sig->generic_param_count = 0;
6740 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6742 MonoClass *klass = mono_object_class (prop);
6743 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6744 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6745 *name = mono_string_to_utf8 (pb->name);
6746 *type = pb->type->type;
6748 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6749 *name = g_strdup (p->property->name);
6750 if (p->property->get)
6751 *type = p->property->get->signature->ret;
6753 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6758 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6760 MonoClass *klass = mono_object_class (field);
6761 if (strcmp (klass->name, "FieldBuilder") == 0) {
6762 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6763 *name = mono_string_to_utf8 (fb->name);
6764 *type = fb->type->type;
6766 MonoReflectionField *f = (MonoReflectionField *)field;
6767 *name = g_strdup (f->field->name);
6768 *type = f->field->type;
6773 * Encode a value in a custom attribute stream of bytes.
6774 * The value to encode is either supplied as an object in argument val
6775 * (valuetypes are boxed), or as a pointer to the data in the
6777 * @type represents the type of the value
6778 * @buffer is the start of the buffer
6779 * @p the current position in the buffer
6780 * @buflen contains the size of the buffer and is used to return the new buffer size
6781 * if this needs to be realloced.
6782 * @retbuffer and @retp return the start and the position of the buffer
6785 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6787 MonoTypeEnum simple_type;
6789 if ((p-buffer) + 10 >= *buflen) {
6792 newbuf = g_realloc (buffer, *buflen);
6793 p = newbuf + (p-buffer);
6797 argval = ((char*)arg + sizeof (MonoObject));
6798 simple_type = type->type;
6800 switch (simple_type) {
6801 case MONO_TYPE_BOOLEAN:
6806 case MONO_TYPE_CHAR:
6809 swap_with_size (p, argval, 2, 1);
6815 swap_with_size (p, argval, 4, 1);
6821 swap_with_size (p, argval, 8, 1);
6824 case MONO_TYPE_VALUETYPE:
6825 if (type->data.klass->enumtype) {
6826 simple_type = type->data.klass->enum_basetype->type;
6829 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6832 case MONO_TYPE_STRING: {
6839 str = mono_string_to_utf8 ((MonoString*)arg);
6840 slen = strlen (str);
6841 if ((p-buffer) + 10 + slen >= *buflen) {
6845 newbuf = g_realloc (buffer, *buflen);
6846 p = newbuf + (p-buffer);
6849 mono_metadata_encode_value (slen, p, &p);
6850 memcpy (p, str, slen);
6855 case MONO_TYPE_CLASS: {
6863 k = mono_object_class (arg);
6864 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6865 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6866 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6868 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6869 slen = strlen (str);
6870 if ((p-buffer) + 10 + slen >= *buflen) {
6874 newbuf = g_realloc (buffer, *buflen);
6875 p = newbuf + (p-buffer);
6878 mono_metadata_encode_value (slen, p, &p);
6879 memcpy (p, str, slen);
6884 case MONO_TYPE_SZARRAY: {
6886 MonoClass *eclass, *arg_eclass;
6889 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6892 len = mono_array_length ((MonoArray*)arg);
6894 *p++ = (len >> 8) & 0xff;
6895 *p++ = (len >> 16) & 0xff;
6896 *p++ = (len >> 24) & 0xff;
6898 *retbuffer = buffer;
6899 eclass = type->data.klass;
6900 arg_eclass = mono_object_class (arg)->element_class;
6901 if (eclass->valuetype && arg_eclass->valuetype) {
6902 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6903 int elsize = mono_class_array_element_size (eclass);
6904 for (i = 0; i < len; ++i) {
6905 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6909 for (i = 0; i < len; ++i) {
6910 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6915 /* it may be a boxed value or a Type */
6916 case MONO_TYPE_OBJECT: {
6917 MonoClass *klass = mono_object_class (arg);
6921 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6924 } else if (klass->enumtype) {
6926 } else if (klass == mono_defaults.string_class) {
6927 simple_type = MONO_TYPE_STRING;
6930 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6931 *p++ = simple_type = klass->byval_arg.type;
6934 g_error ("unhandled type in custom attr");
6936 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6937 slen = strlen (str);
6938 if ((p-buffer) + 10 + slen >= *buflen) {
6942 newbuf = g_realloc (buffer, *buflen);
6943 p = newbuf + (p-buffer);
6946 mono_metadata_encode_value (slen, p, &p);
6947 memcpy (p, str, slen);
6950 simple_type = klass->enum_basetype->type;
6954 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6957 *retbuffer = buffer;
6961 * mono_reflection_get_custom_attrs_blob:
6962 * @ctor: custom attribute constructor
6963 * @ctorArgs: arguments o the constructor
6969 * Creates the blob of data that needs to be saved in the metadata and that represents
6970 * the custom attributed described by @ctor, @ctorArgs etc.
6971 * Returns: a Byte array representing the blob of data.
6974 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6977 MonoMethodSignature *sig;
6982 MONO_ARCH_SAVE_REGS;
6984 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6985 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6987 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6989 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6991 p = buffer = g_malloc (buflen);
6992 /* write the prolog */
6995 for (i = 0; i < sig->param_count; ++i) {
6996 arg = mono_array_get (ctorArgs, MonoObject*, i);
6997 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7001 i += mono_array_length (properties);
7003 i += mono_array_length (fields);
7005 *p++ = (i >> 8) & 0xff;
7008 for (i = 0; i < mono_array_length (properties); ++i) {
7013 prop = mono_array_get (properties, gpointer, i);
7014 get_prop_name_and_type (prop, &pname, &ptype);
7015 *p++ = 0x54; /* PROPERTY signature */
7017 /* Preallocate a large enough buffer */
7018 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7019 char *str = type_get_qualified_name (ptype, NULL);
7025 len += strlen (pname);
7027 if ((p-buffer) + 20 + len >= buflen) {
7031 newbuf = g_realloc (buffer, buflen);
7032 p = newbuf + (p-buffer);
7036 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7037 char *str = type_get_qualified_name (ptype, NULL);
7038 int slen = strlen (str);
7042 * This seems to be optional...
7045 mono_metadata_encode_value (slen, p, &p);
7046 memcpy (p, str, slen);
7050 mono_metadata_encode_value (ptype->type, p, &p);
7051 if (ptype->type == MONO_TYPE_SZARRAY)
7052 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7054 len = strlen (pname);
7055 mono_metadata_encode_value (len, p, &p);
7056 memcpy (p, pname, len);
7058 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7065 for (i = 0; i < mono_array_length (fields); ++i) {
7070 field = mono_array_get (fields, gpointer, i);
7071 get_field_name_and_type (field, &fname, &ftype);
7072 *p++ = 0x53; /* FIELD signature */
7073 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7074 char *str = type_get_qualified_name (ftype, NULL);
7075 int slen = strlen (str);
7076 if ((p-buffer) + 10 + slen >= buflen) {
7080 newbuf = g_realloc (buffer, buflen);
7081 p = newbuf + (p-buffer);
7086 * This seems to be optional...
7089 mono_metadata_encode_value (slen, p, &p);
7090 memcpy (p, str, slen);
7094 mono_metadata_encode_value (ftype->type, p, &p);
7095 if (ftype->type == MONO_TYPE_SZARRAY)
7096 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7098 len = strlen (fname);
7099 mono_metadata_encode_value (len, p, &p);
7100 memcpy (p, fname, len);
7102 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7107 g_assert (p - buffer <= buflen);
7108 buflen = p - buffer;
7109 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7110 p = mono_array_addr (result, char, 0);
7111 memcpy (p, buffer, buflen);
7113 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7119 * mono_reflection_setup_internal_class:
7120 * @tb: a TypeBuilder object
7122 * Creates a MonoClass that represents the TypeBuilder.
7123 * This is a trick that lets us simplify a lot of reflection code
7124 * (and will allow us to support Build and Run assemblies easier).
7127 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7129 MonoClass *klass, *parent;
7131 MONO_ARCH_SAVE_REGS;
7134 /* check so we can compile corlib correctly */
7135 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7136 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7137 parent = tb->parent->type->data.klass;
7139 parent = my_mono_class_from_mono_type (tb->parent->type);
7145 /* the type has already being created: it means we just have to change the parent */
7146 if (tb->type.type) {
7147 klass = mono_class_from_mono_type (tb->type.type);
7148 klass->parent = NULL;
7149 /* fool mono_class_setup_parent */
7150 g_free (klass->supertypes);
7151 klass->supertypes = NULL;
7152 mono_class_setup_parent (klass, parent);
7153 mono_class_setup_mono_type (klass);
7157 klass = g_new0 (MonoClass, 1);
7159 klass->image = &tb->module->dynamic_image->image;
7161 klass->inited = 1; /* we lie to the runtime */
7162 klass->name = mono_string_to_utf8 (tb->name);
7163 klass->name_space = mono_string_to_utf8 (tb->nspace);
7164 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7165 klass->flags = tb->attrs;
7167 klass->element_class = klass;
7168 klass->reflection_info = tb; /* need to pin. */
7170 /* Put into cache so mono_class_get () will find it */
7171 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7173 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7174 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7176 if (parent != NULL) {
7177 mono_class_setup_parent (klass, parent);
7178 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7179 const char *old_n = klass->name;
7180 /* trick to get relative numbering right when compiling corlib */
7181 klass->name = "BuildingObject";
7182 mono_class_setup_parent (klass, mono_defaults.object_class);
7183 klass->name = old_n;
7186 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7187 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7188 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7189 klass->instance_size = sizeof (MonoObject);
7190 klass->size_inited = 1;
7191 mono_class_setup_vtable (klass, NULL, 0);
7194 mono_class_setup_mono_type (klass);
7196 mono_class_setup_supertypes (klass);
7199 * FIXME: handle interfaces.
7202 tb->type.type = &klass->byval_arg;
7204 if (tb->nesting_type) {
7205 g_assert (tb->nesting_type->type);
7206 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7209 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7213 * mono_reflection_setup_generic_class:
7214 * @tb: a TypeBuilder object
7216 * Setup the generic class after all generic parameters have been added.
7219 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7224 MONO_ARCH_SAVE_REGS;
7226 klass = my_mono_class_from_mono_type (tb->type.type);
7228 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7230 if (klass->gen_params || (count == 0))
7233 klass->num_gen_params = count;
7234 klass->gen_params = g_new0 (MonoGenericParam, count);
7236 for (i = 0; i < count; i++) {
7237 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7238 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7243 * mono_reflection_create_internal_class:
7244 * @tb: a TypeBuilder object
7246 * Actually create the MonoClass that is associated with the TypeBuilder.
7249 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7253 MONO_ARCH_SAVE_REGS;
7255 klass = my_mono_class_from_mono_type (tb->type.type);
7257 if (klass->enumtype && klass->enum_basetype == NULL) {
7258 MonoReflectionFieldBuilder *fb;
7261 g_assert (tb->fields != NULL);
7262 g_assert (mono_array_length (tb->fields) >= 1);
7264 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7266 klass->enum_basetype = fb->type->type;
7267 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7268 if (!klass->element_class)
7269 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7272 * get the element_class from the current corlib.
7274 ec = default_class_from_mono_type (klass->enum_basetype);
7275 klass->instance_size = ec->instance_size;
7276 klass->size_inited = 1;
7278 * this is almost safe to do with enums and it's needed to be able
7279 * to create objects of the enum type (for use in SetConstant).
7281 /* FIXME: Does this mean enums can't have method overrides ? */
7282 mono_class_setup_vtable (klass, NULL, 0);
7286 static MonoMarshalSpec*
7287 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7288 MonoReflectionMarshal *minfo)
7290 MonoMarshalSpec *res;
7292 res = g_new0 (MonoMarshalSpec, 1);
7293 res->native = minfo->type;
7295 switch (minfo->type) {
7296 case MONO_NATIVE_LPARRAY:
7297 res->data.array_data.elem_type = minfo->eltype;
7298 res->data.array_data.param_num = 0; /* Not yet */
7299 res->data.array_data.num_elem = minfo->count;
7302 case MONO_NATIVE_BYVALTSTR:
7303 case MONO_NATIVE_BYVALARRAY:
7304 res->data.array_data.num_elem = minfo->count;
7307 case MONO_NATIVE_CUSTOM:
7308 if (minfo->marshaltyperef)
7309 res->data.custom_data.custom_name =
7310 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7312 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7323 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7324 ReflectionMethodBuilder *rmb,
7325 MonoMethodSignature *sig)
7328 MonoMethodNormal *pm;
7329 MonoMarshalSpec **specs;
7330 MonoReflectionMethodAux *method_aux;
7333 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7334 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7335 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7337 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7339 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7341 pm = (MonoMethodNormal*)m;
7344 m->flags = rmb->attrs;
7345 m->iflags = rmb->iattrs;
7346 m->name = mono_string_to_utf8 (rmb->name);
7350 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7352 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7353 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7356 m->signature->pinvoke = 1;
7357 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7358 m->signature->pinvoke = 1;
7360 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7362 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7363 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7365 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7367 if (klass->image->dynamic)
7368 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7371 } else if (!m->klass->dummy &&
7372 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7373 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7374 MonoMethodHeader *header;
7376 gint32 max_stack, i;
7377 gint32 num_locals = 0;
7378 gint32 num_clauses = 0;
7382 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7383 code_size = rmb->ilgen->code_len;
7384 max_stack = rmb->ilgen->max_stack;
7385 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7386 if (rmb->ilgen->ex_handlers)
7387 num_clauses = method_count_clauses (rmb->ilgen);
7390 code = mono_array_addr (rmb->code, guint8, 0);
7391 code_size = mono_array_length (rmb->code);
7392 /* we probably need to run a verifier on the code... */
7402 header = g_malloc0 (sizeof (MonoMethodHeader) +
7403 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7404 header->code_size = code_size;
7405 header->code = g_malloc (code_size);
7406 memcpy ((char*)header->code, code, code_size);
7407 header->max_stack = max_stack;
7408 header->init_locals = rmb->init_locals;
7409 header->num_locals = num_locals;
7411 for (i = 0; i < num_locals; ++i) {
7412 MonoReflectionLocalBuilder *lb =
7413 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7415 header->locals [i] = g_new0 (MonoType, 1);
7416 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7419 header->num_clauses = num_clauses;
7421 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7422 rmb->ilgen, num_clauses);
7425 pm->header = header;
7428 if (rmb->generic_params) {
7429 int count = mono_array_length (rmb->generic_params);
7430 pm->gen_params = g_new0 (MonoGenericParam, count);
7431 for (i = 0; i < count; i++) {
7432 MonoReflectionGenericParam *gp =
7433 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7435 pm->gen_params [i] = *gp->type.type->data.generic_param;
7440 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7443 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7445 for (i = 0; i < rmb->nrefs; ++i)
7446 mw->data = g_list_append (mw->data, rmb->refs [i]);
7451 /* Parameter names */
7454 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7455 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7456 for (i = 0; i <= m->signature->param_count; ++i) {
7457 MonoReflectionParamBuilder *pb;
7458 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7460 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7462 if (!method_aux->param_cattr)
7463 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7464 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7470 /* Parameter marshalling */
7473 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7474 MonoReflectionParamBuilder *pb;
7475 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7476 if (pb->marshal_info) {
7478 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7479 specs [pb->position] =
7480 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7484 if (specs != NULL) {
7486 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7487 method_aux->param_marshall = specs;
7490 if (klass->image->dynamic && method_aux)
7491 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7497 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7499 ReflectionMethodBuilder rmb;
7500 MonoMethodSignature *sig;
7502 sig = ctor_builder_to_signature (mb);
7504 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7506 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7507 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7509 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7510 /* ilgen is no longer needed */
7518 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7520 ReflectionMethodBuilder rmb;
7521 MonoMethodSignature *sig;
7523 sig = method_builder_to_signature (mb);
7525 reflection_methodbuilder_from_method_builder (&rmb, mb);
7527 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7528 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7530 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7531 /* ilgen is no longer needed */
7537 static MonoClassField*
7538 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7540 MonoClassField *field;
7547 field = g_new0 (MonoClassField, 1);
7549 field->name = mono_string_to_utf8 (fb->name);
7551 /* FIXME: handle type modifiers */
7552 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7553 field->type->attrs = fb->attrs;
7555 field->type = fb->type->type;
7557 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7558 field->data = mono_array_addr (fb->rva_data, char, 0);
7559 if (fb->offset != -1)
7560 field->offset = fb->offset;
7561 field->parent = klass;
7563 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7565 if (fb->def_value) {
7566 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7567 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7568 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7569 /* Copy the data from the blob since it might get realloc-ed */
7570 p = assembly->blob.data + idx;
7571 len = mono_metadata_decode_blob_size (p, &p2);
7573 field->data = g_malloc (len);
7574 memcpy ((gpointer)field->data, p, len);
7581 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7584 MonoReflectionTypeBuilder *tb = NULL;
7585 MonoGenericInst *ginst, *cached;
7590 klass = mono_class_from_mono_type (type->type);
7591 if (!klass->gen_params && !klass->generic_inst &&
7592 !(klass->nested_in && klass->nested_in->gen_params))
7595 mono_loader_lock ();
7597 domain = mono_object_domain (type);
7599 ginst = g_new0 (MonoGenericInst, 1);
7601 if (!klass->generic_inst) {
7602 ginst->type_argc = type_argc;
7603 ginst->type_argv = types;
7605 for (i = 0; i < ginst->type_argc; ++i) {
7606 if (!ginst->is_open)
7607 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7610 ginst->generic_type = &klass->byval_arg;
7612 MonoGenericInst *kginst = klass->generic_inst;
7614 ginst->type_argc = kginst->type_argc;
7615 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7617 for (i = 0; i < ginst->type_argc; i++) {
7618 MonoType *t = kginst->type_argv [i];
7620 if (t->type == MONO_TYPE_VAR)
7621 t = types [t->data.generic_param->num];
7623 if (!ginst->is_open)
7624 ginst->is_open = mono_class_is_open_constructed_type (t);
7626 ginst->type_argv [i] = t;
7629 ginst->generic_type = kginst->generic_type;
7632 geninst = g_new0 (MonoType, 1);
7633 geninst->type = MONO_TYPE_GENERICINST;
7635 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7638 mono_loader_unlock ();
7639 geninst->data.generic_inst = cached;
7643 geninst->data.generic_inst = ginst;
7645 ginst->context = g_new0 (MonoGenericContext, 1);
7646 ginst->context->ginst = ginst;
7648 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7649 tb = (MonoReflectionTypeBuilder *) type;
7651 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7652 ginst->is_dynamic = TRUE;
7653 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7654 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7655 MonoReflectionType *rgt = rgi->generic_type;
7657 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7658 tb = (MonoReflectionTypeBuilder *) rgt;
7660 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7661 ginst->is_dynamic = TRUE;
7663 icount = klass->interface_count;
7666 ginst->ifaces = g_new0 (MonoType *, icount);
7667 ginst->count_ifaces = icount;
7669 for (i = 0; i < icount; i++) {
7670 MonoReflectionType *itype;
7673 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7675 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7676 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7677 if (!ginst->ifaces [i])
7678 ginst->ifaces [i] = itype->type;
7681 mono_class_create_generic (ginst);
7683 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7685 mono_loader_unlock ();
7691 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7693 MonoClass *klass, *pklass = NULL;
7694 MonoReflectionType *parent = NULL;
7696 MonoReflectionTypeBuilder *tb = NULL;
7697 MonoGenericInst *ginst;
7700 domain = mono_object_domain (type);
7701 klass = mono_class_from_mono_type (type->type);
7703 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7704 tb = (MonoReflectionTypeBuilder *) type;
7707 parent = tb->parent;
7708 pklass = mono_class_from_mono_type (parent->type);
7711 pklass = klass->parent;
7713 parent = mono_type_get_object (domain, &pklass->byval_arg);
7716 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7720 ginst = geninst->data.generic_inst;
7722 if (pklass && pklass->generic_inst)
7723 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7728 MonoReflectionMethod*
7729 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7731 MonoMethod *method, *inflated;
7732 MonoReflectionMethodBuilder *mb = NULL;
7733 MonoGenericMethod *gmethod;
7734 MonoGenericContext *context;
7737 MONO_ARCH_SAVE_REGS;
7738 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7739 MonoReflectionTypeBuilder *tb;
7742 mb = (MonoReflectionMethodBuilder *) rmethod;
7743 tb = (MonoReflectionTypeBuilder *) mb->type;
7744 klass = mono_class_from_mono_type (tb->type.type);
7746 method = methodbuilder_to_mono_method (klass, mb);
7748 method = rmethod->method;
7751 count = method->signature->generic_param_count;
7752 if (count != mono_array_length (types))
7755 gmethod = g_new0 (MonoGenericMethod, 1);
7756 gmethod->mtype_argc = count;
7757 gmethod->mtype_argv = g_new0 (MonoType *, count);
7758 for (i = 0; i < count; i++) {
7759 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7760 gmethod->mtype_argv [i] = garg->type;
7763 gmethod->reflection_info = rmethod;
7765 context = g_new0 (MonoGenericContext, 1);
7766 context->ginst = method->klass->generic_inst;
7767 context->gmethod = gmethod;
7769 inflated = mono_class_inflate_generic_method (method, context, NULL);
7771 return mono_method_get_object (
7772 mono_object_domain (rmethod), inflated, NULL);
7776 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7778 MonoGenericMethod *gmethod;
7779 MonoGenericInst *ginst;
7780 MonoGenericContext *context;
7783 ginst = type->type.type->data.generic_inst;
7785 gmethod = g_new0 (MonoGenericMethod, 1);
7786 gmethod->reflection_info = obj;
7788 gmethod->mtype_argc = method->signature->generic_param_count;
7789 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7791 for (i = 0; i < gmethod->mtype_argc; i++) {
7792 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7793 MonoGenericParam *gparam = &mn->gen_params [i];
7795 g_assert (gparam->pklass);
7796 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7799 context = g_new0 (MonoGenericContext, 1);
7800 context->ginst = ginst;
7801 context->gmethod = gmethod;
7803 return mono_class_inflate_generic_method (method, context, ginst->klass);
7807 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7812 klass = mono_class_from_mono_type (type->type.type);
7814 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7815 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7816 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7817 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7818 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7819 method = ((MonoReflectionMethod *) obj)->method;
7821 method = NULL; /* prevent compiler warning */
7822 g_assert_not_reached ();
7825 return inflate_mono_method (type, method, obj);
7829 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
7830 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7832 MonoGenericInst *ginst;
7833 MonoDynamicGenericInst *dginst;
7834 MonoClass *klass, *gklass, *pklass;
7837 MONO_ARCH_SAVE_REGS;
7839 klass = mono_class_from_mono_type (type->type.type);
7840 ginst = type->type.type->data.generic_inst;
7842 if (ginst->initialized)
7845 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7847 gklass = mono_class_from_mono_type (ginst->generic_type);
7848 mono_class_init (gklass);
7851 pklass = mono_class_from_mono_type (ginst->parent);
7853 pklass = gklass->parent;
7855 mono_class_setup_parent (klass, pklass);
7857 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7858 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7859 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7860 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7861 dginst->count_events = events ? mono_array_length (events) : 0;
7863 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7864 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7865 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7866 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7867 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7869 for (i = 0; i < dginst->count_methods; i++) {
7870 MonoObject *obj = mono_array_get (methods, gpointer, i);
7872 dginst->methods [i] = inflate_method (type, obj);
7875 for (i = 0; i < dginst->count_ctors; i++) {
7876 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7878 dginst->ctors [i] = inflate_method (type, obj);
7881 for (i = 0; i < dginst->count_fields; i++) {
7882 MonoObject *obj = mono_array_get (fields, gpointer, i);
7883 MonoClassField *field;
7884 MonoInflatedField *ifield;
7886 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7887 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7888 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7889 field = ((MonoReflectionField *) obj)->field;
7891 field = NULL; /* prevent compiler warning */
7892 g_assert_not_reached ();
7895 ifield = g_new0 (MonoInflatedField, 1);
7896 ifield->generic_type = field->type;
7897 ifield->reflection_info = obj;
7899 dginst->fields [i] = *field;
7900 dginst->fields [i].generic_info = ifield;
7901 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7904 for (i = 0; i < dginst->count_properties; i++) {
7905 MonoObject *obj = mono_array_get (properties, gpointer, i);
7906 MonoProperty *property = &dginst->properties [i];
7908 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7909 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7911 property->parent = klass;
7912 property->attrs = pb->attrs;
7913 property->name = mono_string_to_utf8 (pb->name);
7915 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7917 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7918 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7919 *property = *((MonoReflectionProperty *) obj)->property;
7922 property->get = inflate_mono_method (type, property->get, NULL);
7924 property->set = inflate_mono_method (type, property->set, NULL);
7926 g_assert_not_reached ();
7929 for (i = 0; i < dginst->count_events; i++) {
7930 MonoObject *obj = mono_array_get (events, gpointer, i);
7931 MonoEvent *event = &dginst->events [i];
7933 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7934 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7936 event->parent = klass;
7937 event->attrs = eb->attrs;
7938 event->name = mono_string_to_utf8 (eb->name);
7940 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7941 if (eb->remove_method)
7942 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7943 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7944 *event = *((MonoReflectionEvent *) obj)->event;
7947 event->add = inflate_mono_method (type, event->add, NULL);
7949 event->remove = inflate_mono_method (type, event->remove, NULL);
7951 g_assert_not_reached ();
7954 ginst->initialized = TRUE;
7958 ensure_runtime_vtable (MonoClass *klass)
7960 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7961 int i, num, j, onum;
7962 MonoMethod **overrides;
7964 if (!tb || klass->wastypebuilder)
7967 ensure_runtime_vtable (klass->parent);
7969 num = tb->ctors? mono_array_length (tb->ctors): 0;
7970 num += tb->num_methods;
7971 klass->method.count = num;
7972 klass->methods = g_new (MonoMethod*, num);
7973 num = tb->ctors? mono_array_length (tb->ctors): 0;
7974 for (i = 0; i < num; ++i)
7975 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7976 num = tb->num_methods;
7978 for (i = 0; i < num; ++i)
7979 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7981 klass->wastypebuilder = TRUE;
7982 if (tb->interfaces) {
7983 klass->interface_count = mono_array_length (tb->interfaces);
7984 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7985 for (i = 0; i < klass->interface_count; ++i) {
7986 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7987 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7991 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7992 for (i = 0; i < klass->method.count; ++i)
7993 klass->methods [i]->slot = i;
7998 for (i = 0; i < tb->num_methods; ++i) {
7999 MonoReflectionMethodBuilder *mb =
8000 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8001 if (mb->override_method)
8006 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8010 for (i = 0; i < tb->num_methods; ++i) {
8011 MonoReflectionMethodBuilder *mb =
8012 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8013 if (mb->override_method) {
8014 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8015 overrides [onum * 2] =
8016 mb->override_method->method;
8017 overrides [onum * 2 + 1] =
8020 g_assert (mb->mhandle);
8027 mono_class_setup_vtable (klass, overrides, onum);
8031 typebuilder_setup_fields (MonoClass *klass)
8033 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8034 MonoReflectionFieldBuilder *fb;
8035 MonoClassField *field;
8040 klass->field.count = tb->num_fields;
8041 klass->field.first = 0;
8042 klass->field.last = klass->field.count;
8044 if (!klass->field.count)
8047 klass->fields = g_new0 (MonoClassField, klass->field.count);
8049 for (i = 0; i < klass->field.count; ++i) {
8050 fb = mono_array_get (tb->fields, gpointer, i);
8051 field = &klass->fields [i];
8052 field->name = mono_string_to_utf8 (fb->name);
8054 /* FIXME: handle type modifiers */
8055 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8056 field->type->attrs = fb->attrs;
8058 field->type = fb->type->type;
8060 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8061 field->data = mono_array_addr (fb->rva_data, char, 0);
8062 if (fb->offset != -1)
8063 field->offset = fb->offset;
8064 field->parent = klass;
8066 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8068 if (fb->def_value) {
8069 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8070 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8071 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8072 /* Copy the data from the blob since it might get realloc-ed */
8073 p = assembly->blob.data + idx;
8074 len = mono_metadata_decode_blob_size (p, &p2);
8076 field->data = g_malloc (len);
8077 memcpy ((gpointer)field->data, p, len);
8080 mono_class_layout_fields (klass);
8084 typebuilder_setup_properties (MonoClass *klass)
8086 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8087 MonoReflectionPropertyBuilder *pb;
8090 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8091 klass->property.first = 0;
8092 klass->property.last = klass->property.count;
8094 klass->properties = g_new0 (MonoProperty, klass->property.count);
8095 for (i = 0; i < klass->property.count; ++i) {
8096 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8097 klass->properties [i].parent = klass;
8098 klass->properties [i].attrs = pb->attrs;
8099 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8101 klass->properties [i].get = pb->get_method->mhandle;
8103 klass->properties [i].set = pb->set_method->mhandle;
8107 MonoReflectionEvent *
8108 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8110 MonoEvent *event = g_new0 (MonoEvent, 1);
8114 klass = my_mono_class_from_mono_type (tb->type.type);
8116 event->parent = klass;
8117 event->attrs = eb->attrs;
8118 event->name = mono_string_to_utf8 (eb->name);
8120 event->add = eb->add_method->mhandle;
8121 if (eb->remove_method)
8122 event->remove = eb->remove_method->mhandle;
8123 if (eb->raise_method)
8124 event->raise = eb->raise_method->mhandle;
8126 if (eb->other_methods) {
8127 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8128 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8129 MonoReflectionMethodBuilder *mb =
8130 mono_array_get (eb->other_methods,
8131 MonoReflectionMethodBuilder*, j);
8132 event->other [j] = mb->mhandle;
8136 return mono_event_get_object (mono_object_domain (tb), klass, event);
8140 typebuilder_setup_events (MonoClass *klass)
8142 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8143 MonoReflectionEventBuilder *eb;
8146 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8147 klass->event.first = 0;
8148 klass->event.last = klass->event.count;
8150 klass->events = g_new0 (MonoEvent, klass->event.count);
8151 for (i = 0; i < klass->event.count; ++i) {
8152 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8153 klass->events [i].parent = klass;
8154 klass->events [i].attrs = eb->attrs;
8155 klass->events [i].name = mono_string_to_utf8 (eb->name);
8157 klass->events [i].add = eb->add_method->mhandle;
8158 if (eb->remove_method)
8159 klass->events [i].remove = eb->remove_method->mhandle;
8160 if (eb->raise_method)
8161 klass->events [i].raise = eb->raise_method->mhandle;
8163 if (eb->other_methods) {
8164 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8165 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8166 MonoReflectionMethodBuilder *mb =
8167 mono_array_get (eb->other_methods,
8168 MonoReflectionMethodBuilder*, j);
8169 klass->events [i].other [j] = mb->mhandle;
8176 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8179 MonoReflectionType* res;
8182 MONO_ARCH_SAVE_REGS;
8184 klass = my_mono_class_from_mono_type (tb->type.type);
8186 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8189 * Fields to set in klass:
8190 * the various flags: delegate/unicode/contextbound etc.
8192 klass->flags = tb->attrs;
8194 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8195 /* No need to fully construct the type */
8196 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8198 /* enums are done right away */
8199 if (!klass->enumtype)
8200 ensure_runtime_vtable (klass);
8203 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8204 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8205 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8209 /* fields and object layout */
8210 if (klass->parent) {
8211 if (!klass->parent->size_inited)
8212 mono_class_init (klass->parent);
8213 klass->instance_size += klass->parent->instance_size;
8214 klass->class_size += klass->parent->class_size;
8215 klass->min_align = klass->parent->min_align;
8217 klass->instance_size = sizeof (MonoObject);
8218 klass->min_align = 1;
8221 /* FIXME: handle packing_size and instance_size */
8222 typebuilder_setup_fields (klass);
8224 typebuilder_setup_properties (klass);
8226 typebuilder_setup_events (klass);
8228 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8229 /* with enums res == tb: need to fix that. */
8230 if (!klass->enumtype)
8231 g_assert (res != (MonoReflectionType*)tb);
8236 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8238 MonoGenericParam *param;
8241 MONO_ARCH_SAVE_REGS;
8243 param = g_new0 (MonoGenericParam, 1);
8245 param->method = NULL;
8246 param->name = mono_string_to_utf8 (gparam->name);
8247 param->num = gparam->index;
8249 image = &gparam->tbuilder->module->dynamic_image->image;
8250 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8252 param->pklass->reflection_info = gparam;
8254 gparam->type.type = g_new0 (MonoType, 1);
8255 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8256 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8257 gparam->type.type->data.generic_param = param;
8261 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8263 MonoDynamicImage *assembly = sig->module->dynamic_image;
8264 guint32 na = mono_array_length (sig->arguments);
8269 MONO_ARCH_SAVE_REGS;
8271 p = buf = g_malloc (10 + na * 10);
8273 mono_metadata_encode_value (0x07, p, &p);
8274 mono_metadata_encode_value (na, p, &p);
8275 for (i = 0; i < na; ++i) {
8276 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8277 encode_reflection_type (assembly, type, p, &p);
8281 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8282 p = mono_array_addr (result, char, 0);
8283 memcpy (p, buf, buflen);
8290 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8292 MonoDynamicImage *assembly = sig->module->dynamic_image;
8293 guint32 na = mono_array_length (sig->arguments);
8298 MONO_ARCH_SAVE_REGS;
8300 p = buf = g_malloc (10 + na * 10);
8302 mono_metadata_encode_value (0x06, p, &p);
8303 for (i = 0; i < na; ++i) {
8304 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8305 encode_reflection_type (assembly, type, p, &p);
8309 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8310 p = mono_array_addr (result, char, 0);
8311 memcpy (p, buf, buflen);
8318 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8320 ReflectionMethodBuilder rmb;
8321 MonoMethodSignature *sig;
8324 sig = dynamic_method_to_signature (mb);
8326 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8329 * Resolve references.
8331 rmb.nrefs = mb->nrefs;
8332 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8333 for (i = 0; i < mb->nrefs; ++i) {
8334 gpointer ref = resolve_object (mb->module->image,
8335 mono_array_get (mb->refs, MonoObject*, i));
8338 mono_raise_exception (mono_get_exception_type_load (NULL));
8345 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8349 /* ilgen is no longer needed */
8354 * mono_reflection_lookup_dynamic_token:
8356 * Finish the Builder object pointed to by TOKEN and return the corresponding
8357 * runtime structure.
8360 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8362 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8365 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8368 return resolve_object (image, obj);
8372 resolve_object (MonoImage *image, MonoObject *obj)
8374 gpointer result = NULL;
8376 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8377 result = mono_string_intern ((MonoString*)obj);
8379 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8380 MonoReflectionType *tb = (MonoReflectionType*)obj;
8381 result = mono_class_from_mono_type (tb->type);
8383 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8384 result = ((MonoReflectionMethod*)obj)->method;
8386 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8387 result = ((MonoReflectionMethod*)obj)->method;
8389 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8390 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8391 result = mb->mhandle;
8393 /* Type is not yet created */
8394 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8396 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8399 * Hopefully this has been filled in by calling CreateType() on the
8403 * TODO: This won't work if the application finishes another
8404 * TypeBuilder instance instead of this one.
8406 result = mb->mhandle;
8408 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8409 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8411 result = cb->mhandle;
8413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8415 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8416 result = cb->mhandle;
8418 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8419 result = ((MonoReflectionField*)obj)->field;
8421 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8422 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8423 result = fb->handle;
8426 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8428 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8429 result = fb->handle;
8431 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8432 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8435 klass = tb->type.type->data.klass;
8436 if (klass->wastypebuilder) {
8437 /* Already created */
8441 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8442 result = tb->type.type->data.klass;
8445 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8446 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8447 MonoMethodSignature *sig;
8450 if (helper->arguments)
8451 nargs = mono_array_length (helper->arguments);
8455 sig = mono_metadata_signature_alloc (image, nargs);
8456 sig->explicit_this = helper->call_conv & 64;
8457 sig->hasthis = helper->call_conv & 32;
8459 if (helper->call_conv == 0) /* unmanaged */
8460 sig->call_convention = helper->unmanaged_call_conv - 1;
8462 if (helper->call_conv & 0x02)
8463 sig->call_convention = MONO_CALL_VARARG;
8465 sig->call_convention = MONO_CALL_DEFAULT;
8467 sig->param_count = nargs;
8468 /* TODO: Copy type ? */
8469 sig->ret = helper->return_type->type;
8470 for (i = 0; i < nargs; ++i) {
8471 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8472 sig->params [i] = rt->type;
8477 g_print (obj->vtable->klass->name);
8478 g_assert_not_reached ();