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 if (ex_block->extype) {
877 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
879 /* FIXME: handle filters */
880 clause->data.filter_offset = 0;
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 stream_data_align (&assembly->code);
939 /* check for exceptions, maxstack, locals */
940 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
942 if (code_size < 64 && !(code_size & 1)) {
943 flags = (code_size << 2) | 0x2;
944 } else if (code_size < 32 && (code_size & 1)) {
945 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
949 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
953 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
954 return assembly->text_rva + idx;
958 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
960 * FIXME: need to set also the header size in fat_flags.
961 * (and more sects and init locals flags)
965 fat_flags |= METHOD_HEADER_MORE_SECTS;
967 fat_flags |= METHOD_HEADER_INIT_LOCALS;
968 fat_header [0] = fat_flags;
969 fat_header [1] = (header_size / 4 ) << 4;
970 shortp = (guint16*)(fat_header + 2);
971 *shortp = GUINT16_TO_LE (max_stack);
972 intp = (guint32*)(fat_header + 4);
973 *intp = GUINT32_TO_LE (code_size);
974 intp = (guint32*)(fat_header + 8);
975 *intp = GUINT32_TO_LE (local_sig);
976 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
977 /* add to the fixup todo list */
978 if (mb->ilgen && mb->ilgen->num_token_fixups)
979 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
983 unsigned char sheader [4];
984 MonoILExceptionInfo * ex_info;
985 MonoILExceptionBlock * ex_block;
988 stream_data_align (&assembly->code);
989 /* always use fat format for now */
990 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
991 num_exception *= 6 * sizeof (guint32);
992 num_exception += 4; /* include the size of the header */
993 sheader [1] = num_exception & 0xff;
994 sheader [2] = (num_exception >> 8) & 0xff;
995 sheader [3] = (num_exception >> 16) & 0xff;
996 mono_image_add_stream_data (&assembly->code, sheader, 4);
997 /* fat header, so we are already aligned */
999 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1000 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1001 if (ex_info->handlers) {
1002 int finally_start = ex_info->start + ex_info->len;
1003 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1005 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1007 val = GUINT32_TO_LE (ex_block->type);
1008 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1010 val = GUINT32_TO_LE (ex_info->start);
1011 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1012 /* need fault, too, probably */
1013 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1014 val = GUINT32_TO_LE (finally_start - ex_info->start);
1016 val = GUINT32_TO_LE (ex_info->len);
1017 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1018 /* handler offset */
1019 val = GUINT32_TO_LE (ex_block->start);
1020 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1022 val = GUINT32_TO_LE (ex_block->len);
1023 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1024 finally_start = ex_block->start + ex_block->len;
1025 if (ex_block->extype) {
1026 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1028 /* FIXME: handle filters */
1031 val = GUINT32_TO_LE (val);
1032 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1033 /*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",
1034 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);*/
1037 g_error ("No clauses for ex info block %d", i);
1041 return assembly->text_rva + idx;
1045 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1048 MonoDynamicTable *table;
1051 table = &assembly->tables [table_idx];
1053 g_assert (col < table->columns);
1055 values = table->values + table->columns;
1056 for (i = 1; i <= table->rows; ++i) {
1057 if (values [col] == token)
1059 values += table->columns;
1064 static GHashTable *dynamic_custom_attrs = NULL;
1066 static MonoCustomAttrInfo*
1067 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1070 MonoCustomAttrInfo *ainfo;
1071 MonoReflectionCustomAttr *cattr;
1075 /* FIXME: check in assembly the Run flag is set */
1077 count = mono_array_length (cattrs);
1079 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1081 ainfo->image = image;
1082 ainfo->num_attrs = count;
1083 for (i = 0; i < count; ++i) {
1084 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1085 ainfo->attrs [i].ctor = cattr->ctor->method;
1086 /* FIXME: might want to memdup the data here */
1087 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1088 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1095 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1097 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1102 if (!dynamic_custom_attrs)
1103 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1105 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1106 ainfo->cached = TRUE;
1110 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1112 /* they are cached, so we don't free them */
1113 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1119 * idx is the table index of the object
1120 * type is one of MONO_CUSTOM_ATTR_*
1123 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1125 MonoDynamicTable *table;
1126 MonoReflectionCustomAttr *cattr;
1128 guint32 count, i, token;
1130 char *p = blob_size;
1132 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1135 count = mono_array_length (cattrs);
1136 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1137 table->rows += count;
1138 alloc_table (table, table->rows);
1139 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1140 idx <<= MONO_CUSTOM_ATTR_BITS;
1142 for (i = 0; i < count; ++i) {
1143 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1144 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1145 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1146 type = mono_metadata_token_index (token);
1147 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1148 switch (mono_metadata_token_table (token)) {
1149 case MONO_TABLE_METHOD:
1150 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1152 case MONO_TABLE_MEMBERREF:
1153 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1156 g_warning ("got wrong token in custom attr");
1159 values [MONO_CUSTOM_ATTR_TYPE] = type;
1161 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1162 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1163 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1164 values += MONO_CUSTOM_ATTR_SIZE;
1170 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1172 MonoDynamicTable *table;
1174 guint32 count, i, idx;
1175 MonoReflectionPermissionSet *perm;
1180 count = mono_array_length (permissions);
1181 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1182 table->rows += count;
1183 alloc_table (table, table->rows);
1185 for (i = 0; i < mono_array_length (permissions); ++i) {
1186 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1188 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1190 idx = mono_metadata_token_index (parent_token);
1191 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1192 switch (mono_metadata_token_table (parent_token)) {
1193 case MONO_TABLE_TYPEDEF:
1194 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1196 case MONO_TABLE_METHOD:
1197 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1199 case MONO_TABLE_ASSEMBLY:
1200 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1203 g_assert_not_reached ();
1206 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1207 values [MONO_DECL_SECURITY_PARENT] = idx;
1208 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1215 * Fill in the MethodDef and ParamDef tables for a method.
1216 * This is used for both normal methods and constructors.
1219 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1221 MonoDynamicTable *table;
1226 /* room in this table is already allocated */
1227 table = &assembly->tables [MONO_TABLE_METHOD];
1228 *mb->table_idx = table->next_idx ++;
1229 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1230 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1231 name = mono_string_to_utf8 (mb->name);
1232 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1234 values [MONO_METHOD_FLAGS] = mb->attrs;
1235 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1236 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1237 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1239 table = &assembly->tables [MONO_TABLE_PARAM];
1240 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1242 mono_image_add_decl_security (assembly,
1243 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1246 MonoDynamicTable *mtable;
1249 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1250 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1253 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1254 if (mono_array_get (mb->pinfo, gpointer, i))
1257 table->rows += count;
1258 alloc_table (table, table->rows);
1259 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1260 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1261 MonoReflectionParamBuilder *pb;
1262 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1263 values [MONO_PARAM_FLAGS] = pb->attrs;
1264 values [MONO_PARAM_SEQUENCE] = i;
1265 if (pb->name != NULL) {
1266 name = mono_string_to_utf8 (pb->name);
1267 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1270 values [MONO_PARAM_NAME] = 0;
1272 values += MONO_PARAM_SIZE;
1273 if (pb->marshal_info) {
1275 alloc_table (mtable, mtable->rows);
1276 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1277 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1278 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1280 pb->table_idx = table->next_idx++;
1281 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1282 guint32 field_type = 0;
1283 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1285 alloc_table (mtable, mtable->rows);
1286 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1287 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1288 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1289 mvalues [MONO_CONSTANT_TYPE] = field_type;
1290 mvalues [MONO_CONSTANT_PADDING] = 0;
1298 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1300 rmb->ilgen = mb->ilgen;
1301 rmb->rtype = mb->rtype;
1302 rmb->parameters = mb->parameters;
1303 rmb->generic_params = mb->generic_params;
1304 rmb->opt_types = NULL;
1305 rmb->pinfo = mb->pinfo;
1306 rmb->attrs = mb->attrs;
1307 rmb->iattrs = mb->iattrs;
1308 rmb->call_conv = mb->call_conv;
1309 rmb->code = mb->code;
1310 rmb->type = mb->type;
1311 rmb->name = mb->name;
1312 rmb->table_idx = &mb->table_idx;
1313 rmb->init_locals = mb->init_locals;
1314 rmb->return_modreq = mb->return_modreq;
1315 rmb->return_modopt = mb->return_modopt;
1316 rmb->param_modreq = mb->param_modreq;
1317 rmb->param_modopt = mb->param_modopt;
1318 rmb->permissions = mb->permissions;
1319 rmb->mhandle = mb->mhandle;
1324 rmb->charset = rmb->charset & 0xf;
1325 rmb->lasterr = rmb->charset & 0x40;
1326 rmb->native_cc = rmb->native_cc;
1327 rmb->dllentry = mb->dllentry;
1333 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1335 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1337 rmb->ilgen = mb->ilgen;
1338 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1339 rmb->parameters = mb->parameters;
1340 rmb->generic_params = NULL;
1341 rmb->opt_types = NULL;
1342 rmb->pinfo = mb->pinfo;
1343 rmb->attrs = mb->attrs;
1344 rmb->iattrs = mb->iattrs;
1345 rmb->call_conv = mb->call_conv;
1347 rmb->type = mb->type;
1348 rmb->name = mono_string_new (mono_domain_get (), name);
1349 rmb->table_idx = &mb->table_idx;
1350 rmb->init_locals = mb->init_locals;
1351 rmb->return_modreq = NULL;
1352 rmb->return_modopt = NULL;
1353 rmb->param_modreq = mb->param_modreq;
1354 rmb->param_modopt = mb->param_modopt;
1355 rmb->permissions = mb->permissions;
1356 rmb->mhandle = mb->mhandle;
1362 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1364 rmb->ilgen = mb->ilgen;
1365 rmb->rtype = mb->rtype;
1366 rmb->parameters = mb->parameters;
1367 rmb->generic_params = NULL;
1368 rmb->opt_types = NULL;
1370 rmb->attrs = mb->attrs;
1372 rmb->call_conv = mb->call_conv;
1375 rmb->name = mb->name;
1376 rmb->table_idx = NULL;
1377 rmb->init_locals = mb->init_locals;
1378 rmb->return_modreq = NULL;
1379 rmb->return_modopt = NULL;
1380 rmb->param_modreq = NULL;
1381 rmb->param_modopt = NULL;
1382 rmb->permissions = NULL;
1383 rmb->mhandle = mb->mhandle;
1389 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1391 MonoDynamicTable *table;
1394 ReflectionMethodBuilder rmb;
1397 reflection_methodbuilder_from_method_builder (&rmb, mb);
1399 mono_image_basic_method (&rmb, assembly);
1401 if (mb->dll) { /* It's a P/Invoke method */
1403 int charset = mb->charset & 0xf;
1404 int lasterr = mb->charset & 0x40;
1405 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1407 alloc_table (table, table->rows);
1408 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1409 /* map CharSet values to on-disk values */
1411 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1412 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1413 name = mono_string_to_utf8 (mb->dllentry);
1414 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1416 name = mono_string_to_utf8 (mb->dll);
1417 moduleref = string_heap_insert (&assembly->sheap, name);
1419 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1420 table = &assembly->tables [MONO_TABLE_MODULEREF];
1422 alloc_table (table, table->rows);
1423 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1424 values [MONO_IMPLMAP_SCOPE] = table->rows;
1428 if (mb->override_method) {
1429 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1431 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1433 alloc_table (table, table->rows);
1434 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1435 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1436 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1438 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1439 switch (mono_metadata_token_table (tok)) {
1440 case MONO_TABLE_MEMBERREF:
1441 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1443 case MONO_TABLE_METHOD:
1444 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1447 g_assert_not_reached ();
1449 values [MONO_METHODIMPL_DECLARATION] = tok;
1452 if (mb->generic_params) {
1453 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1454 table->rows += mono_array_length (mb->generic_params);
1455 alloc_table (table, table->rows);
1456 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1457 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1459 mono_image_get_generic_param_info (
1460 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1467 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1469 ReflectionMethodBuilder rmb;
1471 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1473 mono_image_basic_method (&rmb, assembly);
1477 type_get_fully_qualified_name (MonoType *type) {
1478 char *name, *result;
1482 name = mono_type_get_name (type);
1483 klass = my_mono_class_from_mono_type (type);
1484 ta = klass->image->assembly;
1486 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1487 name, ta->aname.name,
1488 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1489 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1490 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1496 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1500 klass = my_mono_class_from_mono_type (type);
1502 return mono_type_get_name (type);
1503 ta = klass->image->assembly;
1504 if (ta == ass || klass->image == mono_defaults.corlib)
1505 return mono_type_get_name (type);
1507 return type_get_fully_qualified_name (type);
1511 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1513 char blob_size [64];
1514 char *b = blob_size;
1519 if (!assembly->save)
1522 p = buf = g_malloc (64);
1524 mono_metadata_encode_value (0x06, p, &p);
1525 /* encode custom attributes before the type */
1526 encode_type (assembly, type, p, &p);
1527 g_assert (p-buf < 64);
1528 mono_metadata_encode_value (p-buf, b, &b);
1529 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1535 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1537 char blob_size [64];
1538 char *b = blob_size;
1543 p = buf = g_malloc (64);
1545 mono_metadata_encode_value (0x06, p, &p);
1546 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1547 /* encode custom attributes before the type */
1548 encode_reflection_type (assembly, fb->type, p, &p);
1549 g_assert (p-buf < 64);
1550 mono_metadata_encode_value (p-buf, b, &b);
1551 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1557 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1558 char blob_size [64];
1559 char *b = blob_size;
1562 guint32 idx = 0, len = 0, dummy = 0;
1564 p = buf = g_malloc (64);
1566 *ret_type = MONO_TYPE_CLASS;
1568 box_val = (char*)&dummy;
1570 box_val = ((char*)val) + sizeof (MonoObject);
1571 *ret_type = val->vtable->klass->byval_arg.type;
1574 switch (*ret_type) {
1575 case MONO_TYPE_BOOLEAN:
1580 case MONO_TYPE_CHAR:
1595 case MONO_TYPE_VALUETYPE:
1596 if (val->vtable->klass->enumtype) {
1597 *ret_type = val->vtable->klass->enum_basetype->type;
1600 g_error ("we can't encode valuetypes");
1601 case MONO_TYPE_CLASS:
1603 case MONO_TYPE_STRING: {
1604 MonoString *str = (MonoString*)val;
1605 /* there is no signature */
1606 len = str->length * 2;
1607 mono_metadata_encode_value (len, b, &b);
1608 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1610 char *swapped = g_malloc (2 * mono_string_length (str));
1611 const char *p = (const char*)mono_string_chars (str);
1613 swap_with_size (swapped, p, 2, mono_string_length (str));
1614 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1618 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1625 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1628 /* there is no signature */
1629 mono_metadata_encode_value (len, b, &b);
1630 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1631 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1632 swap_with_size (blob_size, box_val, len, 1);
1633 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1635 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1643 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1644 char blob_size [64];
1645 char *b = blob_size;
1646 char *p, *buf, *str;
1647 guint32 idx, len, bufsize = 256;
1649 p = buf = g_malloc (bufsize);
1651 switch (minfo->type) {
1652 case MONO_NATIVE_BYVALTSTR:
1653 case MONO_NATIVE_BYVALARRAY:
1654 mono_metadata_encode_value (minfo->type, p, &p);
1655 mono_metadata_encode_value (minfo->count, p, &p);
1657 case MONO_NATIVE_LPARRAY:
1658 mono_metadata_encode_value (minfo->type, p, &p);
1659 if (minfo->eltype || (minfo->count > 0)) {
1660 mono_metadata_encode_value (minfo->eltype, p, &p);
1661 if (minfo->count > 0) {
1662 mono_metadata_encode_value (0, p, &p);
1663 mono_metadata_encode_value (minfo->count, p, &p);
1667 case MONO_NATIVE_CUSTOM:
1668 mono_metadata_encode_value (minfo->type, p, &p);
1670 str = mono_string_to_utf8 (minfo->guid);
1672 mono_metadata_encode_value (len, p, &p);
1673 memcpy (p, str, len);
1677 mono_metadata_encode_value (0, p, &p);
1679 if (minfo->marshaltype) {
1680 str = mono_string_to_utf8 (minfo->marshaltype);
1682 mono_metadata_encode_value (len, p, &p);
1683 if (p + len >= buf + bufsize) {
1686 buf = g_realloc (buf, bufsize);
1689 memcpy (p, str, len);
1693 mono_metadata_encode_value (0, p, &p);
1695 if (minfo->marshaltyperef) {
1696 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1698 mono_metadata_encode_value (len, p, &p);
1699 if (p + len >= buf + bufsize) {
1702 buf = g_realloc (buf, bufsize);
1705 memcpy (p, str, len);
1709 mono_metadata_encode_value (0, p, &p);
1711 if (minfo->mcookie) {
1712 str = mono_string_to_utf8 (minfo->mcookie);
1714 mono_metadata_encode_value (len, p, &p);
1715 if (p + len >= buf + bufsize) {
1718 buf = g_realloc (buf, bufsize);
1721 memcpy (p, str, len);
1725 mono_metadata_encode_value (0, p, &p);
1729 mono_metadata_encode_value (minfo->type, p, &p);
1733 mono_metadata_encode_value (len, b, &b);
1734 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1740 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1742 MonoDynamicTable *table;
1746 /* maybe this fixup should be done in the C# code */
1747 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1748 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1749 table = &assembly->tables [MONO_TABLE_FIELD];
1750 fb->table_idx = table->next_idx ++;
1751 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1752 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1753 name = mono_string_to_utf8 (fb->name);
1754 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1756 values [MONO_FIELD_FLAGS] = fb->attrs;
1757 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1759 if (fb->offset != -1) {
1760 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1762 alloc_table (table, table->rows);
1763 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1764 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1765 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1767 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1768 guint32 field_type = 0;
1769 table = &assembly->tables [MONO_TABLE_CONSTANT];
1771 alloc_table (table, table->rows);
1772 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1773 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1774 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1775 values [MONO_CONSTANT_TYPE] = field_type;
1776 values [MONO_CONSTANT_PADDING] = 0;
1778 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1780 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1782 alloc_table (table, table->rows);
1783 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1784 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1786 * We store it in the code section because it's simpler for now.
1789 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1791 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1792 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1794 if (fb->marshal_info) {
1795 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1797 alloc_table (table, table->rows);
1798 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1799 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1800 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1805 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1809 char *b = blob_size;
1810 guint32 nparams = 0;
1811 MonoReflectionMethodBuilder *mb = fb->get_method;
1812 MonoReflectionMethodBuilder *smb = fb->set_method;
1813 guint32 idx, i, size;
1815 if (mb && mb->parameters)
1816 nparams = mono_array_length (mb->parameters);
1817 if (!mb && smb && smb->parameters)
1818 nparams = mono_array_length (smb->parameters) - 1;
1819 size = 24 + nparams * 10;
1820 buf = p = g_malloc (size);
1823 mono_metadata_encode_value (nparams, p, &p);
1825 encode_reflection_type (assembly, mb->rtype, p, &p);
1826 for (i = 0; i < nparams; ++i) {
1827 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1828 encode_reflection_type (assembly, pt, p, &p);
1831 /* the property type is the last param */
1832 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1833 for (i = 0; i < nparams; ++i) {
1834 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1835 encode_reflection_type (assembly, pt, p, &p);
1839 g_assert (p - buf < size);
1840 mono_metadata_encode_value (p-buf, b, &b);
1841 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1847 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1849 MonoDynamicTable *table;
1852 guint num_methods = 0;
1856 * we need to set things in the following tables:
1857 * PROPERTYMAP (info already filled in _get_type_info ())
1858 * PROPERTY (rows already preallocated in _get_type_info ())
1859 * METHOD (method info already done with the generic method code)
1862 table = &assembly->tables [MONO_TABLE_PROPERTY];
1863 pb->table_idx = table->next_idx ++;
1864 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1865 name = mono_string_to_utf8 (pb->name);
1866 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1868 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1869 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1871 /* FIXME: we still don't handle 'other' methods */
1872 if (pb->get_method) num_methods ++;
1873 if (pb->set_method) num_methods ++;
1875 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1876 table->rows += num_methods;
1877 alloc_table (table, table->rows);
1879 if (pb->get_method) {
1880 semaidx = table->next_idx ++;
1881 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1882 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1883 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1884 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1886 if (pb->set_method) {
1887 semaidx = table->next_idx ++;
1888 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1889 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1890 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1891 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1896 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1898 MonoDynamicTable *table;
1901 guint num_methods = 0;
1905 * we need to set things in the following tables:
1906 * EVENTMAP (info already filled in _get_type_info ())
1907 * EVENT (rows already preallocated in _get_type_info ())
1908 * METHOD (method info already done with the generic method code)
1911 table = &assembly->tables [MONO_TABLE_EVENT];
1912 eb->table_idx = table->next_idx ++;
1913 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1914 name = mono_string_to_utf8 (eb->name);
1915 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1917 values [MONO_EVENT_FLAGS] = eb->attrs;
1918 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1921 * FIXME: we still don't handle 'other' methods
1923 if (eb->add_method) num_methods ++;
1924 if (eb->remove_method) num_methods ++;
1925 if (eb->raise_method) num_methods ++;
1927 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1928 table->rows += num_methods;
1929 alloc_table (table, table->rows);
1931 if (eb->add_method) {
1932 semaidx = table->next_idx ++;
1933 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1934 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1935 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1936 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1938 if (eb->remove_method) {
1939 semaidx = table->next_idx ++;
1940 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1941 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1942 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1943 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1945 if (eb->raise_method) {
1946 semaidx = table->next_idx ++;
1947 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1948 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1949 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1950 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1955 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1957 static MonoClass *NewConstraintAttr;
1958 static MonoMethod *NewConstraintAttr_ctor;
1959 MonoDynamicTable *table;
1961 guint32 token, type;
1962 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1965 if (!NewConstraintAttr)
1966 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1967 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1968 g_assert (NewConstraintAttr);
1970 if (!NewConstraintAttr_ctor) {
1973 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1974 MonoMethod *m = NewConstraintAttr->methods [i];
1976 if (strcmp (m->name, ".ctor"))
1979 NewConstraintAttr_ctor = m;
1983 g_assert (NewConstraintAttr_ctor);
1986 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1988 alloc_table (table, table->rows);
1990 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1991 owner <<= MONO_CUSTOM_ATTR_BITS;
1992 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1993 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1995 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1997 type = mono_metadata_token_index (token);
1998 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1999 switch (mono_metadata_token_table (token)) {
2000 case MONO_TABLE_METHOD:
2001 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
2003 case MONO_TABLE_MEMBERREF:
2004 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
2007 g_warning ("got wrong token in custom attr");
2010 values [MONO_CUSTOM_ATTR_TYPE] = type;
2012 buf = p = g_malloc (1);
2013 mono_metadata_encode_value (4, p, &p);
2014 g_assert (p-buf == 1);
2016 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2018 values += MONO_CUSTOM_ATTR_SIZE;
2023 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2025 MonoDynamicTable *table;
2026 guint32 num_constraints, i;
2030 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2031 num_constraints = gparam->iface_constraints ?
2032 mono_array_length (gparam->iface_constraints) : 0;
2033 table->rows += num_constraints;
2034 if (gparam->base_type)
2036 alloc_table (table, table->rows);
2038 if (gparam->base_type) {
2039 table_idx = table->next_idx ++;
2040 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2042 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2043 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2044 assembly, gparam->base_type->type);
2047 for (i = 0; i < num_constraints; i++) {
2048 MonoReflectionType *constraint = mono_array_get (
2049 gparam->iface_constraints, gpointer, i);
2051 table_idx = table->next_idx ++;
2052 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2054 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2055 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2056 assembly, constraint->type);
2059 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2060 encode_new_constraint (assembly, owner);
2064 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2066 GenericParamTableEntry *entry;
2069 * The GenericParam table must be sorted according to the `owner' field.
2070 * We need to do this sorting prior to writing the GenericParamConstraint
2071 * table, since we have to use the final GenericParam table indices there
2072 * and they must also be sorted.
2075 entry = g_new0 (GenericParamTableEntry, 1);
2076 entry->owner = owner;
2077 entry->gparam = gparam;
2079 g_ptr_array_add (assembly->gen_params, entry);
2083 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2085 MonoDynamicTable *table;
2086 MonoGenericParam *param;
2090 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2091 table_idx = table->next_idx ++;
2092 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2094 param = entry->gparam->type.type->data.generic_param;
2096 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2097 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2098 values [MONO_GENERICPARAM_NUMBER] = param->num;
2099 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2100 values [MONO_GENERICPARAM_KIND] = 0;
2102 encode_constraints (entry->gparam, table_idx, assembly);
2106 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2108 MonoDynamicTable *table;
2111 guint32 cols [MONO_ASSEMBLY_SIZE];
2115 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2118 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2119 table = &assembly->tables [MONO_TABLE_MODULEREF];
2120 token = table->next_idx ++;
2122 alloc_table (table, table->rows);
2123 values = table->values + token * MONO_MODULEREF_SIZE;
2124 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2126 token <<= MONO_RESOLTION_SCOPE_BITS;
2127 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2128 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2133 if (image->assembly->dynamic)
2135 memset (cols, 0, sizeof (cols));
2137 /* image->assembly->image is the manifest module */
2138 image = image->assembly->image;
2139 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2142 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2143 token = table->next_idx ++;
2145 alloc_table (table, table->rows);
2146 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2147 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2148 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2149 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2150 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2151 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2152 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2153 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2154 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2156 if (strcmp ("", image->assembly->aname.culture)) {
2157 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2158 image->assembly->aname.culture);
2161 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2162 guchar pubtoken [9];
2164 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2165 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2167 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2169 token <<= MONO_RESOLTION_SCOPE_BITS;
2170 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2171 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2176 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2178 MonoDynamicTable *table;
2184 char *b = blob_size;
2186 switch (type->type) {
2187 case MONO_TYPE_FNPTR:
2189 case MONO_TYPE_SZARRAY:
2190 case MONO_TYPE_ARRAY:
2192 case MONO_TYPE_MVAR:
2193 case MONO_TYPE_GENERICINST:
2194 encode_type (assembly, type, p, &p);
2196 case MONO_TYPE_CLASS:
2197 case MONO_TYPE_VALUETYPE: {
2198 MonoClass *k = mono_class_from_mono_type (type);
2199 if (!k || !k->generic_inst)
2201 encode_generic_inst (assembly, k->generic_inst, p, &p);
2208 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2209 if (assembly->save) {
2210 g_assert (p-sig < 128);
2211 mono_metadata_encode_value (p-sig, b, &b);
2212 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2213 alloc_table (table, table->rows + 1);
2214 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2215 values [MONO_TYPESPEC_SIGNATURE] = token;
2218 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2219 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2225 * Despite the name, we handle also TypeSpec (with the above helper).
2228 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2230 MonoDynamicTable *table;
2232 guint32 token, scope, enclosing;
2235 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2238 token = create_typespec (assembly, type);
2241 klass = my_mono_class_from_mono_type (type);
2243 klass = mono_class_from_mono_type (type);
2246 * If it's in the same module and not a generic type parameter:
2248 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2249 (type->type != MONO_TYPE_MVAR)) {
2250 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2251 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2252 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2256 if (klass->nested_in) {
2257 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2258 /* get the typeref idx of the enclosing type */
2259 enclosing >>= MONO_TYPEDEFORREF_BITS;
2260 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2262 scope = resolution_scope_from_image (assembly, klass->image);
2264 table = &assembly->tables [MONO_TABLE_TYPEREF];
2265 if (assembly->save) {
2266 alloc_table (table, table->rows + 1);
2267 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2268 values [MONO_TYPEREF_SCOPE] = scope;
2269 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2270 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2272 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2273 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2275 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2280 * Insert a memberef row into the metadata: the token that point to the memberref
2281 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2282 * mono_image_get_fieldref_token()).
2283 * The sig param is an index to an already built signature.
2286 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2288 MonoDynamicTable *table;
2290 guint32 token, pclass;
2293 parent = mono_image_typedef_or_ref (assembly, type);
2294 switch (parent & MONO_TYPEDEFORREF_MASK) {
2295 case MONO_TYPEDEFORREF_TYPEREF:
2296 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2298 case MONO_TYPEDEFORREF_TYPESPEC:
2299 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2301 case MONO_TYPEDEFORREF_TYPEDEF:
2302 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2305 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2308 /* extract the index */
2309 parent >>= MONO_TYPEDEFORREF_BITS;
2311 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2313 if (assembly->save) {
2314 alloc_table (table, table->rows + 1);
2315 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2316 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2317 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2318 values [MONO_MEMBERREF_SIGNATURE] = sig;
2321 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2328 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2331 MonoMethodSignature *sig;
2333 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2338 * A methodref signature can't contain an unmanaged calling convention.
2340 sig = mono_metadata_signature_dup (method->signature);
2341 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2342 sig->call_convention = MONO_CALL_DEFAULT;
2343 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2344 method->name, method_encode_signature (assembly, sig));
2346 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2351 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2352 const gchar *name, guint32 sig)
2354 MonoDynamicTable *table;
2358 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2360 if (assembly->save) {
2361 alloc_table (table, table->rows + 1);
2362 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2363 values [MONO_MEMBERREF_CLASS] = original;
2364 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2365 values [MONO_MEMBERREF_SIGNATURE] = sig;
2368 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2375 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2378 ReflectionMethodBuilder rmb;
2380 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2384 reflection_methodbuilder_from_method_builder (&rmb, mb);
2386 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2387 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2388 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2393 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2396 ReflectionMethodBuilder rmb;
2398 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2402 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2404 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2405 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2406 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2411 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2416 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2419 g_assert (f->field->parent);
2420 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2421 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2422 f->field->name, fieldref_encode_signature (assembly, type));
2423 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2428 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2433 guint32 nparams = gmethod->mtype_argc;
2434 guint32 size = 10 + nparams * 10;
2437 char *b = blob_size;
2439 if (!assembly->save)
2442 p = buf = g_malloc (size);
2444 * FIXME: vararg, explicit_this, differenc call_conv values...
2446 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2447 mono_metadata_encode_value (nparams, p, &p);
2449 for (i = 0; i < nparams; i++)
2450 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2453 g_assert (p - buf < size);
2454 mono_metadata_encode_value (p-buf, b, &b);
2455 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2461 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2463 MonoDynamicTable *table;
2465 guint32 token, mtoken = 0, sig;
2466 MonoMethodInflated *imethod;
2467 MonoMethod *declaring;
2469 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2471 g_assert (method->signature->is_inflated);
2472 imethod = (MonoMethodInflated *) method;
2473 declaring = imethod->declaring;
2475 sig = method_encode_signature (assembly, declaring->signature);
2476 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2478 if (!declaring->signature->generic_param_count)
2481 switch (mono_metadata_token_table (mtoken)) {
2482 case MONO_TABLE_MEMBERREF:
2483 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2485 case MONO_TABLE_METHOD:
2486 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2489 g_assert_not_reached ();
2492 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2494 if (assembly->save) {
2495 alloc_table (table, table->rows + 1);
2496 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2497 values [MONO_METHODSPEC_METHOD] = mtoken;
2498 values [MONO_METHODSPEC_SIGNATURE] = sig;
2501 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2508 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2510 MonoMethodInflated *imethod;
2513 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2517 g_assert (m->signature->is_inflated);
2518 imethod = (MonoMethodInflated *) m;
2520 if (imethod->declaring->signature->generic_param_count) {
2521 token = method_encode_methodspec (assembly, m);
2523 guint32 sig = method_encode_signature (
2524 assembly, imethod->declaring->signature);
2525 token = mono_image_get_memberref_token (
2526 assembly, &m->klass->byval_arg, m->name, sig);
2529 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2534 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2536 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2539 sig = method_encode_signature (assembly, imethod->declaring->signature);
2540 token = mono_image_get_memberref_token (
2541 assembly, &m->klass->byval_arg, m->name, sig);
2547 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2549 MonoDynamicTable *table;
2556 char *b = blob_size;
2560 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2561 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2562 * Because of this, we must not insert it into the `typeref' hash table.
2565 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2569 g_assert (tb->generic_params);
2570 klass = mono_class_from_mono_type (tb->type.type);
2572 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2573 encode_type (assembly, &klass->byval_arg, p, &p);
2575 count = mono_array_length (tb->generic_params);
2576 mono_metadata_encode_value (count, p, &p);
2577 for (i = 0; i < count; i++) {
2578 MonoReflectionGenericParam *gparam;
2580 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2582 encode_type (assembly, gparam->type.type, p, &p);
2585 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2586 if (assembly->save) {
2587 g_assert (p-sig < 128);
2588 mono_metadata_encode_value (p-sig, b, &b);
2589 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2590 alloc_table (table, table->rows + 1);
2591 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2592 values [MONO_TYPESPEC_SIGNATURE] = token;
2595 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2596 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2602 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2604 MonoDynamicTable *table;
2607 guint32 token, pclass, parent, sig;
2610 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2614 klass = mono_class_from_mono_type (fb->typeb->type);
2615 name = mono_string_to_utf8 (fb->name);
2617 sig = fieldref_encode_signature (assembly, fb->type->type);
2619 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2620 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2622 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2623 parent >>= MONO_TYPEDEFORREF_BITS;
2625 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2627 if (assembly->save) {
2628 alloc_table (table, table->rows + 1);
2629 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2630 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2631 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2632 values [MONO_MEMBERREF_SIGNATURE] = sig;
2635 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2637 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2642 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2650 char *b = blob_size;
2652 if (!assembly->save)
2656 g_assert (helper->type == 2);
2658 if (helper->arguments)
2659 nargs = mono_array_length (helper->arguments);
2663 size = 10 + (nargs * 10);
2665 p = buf = g_malloc (size);
2667 /* Encode calling convention */
2668 /* Change Any to Standard */
2669 if ((helper->call_conv & 0x03) == 0x03)
2670 helper->call_conv = 0x01;
2671 /* explicit_this implies has_this */
2672 if (helper->call_conv & 0x40)
2673 helper->call_conv &= 0x20;
2675 if (helper->call_conv == 0) { /* Unmanaged */
2676 *p = helper->unmanaged_call_conv - 1;
2679 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2680 if (helper->call_conv & 0x02) /* varargs */
2685 mono_metadata_encode_value (nargs, p, &p);
2686 encode_reflection_type (assembly, helper->return_type, p, &p);
2687 for (i = 0; i < nargs; ++i) {
2688 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2689 encode_reflection_type (assembly, pt, p, &p);
2692 g_assert (p - buf < size);
2693 mono_metadata_encode_value (p-buf, b, &b);
2694 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2701 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2704 MonoDynamicTable *table;
2707 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2708 idx = table->next_idx ++;
2710 alloc_table (table, table->rows);
2711 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2713 values [MONO_STAND_ALONE_SIGNATURE] =
2714 mono_reflection_encode_sighelper (assembly, helper);
2720 reflection_cc_to_file (int call_conv) {
2721 switch (call_conv & 0x3) {
2723 case 1: return MONO_CALL_DEFAULT;
2724 case 2: return MONO_CALL_VARARG;
2726 g_assert_not_reached ();
2733 MonoMethodSignature *sig;
2739 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2744 MonoMethodSignature *sig;
2747 name = mono_string_to_utf8 (m->name);
2748 nparams = mono_array_length (m->parameters);
2749 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2751 sig->sentinelpos = -1;
2752 sig->call_convention = reflection_cc_to_file (m->call_conv);
2753 sig->param_count = nparams;
2754 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2755 for (i = 0; i < nparams; ++i) {
2756 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2757 sig->params [i] = t->type;
2760 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2762 if (strcmp (name, am->name) == 0 &&
2763 mono_metadata_type_equal (am->parent, m->parent->type) &&
2764 mono_metadata_signature_equal (am->sig, sig)) {
2767 m->table_idx = am->token & 0xffffff;
2771 am = g_new0 (ArrayMethod, 1);
2774 am->parent = m->parent->type;
2775 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2776 method_encode_signature (assembly, sig));
2777 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2778 m->table_idx = am->token & 0xffffff;
2783 * Insert into the metadata tables all the info about the TypeBuilder tb.
2784 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2787 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2789 MonoDynamicTable *table;
2791 int i, is_object = 0, is_system = 0;
2794 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2795 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2796 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2797 n = mono_string_to_utf8 (tb->name);
2798 if (strcmp (n, "Object") == 0)
2800 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2802 n = mono_string_to_utf8 (tb->nspace);
2803 if (strcmp (n, "System") == 0)
2805 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2807 if (tb->parent && !(is_system && is_object) &&
2808 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2809 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2811 values [MONO_TYPEDEF_EXTENDS] = 0;
2813 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2814 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2817 * if we have explicitlayout or sequentiallayouts, output data in the
2818 * ClassLayout table.
2820 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2821 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2822 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2824 alloc_table (table, table->rows);
2825 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2826 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2827 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2828 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2831 /* handle interfaces */
2832 if (tb->interfaces) {
2833 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2835 table->rows += mono_array_length (tb->interfaces);
2836 alloc_table (table, table->rows);
2837 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2838 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2839 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2840 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2841 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2842 values += MONO_INTERFACEIMPL_SIZE;
2848 table = &assembly->tables [MONO_TABLE_FIELD];
2849 table->rows += tb->num_fields;
2850 alloc_table (table, table->rows);
2851 for (i = 0; i < tb->num_fields; ++i)
2852 mono_image_get_field_info (
2853 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2856 /* handle constructors */
2858 table = &assembly->tables [MONO_TABLE_METHOD];
2859 table->rows += mono_array_length (tb->ctors);
2860 alloc_table (table, table->rows);
2861 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2862 mono_image_get_ctor_info (domain,
2863 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2866 /* handle methods */
2868 table = &assembly->tables [MONO_TABLE_METHOD];
2869 table->rows += tb->num_methods;
2870 alloc_table (table, table->rows);
2871 for (i = 0; i < tb->num_methods; ++i)
2872 mono_image_get_method_info (
2873 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2876 /* Do the same with properties etc.. */
2877 if (tb->events && mono_array_length (tb->events)) {
2878 table = &assembly->tables [MONO_TABLE_EVENT];
2879 table->rows += mono_array_length (tb->events);
2880 alloc_table (table, table->rows);
2881 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2883 alloc_table (table, table->rows);
2884 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2885 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2886 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2887 for (i = 0; i < mono_array_length (tb->events); ++i)
2888 mono_image_get_event_info (
2889 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2891 if (tb->properties && mono_array_length (tb->properties)) {
2892 table = &assembly->tables [MONO_TABLE_PROPERTY];
2893 table->rows += mono_array_length (tb->properties);
2894 alloc_table (table, table->rows);
2895 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2897 alloc_table (table, table->rows);
2898 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2899 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2900 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2901 for (i = 0; i < mono_array_length (tb->properties); ++i)
2902 mono_image_get_property_info (
2903 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2906 /* handle generic parameters */
2907 if (tb->generic_params) {
2908 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2909 table->rows += mono_array_length (tb->generic_params);
2910 alloc_table (table, table->rows);
2911 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2912 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2914 mono_image_get_generic_param_info (
2915 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2919 mono_image_add_decl_security (assembly,
2920 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2923 MonoDynamicTable *ntable;
2925 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2926 ntable->rows += mono_array_length (tb->subtypes);
2927 alloc_table (ntable, ntable->rows);
2928 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2930 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2931 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2933 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2934 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2935 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2936 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2937 mono_string_to_utf8 (tb->name), tb->table_idx,
2938 ntable->next_idx, ntable->rows);*/
2939 values += MONO_NESTED_CLASS_SIZE;
2946 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2950 g_ptr_array_add (types, type);
2952 if (!type->subtypes)
2955 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2956 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2957 collect_types (types, subtype);
2962 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2964 if ((*type1)->table_idx < (*type2)->table_idx)
2967 if ((*type1)->table_idx > (*type2)->table_idx)
2974 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2979 for (i = 0; i < mono_array_length (pinfo); ++i) {
2980 MonoReflectionParamBuilder *pb;
2981 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2984 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2989 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2992 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2994 for (i = 0; i < tb->num_fields; ++i) {
2995 MonoReflectionFieldBuilder* fb;
2996 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2997 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3001 for (i = 0; i < mono_array_length (tb->events); ++i) {
3002 MonoReflectionEventBuilder* eb;
3003 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3004 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3007 if (tb->properties) {
3008 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3009 MonoReflectionPropertyBuilder* pb;
3010 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3011 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3015 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3016 MonoReflectionCtorBuilder* cb;
3017 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3018 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3019 params_add_cattrs (assembly, cb->pinfo);
3024 for (i = 0; i < tb->num_methods; ++i) {
3025 MonoReflectionMethodBuilder* mb;
3026 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3027 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3028 params_add_cattrs (assembly, mb->pinfo);
3033 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3034 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3039 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3042 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3044 /* no types in the module */
3048 for (i = 0; i < mb->num_types; ++i)
3049 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3053 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3055 MonoDynamicTable *table;
3059 char *b = blob_size;
3062 table = &assembly->tables [MONO_TABLE_FILE];
3064 alloc_table (table, table->rows);
3065 values = table->values + table->next_idx * MONO_FILE_SIZE;
3066 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3067 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3068 if (module->image->dynamic) {
3069 /* This depends on the fact that the main module is emitted last */
3070 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3071 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3074 path = g_strdup (module->image->name);
3076 mono_sha1_get_digest_from_file (path, hash);
3079 mono_metadata_encode_value (20, b, &b);
3080 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3081 mono_image_add_stream_data (&assembly->blob, hash, 20);
3086 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3088 MonoDynamicTable *table;
3092 table = &assembly->tables [MONO_TABLE_MODULE];
3093 mb->table_idx = table->next_idx ++;
3094 name = mono_string_to_utf8 (mb->module.name);
3095 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3097 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3100 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3101 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3102 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3106 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3107 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3109 MonoDynamicTable *table;
3113 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3114 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3117 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3119 alloc_table (table, table->rows);
3120 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3122 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3123 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3124 if (klass->nested_in)
3125 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3127 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3128 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3129 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3131 res = table->next_idx;
3135 /* Emit nested types */
3136 if (klass->nested_classes) {
3139 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3140 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3147 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3148 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3153 klass = mono_class_from_mono_type (tb->type.type);
3155 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3157 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3158 parent_index, assembly);
3162 * We need to do this ourselves since klass->nested_classes is not set up.
3165 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3166 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3171 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3172 guint32 module_index, MonoDynamicImage *assembly)
3174 MonoImage *image = module->image;
3178 t = &image->tables [MONO_TABLE_TYPEDEF];
3180 for (i = 0; i < t->rows; ++i) {
3181 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3183 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3184 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3188 #define align_pointer(base,p)\
3190 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3192 (p) += 4 - (__diff & 3);\
3196 compare_semantics (const void *a, const void *b)
3198 const guint32 *a_values = a;
3199 const guint32 *b_values = b;
3200 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3203 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3207 compare_custom_attrs (const void *a, const void *b)
3209 const guint32 *a_values = a;
3210 const guint32 *b_values = b;
3212 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3216 compare_field_marshal (const void *a, const void *b)
3218 const guint32 *a_values = a;
3219 const guint32 *b_values = b;
3221 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3225 compare_nested (const void *a, const void *b)
3227 const guint32 *a_values = a;
3228 const guint32 *b_values = b;
3230 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3234 compare_genericparam (const void *a, const void *b)
3236 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3237 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3239 return (*a_entry)->owner - (*b_entry)->owner;
3243 compare_declsecurity_attrs (const void *a, const void *b)
3245 const guint32 *a_values = a;
3246 const guint32 *b_values = b;
3248 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3252 pad_heap (MonoDynamicStream *sh)
3254 if (sh->index & 3) {
3255 int sz = 4 - (sh->index & 3);
3256 memset (sh->data + sh->index, 0, sz);
3263 MonoDynamicStream *stream;
3267 * build_compressed_metadata() fills in the blob of data that represents the
3268 * raw metadata as it will be saved in the PE file. The five streams are output
3269 * and the metadata tables are comnpressed from the guint32 array representation,
3270 * to the compressed on-disk format.
3273 build_compressed_metadata (MonoDynamicImage *assembly)
3275 MonoDynamicTable *table;
3277 guint64 valid_mask = 0;
3278 guint64 sorted_mask;
3279 guint32 heapt_size = 0;
3280 guint32 meta_size = 256; /* allow for header and other stuff */
3281 guint32 table_offset;
3282 guint32 ntables = 0;
3288 struct StreamDesc stream_desc [5];
3290 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3291 for (i = 0; i < assembly->gen_params->len; i++){
3292 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3293 write_generic_param_entry (assembly, entry);
3296 stream_desc [0].name = "#~";
3297 stream_desc [0].stream = &assembly->tstream;
3298 stream_desc [1].name = "#Strings";
3299 stream_desc [1].stream = &assembly->sheap;
3300 stream_desc [2].name = "#US";
3301 stream_desc [2].stream = &assembly->us;
3302 stream_desc [3].name = "#Blob";
3303 stream_desc [3].stream = &assembly->blob;
3304 stream_desc [4].name = "#GUID";
3305 stream_desc [4].stream = &assembly->guid;
3307 /* tables that are sorted */
3308 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3309 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3310 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3311 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3312 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3313 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3315 /* Compute table sizes */
3316 /* the MonoImage has already been created in mono_image_basic_init() */
3317 meta = &assembly->image;
3319 /* sizes should be multiple of 4 */
3320 pad_heap (&assembly->blob);
3321 pad_heap (&assembly->guid);
3322 pad_heap (&assembly->sheap);
3323 pad_heap (&assembly->us);
3325 /* Setup the info used by compute_sizes () */
3326 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3327 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3328 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3330 meta_size += assembly->blob.index;
3331 meta_size += assembly->guid.index;
3332 meta_size += assembly->sheap.index;
3333 meta_size += assembly->us.index;
3335 for (i=0; i < 64; ++i)
3336 meta->tables [i].rows = assembly->tables [i].rows;
3338 for (i = 0; i < 64; i++){
3339 if (meta->tables [i].rows == 0)
3341 valid_mask |= (guint64)1 << i;
3343 meta->tables [i].row_size = mono_metadata_compute_size (
3344 meta, i, &meta->tables [i].size_bitfield);
3345 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3347 heapt_size += 24; /* #~ header size */
3348 heapt_size += ntables * 4;
3349 /* make multiple of 4 */
3352 meta_size += heapt_size;
3353 meta->raw_metadata = g_malloc0 (meta_size);
3354 p = meta->raw_metadata;
3355 /* the metadata signature */
3356 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3357 /* version numbers and 4 bytes reserved */
3358 int16val = (guint16*)p;
3359 *int16val++ = GUINT16_TO_LE (1);
3360 *int16val = GUINT16_TO_LE (1);
3362 /* version string */
3363 int32val = (guint32*)p;
3364 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3366 memcpy (p, meta->version, strlen (meta->version));
3367 p += GUINT32_FROM_LE (*int32val);
3368 align_pointer (meta->raw_metadata, p);
3369 int16val = (guint16*)p;
3370 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3371 *int16val = GUINT16_TO_LE (5); /* number of streams */
3375 * write the stream info.
3377 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3378 table_offset += 3; table_offset &= ~3;
3380 assembly->tstream.index = heapt_size;
3381 for (i = 0; i < 5; ++i) {
3382 int32val = (guint32*)p;
3383 stream_desc [i].stream->offset = table_offset;
3384 *int32val++ = GUINT32_TO_LE (table_offset);
3385 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3386 table_offset += GUINT32_FROM_LE (*int32val);
3387 table_offset += 3; table_offset &= ~3;
3389 strcpy (p, stream_desc [i].name);
3390 p += strlen (stream_desc [i].name) + 1;
3391 align_pointer (meta->raw_metadata, p);
3394 * now copy the data, the table stream header and contents goes first.
3396 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3397 p = meta->raw_metadata + assembly->tstream.offset;
3398 int32val = (guint32*)p;
3399 *int32val = GUINT32_TO_LE (0); /* reserved */
3402 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3403 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3404 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3405 *p++ = 1; /* version */
3408 *p++ = 1; /* version */
3412 if (meta->idx_string_wide)
3414 if (meta->idx_guid_wide)
3416 if (meta->idx_blob_wide)
3419 *p++ = 1; /* reserved */
3420 int64val = (guint64*)p;
3421 *int64val++ = GUINT64_TO_LE (valid_mask);
3422 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3424 int32val = (guint32*)p;
3425 for (i = 0; i < 64; i++){
3426 if (meta->tables [i].rows == 0)
3428 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3430 p = (unsigned char*)int32val;
3432 /* sort the tables that still need sorting */
3433 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3435 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3436 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3438 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3439 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3441 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3442 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3444 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3445 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3446 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3448 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3450 /* compress the tables */
3451 for (i = 0; i < 64; i++){
3454 guint32 bitfield = meta->tables [i].size_bitfield;
3455 if (!meta->tables [i].rows)
3457 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3458 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3459 meta->tables [i].base = p;
3460 for (row = 1; row <= meta->tables [i].rows; ++row) {
3461 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3462 for (col = 0; col < assembly->tables [i].columns; ++col) {
3463 switch (mono_metadata_table_size (bitfield, col)) {
3465 *p++ = values [col];
3468 *p++ = values [col] & 0xff;
3469 *p++ = (values [col] >> 8) & 0xff;
3472 *p++ = values [col] & 0xff;
3473 *p++ = (values [col] >> 8) & 0xff;
3474 *p++ = (values [col] >> 16) & 0xff;
3475 *p++ = (values [col] >> 24) & 0xff;
3478 g_assert_not_reached ();
3482 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3485 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3486 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3487 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3488 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3489 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3491 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3495 * Some tables in metadata need to be sorted according to some criteria, but
3496 * when methods and fields are first created with reflection, they may be assigned a token
3497 * that doesn't correspond to the final token they will get assigned after the sorting.
3498 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3499 * with the reflection objects that represent them. Once all the tables are set up, the
3500 * reflection objects will contains the correct table index. fixup_method() will fixup the
3501 * tokens for the method with ILGenerator @ilgen.
3504 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3505 guint32 code_idx = GPOINTER_TO_UINT (value);
3506 MonoReflectionILTokenInfo *iltoken;
3507 MonoReflectionFieldBuilder *field;
3508 MonoReflectionCtorBuilder *ctor;
3509 MonoReflectionMethodBuilder *method;
3510 MonoReflectionTypeBuilder *tb;
3511 MonoReflectionArrayMethod *am;
3513 unsigned char *target;
3515 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3516 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3517 target = assembly->code.data + code_idx + iltoken->code_pos;
3518 switch (target [3]) {
3519 case MONO_TABLE_FIELD:
3520 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3521 field = (MonoReflectionFieldBuilder *)iltoken->member;
3522 idx = field->table_idx;
3523 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3524 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3525 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3527 g_assert_not_reached ();
3530 case MONO_TABLE_METHOD:
3531 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3532 method = (MonoReflectionMethodBuilder *)iltoken->member;
3533 idx = method->table_idx;
3534 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3535 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3536 idx = ctor->table_idx;
3537 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3538 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3539 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3540 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3542 g_assert_not_reached ();
3545 case MONO_TABLE_TYPEDEF:
3546 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3547 g_assert_not_reached ();
3548 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3549 idx = tb->table_idx;
3551 case MONO_TABLE_MEMBERREF:
3552 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3553 am = (MonoReflectionArrayMethod*)iltoken->member;
3554 idx = am->table_idx;
3555 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3556 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3557 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3558 g_assert (m->klass->generic_inst);
3560 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3562 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3563 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3564 g_assert (f->generic_info);
3566 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3569 g_assert_not_reached ();
3572 case MONO_TABLE_METHODSPEC:
3573 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3574 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3575 g_assert (m->signature->generic_param_count);
3578 g_assert_not_reached ();
3582 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3584 target [0] = idx & 0xff;
3585 target [1] = (idx >> 8) & 0xff;
3586 target [2] = (idx >> 16) & 0xff;
3593 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3594 * value is not known when the table is emitted.
3597 fixup_cattrs (MonoDynamicImage *assembly)
3599 MonoDynamicTable *table;
3601 guint32 type, i, idx, token;
3604 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3606 for (i = 0; i < table->rows; ++i) {
3607 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3609 type = values [MONO_CUSTOM_ATTR_TYPE];
3610 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3611 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3612 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3613 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3616 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3617 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3618 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3619 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3626 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3628 MonoDynamicTable *table;
3632 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3634 alloc_table (table, table->rows);
3635 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3636 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3637 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3638 name = mono_string_to_utf8 (rsrc->name);
3639 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3641 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3646 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3648 MonoDynamicTable *table;
3652 char *b = blob_size;
3654 guint32 idx, offset;
3656 if (rsrc->filename) {
3657 name = mono_string_to_utf8 (rsrc->filename);
3658 sname = g_path_get_basename (name);
3660 table = &assembly->tables [MONO_TABLE_FILE];
3662 alloc_table (table, table->rows);
3663 values = table->values + table->next_idx * MONO_FILE_SIZE;
3664 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3665 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3668 mono_sha1_get_digest_from_file (name, hash);
3669 mono_metadata_encode_value (20, b, &b);
3670 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3671 mono_image_add_stream_data (&assembly->blob, hash, 20);
3673 idx = table->next_idx++;
3675 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3678 offset = mono_array_length (rsrc->data);
3679 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3680 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3681 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3682 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3686 * The entry should be emitted into the MANIFESTRESOURCE table of
3687 * the main module, but that needs to reference the FILE table
3688 * which isn't emitted yet.
3695 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3699 set_version_from_string (MonoString *version, guint32 *values)
3701 gchar *ver, *p, *str;
3704 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3705 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3706 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3707 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3710 ver = str = mono_string_to_utf8 (version);
3711 for (i = 0; i < 4; ++i) {
3712 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3718 /* handle Revision and Build */
3728 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3732 char *b = blob_size;
3737 len = mono_array_length (pkey);
3738 mono_metadata_encode_value (len, b, &b);
3739 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3740 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3742 /* need to get the actual value from the key type... */
3743 assembly->strong_name_size = 128;
3744 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3750 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3752 MonoDynamicTable *table;
3753 MonoDynamicImage *assembly;
3754 MonoReflectionAssemblyBuilder *assemblyb;
3759 guint32 module_index;
3761 assemblyb = moduleb->assemblyb;
3762 assembly = moduleb->dynamic_image;
3763 domain = mono_object_domain (assemblyb);
3765 /* Emit ASSEMBLY table */
3766 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3767 alloc_table (table, 1);
3768 values = table->values + MONO_ASSEMBLY_SIZE;
3769 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3770 name = mono_string_to_utf8 (assemblyb->name);
3771 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3773 if (assemblyb->culture) {
3774 name = mono_string_to_utf8 (assemblyb->culture);
3775 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3778 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3780 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3781 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3782 set_version_from_string (assemblyb->version, values);
3784 /* Emit FILE + EXPORTED_TYPE table */
3786 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3788 MonoReflectionModuleBuilder *file_module =
3789 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3790 if (file_module != moduleb) {
3791 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3793 if (file_module->types) {
3794 for (j = 0; j < file_module->num_types; ++j) {
3795 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3796 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3801 if (assemblyb->loaded_modules) {
3802 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3803 MonoReflectionModule *file_module =
3804 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3805 mono_image_fill_file_table (domain, file_module, assembly);
3807 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3811 /* Emit MANIFESTRESOURCE table */
3813 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3815 MonoReflectionModuleBuilder *file_module =
3816 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3817 /* The table for the main module is emitted later */
3818 if (file_module != moduleb) {
3820 if (file_module->resources) {
3821 int len = mono_array_length (file_module->resources);
3822 for (j = 0; j < len; ++j) {
3823 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3824 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3832 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3833 * for the modulebuilder @moduleb.
3834 * At the end of the process, method and field tokens are fixed up and the
3835 * on-disk compressed metadata representation is created.
3838 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3840 MonoDynamicTable *table;
3841 MonoDynamicImage *assembly;
3842 MonoReflectionAssemblyBuilder *assemblyb;
3847 assemblyb = moduleb->assemblyb;
3848 assembly = moduleb->dynamic_image;
3849 domain = mono_object_domain (assemblyb);
3851 if (assembly->text_rva)
3854 assembly->text_rva = START_TEXT_RVA;
3856 if (moduleb->is_main) {
3857 mono_image_emit_manifest (moduleb);
3860 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3861 table->rows = 1; /* .<Module> */
3863 alloc_table (table, table->rows);
3865 * Set the first entry.
3867 values = table->values + table->columns;
3868 values [MONO_TYPEDEF_FLAGS] = 0;
3869 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3870 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3871 values [MONO_TYPEDEF_EXTENDS] = 0;
3872 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3873 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3876 * handle global methods
3877 * FIXME: test what to do when global methods are defined in multiple modules.
3879 if (moduleb->global_methods) {
3880 table = &assembly->tables [MONO_TABLE_METHOD];
3881 table->rows += mono_array_length (moduleb->global_methods);
3882 alloc_table (table, table->rows);
3883 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3884 mono_image_get_method_info (
3885 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3887 if (moduleb->global_fields) {
3888 table = &assembly->tables [MONO_TABLE_FIELD];
3889 table->rows += mono_array_length (moduleb->global_fields);
3890 alloc_table (table, table->rows);
3891 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3892 mono_image_get_field_info (
3893 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3896 table = &assembly->tables [MONO_TABLE_MODULE];
3897 alloc_table (table, 1);
3898 mono_image_fill_module_table (domain, moduleb, assembly);
3902 /* Collect all types into a list sorted by their table_idx */
3903 GPtrArray *types = g_ptr_array_new ();
3906 for (i = 0; i < moduleb->num_types; ++i) {
3907 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3908 collect_types (types, type);
3911 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3912 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3913 table->rows += types->len;
3914 alloc_table (table, table->rows);
3916 for (i = 0; i < types->len; ++i) {
3917 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3918 mono_image_get_type_info (domain, type, assembly);
3920 g_ptr_array_free (types, TRUE);
3924 * table->rows is already set above and in mono_image_fill_module_table.
3926 /* add all the custom attributes at the end, once all the indexes are stable */
3927 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3929 /* CAS assembly permissions */
3930 if (assemblyb->permissions_minimum)
3931 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3932 if (assemblyb->permissions_optional)
3933 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3934 if (assemblyb->permissions_refused)
3935 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3937 module_add_cattrs (assembly, moduleb);
3940 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3941 fixup_cattrs (assembly);
3945 * mono_image_insert_string:
3946 * @module: module builder object
3949 * Insert @str into the user string stream of @module.
3952 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3954 MonoDynamicImage *assembly;
3959 MONO_ARCH_SAVE_REGS;
3961 if (!module->dynamic_image)
3962 mono_image_module_basic_init (module);
3964 assembly = module->dynamic_image;
3966 if (assembly->save) {
3967 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3968 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3969 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3971 char *swapped = g_malloc (2 * mono_string_length (str));
3972 const char *p = (const char*)mono_string_chars (str);
3974 swap_with_size (swapped, p, 2, mono_string_length (str));
3975 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3979 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3981 mono_image_add_stream_data (&assembly->us, "", 1);
3983 idx = assembly->us.index ++;
3986 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3988 return MONO_TOKEN_STRING | idx;
3992 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3997 klass = obj->vtable->klass;
3998 if (strcmp (klass->name, "MonoMethod") == 0) {
3999 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4000 MonoMethodSignature *sig, *old;
4001 guint32 sig_token, parent;
4004 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4006 nargs = mono_array_length (opt_param_types);
4007 old = method->signature;
4008 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4010 sig->hasthis = old->hasthis;
4011 sig->explicit_this = old->explicit_this;
4012 sig->call_convention = old->call_convention;
4013 sig->generic_param_count = old->generic_param_count;
4014 sig->param_count = old->param_count + nargs;
4015 sig->sentinelpos = old->param_count;
4016 sig->ret = old->ret;
4018 for (i = 0; i < old->param_count; i++)
4019 sig->params [i] = old->params [i];
4021 for (i = 0; i < nargs; i++) {
4022 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4023 sig->params [old->param_count + i] = rt->type;
4026 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4027 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4028 parent >>= MONO_TYPEDEFORREF_BITS;
4030 parent <<= MONO_MEMBERREF_PARENT_BITS;
4031 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4033 sig_token = method_encode_signature (assembly, sig);
4034 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4035 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4036 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4037 ReflectionMethodBuilder rmb;
4038 guint32 parent, sig;
4040 reflection_methodbuilder_from_method_builder (&rmb, mb);
4041 rmb.opt_types = opt_param_types;
4043 sig = method_builder_encode_signature (assembly, &rmb);
4045 parent = mono_image_create_token (assembly, obj, TRUE);
4046 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4048 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4049 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4051 token = mono_image_get_varargs_method_token (
4052 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4054 g_error ("requested method token for %s\n", klass->name);
4061 * mono_image_create_token:
4062 * @assembly: a dynamic assembly
4065 * Get a token to insert in the IL code stream for the given MemberInfo.
4066 * @obj can be one of:
4067 * ConstructorBuilder
4077 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4082 klass = obj->vtable->klass;
4083 if (strcmp (klass->name, "MethodBuilder") == 0) {
4084 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4086 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4087 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4089 token = mono_image_get_methodbuilder_token (assembly, mb);
4090 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4091 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4092 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4094 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4095 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4097 token = mono_image_get_ctorbuilder_token (assembly, mb);
4098 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4099 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4100 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4101 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4102 if (tb->generic_params) {
4103 token = mono_image_get_generic_field_token (assembly, fb);
4105 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4107 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4108 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4109 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4110 } else if (strcmp (klass->name, "MonoType") == 0 ||
4111 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4112 MonoReflectionType *tb = (MonoReflectionType *)obj;
4113 token = mono_metadata_token_from_dor (
4114 mono_image_typedef_or_ref (assembly, tb->type));
4115 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4116 MonoReflectionType *tb = (MonoReflectionType *)obj;
4117 token = mono_metadata_token_from_dor (
4118 mono_image_typedef_or_ref (assembly, tb->type));
4119 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4120 strcmp (klass->name, "MonoMethod") == 0) {
4121 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4122 if (m->method->signature->is_inflated) {
4123 if (create_methodspec)
4124 token = mono_image_get_methodspec_token (assembly, m->method);
4126 token = mono_image_get_inflated_method_token (assembly, m->method);
4127 } else if (m->method->signature->generic_param_count) {
4128 g_assert_not_reached ();
4129 } else if ((m->method->klass->image == &assembly->image) &&
4130 !m->method->klass->generic_inst) {
4131 static guint32 method_table_idx = 0xffffff;
4132 if (m->method->klass->wastypebuilder) {
4133 /* we use the same token as the one that was assigned
4134 * to the Methodbuilder.
4135 * FIXME: do the equivalent for Fields.
4137 token = m->method->token;
4140 * Each token should have a unique index, but the indexes are
4141 * assigned by managed code, so we don't know about them. An
4142 * easy solution is to count backwards...
4144 method_table_idx --;
4145 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4148 token = mono_image_get_methodref_token (assembly, m->method);
4150 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4151 } else if (strcmp (klass->name, "MonoField") == 0) {
4152 MonoReflectionField *f = (MonoReflectionField *)obj;
4153 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4154 static guint32 field_table_idx = 0xffffff;
4156 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4158 token = mono_image_get_fieldref_token (assembly, f);
4160 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4161 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4162 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4163 token = mono_image_get_array_token (assembly, m);
4164 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4165 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4166 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4168 g_error ("requested token for %s\n", klass->name);
4171 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4177 guint32 import_lookup_table;
4181 guint32 import_address_table_rva;
4189 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4191 static MonoDynamicImage*
4192 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4194 static const guchar entrycode [16] = {0xff, 0x25, 0};
4195 MonoDynamicImage *image;
4198 const char *version = mono_get_runtime_version ();
4201 image = GC_MALLOC (sizeof (MonoDynamicImage));
4203 image = g_new0 (MonoDynamicImage, 1);
4206 /* keep in sync with image.c */
4207 image->image.name = assembly_name;
4208 image->image.assembly_name = image->image.name; /* they may be different */
4209 image->image.module_name = module_name;
4210 image->image.version = g_strdup (version);
4211 image->image.dynamic = TRUE;
4213 image->image.references = g_new0 (MonoAssembly*, 1);
4214 image->image.references [0] = NULL;
4216 mono_image_init (&image->image);
4218 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4219 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4220 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4221 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4222 image->handleref = g_hash_table_new (NULL, NULL);
4223 image->tokens = mono_g_hash_table_new (NULL, NULL);
4224 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4225 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4226 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4227 image->gen_params = g_ptr_array_new ();
4229 string_heap_init (&image->sheap);
4230 mono_image_add_stream_data (&image->us, "", 1);
4231 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4232 /* import tables... */
4233 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4234 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4235 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4236 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4237 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4238 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4239 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4240 stream_data_align (&image->code);
4242 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4244 for (i=0; i < 64; ++i) {
4245 image->tables [i].next_idx = 1;
4246 image->tables [i].columns = table_sizes [i];
4249 image->image.assembly = (MonoAssembly*)assembly;
4250 image->run = assembly->run;
4251 image->save = assembly->save;
4252 image->pe_kind = 0x1; /* ILOnly */
4253 image->machine = 0x14c; /* I386 */
4259 * mono_image_basic_init:
4260 * @assembly: an assembly builder object
4262 * Create the MonoImage that represents the assembly builder and setup some
4263 * of the helper hash table and the basic metadata streams.
4266 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4268 MonoDynamicAssembly *assembly;
4269 MonoDynamicImage *image;
4271 MONO_ARCH_SAVE_REGS;
4273 if (assemblyb->dynamic_assembly)
4277 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4279 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4282 assembly->assembly.dynamic = TRUE;
4283 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4284 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4285 if (assemblyb->culture)
4286 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4288 assembly->assembly.aname.culture = g_strdup ("");
4290 assembly->run = assemblyb->access != 2;
4291 assembly->save = assemblyb->access != 1;
4293 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4294 image->initial_image = TRUE;
4295 assembly->assembly.aname.name = image->image.name;
4296 assembly->assembly.image = &image->image;
4298 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4299 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4303 calc_section_size (MonoDynamicImage *assembly)
4307 /* alignment constraints */
4308 assembly->code.index += 3;
4309 assembly->code.index &= ~3;
4310 assembly->meta_size += 3;
4311 assembly->meta_size &= ~3;
4312 assembly->resources.index += 3;
4313 assembly->resources.index &= ~3;
4315 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4316 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4319 if (assembly->win32_res) {
4320 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4322 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4323 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4327 assembly->sections [MONO_SECTION_RELOC].size = 12;
4328 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4338 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4342 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4344 ResTreeNode *t1 = (ResTreeNode*)a;
4345 ResTreeNode *t2 = (ResTreeNode*)b;
4347 return t1->id - t2->id;
4351 * resource_tree_create:
4353 * Organize the resources into a resource tree.
4355 static ResTreeNode *
4356 resource_tree_create (MonoArray *win32_resources)
4358 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4362 tree = g_new0 (ResTreeNode, 1);
4364 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4365 MonoReflectionWin32Resource *win32_res =
4366 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4370 lang_node = g_new0 (ResTreeNode, 1);
4371 lang_node->id = win32_res->lang_id;
4372 lang_node->win32_res = win32_res;
4374 /* Create type node if neccesary */
4376 for (l = tree->children; l; l = l->next)
4377 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4378 type_node = (ResTreeNode*)l->data;
4383 type_node = g_new0 (ResTreeNode, 1);
4384 type_node->id = win32_res->res_type;
4387 * The resource types have to be sorted otherwise
4388 * Windows Explorer can't display the version information.
4390 tree->children = g_slist_insert_sorted (tree->children,
4391 type_node, resource_tree_compare_by_id);
4394 /* Create res node if neccesary */
4396 for (l = type_node->children; l; l = l->next)
4397 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4398 res_node = (ResTreeNode*)l->data;
4403 res_node = g_new0 (ResTreeNode, 1);
4404 res_node->id = win32_res->res_id;
4405 type_node->children = g_slist_append (type_node->children, res_node);
4408 res_node->children = g_slist_append (res_node->children, lang_node);
4415 * resource_tree_encode:
4417 * Encode the resource tree into the format used in the PE file.
4420 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4423 MonoPEResourceDir dir;
4424 MonoPEResourceDirEntry dir_entry;
4425 MonoPEResourceDataEntry data_entry;
4429 * For the format of the resource directory, see the article
4430 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4434 memset (&dir, 0, sizeof (dir));
4435 memset (&dir_entry, 0, sizeof (dir_entry));
4436 memset (&data_entry, 0, sizeof (data_entry));
4438 g_assert (sizeof (dir) == 16);
4439 g_assert (sizeof (dir_entry) == 8);
4440 g_assert (sizeof (data_entry) == 16);
4442 node->offset = p - begin;
4444 /* IMAGE_RESOURCE_DIRECTORY */
4445 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4447 memcpy (p, &dir, sizeof (dir));
4450 /* Reserve space for entries */
4452 p += sizeof (dir_entry) * dir.res_id_entries;
4454 /* Write children */
4455 for (l = node->children; l; l = l->next) {
4456 ResTreeNode *child = (ResTreeNode*)l->data;
4458 if (child->win32_res) {
4460 child->offset = p - begin;
4462 /* IMAGE_RESOURCE_DATA_ENTRY */
4463 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4464 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4466 memcpy (p, &data_entry, sizeof (data_entry));
4467 p += sizeof (data_entry);
4469 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4470 p += data_entry.rde_size;
4472 resource_tree_encode (child, begin, p, &p);
4476 /* IMAGE_RESOURCE_ENTRY */
4477 for (l = node->children; l; l = l->next) {
4478 ResTreeNode *child = (ResTreeNode*)l->data;
4479 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4481 dir_entry.is_dir = child->win32_res ? 0 : 1;
4482 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4484 memcpy (entries, &dir_entry, sizeof (dir_entry));
4485 entries += sizeof (dir_entry);
4492 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4497 MonoReflectionWin32Resource *win32_res;
4500 if (!assemblyb->win32_resources)
4504 * Resources are stored in a three level tree inside the PE file.
4505 * - level one contains a node for each type of resource
4506 * - level two contains a node for each resource
4507 * - level three contains a node for each instance of a resource for a
4508 * specific language.
4511 tree = resource_tree_create (assemblyb->win32_resources);
4513 /* Estimate the size of the encoded tree */
4515 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4516 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4517 size += mono_array_length (win32_res->res_data);
4519 /* Directory structure */
4520 size += mono_array_length (assemblyb->win32_resources) * 256;
4521 p = buf = g_malloc (size);
4523 resource_tree_encode (tree, p, p, &p);
4525 g_assert (p - buf < size);
4527 assembly->win32_res = g_malloc (p - buf);
4528 assembly->win32_res_size = p - buf;
4529 memcpy (assembly->win32_res, buf, p - buf);
4535 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4537 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4540 p += sizeof (MonoPEResourceDir);
4541 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4542 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4543 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4544 if (dir_entry->is_dir) {
4545 fixup_resource_directory (res_section, child, rva);
4547 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4548 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4551 p += sizeof (MonoPEResourceDirEntry);
4556 * mono_image_create_pefile:
4557 * @mb: a module builder object
4559 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4560 * assembly->pefile where it can be easily retrieved later in chunks.
4563 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4564 MonoMSDOSHeader *msdos;
4565 MonoDotNetHeader *header;
4566 MonoSectionTable *section;
4567 MonoCLIHeader *cli_header;
4568 guint32 size, image_size, virtual_base, text_offset;
4569 guint32 header_start, section_start, file_offset, virtual_offset;
4570 MonoDynamicImage *assembly;
4571 MonoReflectionAssemblyBuilder *assemblyb;
4572 MonoDynamicStream *pefile;
4574 guint32 *rva, value;
4577 static const unsigned char msheader[] = {
4578 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4579 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4582 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4583 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4584 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4585 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4588 assemblyb = mb->assemblyb;
4590 mono_image_basic_init (assemblyb);
4591 assembly = mb->dynamic_image;
4593 assembly->pe_kind = assemblyb->pe_kind;
4594 assembly->machine = assemblyb->machine;
4595 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4596 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4598 /* already created */
4599 if (assembly->pefile.index)
4602 mono_image_build_metadata (mb);
4604 if (mb->is_main && assemblyb->resources) {
4605 int len = mono_array_length (assemblyb->resources);
4606 for (i = 0; i < len; ++i)
4607 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4610 if (mb->resources) {
4611 int len = mono_array_length (mb->resources);
4612 for (i = 0; i < len; ++i)
4613 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4616 build_compressed_metadata (assembly);
4619 assembly_add_win32_resources (assembly, assemblyb);
4621 nsections = calc_section_size (assembly);
4623 pefile = &assembly->pefile;
4625 /* The DOS header and stub */
4626 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4627 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4629 /* the dotnet header */
4630 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4632 /* the section tables */
4633 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4635 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4636 virtual_offset = VIRT_ALIGN;
4639 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4640 if (!assembly->sections [i].size)
4643 file_offset += FILE_ALIGN - 1;
4644 file_offset &= ~(FILE_ALIGN - 1);
4645 virtual_offset += VIRT_ALIGN - 1;
4646 virtual_offset &= ~(VIRT_ALIGN - 1);
4648 assembly->sections [i].offset = file_offset;
4649 assembly->sections [i].rva = virtual_offset;
4651 file_offset += assembly->sections [i].size;
4652 virtual_offset += assembly->sections [i].size;
4653 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4656 file_offset += FILE_ALIGN - 1;
4657 file_offset &= ~(FILE_ALIGN - 1);
4658 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4660 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4662 /* back-patch info */
4663 msdos = (MonoMSDOSHeader*)pefile->data;
4664 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4665 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4666 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4668 header = (MonoDotNetHeader*)(pefile->data + header_start);
4669 header->pesig [0] = 'P';
4670 header->pesig [1] = 'E';
4672 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4673 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4674 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4675 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4676 if (assemblyb->pekind == 1) {
4678 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4681 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4684 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4686 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4687 header->pe.pe_major = 6;
4688 header->pe.pe_minor = 0;
4689 size = assembly->sections [MONO_SECTION_TEXT].size;
4690 size += FILE_ALIGN - 1;
4691 size &= ~(FILE_ALIGN - 1);
4692 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4693 size = assembly->sections [MONO_SECTION_RSRC].size;
4694 size += FILE_ALIGN - 1;
4695 size &= ~(FILE_ALIGN - 1);
4696 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4697 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4698 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4699 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4700 /* pe_rva_entry_point always at the beginning of the text section */
4701 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4703 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4704 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4705 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4706 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4707 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4708 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4709 size = section_start;
4710 size += FILE_ALIGN - 1;
4711 size &= ~(FILE_ALIGN - 1);
4712 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4714 size += VIRT_ALIGN - 1;
4715 size &= ~(VIRT_ALIGN - 1);
4716 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4719 // Translate the PEFileKind value to the value expected by the Windows loader
4725 // PEFileKinds.Dll == 1
4726 // PEFileKinds.ConsoleApplication == 2
4727 // PEFileKinds.WindowApplication == 3
4730 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4731 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4733 if (assemblyb->pekind == 3)
4738 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4740 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4741 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4742 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4743 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4744 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4745 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4747 /* fill data directory entries */
4749 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4750 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4752 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4753 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4755 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4756 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4757 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4758 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4759 /* patch entrypoint name */
4760 if (assemblyb->pekind == 1)
4761 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4763 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4764 /* patch imported function RVA name */
4765 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4766 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4768 /* the import table */
4769 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4770 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4771 /* patch imported dll RVA name and other entries in the dir */
4772 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4773 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4774 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4775 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4776 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4777 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4779 p = (assembly->code.data + assembly->ilt_offset);
4780 value = (assembly->text_rva + assembly->imp_names_offset);
4781 *p++ = (value) & 0xff;
4782 *p++ = (value >> 8) & (0xff);
4783 *p++ = (value >> 16) & (0xff);
4784 *p++ = (value >> 24) & (0xff);
4786 /* the CLI header info */
4787 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4788 cli_header->ch_size = GUINT32_FROM_LE (72);
4789 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4790 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4791 if (assemblyb->entry_point) {
4792 guint32 table_idx = 0;
4793 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4794 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4795 table_idx = methodb->table_idx;
4797 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4799 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4801 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4803 /* The embedded managed resources */
4804 text_offset = assembly->text_rva + assembly->code.index;
4805 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4806 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4807 text_offset += assembly->resources.index;
4808 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4809 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4810 text_offset += assembly->meta_size;
4811 if (assembly->strong_name_size) {
4812 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4813 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4814 text_offset += assembly->strong_name_size;
4817 /* write the section tables and section content */
4818 section = (MonoSectionTable*)(pefile->data + section_start);
4819 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4820 static const char *section_names [] = {
4821 ".text", ".rsrc", ".reloc"
4823 if (!assembly->sections [i].size)
4825 strcpy (section->st_name, section_names [i]);
4826 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4827 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4828 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4829 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4830 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4831 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4832 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4834 case MONO_SECTION_TEXT:
4835 /* patch entry point */
4836 p = (assembly->code.data + 2);
4837 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4838 *p++ = (value) & 0xff;
4839 *p++ = (value >> 8) & 0xff;
4840 *p++ = (value >> 16) & 0xff;
4841 *p++ = (value >> 24) & 0xff;
4843 text_offset = assembly->sections [i].offset;
4844 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4845 text_offset += assembly->code.index;
4846 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4847 text_offset += assembly->resources.index;
4848 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4849 text_offset += assembly->meta_size;
4850 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4852 g_free (assembly->image.raw_metadata);
4854 case MONO_SECTION_RELOC:
4855 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4856 *rva = GUINT32_FROM_LE (assembly->text_rva);
4858 *rva = GUINT32_FROM_LE (12);
4860 data16 = (guint16*)rva;
4862 * the entrypoint is always at the start of the text section
4863 * 3 is IMAGE_REL_BASED_HIGHLOW
4864 * 2 is patch_size_rva - text_rva
4866 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4868 *data16 = 0; /* terminate */
4870 case MONO_SECTION_RSRC:
4871 if (assembly->win32_res) {
4872 text_offset = assembly->sections [i].offset;
4874 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4875 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4877 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4881 g_assert_not_reached ();
4886 /* check that the file is properly padded */
4889 FILE *f = fopen ("mypetest.exe", "w");
4890 fwrite (pefile->data, pefile->index, 1, f);
4896 MonoReflectionModule *
4897 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4901 MonoImageOpenStatus status;
4902 MonoDynamicAssembly *assembly;
4903 guint32 module_count;
4904 MonoImage **new_modules;
4906 name = mono_string_to_utf8 (fileName);
4908 image = mono_image_open (name, &status);
4911 if (status == MONO_IMAGE_ERROR_ERRNO)
4912 exc = mono_get_exception_file_not_found (fileName);
4914 exc = mono_get_exception_bad_image_format (name);
4916 mono_raise_exception (exc);
4921 assembly = ab->dynamic_assembly;
4922 image->assembly = (MonoAssembly*)assembly;
4924 module_count = image->assembly->image->module_count;
4925 new_modules = g_new0 (MonoImage *, module_count + 1);
4927 if (image->assembly->image->modules)
4928 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4929 new_modules [module_count] = image;
4931 g_free (image->assembly->image->modules);
4932 image->assembly->image->modules = new_modules;
4933 image->assembly->image->module_count ++;
4935 mono_assembly_load_references (image, &status);
4937 mono_image_close (image);
4938 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4941 return mono_module_get_object (mono_domain_get (), image);
4945 * We need to return always the same object for MethodInfo, FieldInfo etc..
4946 * but we need to consider the reflected type.
4947 * type uses a different hash, since it uses custom hash/equal functions.
4952 MonoClass *refclass;
4956 reflected_equal (gconstpointer a, gconstpointer b) {
4957 const ReflectedEntry *ea = a;
4958 const ReflectedEntry *eb = b;
4960 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4964 reflected_hash (gconstpointer a) {
4965 const ReflectedEntry *ea = a;
4966 return GPOINTER_TO_UINT (ea->item);
4969 #define CHECK_OBJECT(t,p,k) \
4975 mono_domain_lock (domain); \
4976 if (!domain->refobject_hash) \
4977 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4978 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4979 mono_domain_unlock (domain); \
4985 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4987 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4990 #define CACHE_OBJECT(p,o,k) \
4992 ReflectedEntry *e = ALLOC_REFENTRY; \
4994 e->refclass = (k); \
4995 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4996 mono_domain_unlock (domain); \
5000 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5002 /* this is done only once */
5003 mono_domain_lock (domain);
5004 CACHE_OBJECT (assembly, res, NULL);
5008 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5010 /* this is done only once */
5011 mono_domain_lock (domain);
5012 CACHE_OBJECT (module, res, NULL);
5016 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5018 MonoDynamicImage *image = moduleb->dynamic_image;
5019 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5022 * FIXME: we already created an image in mono_image_basic_init (), but
5023 * we don't know which module it belongs to, since that is only
5024 * determined at assembly save time.
5026 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5027 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5029 moduleb->module.image = &image->image;
5030 moduleb->dynamic_image = image;
5031 register_module (mono_object_domain (moduleb), moduleb, image);
5036 * mono_assembly_get_object:
5037 * @domain: an app domain
5038 * @assembly: an assembly
5040 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5042 MonoReflectionAssembly*
5043 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5045 static MonoClass *System_Reflection_Assembly;
5046 MonoReflectionAssembly *res;
5048 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5049 if (!System_Reflection_Assembly)
5050 System_Reflection_Assembly = mono_class_from_name (
5051 mono_defaults.corlib, "System.Reflection", "Assembly");
5052 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5053 res->assembly = assembly;
5054 CACHE_OBJECT (assembly, res, NULL);
5060 MonoReflectionModule*
5061 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5063 static MonoClass *System_Reflection_Module;
5064 MonoReflectionModule *res;
5067 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
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);
5074 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5076 res->fqname = mono_string_new (domain, image->name);
5077 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5078 res->scopename = mono_string_new (domain, image->module_name);
5082 if (image->assembly->image == image) {
5083 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5086 g_assert (image->assembly->image->modules);
5088 for (i = 0; i < image->assembly->image->module_count; i++) {
5089 if (image->assembly->image->modules [i] == image)
5090 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5092 g_assert (res->token);
5095 mono_image_addref (image);
5097 CACHE_OBJECT (image, res, NULL);
5101 MonoReflectionModule*
5102 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5104 static MonoClass *System_Reflection_Module;
5105 MonoReflectionModule *res;
5106 MonoTableInfo *table;
5107 guint32 cols [MONO_FILE_SIZE];
5109 guint32 i, name_idx;
5112 if (!System_Reflection_Module)
5113 System_Reflection_Module = mono_class_from_name (
5114 mono_defaults.corlib, "System.Reflection", "Module");
5115 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5117 table = &image->tables [MONO_TABLE_FILE];
5118 g_assert (table_index < table->rows);
5119 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5122 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5123 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5125 /* Check whenever the row has a corresponding row in the moduleref table */
5126 table = &image->tables [MONO_TABLE_MODULEREF];
5127 for (i = 0; i < table->rows; ++i) {
5128 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5129 val = mono_metadata_string_heap (image, name_idx);
5130 if (strcmp (val, name) == 0)
5131 res->image = image->modules [i];
5134 res->fqname = mono_string_new (domain, name);
5135 res->name = mono_string_new (domain, name);
5136 res->scopename = mono_string_new (domain, name);
5137 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5138 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5144 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5146 if ((t1->type != t2->type) ||
5147 (t1->byref != t2->byref))
5151 case MONO_TYPE_VOID:
5152 case MONO_TYPE_BOOLEAN:
5153 case MONO_TYPE_CHAR:
5164 case MONO_TYPE_STRING:
5167 case MONO_TYPE_OBJECT:
5168 case MONO_TYPE_TYPEDBYREF:
5170 case MONO_TYPE_VALUETYPE:
5171 case MONO_TYPE_CLASS:
5172 case MONO_TYPE_SZARRAY:
5173 return t1->data.klass == t2->data.klass;
5175 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5176 case MONO_TYPE_ARRAY:
5177 if (t1->data.array->rank != t2->data.array->rank)
5179 return t1->data.array->eklass == t2->data.array->eklass;
5180 case MONO_TYPE_GENERICINST: {
5182 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5184 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5186 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5187 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5193 case MONO_TYPE_MVAR:
5194 return t1->data.generic_param == t2->data.generic_param;
5196 g_error ("implement type compare for %0x!", t1->type);
5204 mymono_metadata_type_hash (MonoType *t1)
5210 hash |= t1->byref << 6; /* do not collide with t1->type values */
5212 case MONO_TYPE_VALUETYPE:
5213 case MONO_TYPE_CLASS:
5214 case MONO_TYPE_SZARRAY:
5215 /* check if the distribution is good enough */
5216 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5218 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5223 static MonoReflectionGenericInst*
5224 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5226 static MonoClass *System_Reflection_MonoGenericInst;
5227 MonoReflectionGenericInst *res;
5228 MonoGenericInst *ginst;
5231 if (!System_Reflection_MonoGenericInst) {
5232 System_Reflection_MonoGenericInst = mono_class_from_name (
5233 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5234 g_assert (System_Reflection_MonoGenericInst);
5237 ginst = geninst->data.generic_inst;
5238 gklass = mono_class_from_mono_type (ginst->generic_type);
5240 mono_class_init (ginst->klass);
5242 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5244 res->type.type = geninst;
5245 if (gklass->wastypebuilder && gklass->reflection_info)
5246 res->generic_type = gklass->reflection_info;
5248 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5254 * mono_type_get_object:
5255 * @domain: an app domain
5258 * Return an System.MonoType object representing the type @type.
5261 mono_type_get_object (MonoDomain *domain, MonoType *type)
5263 MonoReflectionType *res;
5264 MonoClass *klass = mono_class_from_mono_type (type);
5266 mono_domain_lock (domain);
5267 if (!domain->type_hash)
5268 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5269 (GCompareFunc)mymono_metadata_type_equal);
5270 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5271 mono_domain_unlock (domain);
5274 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5275 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5276 mono_g_hash_table_insert (domain->type_hash, type, res);
5277 mono_domain_unlock (domain);
5280 if (klass->reflection_info && !klass->wastypebuilder) {
5281 /* g_assert_not_reached (); */
5282 /* should this be considered an error condition? */
5284 mono_domain_unlock (domain);
5285 return klass->reflection_info;
5288 mono_class_init (klass);
5289 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5291 mono_g_hash_table_insert (domain->type_hash, type, res);
5292 mono_domain_unlock (domain);
5297 * mono_method_get_object:
5298 * @domain: an app domain
5300 * @refclass: the reflected type (can be NULL)
5302 * Return an System.Reflection.MonoMethod object representing the method @method.
5304 MonoReflectionMethod*
5305 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5308 * We use the same C representation for methods and constructors, but the type
5309 * name in C# is different.
5313 MonoReflectionMethod *ret;
5316 refclass = method->klass;
5318 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5319 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5320 cname = "MonoCMethod";
5322 cname = "MonoMethod";
5323 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5325 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5326 ret->method = method;
5327 ret->name = mono_string_new (domain, method->name);
5328 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5329 CACHE_OBJECT (method, ret, refclass);
5334 * mono_field_get_object:
5335 * @domain: an app domain
5339 * Return an System.Reflection.MonoField object representing the field @field
5342 MonoReflectionField*
5343 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5345 MonoReflectionField *res;
5348 CHECK_OBJECT (MonoReflectionField *, field, klass);
5349 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5350 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5353 res->name = mono_string_new (domain, field->name);
5354 if (field->generic_info)
5355 res->attrs = field->generic_info->generic_type->attrs;
5357 res->attrs = field->type->attrs;
5358 res->type = mono_type_get_object (domain, field->type);
5359 CACHE_OBJECT (field, res, klass);
5364 * mono_property_get_object:
5365 * @domain: an app domain
5367 * @property: a property
5369 * Return an System.Reflection.MonoProperty object representing the property @property
5372 MonoReflectionProperty*
5373 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5375 MonoReflectionProperty *res;
5378 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5379 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5380 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5382 res->property = property;
5383 CACHE_OBJECT (property, res, klass);
5388 * mono_event_get_object:
5389 * @domain: an app domain
5393 * Return an System.Reflection.MonoEvent object representing the event @event
5396 MonoReflectionEvent*
5397 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5399 MonoReflectionEvent *res;
5402 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5403 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5404 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5407 CACHE_OBJECT (event, res, klass);
5412 * mono_param_get_objects:
5413 * @domain: an app domain
5416 * Return an System.Reflection.ParameterInfo array object representing the parameters
5417 * in the method @method.
5420 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5422 static MonoClass *System_Reflection_ParameterInfo;
5423 MonoArray *res = NULL;
5424 MonoReflectionMethod *member = NULL;
5425 MonoReflectionParameter *param = NULL;
5426 char **names, **blobs = NULL;
5427 MonoObject *dbnull = mono_get_dbnull_object (domain);
5428 MonoMarshalSpec **mspecs;
5431 if (!System_Reflection_ParameterInfo)
5432 System_Reflection_ParameterInfo = mono_class_from_name (
5433 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5435 if (!method->signature->param_count)
5436 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5438 /* Note: the cache is based on the address of the signature into the method
5439 * since we already cache MethodInfos with the method as keys.
5441 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5443 member = mono_method_get_object (domain, method, NULL);
5444 names = g_new (char *, method->signature->param_count);
5445 mono_method_get_param_names (method, (const char **) names);
5447 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5448 mono_method_get_marshal_info (method, mspecs);
5450 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5451 for (i = 0; i < method->signature->param_count; ++i) {
5452 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5453 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5454 param->MemberImpl = (MonoObject*)member;
5455 param->NameImpl = mono_string_new (domain, names [i]);
5456 param->PositionImpl = i;
5457 param->AttrsImpl = method->signature->params [i]->attrs;
5459 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5460 param->DefaultValueImpl = dbnull;
5462 MonoType *type = param->ClassImpl->type;
5465 blobs = g_new0 (char *, method->signature->param_count);
5466 get_default_param_value_blobs (method, blobs);
5469 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5471 if (!param->DefaultValueImpl) {
5472 param->DefaultValueImpl = dbnull;
5477 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5479 mono_array_set (res, gpointer, i, param);
5484 for (i = method->signature->param_count; i >= 0; i--)
5486 mono_metadata_free_marshal_spec (mspecs [i]);
5489 CACHE_OBJECT (&(method->signature), res, NULL);
5494 * mono_method_body_get_object:
5495 * @domain: an app domain
5498 * Return an System.Reflection.MethodBody object representing the method @method.
5500 MonoReflectionMethodBody*
5501 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5503 static MonoClass *System_Reflection_MethodBody = NULL;
5504 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5505 MonoReflectionMethodBody *ret;
5506 MonoMethodNormal *mn;
5507 MonoMethodHeader *header;
5510 if (!System_Reflection_MethodBody)
5511 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5512 if (!System_Reflection_LocalVariableInfo)
5513 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5515 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5517 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5518 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5520 mn = (MonoMethodNormal *)method;
5521 header = mono_method_get_header (method);
5523 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5524 /* FIXME: Other fields */
5525 ret->init_locals = header->init_locals;
5526 ret->max_stack = header->max_stack;
5527 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5528 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5529 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5530 for (i = 0; i < header->num_locals; ++i) {
5531 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5532 info->local_type = mono_type_get_object (domain, header->locals [i]);
5533 info->is_pinned = header->locals [i]->pinned;
5534 info->local_index = 0;
5537 CACHE_OBJECT (method, ret, NULL);
5542 mono_get_dbnull_object (MonoDomain *domain)
5546 static MonoClassField *dbnull_value_field = NULL;
5548 if (!dbnull_value_field) {
5549 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5550 mono_class_init (klass);
5551 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5552 g_assert (dbnull_value_field);
5554 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5561 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5563 guint32 param_index, i, lastp, crow = 0;
5564 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5567 MonoClass *klass = method->klass;
5568 MonoImage *image = klass->image;
5569 MonoMethodSignature *methodsig = method->signature;
5571 MonoTableInfo *constt;
5572 MonoTableInfo *methodt;
5573 MonoTableInfo *paramt;
5575 if (!methodsig->param_count)
5578 if (klass->generic_inst) {
5579 return; /* FIXME - ??? */
5582 mono_class_init (klass);
5584 if (klass->image->dynamic) {
5585 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5586 if (aux && aux->param_defaults)
5587 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5591 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5592 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5593 constt = &image->tables [MONO_TABLE_CONSTANT];
5595 for (i = 0; i < klass->method.count; ++i) {
5596 if (method == klass->methods [i]) {
5597 idx = klass->method.first + i;
5602 g_assert (idx != -1);
5604 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5605 if (idx + 1 < methodt->rows)
5606 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5608 lastp = paramt->rows + 1;
5610 for (i = param_index; i < lastp; ++i) {
5613 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5614 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5616 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5619 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5624 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5625 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5632 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5641 klass = mono_class_from_mono_type (type);
5642 if (klass->valuetype) {
5643 object = mono_object_new (domain, klass);
5644 retval = ((gchar *) object + sizeof (MonoObject));
5649 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5656 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5660 memset (assembly, 0, sizeof (MonoAssemblyName));
5662 assembly->culture = "";
5663 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5665 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5668 while (*p == ' ' || *p == ',') {
5677 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5679 assembly->major = strtoul (p, &s, 10);
5680 if (s == p || *s != '.')
5683 assembly->minor = strtoul (p, &s, 10);
5684 if (s == p || *s != '.')
5687 assembly->build = strtoul (p, &s, 10);
5688 if (s == p || *s != '.')
5691 assembly->revision = strtoul (p, &s, 10);
5695 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5697 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5698 assembly->culture = "";
5701 assembly->culture = p;
5702 while (*p && *p != ',') {
5706 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5708 if (strncmp (p, "null", 4) == 0) {
5713 while (*p && *p != ',') {
5716 len = (p - start + 1);
5717 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5718 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5719 g_strlcpy (assembly->public_key_token, start, len);
5722 while (*p && *p != ',')
5726 while (*p == ' ' || *p == ',') {
5740 * mono_reflection_parse_type:
5743 * Parse a type name as accepted by the GetType () method and output the info
5744 * extracted in the info structure.
5745 * the name param will be mangled, so, make a copy before passing it to this function.
5746 * The fields in info will be valid until the memory pointed to by name is valid.
5747 * Returns 0 on parse error.
5748 * See also mono_type_get_name () below.
5751 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5753 char *start, *p, *w, *last_point, *startn;
5754 int in_modifiers = 0;
5755 int isbyref = 0, rank;
5757 start = p = w = name;
5759 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5760 info->name = info->name_space = NULL;
5761 info->nested = NULL;
5762 info->modifiers = NULL;
5764 /* last_point separates the namespace from the name */
5770 *p = 0; /* NULL terminate the name */
5772 info->nested = g_list_append (info->nested, startn);
5773 /* we have parsed the nesting namespace + name */
5777 info->name_space = start;
5779 info->name = last_point + 1;
5781 info->name_space = (char *)"";
5807 info->name_space = start;
5809 info->name = last_point + 1;
5811 info->name_space = (char *)"";
5818 if (isbyref) /* only one level allowed by the spec */
5821 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5825 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5836 else if (*p != '*') /* '*' means unknown lower bound */
5842 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5854 return 0; /* missing assembly name */
5855 if (!assembly_name_to_aname (&info->assembly, p))
5862 if (info->assembly.name)
5865 *w = 0; /* terminate class name */
5866 if (!info->name || !*info->name)
5868 /* add other consistency checks */
5873 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5880 image = mono_defaults.corlib;
5883 klass = mono_class_from_name_case (image, info->name_space, info->name);
5885 klass = mono_class_from_name (image, info->name_space, info->name);
5888 for (mod = info->nested; mod; mod = mod->next) {
5891 mono_class_init (klass);
5892 nested = klass->nested_classes;
5895 klass = nested->data;
5897 if (g_strcasecmp (klass->name, mod->data) == 0)
5900 if (strcmp (klass->name, mod->data) == 0)
5904 nested = nested->next;
5911 mono_class_init (klass);
5912 for (mod = info->modifiers; mod; mod = mod->next) {
5913 modval = GPOINTER_TO_UINT (mod->data);
5914 if (!modval) { /* byref: must be last modifier */
5915 return &klass->this_arg;
5916 } else if (modval == -1) {
5917 klass = mono_ptr_class_get (&klass->byval_arg);
5918 } else { /* array rank */
5919 klass = mono_array_class_get (klass, modval);
5921 mono_class_init (klass);
5924 return &klass->byval_arg;
5928 * mono_reflection_get_type:
5929 * @image: a metadata context
5930 * @info: type description structure
5931 * @ignorecase: flag for case-insensitive string compares
5932 * @type_resolve: whenever type resolve was already tried
5934 * Build a MonoType from the type description in @info.
5939 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5942 MonoReflectionAssembly *assembly;
5946 type = mono_reflection_get_type_internal (image, info, ignorecase);
5949 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5956 *type_resolve = TRUE;
5959 /* Reconstruct the type name */
5960 fullName = g_string_new ("");
5961 if (info->name_space && (info->name_space [0] != '\0'))
5962 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5964 g_string_printf (fullName, info->name);
5965 for (mod = info->nested; mod; mod = mod->next)
5966 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5968 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5970 if (assembly->assembly->dynamic) {
5971 /* Enumerate all modules */
5972 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5976 if (abuilder->modules) {
5977 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5978 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5979 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5985 if (!type && abuilder->loaded_modules) {
5986 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5987 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5988 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5995 type = mono_reflection_get_type_internal (assembly->assembly->image,
5998 g_string_free (fullName, TRUE);
6003 * mono_reflection_type_from_name:
6005 * @image: a metadata context (can be NULL).
6007 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6008 * it defaults to get the type from @image or, if @image is NULL or loading
6009 * from it fails, uses corlib.
6013 mono_reflection_type_from_name (char *name, MonoImage *image)
6016 MonoTypeNameParse info;
6017 MonoAssembly *assembly;
6019 gboolean type_resolve = FALSE;
6021 /* Make a copy since parse_type modifies its argument */
6022 tmp = g_strdup (name);
6024 /*g_print ("requested type %s\n", str);*/
6025 if (!mono_reflection_parse_type (tmp, &info)) {
6027 g_list_free (info.modifiers);
6028 g_list_free (info.nested);
6032 if (info.assembly.name) {
6033 assembly = mono_assembly_loaded (&info.assembly);
6035 /* then we must load the assembly ourselve - see #60439 */
6036 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6039 g_list_free (info.modifiers);
6040 g_list_free (info.nested);
6044 image = assembly->image;
6045 } else if (image == NULL) {
6046 image = mono_defaults.corlib;
6049 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6050 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6051 image = mono_defaults.corlib;
6052 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6056 g_list_free (info.modifiers);
6057 g_list_free (info.nested);
6062 * mono_reflection_get_token:
6064 * Return the metadata token of OBJ which should be an object
6065 * representing a metadata element.
6068 mono_reflection_get_token (MonoObject *obj)
6073 klass = obj->vtable->klass;
6075 if (strcmp (klass->name, "MethodBuilder") == 0) {
6076 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6078 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6079 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6080 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6082 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6083 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6084 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6085 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6086 if (tb->generic_params) {
6087 g_assert_not_reached ();
6089 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6091 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6092 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6093 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6094 } else if (strcmp (klass->name, "MonoType") == 0) {
6095 MonoReflectionType *tb = (MonoReflectionType *)obj;
6096 token = mono_class_from_mono_type (tb->type)->type_token;
6097 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6098 strcmp (klass->name, "MonoMethod") == 0) {
6099 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6100 if (m->method->signature->is_inflated) {
6101 g_assert_not_reached ();
6102 } else if (m->method->signature->generic_param_count) {
6103 g_assert_not_reached ();
6104 } else if (m->method->klass->generic_inst) {
6105 g_assert_not_reached ();
6107 token = m->method->token;
6109 } else if (strcmp (klass->name, "MonoField") == 0) {
6110 MonoReflectionField *f = (MonoReflectionField*)obj;
6112 token = mono_class_get_field_token (f->field);
6113 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6114 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6116 token = mono_class_get_property_token (p->property);
6117 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6118 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6120 token = mono_class_get_event_token (p->event);
6121 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6122 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6124 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6125 } else if (strcmp (klass->name, "Module") == 0) {
6126 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6129 } else if (strcmp (klass->name, "Assembly") == 0) {
6130 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6132 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6133 MonoException *ex = mono_get_exception_not_implemented (msg);
6135 mono_raise_exception (ex);
6142 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6144 int slen, type = t->type;
6149 case MONO_TYPE_BOOLEAN: {
6150 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6155 case MONO_TYPE_CHAR:
6157 case MONO_TYPE_I2: {
6158 guint16 *val = g_malloc (sizeof (guint16));
6163 #if SIZEOF_VOID_P == 4
6169 case MONO_TYPE_I4: {
6170 guint32 *val = g_malloc (sizeof (guint32));
6175 #if SIZEOF_VOID_P == 8
6176 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6181 case MONO_TYPE_I8: {
6182 guint64 *val = g_malloc (sizeof (guint64));
6187 case MONO_TYPE_VALUETYPE:
6188 if (t->data.klass->enumtype) {
6189 type = t->data.klass->enum_basetype->type;
6192 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6195 case MONO_TYPE_STRING:
6196 if (*p == (char)0xFF) {
6200 slen = mono_metadata_decode_value (p, &p);
6202 return mono_string_new_len (mono_domain_get (), p, slen);
6203 case MONO_TYPE_CLASS: {
6206 if (*p == (char)0xFF) {
6211 slen = mono_metadata_decode_value (p, &p);
6212 n = g_memdup (p, slen + 1);
6214 t = mono_reflection_type_from_name (n, image);
6216 g_warning ("Cannot load type '%s'", n);
6220 return mono_type_get_object (mono_domain_get (), t);
6224 case MONO_TYPE_OBJECT: {
6227 MonoClass *subc = NULL;
6232 } else if (subt == 0x0E) {
6233 type = MONO_TYPE_STRING;
6235 } else if (subt == 0x55) {
6238 slen = mono_metadata_decode_value (p, &p);
6239 n = g_memdup (p, slen + 1);
6241 t = mono_reflection_type_from_name (n, image);
6243 g_warning ("Cannot load type '%s'", n);
6246 subc = mono_class_from_mono_type (t);
6247 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6248 MonoType simple_type = {{0}};
6249 simple_type.type = subt;
6250 subc = mono_class_from_mono_type (&simple_type);
6252 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6254 val = load_cattr_value (image, &subc->byval_arg, p, end);
6255 obj = mono_object_new (mono_domain_get (), subc);
6256 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6260 case MONO_TYPE_SZARRAY: {
6262 guint32 i, alen, basetype;
6265 if (alen == 0xffffffff) {
6269 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6270 basetype = t->data.klass->byval_arg.type;
6275 case MONO_TYPE_BOOLEAN:
6276 for (i = 0; i < alen; i++) {
6277 MonoBoolean val = *p++;
6278 mono_array_set (arr, MonoBoolean, i, val);
6281 case MONO_TYPE_CHAR:
6284 for (i = 0; i < alen; i++) {
6285 guint16 val = read16 (p);
6286 mono_array_set (arr, guint16, i, val);
6293 for (i = 0; i < alen; i++) {
6294 guint32 val = read32 (p);
6295 mono_array_set (arr, guint32, i, val);
6302 for (i = 0; i < alen; i++) {
6303 guint64 val = read64 (p);
6304 mono_array_set (arr, guint64, i, val);
6308 case MONO_TYPE_CLASS:
6309 case MONO_TYPE_OBJECT:
6310 case MONO_TYPE_STRING:
6311 for (i = 0; i < alen; i++) {
6312 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6313 mono_array_set (arr, gpointer, i, item);
6317 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6323 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6329 type_is_reference (MonoType *type)
6331 switch (type->type) {
6332 case MONO_TYPE_BOOLEAN:
6333 case MONO_TYPE_CHAR:
6346 case MONO_TYPE_VALUETYPE:
6354 free_param_data (MonoMethodSignature *sig, void **params) {
6356 for (i = 0; i < sig->param_count; ++i) {
6357 if (!type_is_reference (sig->params [i]))
6358 g_free (params [i]);
6363 * Find the method index in the metadata methodDef table.
6364 * Later put these three helper methods in metadata and export them.
6367 find_method_index (MonoMethod *method) {
6368 MonoClass *klass = method->klass;
6371 for (i = 0; i < klass->method.count; ++i) {
6372 if (method == klass->methods [i])
6373 return klass->method.first + 1 + i;
6379 * Find the field index in the metadata FieldDef table.
6382 find_field_index (MonoClass *klass, MonoClassField *field) {
6385 for (i = 0; i < klass->field.count; ++i) {
6386 if (field == &klass->fields [i])
6387 return klass->field.first + 1 + i;
6393 * Find the property index in the metadata Property table.
6396 find_property_index (MonoClass *klass, MonoProperty *property) {
6399 for (i = 0; i < klass->property.count; ++i) {
6400 if (property == &klass->properties [i])
6401 return klass->property.first + 1 + i;
6407 * Find the event index in the metadata Event table.
6410 find_event_index (MonoClass *klass, MonoEvent *event) {
6413 for (i = 0; i < klass->event.count; ++i) {
6414 if (event == &klass->events [i])
6415 return klass->event.first + 1 + i;
6421 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6423 const char *p = data;
6425 guint32 i, j, num_named;
6429 mono_class_init (method->klass);
6432 attr = mono_object_new (mono_domain_get (), method->klass);
6433 mono_runtime_invoke (method, attr, NULL, NULL);
6437 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6440 /*g_print ("got attr %s\n", method->klass->name);*/
6442 params = g_new (void*, method->signature->param_count);
6446 for (i = 0; i < method->signature->param_count; ++i) {
6447 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6451 attr = mono_object_new (mono_domain_get (), method->klass);
6452 mono_runtime_invoke (method, attr, params, NULL);
6453 free_param_data (method->signature, params);
6455 num_named = read16 (named);
6457 for (j = 0; j < num_named; j++) {
6459 char *name, named_type, data_type;
6460 named_type = *named++;
6461 data_type = *named++; /* type of data */
6462 if (data_type == 0x55) {
6465 type_len = mono_metadata_decode_blob_size (named, &named);
6466 type_name = g_malloc (type_len + 1);
6467 memcpy (type_name, named, type_len);
6468 type_name [type_len] = 0;
6470 /* FIXME: lookup the type and check type consistency */
6471 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6472 /* this seems to be the type of the element of the array */
6473 /* g_print ("skipping 0x%02x after prop\n", *named); */
6476 name_len = mono_metadata_decode_blob_size (named, &named);
6477 name = g_malloc (name_len + 1);
6478 memcpy (name, named, name_len);
6479 name [name_len] = 0;
6481 if (named_type == 0x53) {
6482 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6483 void *val = load_cattr_value (image, field->type, named, &named);
6484 mono_field_set_value (attr, field, val);
6485 if (!type_is_reference (field->type))
6487 } else if (named_type == 0x54) {
6490 MonoType *prop_type;
6492 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6493 /* can we have more that 1 arg in a custom attr named property? */
6494 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6495 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6496 mono_property_set_value (prop, attr, pparams, NULL);
6497 if (!type_is_reference (prop_type))
6498 g_free (pparams [0]);
6507 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6514 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6515 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6516 for (i = 0; i < cinfo->num_attrs; ++i) {
6517 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6518 mono_array_set (result, gpointer, i, attr);
6524 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6526 guint32 mtoken, i, len;
6527 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6529 MonoCustomAttrInfo *ainfo;
6530 GList *tmp, *list = NULL;
6533 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6535 i = mono_metadata_custom_attrs_from_index (image, idx);
6539 while (i < ca->rows) {
6540 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6542 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6545 len = g_list_length (list);
6548 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6549 ainfo->num_attrs = len;
6550 ainfo->image = image;
6551 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6552 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6553 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6554 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6555 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6556 mtoken |= MONO_TOKEN_METHOD_DEF;
6558 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6559 mtoken |= MONO_TOKEN_MEMBER_REF;
6562 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6565 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6566 if (!ainfo->attrs [i].ctor)
6567 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6568 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6569 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6570 ainfo->attrs [i].data = data;
6578 mono_custom_attrs_from_method (MonoMethod *method)
6580 MonoCustomAttrInfo *cinfo;
6583 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6585 idx = find_method_index (method);
6586 idx <<= MONO_CUSTOM_ATTR_BITS;
6587 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6588 return mono_custom_attrs_from_index (method->klass->image, idx);
6592 mono_custom_attrs_from_class (MonoClass *klass)
6594 MonoCustomAttrInfo *cinfo;
6597 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6599 idx = mono_metadata_token_index (klass->type_token);
6600 idx <<= MONO_CUSTOM_ATTR_BITS;
6601 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6602 return mono_custom_attrs_from_index (klass->image, idx);
6606 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6608 MonoCustomAttrInfo *cinfo;
6611 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6613 idx = 1; /* there is only one assembly */
6614 idx <<= MONO_CUSTOM_ATTR_BITS;
6615 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6616 return mono_custom_attrs_from_index (assembly->image, idx);
6619 static MonoCustomAttrInfo*
6620 mono_custom_attrs_from_module (MonoImage *image)
6622 MonoCustomAttrInfo *cinfo;
6625 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6627 idx = 1; /* there is only one module */
6628 idx <<= MONO_CUSTOM_ATTR_BITS;
6629 idx |= MONO_CUSTOM_ATTR_MODULE;
6630 return mono_custom_attrs_from_index (image, idx);
6634 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6636 MonoCustomAttrInfo *cinfo;
6639 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6641 idx = find_property_index (klass, property);
6642 idx <<= MONO_CUSTOM_ATTR_BITS;
6643 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6644 return mono_custom_attrs_from_index (klass->image, idx);
6648 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6650 MonoCustomAttrInfo *cinfo;
6653 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6655 idx = find_event_index (klass, event);
6656 idx <<= MONO_CUSTOM_ATTR_BITS;
6657 idx |= MONO_CUSTOM_ATTR_EVENT;
6658 return mono_custom_attrs_from_index (klass->image, idx);
6662 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6664 MonoCustomAttrInfo *cinfo;
6667 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6669 idx = find_field_index (klass, field);
6670 idx <<= MONO_CUSTOM_ATTR_BITS;
6671 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6672 return mono_custom_attrs_from_index (klass->image, idx);
6676 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6679 guint32 i, idx, method_index;
6680 guint32 param_list, param_last, param_pos, found;
6682 MonoReflectionMethodAux *aux;
6684 if (method->klass->image->dynamic) {
6685 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6686 if (!aux || !aux->param_cattr)
6688 return aux->param_cattr [param];
6691 image = method->klass->image;
6692 method_index = find_method_index (method);
6693 ca = &image->tables [MONO_TABLE_METHOD];
6695 if (method->klass->generic_inst || method->klass->generic_container ||
6696 method->signature->generic_param_count) {
6697 /* FIXME FIXME FIXME */
6701 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6702 if (method_index == ca->rows) {
6703 ca = &image->tables [MONO_TABLE_PARAM];
6704 param_last = ca->rows + 1;
6706 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6707 ca = &image->tables [MONO_TABLE_PARAM];
6710 for (i = param_list; i < param_last; ++i) {
6711 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6712 if (param_pos == param) {
6720 idx <<= MONO_CUSTOM_ATTR_BITS;
6721 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6722 return mono_custom_attrs_from_index (image, idx);
6726 * mono_reflection_get_custom_attrs:
6727 * @obj: a reflection object handle
6729 * Return an array with all the custom attributes defined of the
6730 * reflection handle @obj. The objects are fully build.
6733 mono_reflection_get_custom_attrs (MonoObject *obj)
6737 MonoCustomAttrInfo *cinfo = NULL;
6739 MONO_ARCH_SAVE_REGS;
6741 klass = obj->vtable->klass;
6742 if (klass == mono_defaults.monotype_class) {
6743 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6744 klass = mono_class_from_mono_type (rtype->type);
6745 cinfo = mono_custom_attrs_from_class (klass);
6746 } else if (strcmp ("Assembly", klass->name) == 0) {
6747 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6748 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6749 } else if (strcmp ("Module", klass->name) == 0) {
6750 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6751 cinfo = mono_custom_attrs_from_module (module->image);
6752 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6753 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6754 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6755 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6756 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6757 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6758 } else if (strcmp ("MonoField", klass->name) == 0) {
6759 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6760 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6761 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6762 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6763 cinfo = mono_custom_attrs_from_method (rmethod->method);
6764 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6765 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6766 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6767 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6768 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6769 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6770 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6771 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6772 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6773 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6774 } else { /* handle other types here... */
6775 g_error ("get custom attrs not yet supported for %s", klass->name);
6779 result = mono_custom_attrs_construct (cinfo);
6781 mono_custom_attrs_free (cinfo);
6783 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6784 result = mono_array_new (mono_domain_get (), klass, 0);
6790 static MonoMethodSignature*
6791 parameters_to_signature (MonoArray *parameters) {
6792 MonoMethodSignature *sig;
6795 count = parameters? mono_array_length (parameters): 0;
6797 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6798 sig->param_count = count;
6799 sig->sentinelpos = -1; /* FIXME */
6800 for (i = 0; i < count; ++i) {
6801 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6802 sig->params [i] = pt->type;
6807 static MonoMethodSignature*
6808 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6809 MonoMethodSignature *sig;
6811 sig = parameters_to_signature (ctor->parameters);
6812 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6813 sig->ret = &mono_defaults.void_class->byval_arg;
6817 static MonoMethodSignature*
6818 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6819 MonoMethodSignature *sig;
6821 sig = parameters_to_signature (method->parameters);
6822 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6823 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6824 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6828 static MonoMethodSignature*
6829 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6830 MonoMethodSignature *sig;
6832 sig = parameters_to_signature (method->parameters);
6833 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6834 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6835 sig->generic_param_count = 0;
6840 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6842 MonoClass *klass = mono_object_class (prop);
6843 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6844 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6845 *name = mono_string_to_utf8 (pb->name);
6846 *type = pb->type->type;
6848 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6849 *name = g_strdup (p->property->name);
6850 if (p->property->get)
6851 *type = p->property->get->signature->ret;
6853 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6858 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6860 MonoClass *klass = mono_object_class (field);
6861 if (strcmp (klass->name, "FieldBuilder") == 0) {
6862 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6863 *name = mono_string_to_utf8 (fb->name);
6864 *type = fb->type->type;
6866 MonoReflectionField *f = (MonoReflectionField *)field;
6867 *name = g_strdup (f->field->name);
6868 *type = f->field->type;
6873 * Encode a value in a custom attribute stream of bytes.
6874 * The value to encode is either supplied as an object in argument val
6875 * (valuetypes are boxed), or as a pointer to the data in the
6877 * @type represents the type of the value
6878 * @buffer is the start of the buffer
6879 * @p the current position in the buffer
6880 * @buflen contains the size of the buffer and is used to return the new buffer size
6881 * if this needs to be realloced.
6882 * @retbuffer and @retp return the start and the position of the buffer
6885 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6887 MonoTypeEnum simple_type;
6889 if ((p-buffer) + 10 >= *buflen) {
6892 newbuf = g_realloc (buffer, *buflen);
6893 p = newbuf + (p-buffer);
6897 argval = ((char*)arg + sizeof (MonoObject));
6898 simple_type = type->type;
6900 switch (simple_type) {
6901 case MONO_TYPE_BOOLEAN:
6906 case MONO_TYPE_CHAR:
6909 swap_with_size (p, argval, 2, 1);
6915 swap_with_size (p, argval, 4, 1);
6921 swap_with_size (p, argval, 8, 1);
6924 case MONO_TYPE_VALUETYPE:
6925 if (type->data.klass->enumtype) {
6926 simple_type = type->data.klass->enum_basetype->type;
6929 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6932 case MONO_TYPE_STRING: {
6939 str = mono_string_to_utf8 ((MonoString*)arg);
6940 slen = strlen (str);
6941 if ((p-buffer) + 10 + slen >= *buflen) {
6945 newbuf = g_realloc (buffer, *buflen);
6946 p = newbuf + (p-buffer);
6949 mono_metadata_encode_value (slen, p, &p);
6950 memcpy (p, str, slen);
6955 case MONO_TYPE_CLASS: {
6963 k = mono_object_class (arg);
6964 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6965 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6966 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6968 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6969 slen = strlen (str);
6970 if ((p-buffer) + 10 + slen >= *buflen) {
6974 newbuf = g_realloc (buffer, *buflen);
6975 p = newbuf + (p-buffer);
6978 mono_metadata_encode_value (slen, p, &p);
6979 memcpy (p, str, slen);
6984 case MONO_TYPE_SZARRAY: {
6986 MonoClass *eclass, *arg_eclass;
6989 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6992 len = mono_array_length ((MonoArray*)arg);
6994 *p++ = (len >> 8) & 0xff;
6995 *p++ = (len >> 16) & 0xff;
6996 *p++ = (len >> 24) & 0xff;
6998 *retbuffer = buffer;
6999 eclass = type->data.klass;
7000 arg_eclass = mono_object_class (arg)->element_class;
7001 if (eclass->valuetype && arg_eclass->valuetype) {
7002 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7003 int elsize = mono_class_array_element_size (eclass);
7004 for (i = 0; i < len; ++i) {
7005 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7009 for (i = 0; i < len; ++i) {
7010 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7015 /* it may be a boxed value or a Type */
7016 case MONO_TYPE_OBJECT: {
7017 MonoClass *klass = mono_object_class (arg);
7021 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7024 } else if (klass->enumtype) {
7026 } else if (klass == mono_defaults.string_class) {
7027 simple_type = MONO_TYPE_STRING;
7030 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7031 *p++ = simple_type = klass->byval_arg.type;
7034 g_error ("unhandled type in custom attr");
7036 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7037 slen = strlen (str);
7038 if ((p-buffer) + 10 + slen >= *buflen) {
7042 newbuf = g_realloc (buffer, *buflen);
7043 p = newbuf + (p-buffer);
7046 mono_metadata_encode_value (slen, p, &p);
7047 memcpy (p, str, slen);
7050 simple_type = klass->enum_basetype->type;
7054 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7057 *retbuffer = buffer;
7061 * mono_reflection_get_custom_attrs_blob:
7062 * @ctor: custom attribute constructor
7063 * @ctorArgs: arguments o the constructor
7069 * Creates the blob of data that needs to be saved in the metadata and that represents
7070 * the custom attributed described by @ctor, @ctorArgs etc.
7071 * Returns: a Byte array representing the blob of data.
7074 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7077 MonoMethodSignature *sig;
7082 MONO_ARCH_SAVE_REGS;
7084 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7085 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7087 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7089 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7091 p = buffer = g_malloc (buflen);
7092 /* write the prolog */
7095 for (i = 0; i < sig->param_count; ++i) {
7096 arg = mono_array_get (ctorArgs, MonoObject*, i);
7097 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7101 i += mono_array_length (properties);
7103 i += mono_array_length (fields);
7105 *p++ = (i >> 8) & 0xff;
7108 for (i = 0; i < mono_array_length (properties); ++i) {
7113 prop = mono_array_get (properties, gpointer, i);
7114 get_prop_name_and_type (prop, &pname, &ptype);
7115 *p++ = 0x54; /* PROPERTY signature */
7117 /* Preallocate a large enough buffer */
7118 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7119 char *str = type_get_qualified_name (ptype, NULL);
7125 len += strlen (pname);
7127 if ((p-buffer) + 20 + len >= buflen) {
7131 newbuf = g_realloc (buffer, buflen);
7132 p = newbuf + (p-buffer);
7136 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7137 char *str = type_get_qualified_name (ptype, NULL);
7138 int slen = strlen (str);
7142 * This seems to be optional...
7145 mono_metadata_encode_value (slen, p, &p);
7146 memcpy (p, str, slen);
7150 mono_metadata_encode_value (ptype->type, p, &p);
7151 if (ptype->type == MONO_TYPE_SZARRAY)
7152 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7154 len = strlen (pname);
7155 mono_metadata_encode_value (len, p, &p);
7156 memcpy (p, pname, len);
7158 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7165 for (i = 0; i < mono_array_length (fields); ++i) {
7170 field = mono_array_get (fields, gpointer, i);
7171 get_field_name_and_type (field, &fname, &ftype);
7172 *p++ = 0x53; /* FIELD signature */
7173 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7174 char *str = type_get_qualified_name (ftype, NULL);
7175 int slen = strlen (str);
7176 if ((p-buffer) + 10 + slen >= buflen) {
7180 newbuf = g_realloc (buffer, buflen);
7181 p = newbuf + (p-buffer);
7186 * This seems to be optional...
7189 mono_metadata_encode_value (slen, p, &p);
7190 memcpy (p, str, slen);
7194 mono_metadata_encode_value (ftype->type, p, &p);
7195 if (ftype->type == MONO_TYPE_SZARRAY)
7196 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7198 len = strlen (fname);
7199 mono_metadata_encode_value (len, p, &p);
7200 memcpy (p, fname, len);
7202 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7207 g_assert (p - buffer <= buflen);
7208 buflen = p - buffer;
7209 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7210 p = mono_array_addr (result, char, 0);
7211 memcpy (p, buffer, buflen);
7213 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7219 * mono_reflection_setup_internal_class:
7220 * @tb: a TypeBuilder object
7222 * Creates a MonoClass that represents the TypeBuilder.
7223 * This is a trick that lets us simplify a lot of reflection code
7224 * (and will allow us to support Build and Run assemblies easier).
7227 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7229 MonoClass *klass, *parent;
7231 MONO_ARCH_SAVE_REGS;
7234 /* check so we can compile corlib correctly */
7235 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7236 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7237 parent = tb->parent->type->data.klass;
7239 parent = my_mono_class_from_mono_type (tb->parent->type);
7245 /* the type has already being created: it means we just have to change the parent */
7246 if (tb->type.type) {
7247 klass = mono_class_from_mono_type (tb->type.type);
7248 klass->parent = NULL;
7249 /* fool mono_class_setup_parent */
7250 g_free (klass->supertypes);
7251 klass->supertypes = NULL;
7252 mono_class_setup_parent (klass, parent);
7253 mono_class_setup_mono_type (klass);
7257 klass = g_new0 (MonoClass, 1);
7259 klass->image = &tb->module->dynamic_image->image;
7261 klass->inited = 1; /* we lie to the runtime */
7262 klass->name = mono_string_to_utf8 (tb->name);
7263 klass->name_space = mono_string_to_utf8 (tb->nspace);
7264 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7265 klass->flags = tb->attrs;
7267 klass->element_class = klass;
7268 klass->reflection_info = tb; /* need to pin. */
7270 /* Put into cache so mono_class_get () will find it */
7271 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7273 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7274 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7276 if (parent != NULL) {
7277 mono_class_setup_parent (klass, parent);
7278 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7279 const char *old_n = klass->name;
7280 /* trick to get relative numbering right when compiling corlib */
7281 klass->name = "BuildingObject";
7282 mono_class_setup_parent (klass, mono_defaults.object_class);
7283 klass->name = old_n;
7286 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7287 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7288 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7289 klass->instance_size = sizeof (MonoObject);
7290 klass->size_inited = 1;
7291 mono_class_setup_vtable (klass, NULL, 0);
7294 mono_class_setup_mono_type (klass);
7296 mono_class_setup_supertypes (klass);
7299 * FIXME: handle interfaces.
7302 tb->type.type = &klass->byval_arg;
7304 if (tb->nesting_type) {
7305 g_assert (tb->nesting_type->type);
7306 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7309 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7313 * mono_reflection_setup_generic_class:
7314 * @tb: a TypeBuilder object
7316 * Setup the generic class before adding the first generic parameter.
7319 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7323 MONO_ARCH_SAVE_REGS;
7325 klass = my_mono_class_from_mono_type (tb->type.type);
7326 if (tb->generic_container)
7329 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7330 tb->generic_container->klass = klass;
7334 * mono_reflection_create_generic_class:
7335 * @tb: a TypeBuilder object
7337 * Creates the generic class after all generic parameters have been added.
7340 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7345 MONO_ARCH_SAVE_REGS;
7347 klass = my_mono_class_from_mono_type (tb->type.type);
7349 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7351 if (klass->generic_container || (count == 0))
7354 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7356 klass->generic_container = tb->generic_container;
7358 klass->generic_container->type_argc = count;
7359 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7361 for (i = 0; i < count; i++) {
7362 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7363 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7364 g_assert (klass->generic_container->type_params [i].owner);
7369 * mono_reflection_create_internal_class:
7370 * @tb: a TypeBuilder object
7372 * Actually create the MonoClass that is associated with the TypeBuilder.
7375 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7379 MONO_ARCH_SAVE_REGS;
7381 klass = my_mono_class_from_mono_type (tb->type.type);
7383 if (klass->enumtype && klass->enum_basetype == NULL) {
7384 MonoReflectionFieldBuilder *fb;
7387 g_assert (tb->fields != NULL);
7388 g_assert (mono_array_length (tb->fields) >= 1);
7390 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7392 klass->enum_basetype = fb->type->type;
7393 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7394 if (!klass->element_class)
7395 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7398 * get the element_class from the current corlib.
7400 ec = default_class_from_mono_type (klass->enum_basetype);
7401 klass->instance_size = ec->instance_size;
7402 klass->size_inited = 1;
7404 * this is almost safe to do with enums and it's needed to be able
7405 * to create objects of the enum type (for use in SetConstant).
7407 /* FIXME: Does this mean enums can't have method overrides ? */
7408 mono_class_setup_vtable (klass, NULL, 0);
7412 static MonoMarshalSpec*
7413 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7414 MonoReflectionMarshal *minfo)
7416 MonoMarshalSpec *res;
7418 res = g_new0 (MonoMarshalSpec, 1);
7419 res->native = minfo->type;
7421 switch (minfo->type) {
7422 case MONO_NATIVE_LPARRAY:
7423 res->data.array_data.elem_type = minfo->eltype;
7424 res->data.array_data.param_num = 0; /* Not yet */
7425 res->data.array_data.num_elem = minfo->count;
7428 case MONO_NATIVE_BYVALTSTR:
7429 case MONO_NATIVE_BYVALARRAY:
7430 res->data.array_data.num_elem = minfo->count;
7433 case MONO_NATIVE_CUSTOM:
7434 if (minfo->marshaltyperef)
7435 res->data.custom_data.custom_name =
7436 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7438 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7448 MonoReflectionMarshal*
7449 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7450 MonoMarshalSpec *spec)
7452 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7453 MonoReflectionMarshal *minfo;
7456 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7457 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7458 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7459 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7462 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7463 minfo->type = spec->native;
7465 switch (minfo->type) {
7466 case MONO_NATIVE_LPARRAY:
7467 minfo->eltype = spec->data.array_data.elem_type;
7468 minfo->count = spec->data.array_data.num_elem;
7471 case MONO_NATIVE_BYVALTSTR:
7472 case MONO_NATIVE_BYVALARRAY:
7473 minfo->count = spec->data.array_data.num_elem;
7476 case MONO_NATIVE_CUSTOM:
7477 if (spec->data.custom_data.custom_name) {
7478 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7480 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7482 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7484 if (spec->data.custom_data.cookie)
7485 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7496 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7497 ReflectionMethodBuilder *rmb,
7498 MonoMethodSignature *sig)
7501 MonoMethodNormal *pm;
7502 MonoMarshalSpec **specs;
7503 MonoReflectionMethodAux *method_aux;
7506 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7507 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7508 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7510 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7512 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7514 pm = (MonoMethodNormal*)m;
7517 m->flags = rmb->attrs;
7518 m->iflags = rmb->iattrs;
7519 m->name = mono_string_to_utf8 (rmb->name);
7523 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7525 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7526 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7529 m->signature->pinvoke = 1;
7530 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7531 m->signature->pinvoke = 1;
7533 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7535 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7536 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7538 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7540 if (klass->image->dynamic)
7541 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7544 } else if (!m->klass->dummy &&
7545 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7546 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7547 MonoMethodHeader *header;
7549 gint32 max_stack, i;
7550 gint32 num_locals = 0;
7551 gint32 num_clauses = 0;
7555 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7556 code_size = rmb->ilgen->code_len;
7557 max_stack = rmb->ilgen->max_stack;
7558 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7559 if (rmb->ilgen->ex_handlers)
7560 num_clauses = method_count_clauses (rmb->ilgen);
7563 code = mono_array_addr (rmb->code, guint8, 0);
7564 code_size = mono_array_length (rmb->code);
7565 /* we probably need to run a verifier on the code... */
7575 header = g_malloc0 (sizeof (MonoMethodHeader) +
7576 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7577 header->code_size = code_size;
7578 header->code = g_malloc (code_size);
7579 memcpy ((char*)header->code, code, code_size);
7580 header->max_stack = max_stack;
7581 header->init_locals = rmb->init_locals;
7582 header->num_locals = num_locals;
7584 for (i = 0; i < num_locals; ++i) {
7585 MonoReflectionLocalBuilder *lb =
7586 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7588 header->locals [i] = g_new0 (MonoType, 1);
7589 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7592 header->num_clauses = num_clauses;
7594 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7595 rmb->ilgen, num_clauses);
7598 pm->header = header;
7601 if (rmb->generic_params) {
7602 int count = mono_array_length (rmb->generic_params);
7603 MonoGenericContainer *container;
7605 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7606 container->type_argc = count;
7607 container->type_params = g_new0 (MonoGenericParam, count);
7609 for (i = 0; i < count; i++) {
7610 MonoReflectionGenericParam *gp =
7611 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7613 container->type_params [i] = *gp->type.type->data.generic_param;
7618 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7621 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7623 for (i = 0; i < rmb->nrefs; ++i)
7624 mw->data = g_list_append (mw->data, rmb->refs [i]);
7629 /* Parameter info */
7632 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7633 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7634 for (i = 0; i <= m->signature->param_count; ++i) {
7635 MonoReflectionParamBuilder *pb;
7636 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7638 m->signature->params [i - 1]->attrs = pb->attrs;
7640 if (pb->def_value) {
7641 MonoDynamicImage *assembly;
7642 guint32 idx, def_type, len;
7646 if (!method_aux->param_defaults)
7647 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7648 assembly = (MonoDynamicImage*)klass->image;
7649 idx = encode_constant (assembly, pb->def_value, &def_type);
7650 /* Copy the data from the blob since it might get realloc-ed */
7651 p = assembly->blob.data + idx;
7652 len = mono_metadata_decode_blob_size (p, &p2);
7654 method_aux->param_defaults [i] = g_malloc (len);
7655 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7659 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7661 if (!method_aux->param_cattr)
7662 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7663 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7669 /* Parameter marshalling */
7672 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7673 MonoReflectionParamBuilder *pb;
7674 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7675 if (pb->marshal_info) {
7677 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7678 specs [pb->position] =
7679 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7683 if (specs != NULL) {
7685 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7686 method_aux->param_marshall = specs;
7689 if (klass->image->dynamic && method_aux)
7690 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7696 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7698 ReflectionMethodBuilder rmb;
7699 MonoMethodSignature *sig;
7701 sig = ctor_builder_to_signature (mb);
7703 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7705 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7706 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7708 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7709 /* ilgen is no longer needed */
7717 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7719 ReflectionMethodBuilder rmb;
7720 MonoMethodSignature *sig;
7722 sig = method_builder_to_signature (mb);
7724 reflection_methodbuilder_from_method_builder (&rmb, mb);
7726 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7727 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7729 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7730 /* ilgen is no longer needed */
7736 static MonoClassField*
7737 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7739 MonoClassField *field;
7746 field = g_new0 (MonoClassField, 1);
7748 field->name = mono_string_to_utf8 (fb->name);
7750 /* FIXME: handle type modifiers */
7751 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7752 field->type->attrs = fb->attrs;
7754 field->type = fb->type->type;
7756 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7757 field->data = mono_array_addr (fb->rva_data, char, 0);
7758 if (fb->offset != -1)
7759 field->offset = fb->offset;
7760 field->parent = klass;
7762 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7764 if (fb->def_value) {
7765 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7766 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7767 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7768 /* Copy the data from the blob since it might get realloc-ed */
7769 p = assembly->blob.data + idx;
7770 len = mono_metadata_decode_blob_size (p, &p2);
7772 field->data = g_malloc (len);
7773 memcpy ((gpointer)field->data, p, len);
7780 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7782 MonoClass *klass, *gklass;
7783 MonoReflectionTypeBuilder *tb = NULL;
7784 MonoGenericInst *ginst, *cached;
7789 klass = mono_class_from_mono_type (type->type);
7790 if (!klass->generic_container && !klass->generic_inst &&
7791 !(klass->nested_in && klass->nested_in->generic_container))
7794 mono_loader_lock ();
7796 domain = mono_object_domain (type);
7798 ginst = g_new0 (MonoGenericInst, 1);
7800 if (!klass->generic_inst) {
7801 ginst->type_argc = type_argc;
7802 ginst->type_argv = types;
7804 for (i = 0; i < ginst->type_argc; ++i) {
7805 if (!ginst->is_open)
7806 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7809 ginst->generic_type = &klass->byval_arg;
7811 MonoGenericInst *kginst = klass->generic_inst;
7813 ginst->type_argc = kginst->type_argc;
7814 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7816 for (i = 0; i < ginst->type_argc; i++) {
7817 MonoType *t = kginst->type_argv [i];
7819 if (t->type == MONO_TYPE_VAR)
7820 t = types [t->data.generic_param->num];
7822 if (!ginst->is_open)
7823 ginst->is_open = mono_class_is_open_constructed_type (t);
7825 ginst->type_argv [i] = t;
7828 ginst->generic_type = kginst->generic_type;
7831 geninst = g_new0 (MonoType, 1);
7832 geninst->type = MONO_TYPE_GENERICINST;
7834 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7837 mono_loader_unlock ();
7838 geninst->data.generic_inst = cached;
7842 gklass = mono_class_from_mono_type (ginst->generic_type);
7843 g_assert ((ginst->container = gklass->generic_container) != NULL);
7845 geninst->data.generic_inst = ginst;
7847 ginst->context = g_new0 (MonoGenericContext, 1);
7848 ginst->context->ginst = ginst;
7850 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7851 tb = (MonoReflectionTypeBuilder *) type;
7853 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7854 ginst->is_dynamic = TRUE;
7855 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7856 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7857 MonoReflectionType *rgt = rgi->generic_type;
7859 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7860 tb = (MonoReflectionTypeBuilder *) rgt;
7862 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7863 ginst->is_dynamic = TRUE;
7865 icount = klass->interface_count;
7868 ginst->ifaces = g_new0 (MonoType *, icount);
7869 ginst->count_ifaces = icount;
7871 for (i = 0; i < icount; i++) {
7872 MonoReflectionType *itype;
7875 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7877 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7878 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7879 if (!ginst->ifaces [i])
7880 ginst->ifaces [i] = itype->type;
7883 mono_class_create_generic (ginst);
7885 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7887 mono_loader_unlock ();
7893 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7895 MonoClass *klass, *pklass = NULL;
7896 MonoReflectionType *parent = NULL;
7898 MonoReflectionTypeBuilder *tb = NULL;
7899 MonoGenericInst *ginst;
7902 domain = mono_object_domain (type);
7903 klass = mono_class_from_mono_type (type->type);
7905 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7906 tb = (MonoReflectionTypeBuilder *) type;
7909 parent = tb->parent;
7910 pklass = mono_class_from_mono_type (parent->type);
7913 pklass = klass->parent;
7915 parent = mono_type_get_object (domain, &pklass->byval_arg);
7916 else if (klass->generic_inst && klass->generic_inst->parent) {
7917 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7918 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7922 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7926 ginst = geninst->data.generic_inst;
7928 if (pklass && pklass->generic_inst)
7929 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7934 MonoReflectionMethod*
7935 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7937 MonoMethod *method, *inflated;
7938 MonoReflectionMethodBuilder *mb = NULL;
7939 MonoGenericMethod *gmethod;
7940 MonoGenericContext *context;
7943 MONO_ARCH_SAVE_REGS;
7944 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7945 MonoReflectionTypeBuilder *tb;
7948 mb = (MonoReflectionMethodBuilder *) rmethod;
7949 tb = (MonoReflectionTypeBuilder *) mb->type;
7950 klass = mono_class_from_mono_type (tb->type.type);
7952 method = methodbuilder_to_mono_method (klass, mb);
7954 method = rmethod->method;
7957 count = method->signature->generic_param_count;
7958 if (count != mono_array_length (types))
7961 gmethod = g_new0 (MonoGenericMethod, 1);
7962 gmethod->mtype_argc = count;
7963 gmethod->mtype_argv = g_new0 (MonoType *, count);
7964 for (i = 0; i < count; i++) {
7965 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7966 gmethod->mtype_argv [i] = garg->type;
7969 gmethod->reflection_info = rmethod;
7971 context = g_new0 (MonoGenericContext, 1);
7972 context->ginst = method->klass->generic_inst;
7973 context->gmethod = gmethod;
7975 inflated = mono_class_inflate_generic_method (method, context, NULL);
7977 return mono_method_get_object (
7978 mono_object_domain (rmethod), inflated, NULL);
7982 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7984 MonoGenericMethod *gmethod;
7985 MonoGenericInst *ginst;
7986 MonoGenericContext *context;
7989 ginst = type->type.type->data.generic_inst;
7991 gmethod = g_new0 (MonoGenericMethod, 1);
7992 gmethod->reflection_info = obj;
7994 gmethod->mtype_argc = method->signature->generic_param_count;
7995 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7997 for (i = 0; i < gmethod->mtype_argc; i++) {
7998 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7999 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8001 g_assert (gparam->pklass);
8002 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8005 context = g_new0 (MonoGenericContext, 1);
8006 context->ginst = ginst;
8007 context->gmethod = gmethod;
8009 return mono_class_inflate_generic_method (method, context, ginst->klass);
8013 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8018 klass = mono_class_from_mono_type (type->type.type);
8020 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8021 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8022 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8023 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8024 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8025 method = ((MonoReflectionMethod *) obj)->method;
8027 method = NULL; /* prevent compiler warning */
8028 g_assert_not_reached ();
8031 return inflate_mono_method (type, method, obj);
8035 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8036 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8038 MonoGenericInst *ginst;
8039 MonoDynamicGenericInst *dginst;
8040 MonoClass *klass, *gklass, *pklass;
8043 MONO_ARCH_SAVE_REGS;
8045 klass = mono_class_from_mono_type (type->type.type);
8046 ginst = type->type.type->data.generic_inst;
8048 if (ginst->initialized)
8051 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8053 gklass = mono_class_from_mono_type (ginst->generic_type);
8054 mono_class_init (gklass);
8057 pklass = mono_class_from_mono_type (ginst->parent);
8059 pklass = gklass->parent;
8061 mono_class_setup_parent (klass, pklass);
8063 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8064 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8065 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8066 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8067 dginst->count_events = events ? mono_array_length (events) : 0;
8069 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8070 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8071 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8072 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8073 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8075 for (i = 0; i < dginst->count_methods; i++) {
8076 MonoObject *obj = mono_array_get (methods, gpointer, i);
8078 dginst->methods [i] = inflate_method (type, obj);
8081 for (i = 0; i < dginst->count_ctors; i++) {
8082 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8084 dginst->ctors [i] = inflate_method (type, obj);
8087 for (i = 0; i < dginst->count_fields; i++) {
8088 MonoObject *obj = mono_array_get (fields, gpointer, i);
8089 MonoClassField *field;
8090 MonoInflatedField *ifield;
8092 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8093 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8094 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8095 field = ((MonoReflectionField *) obj)->field;
8097 field = NULL; /* prevent compiler warning */
8098 g_assert_not_reached ();
8101 ifield = g_new0 (MonoInflatedField, 1);
8102 ifield->generic_type = field->type;
8103 ifield->reflection_info = obj;
8105 dginst->fields [i] = *field;
8106 dginst->fields [i].generic_info = ifield;
8107 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8110 for (i = 0; i < dginst->count_properties; i++) {
8111 MonoObject *obj = mono_array_get (properties, gpointer, i);
8112 MonoProperty *property = &dginst->properties [i];
8114 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8115 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8117 property->parent = klass;
8118 property->attrs = pb->attrs;
8119 property->name = mono_string_to_utf8 (pb->name);
8121 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8123 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8124 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8125 *property = *((MonoReflectionProperty *) obj)->property;
8128 property->get = inflate_mono_method (type, property->get, NULL);
8130 property->set = inflate_mono_method (type, property->set, NULL);
8132 g_assert_not_reached ();
8135 for (i = 0; i < dginst->count_events; i++) {
8136 MonoObject *obj = mono_array_get (events, gpointer, i);
8137 MonoEvent *event = &dginst->events [i];
8139 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8140 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8142 event->parent = klass;
8143 event->attrs = eb->attrs;
8144 event->name = mono_string_to_utf8 (eb->name);
8146 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8147 if (eb->remove_method)
8148 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8149 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8150 *event = *((MonoReflectionEvent *) obj)->event;
8153 event->add = inflate_mono_method (type, event->add, NULL);
8155 event->remove = inflate_mono_method (type, event->remove, NULL);
8157 g_assert_not_reached ();
8160 ginst->initialized = TRUE;
8164 ensure_runtime_vtable (MonoClass *klass)
8166 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8167 int i, num, j, onum;
8168 MonoMethod **overrides;
8170 if (!tb || klass->wastypebuilder)
8173 ensure_runtime_vtable (klass->parent);
8175 num = tb->ctors? mono_array_length (tb->ctors): 0;
8176 num += tb->num_methods;
8177 klass->method.count = num;
8178 klass->methods = g_new (MonoMethod*, num);
8179 num = tb->ctors? mono_array_length (tb->ctors): 0;
8180 for (i = 0; i < num; ++i)
8181 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8182 num = tb->num_methods;
8184 for (i = 0; i < num; ++i)
8185 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8187 if (tb->interfaces) {
8188 klass->interface_count = mono_array_length (tb->interfaces);
8189 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8190 for (i = 0; i < klass->interface_count; ++i) {
8191 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8192 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8196 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8197 for (i = 0; i < klass->method.count; ++i)
8198 klass->methods [i]->slot = i;
8203 for (i = 0; i < tb->num_methods; ++i) {
8204 MonoReflectionMethodBuilder *mb =
8205 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8206 if (mb->override_method)
8211 overrides = g_new0 (MonoMethod*, onum * 2);
8215 for (i = 0; i < tb->num_methods; ++i) {
8216 MonoReflectionMethodBuilder *mb =
8217 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8218 if (mb->override_method) {
8219 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8220 overrides [onum * 2] =
8221 mb->override_method->method;
8222 overrides [onum * 2 + 1] =
8225 g_assert (mb->mhandle);
8232 mono_class_setup_vtable (klass, overrides, onum);
8237 typebuilder_setup_fields (MonoClass *klass)
8239 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8240 MonoReflectionFieldBuilder *fb;
8241 MonoClassField *field;
8246 klass->field.count = tb->num_fields;
8247 klass->field.first = 0;
8248 klass->field.last = klass->field.count;
8250 if (!klass->field.count)
8253 klass->fields = g_new0 (MonoClassField, klass->field.count);
8255 for (i = 0; i < klass->field.count; ++i) {
8256 fb = mono_array_get (tb->fields, gpointer, i);
8257 field = &klass->fields [i];
8258 field->name = mono_string_to_utf8 (fb->name);
8260 /* FIXME: handle type modifiers */
8261 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8262 field->type->attrs = fb->attrs;
8264 field->type = fb->type->type;
8266 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8267 field->data = mono_array_addr (fb->rva_data, char, 0);
8268 if (fb->offset != -1)
8269 field->offset = fb->offset;
8270 field->parent = klass;
8272 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8274 if (fb->def_value) {
8275 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8276 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8277 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8278 /* Copy the data from the blob since it might get realloc-ed */
8279 p = assembly->blob.data + idx;
8280 len = mono_metadata_decode_blob_size (p, &p2);
8282 field->data = g_malloc (len);
8283 memcpy ((gpointer)field->data, p, len);
8286 mono_class_layout_fields (klass);
8290 typebuilder_setup_properties (MonoClass *klass)
8292 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8293 MonoReflectionPropertyBuilder *pb;
8296 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8297 klass->property.first = 0;
8298 klass->property.last = klass->property.count;
8300 klass->properties = g_new0 (MonoProperty, klass->property.count);
8301 for (i = 0; i < klass->property.count; ++i) {
8302 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8303 klass->properties [i].parent = klass;
8304 klass->properties [i].attrs = pb->attrs;
8305 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8307 klass->properties [i].get = pb->get_method->mhandle;
8309 klass->properties [i].set = pb->set_method->mhandle;
8313 MonoReflectionEvent *
8314 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8316 MonoEvent *event = g_new0 (MonoEvent, 1);
8320 klass = my_mono_class_from_mono_type (tb->type.type);
8322 event->parent = klass;
8323 event->attrs = eb->attrs;
8324 event->name = mono_string_to_utf8 (eb->name);
8326 event->add = eb->add_method->mhandle;
8327 if (eb->remove_method)
8328 event->remove = eb->remove_method->mhandle;
8329 if (eb->raise_method)
8330 event->raise = eb->raise_method->mhandle;
8332 if (eb->other_methods) {
8333 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8334 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8335 MonoReflectionMethodBuilder *mb =
8336 mono_array_get (eb->other_methods,
8337 MonoReflectionMethodBuilder*, j);
8338 event->other [j] = mb->mhandle;
8342 return mono_event_get_object (mono_object_domain (tb), klass, event);
8346 typebuilder_setup_events (MonoClass *klass)
8348 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8349 MonoReflectionEventBuilder *eb;
8352 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8353 klass->event.first = 0;
8354 klass->event.last = klass->event.count;
8356 klass->events = g_new0 (MonoEvent, klass->event.count);
8357 for (i = 0; i < klass->event.count; ++i) {
8358 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8359 klass->events [i].parent = klass;
8360 klass->events [i].attrs = eb->attrs;
8361 klass->events [i].name = mono_string_to_utf8 (eb->name);
8363 klass->events [i].add = eb->add_method->mhandle;
8364 if (eb->remove_method)
8365 klass->events [i].remove = eb->remove_method->mhandle;
8366 if (eb->raise_method)
8367 klass->events [i].raise = eb->raise_method->mhandle;
8369 if (eb->other_methods) {
8370 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8371 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8372 MonoReflectionMethodBuilder *mb =
8373 mono_array_get (eb->other_methods,
8374 MonoReflectionMethodBuilder*, j);
8375 klass->events [i].other [j] = mb->mhandle;
8382 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8385 MonoReflectionType* res;
8388 MONO_ARCH_SAVE_REGS;
8390 klass = my_mono_class_from_mono_type (tb->type.type);
8392 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8395 * Fields to set in klass:
8396 * the various flags: delegate/unicode/contextbound etc.
8398 klass->flags = tb->attrs;
8400 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8401 /* No need to fully construct the type */
8402 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8404 /* enums are done right away */
8405 if (!klass->enumtype)
8406 ensure_runtime_vtable (klass);
8409 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8410 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8411 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8415 /* fields and object layout */
8416 if (klass->parent) {
8417 if (!klass->parent->size_inited)
8418 mono_class_init (klass->parent);
8419 klass->instance_size += klass->parent->instance_size;
8420 klass->class_size += klass->parent->class_size;
8421 klass->min_align = klass->parent->min_align;
8423 klass->instance_size = sizeof (MonoObject);
8424 klass->min_align = 1;
8427 /* FIXME: handle packing_size and instance_size */
8428 typebuilder_setup_fields (klass);
8430 typebuilder_setup_properties (klass);
8432 typebuilder_setup_events (klass);
8434 klass->wastypebuilder = TRUE;
8436 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8437 g_assert (res != (MonoReflectionType*)tb);
8442 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8444 MonoGenericParam *param;
8447 MONO_ARCH_SAVE_REGS;
8449 param = g_new0 (MonoGenericParam, 1);
8451 if (gparam->mbuilder) {
8452 if (!gparam->mbuilder->generic_container)
8453 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8454 param->owner = gparam->mbuilder->generic_container;
8455 } else if (gparam->tbuilder) {
8456 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8457 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8462 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8463 if (gparam->index >= count)
8466 container = nesting->generic_container;
8467 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8470 g_assert (container);
8471 param->owner = container;
8474 param->method = NULL;
8475 param->name = mono_string_to_utf8 (gparam->name);
8476 param->num = gparam->index;
8478 image = &gparam->tbuilder->module->dynamic_image->image;
8479 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8481 param->pklass->reflection_info = gparam;
8483 gparam->type.type = g_new0 (MonoType, 1);
8484 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8485 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8486 gparam->type.type->data.generic_param = param;
8490 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8492 MonoDynamicImage *assembly = sig->module->dynamic_image;
8493 guint32 na = mono_array_length (sig->arguments);
8498 MONO_ARCH_SAVE_REGS;
8500 p = buf = g_malloc (10 + na * 10);
8502 mono_metadata_encode_value (0x07, p, &p);
8503 mono_metadata_encode_value (na, p, &p);
8504 for (i = 0; i < na; ++i) {
8505 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8506 encode_reflection_type (assembly, type, p, &p);
8510 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8511 p = mono_array_addr (result, char, 0);
8512 memcpy (p, buf, buflen);
8519 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8521 MonoDynamicImage *assembly = sig->module->dynamic_image;
8522 guint32 na = mono_array_length (sig->arguments);
8527 MONO_ARCH_SAVE_REGS;
8529 p = buf = g_malloc (10 + na * 10);
8531 mono_metadata_encode_value (0x06, p, &p);
8532 for (i = 0; i < na; ++i) {
8533 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8534 encode_reflection_type (assembly, type, p, &p);
8538 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8539 p = mono_array_addr (result, char, 0);
8540 memcpy (p, buf, buflen);
8547 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8549 ReflectionMethodBuilder rmb;
8550 MonoMethodSignature *sig;
8553 sig = dynamic_method_to_signature (mb);
8555 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8558 * Resolve references.
8560 rmb.nrefs = mb->nrefs;
8561 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8562 for (i = 0; i < mb->nrefs; ++i) {
8563 gpointer ref = resolve_object (mb->module->image,
8564 mono_array_get (mb->refs, MonoObject*, i));
8567 mono_raise_exception (mono_get_exception_type_load (NULL));
8574 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8578 /* ilgen is no longer needed */
8583 * mono_reflection_lookup_dynamic_token:
8585 * Finish the Builder object pointed to by TOKEN and return the corresponding
8586 * runtime structure.
8589 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8591 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8594 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8597 return resolve_object (image, obj);
8601 resolve_object (MonoImage *image, MonoObject *obj)
8603 gpointer result = NULL;
8605 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8606 result = mono_string_intern ((MonoString*)obj);
8608 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8609 MonoReflectionType *tb = (MonoReflectionType*)obj;
8610 result = mono_class_from_mono_type (tb->type);
8612 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8613 result = ((MonoReflectionMethod*)obj)->method;
8615 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8616 result = ((MonoReflectionMethod*)obj)->method;
8618 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8619 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8620 result = mb->mhandle;
8622 /* Type is not yet created */
8623 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8625 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8628 * Hopefully this has been filled in by calling CreateType() on the
8632 * TODO: This won't work if the application finishes another
8633 * TypeBuilder instance instead of this one.
8635 result = mb->mhandle;
8637 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8638 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8640 result = cb->mhandle;
8642 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8644 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8645 result = cb->mhandle;
8647 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8648 result = ((MonoReflectionField*)obj)->field;
8650 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8651 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8652 result = fb->handle;
8655 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8657 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8658 result = fb->handle;
8660 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8661 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8664 klass = tb->type.type->data.klass;
8665 if (klass->wastypebuilder) {
8666 /* Already created */
8670 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8671 result = tb->type.type->data.klass;
8674 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8675 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8676 MonoMethodSignature *sig;
8679 if (helper->arguments)
8680 nargs = mono_array_length (helper->arguments);
8684 sig = mono_metadata_signature_alloc (image, nargs);
8685 sig->explicit_this = helper->call_conv & 64;
8686 sig->hasthis = helper->call_conv & 32;
8688 if (helper->call_conv == 0) /* unmanaged */
8689 sig->call_convention = helper->unmanaged_call_conv - 1;
8691 if (helper->call_conv & 0x02)
8692 sig->call_convention = MONO_CALL_VARARG;
8694 sig->call_convention = MONO_CALL_DEFAULT;
8696 sig->param_count = nargs;
8697 /* TODO: Copy type ? */
8698 sig->ret = helper->return_type->type;
8699 for (i = 0; i < nargs; ++i) {
8700 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8701 sig->params [i] = rt->type;
8706 g_print (obj->vtable->klass->name);
8707 g_assert_not_reached ();