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->klass->image == &assembly->image) &&
4128 !m->method->klass->generic_inst) {
4129 static guint32 method_table_idx = 0xffffff;
4130 if (m->method->klass->wastypebuilder) {
4131 /* we use the same token as the one that was assigned
4132 * to the Methodbuilder.
4133 * FIXME: do the equivalent for Fields.
4135 token = m->method->token;
4138 * Each token should have a unique index, but the indexes are
4139 * assigned by managed code, so we don't know about them. An
4140 * easy solution is to count backwards...
4142 method_table_idx --;
4143 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4146 token = mono_image_get_methodref_token (assembly, m->method);
4148 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4149 } else if (strcmp (klass->name, "MonoField") == 0) {
4150 MonoReflectionField *f = (MonoReflectionField *)obj;
4151 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4152 static guint32 field_table_idx = 0xffffff;
4154 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4156 token = mono_image_get_fieldref_token (assembly, f);
4158 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4159 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4160 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4161 token = mono_image_get_array_token (assembly, m);
4162 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4163 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4164 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4166 g_error ("requested token for %s\n", klass->name);
4169 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4175 guint32 import_lookup_table;
4179 guint32 import_address_table_rva;
4187 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4189 static MonoDynamicImage*
4190 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4192 static const guchar entrycode [16] = {0xff, 0x25, 0};
4193 MonoDynamicImage *image;
4196 const char *version = mono_get_runtime_version ();
4199 image = GC_MALLOC (sizeof (MonoDynamicImage));
4201 image = g_new0 (MonoDynamicImage, 1);
4204 /* keep in sync with image.c */
4205 image->image.name = assembly_name;
4206 image->image.assembly_name = image->image.name; /* they may be different */
4207 image->image.module_name = module_name;
4208 image->image.version = g_strdup (version);
4209 image->image.dynamic = TRUE;
4211 image->image.references = g_new0 (MonoAssembly*, 1);
4212 image->image.references [0] = NULL;
4214 mono_image_init (&image->image);
4216 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4217 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4218 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4219 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4220 image->handleref = g_hash_table_new (NULL, NULL);
4221 image->tokens = mono_g_hash_table_new (NULL, NULL);
4222 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4223 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4224 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4225 image->gen_params = g_ptr_array_new ();
4227 string_heap_init (&image->sheap);
4228 mono_image_add_stream_data (&image->us, "", 1);
4229 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4230 /* import tables... */
4231 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4232 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4233 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4234 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4235 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4236 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4237 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4238 stream_data_align (&image->code);
4240 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4242 for (i=0; i < 64; ++i) {
4243 image->tables [i].next_idx = 1;
4244 image->tables [i].columns = table_sizes [i];
4247 image->image.assembly = (MonoAssembly*)assembly;
4248 image->run = assembly->run;
4249 image->save = assembly->save;
4250 image->pe_kind = 0x1; /* ILOnly */
4251 image->machine = 0x14c; /* I386 */
4257 * mono_image_basic_init:
4258 * @assembly: an assembly builder object
4260 * Create the MonoImage that represents the assembly builder and setup some
4261 * of the helper hash table and the basic metadata streams.
4264 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4266 MonoDynamicAssembly *assembly;
4267 MonoDynamicImage *image;
4269 MONO_ARCH_SAVE_REGS;
4271 if (assemblyb->dynamic_assembly)
4275 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4277 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4280 assembly->assembly.dynamic = TRUE;
4281 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4282 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4283 if (assemblyb->culture)
4284 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4286 assembly->assembly.aname.culture = g_strdup ("");
4288 assembly->run = assemblyb->access != 2;
4289 assembly->save = assemblyb->access != 1;
4291 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4292 image->initial_image = TRUE;
4293 assembly->assembly.aname.name = image->image.name;
4294 assembly->assembly.image = &image->image;
4296 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4297 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4301 calc_section_size (MonoDynamicImage *assembly)
4305 /* alignment constraints */
4306 assembly->code.index += 3;
4307 assembly->code.index &= ~3;
4308 assembly->meta_size += 3;
4309 assembly->meta_size &= ~3;
4310 assembly->resources.index += 3;
4311 assembly->resources.index &= ~3;
4313 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4314 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4317 if (assembly->win32_res) {
4318 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4320 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4321 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4325 assembly->sections [MONO_SECTION_RELOC].size = 12;
4326 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4336 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4340 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4342 ResTreeNode *t1 = (ResTreeNode*)a;
4343 ResTreeNode *t2 = (ResTreeNode*)b;
4345 return t1->id - t2->id;
4349 * resource_tree_create:
4351 * Organize the resources into a resource tree.
4353 static ResTreeNode *
4354 resource_tree_create (MonoArray *win32_resources)
4356 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4360 tree = g_new0 (ResTreeNode, 1);
4362 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4363 MonoReflectionWin32Resource *win32_res =
4364 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4368 lang_node = g_new0 (ResTreeNode, 1);
4369 lang_node->id = win32_res->lang_id;
4370 lang_node->win32_res = win32_res;
4372 /* Create type node if neccesary */
4374 for (l = tree->children; l; l = l->next)
4375 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4376 type_node = (ResTreeNode*)l->data;
4381 type_node = g_new0 (ResTreeNode, 1);
4382 type_node->id = win32_res->res_type;
4385 * The resource types have to be sorted otherwise
4386 * Windows Explorer can't display the version information.
4388 tree->children = g_slist_insert_sorted (tree->children,
4389 type_node, resource_tree_compare_by_id);
4392 /* Create res node if neccesary */
4394 for (l = type_node->children; l; l = l->next)
4395 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4396 res_node = (ResTreeNode*)l->data;
4401 res_node = g_new0 (ResTreeNode, 1);
4402 res_node->id = win32_res->res_id;
4403 type_node->children = g_slist_append (type_node->children, res_node);
4406 res_node->children = g_slist_append (res_node->children, lang_node);
4413 * resource_tree_encode:
4415 * Encode the resource tree into the format used in the PE file.
4418 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4421 MonoPEResourceDir dir;
4422 MonoPEResourceDirEntry dir_entry;
4423 MonoPEResourceDataEntry data_entry;
4427 * For the format of the resource directory, see the article
4428 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4432 memset (&dir, 0, sizeof (dir));
4433 memset (&dir_entry, 0, sizeof (dir_entry));
4434 memset (&data_entry, 0, sizeof (data_entry));
4436 g_assert (sizeof (dir) == 16);
4437 g_assert (sizeof (dir_entry) == 8);
4438 g_assert (sizeof (data_entry) == 16);
4440 node->offset = p - begin;
4442 /* IMAGE_RESOURCE_DIRECTORY */
4443 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4445 memcpy (p, &dir, sizeof (dir));
4448 /* Reserve space for entries */
4450 p += sizeof (dir_entry) * dir.res_id_entries;
4452 /* Write children */
4453 for (l = node->children; l; l = l->next) {
4454 ResTreeNode *child = (ResTreeNode*)l->data;
4456 if (child->win32_res) {
4458 child->offset = p - begin;
4460 /* IMAGE_RESOURCE_DATA_ENTRY */
4461 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4462 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4464 memcpy (p, &data_entry, sizeof (data_entry));
4465 p += sizeof (data_entry);
4467 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4468 p += data_entry.rde_size;
4470 resource_tree_encode (child, begin, p, &p);
4474 /* IMAGE_RESOURCE_ENTRY */
4475 for (l = node->children; l; l = l->next) {
4476 ResTreeNode *child = (ResTreeNode*)l->data;
4477 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4479 dir_entry.is_dir = child->win32_res ? 0 : 1;
4480 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4482 memcpy (entries, &dir_entry, sizeof (dir_entry));
4483 entries += sizeof (dir_entry);
4490 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4495 MonoReflectionWin32Resource *win32_res;
4498 if (!assemblyb->win32_resources)
4502 * Resources are stored in a three level tree inside the PE file.
4503 * - level one contains a node for each type of resource
4504 * - level two contains a node for each resource
4505 * - level three contains a node for each instance of a resource for a
4506 * specific language.
4509 tree = resource_tree_create (assemblyb->win32_resources);
4511 /* Estimate the size of the encoded tree */
4513 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4514 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4515 size += mono_array_length (win32_res->res_data);
4517 /* Directory structure */
4518 size += mono_array_length (assemblyb->win32_resources) * 256;
4519 p = buf = g_malloc (size);
4521 resource_tree_encode (tree, p, p, &p);
4523 g_assert (p - buf < size);
4525 assembly->win32_res = g_malloc (p - buf);
4526 assembly->win32_res_size = p - buf;
4527 memcpy (assembly->win32_res, buf, p - buf);
4533 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4535 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4538 p += sizeof (MonoPEResourceDir);
4539 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4540 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4541 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4542 if (dir_entry->is_dir) {
4543 fixup_resource_directory (res_section, child, rva);
4545 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4546 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4549 p += sizeof (MonoPEResourceDirEntry);
4554 * mono_image_create_pefile:
4555 * @mb: a module builder object
4557 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4558 * assembly->pefile where it can be easily retrieved later in chunks.
4561 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4562 MonoMSDOSHeader *msdos;
4563 MonoDotNetHeader *header;
4564 MonoSectionTable *section;
4565 MonoCLIHeader *cli_header;
4566 guint32 size, image_size, virtual_base, text_offset;
4567 guint32 header_start, section_start, file_offset, virtual_offset;
4568 MonoDynamicImage *assembly;
4569 MonoReflectionAssemblyBuilder *assemblyb;
4570 MonoDynamicStream *pefile;
4572 guint32 *rva, value;
4575 static const unsigned char msheader[] = {
4576 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4577 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4580 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4581 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4582 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4583 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4586 assemblyb = mb->assemblyb;
4588 mono_image_basic_init (assemblyb);
4589 assembly = mb->dynamic_image;
4591 assembly->pe_kind = assemblyb->pe_kind;
4592 assembly->machine = assemblyb->machine;
4593 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4594 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4596 /* already created */
4597 if (assembly->pefile.index)
4600 mono_image_build_metadata (mb);
4602 if (mb->is_main && assemblyb->resources) {
4603 int len = mono_array_length (assemblyb->resources);
4604 for (i = 0; i < len; ++i)
4605 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4608 if (mb->resources) {
4609 int len = mono_array_length (mb->resources);
4610 for (i = 0; i < len; ++i)
4611 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4614 build_compressed_metadata (assembly);
4617 assembly_add_win32_resources (assembly, assemblyb);
4619 nsections = calc_section_size (assembly);
4621 pefile = &assembly->pefile;
4623 /* The DOS header and stub */
4624 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4625 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4627 /* the dotnet header */
4628 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4630 /* the section tables */
4631 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4633 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4634 virtual_offset = VIRT_ALIGN;
4637 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4638 if (!assembly->sections [i].size)
4641 file_offset += FILE_ALIGN - 1;
4642 file_offset &= ~(FILE_ALIGN - 1);
4643 virtual_offset += VIRT_ALIGN - 1;
4644 virtual_offset &= ~(VIRT_ALIGN - 1);
4646 assembly->sections [i].offset = file_offset;
4647 assembly->sections [i].rva = virtual_offset;
4649 file_offset += assembly->sections [i].size;
4650 virtual_offset += assembly->sections [i].size;
4651 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4654 file_offset += FILE_ALIGN - 1;
4655 file_offset &= ~(FILE_ALIGN - 1);
4656 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4658 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4660 /* back-patch info */
4661 msdos = (MonoMSDOSHeader*)pefile->data;
4662 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4663 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4664 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4666 header = (MonoDotNetHeader*)(pefile->data + header_start);
4667 header->pesig [0] = 'P';
4668 header->pesig [1] = 'E';
4670 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4671 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4672 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4673 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4674 if (assemblyb->pekind == 1) {
4676 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4679 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4682 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4684 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4685 header->pe.pe_major = 6;
4686 header->pe.pe_minor = 0;
4687 size = assembly->sections [MONO_SECTION_TEXT].size;
4688 size += FILE_ALIGN - 1;
4689 size &= ~(FILE_ALIGN - 1);
4690 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4691 size = assembly->sections [MONO_SECTION_RSRC].size;
4692 size += FILE_ALIGN - 1;
4693 size &= ~(FILE_ALIGN - 1);
4694 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4695 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4696 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4697 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4698 /* pe_rva_entry_point always at the beginning of the text section */
4699 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4701 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4702 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4703 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4704 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4705 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4706 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4707 size = section_start;
4708 size += FILE_ALIGN - 1;
4709 size &= ~(FILE_ALIGN - 1);
4710 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4712 size += VIRT_ALIGN - 1;
4713 size &= ~(VIRT_ALIGN - 1);
4714 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4717 // Translate the PEFileKind value to the value expected by the Windows loader
4723 // PEFileKinds.Dll == 1
4724 // PEFileKinds.ConsoleApplication == 2
4725 // PEFileKinds.WindowApplication == 3
4728 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4729 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4731 if (assemblyb->pekind == 3)
4736 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4738 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4739 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4740 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4741 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4742 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4743 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4745 /* fill data directory entries */
4747 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4748 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4750 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4751 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4753 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4754 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4755 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4756 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4757 /* patch entrypoint name */
4758 if (assemblyb->pekind == 1)
4759 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4761 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4762 /* patch imported function RVA name */
4763 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4766 /* the import table */
4767 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4768 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4769 /* patch imported dll RVA name and other entries in the dir */
4770 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4771 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4772 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4773 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4774 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4775 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4777 p = (assembly->code.data + assembly->ilt_offset);
4778 value = (assembly->text_rva + assembly->imp_names_offset);
4779 *p++ = (value) & 0xff;
4780 *p++ = (value >> 8) & (0xff);
4781 *p++ = (value >> 16) & (0xff);
4782 *p++ = (value >> 24) & (0xff);
4784 /* the CLI header info */
4785 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4786 cli_header->ch_size = GUINT32_FROM_LE (72);
4787 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4788 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4789 if (assemblyb->entry_point) {
4790 guint32 table_idx = 0;
4791 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4792 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4793 table_idx = methodb->table_idx;
4795 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4797 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4799 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4801 /* The embedded managed resources */
4802 text_offset = assembly->text_rva + assembly->code.index;
4803 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4804 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4805 text_offset += assembly->resources.index;
4806 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4807 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4808 text_offset += assembly->meta_size;
4809 if (assembly->strong_name_size) {
4810 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4811 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4812 text_offset += assembly->strong_name_size;
4815 /* write the section tables and section content */
4816 section = (MonoSectionTable*)(pefile->data + section_start);
4817 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4818 static const char *section_names [] = {
4819 ".text", ".rsrc", ".reloc"
4821 if (!assembly->sections [i].size)
4823 strcpy (section->st_name, section_names [i]);
4824 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4825 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4826 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4827 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4828 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4829 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4830 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4832 case MONO_SECTION_TEXT:
4833 /* patch entry point */
4834 p = (assembly->code.data + 2);
4835 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4836 *p++ = (value) & 0xff;
4837 *p++ = (value >> 8) & 0xff;
4838 *p++ = (value >> 16) & 0xff;
4839 *p++ = (value >> 24) & 0xff;
4841 text_offset = assembly->sections [i].offset;
4842 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4843 text_offset += assembly->code.index;
4844 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4845 text_offset += assembly->resources.index;
4846 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4847 text_offset += assembly->meta_size;
4848 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4850 g_free (assembly->image.raw_metadata);
4852 case MONO_SECTION_RELOC:
4853 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4854 *rva = GUINT32_FROM_LE (assembly->text_rva);
4856 *rva = GUINT32_FROM_LE (12);
4858 data16 = (guint16*)rva;
4860 * the entrypoint is always at the start of the text section
4861 * 3 is IMAGE_REL_BASED_HIGHLOW
4862 * 2 is patch_size_rva - text_rva
4864 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4866 *data16 = 0; /* terminate */
4868 case MONO_SECTION_RSRC:
4869 if (assembly->win32_res) {
4870 text_offset = assembly->sections [i].offset;
4872 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4873 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4875 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4879 g_assert_not_reached ();
4884 /* check that the file is properly padded */
4887 FILE *f = fopen ("mypetest.exe", "w");
4888 fwrite (pefile->data, pefile->index, 1, f);
4894 MonoReflectionModule *
4895 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4899 MonoImageOpenStatus status;
4900 MonoDynamicAssembly *assembly;
4901 guint32 module_count;
4902 MonoImage **new_modules;
4904 name = mono_string_to_utf8 (fileName);
4906 image = mono_image_open (name, &status);
4909 if (status == MONO_IMAGE_ERROR_ERRNO)
4910 exc = mono_get_exception_file_not_found (fileName);
4912 exc = mono_get_exception_bad_image_format (name);
4914 mono_raise_exception (exc);
4919 assembly = ab->dynamic_assembly;
4920 image->assembly = (MonoAssembly*)assembly;
4922 module_count = image->assembly->image->module_count;
4923 new_modules = g_new0 (MonoImage *, module_count + 1);
4925 if (image->assembly->image->modules)
4926 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4927 new_modules [module_count] = image;
4929 g_free (image->assembly->image->modules);
4930 image->assembly->image->modules = new_modules;
4931 image->assembly->image->module_count ++;
4933 mono_assembly_load_references (image, &status);
4935 mono_image_close (image);
4936 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4939 return mono_module_get_object (mono_domain_get (), image);
4943 * We need to return always the same object for MethodInfo, FieldInfo etc..
4944 * but we need to consider the reflected type.
4945 * type uses a different hash, since it uses custom hash/equal functions.
4950 MonoClass *refclass;
4954 reflected_equal (gconstpointer a, gconstpointer b) {
4955 const ReflectedEntry *ea = a;
4956 const ReflectedEntry *eb = b;
4958 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4962 reflected_hash (gconstpointer a) {
4963 const ReflectedEntry *ea = a;
4964 return GPOINTER_TO_UINT (ea->item);
4967 #define CHECK_OBJECT(t,p,k) \
4973 mono_domain_lock (domain); \
4974 if (!domain->refobject_hash) \
4975 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4976 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4977 mono_domain_unlock (domain); \
4983 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4985 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4988 #define CACHE_OBJECT(p,o,k) \
4990 ReflectedEntry *e = ALLOC_REFENTRY; \
4992 e->refclass = (k); \
4993 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4994 mono_domain_unlock (domain); \
4998 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5000 /* this is done only once */
5001 mono_domain_lock (domain);
5002 CACHE_OBJECT (assembly, res, NULL);
5006 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5008 /* this is done only once */
5009 mono_domain_lock (domain);
5010 CACHE_OBJECT (module, res, NULL);
5014 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5016 MonoDynamicImage *image = moduleb->dynamic_image;
5017 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5020 * FIXME: we already created an image in mono_image_basic_init (), but
5021 * we don't know which module it belongs to, since that is only
5022 * determined at assembly save time.
5024 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5025 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5027 moduleb->module.image = &image->image;
5028 moduleb->dynamic_image = image;
5029 register_module (mono_object_domain (moduleb), moduleb, image);
5034 * mono_assembly_get_object:
5035 * @domain: an app domain
5036 * @assembly: an assembly
5038 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5040 MonoReflectionAssembly*
5041 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5043 static MonoClass *System_Reflection_Assembly;
5044 MonoReflectionAssembly *res;
5046 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5047 if (!System_Reflection_Assembly)
5048 System_Reflection_Assembly = mono_class_from_name (
5049 mono_defaults.corlib, "System.Reflection", "Assembly");
5050 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5051 res->assembly = assembly;
5052 CACHE_OBJECT (assembly, res, NULL);
5058 MonoReflectionModule*
5059 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5061 static MonoClass *System_Reflection_Module;
5062 MonoReflectionModule *res;
5065 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5066 if (!System_Reflection_Module)
5067 System_Reflection_Module = mono_class_from_name (
5068 mono_defaults.corlib, "System.Reflection", "Module");
5069 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5072 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5074 res->fqname = mono_string_new (domain, image->name);
5075 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5076 res->scopename = mono_string_new (domain, image->module_name);
5080 if (image->assembly->image == image) {
5081 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5084 g_assert (image->assembly->image->modules);
5086 for (i = 0; i < image->assembly->image->module_count; i++) {
5087 if (image->assembly->image->modules [i] == image)
5088 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5090 g_assert (res->token);
5093 mono_image_addref (image);
5095 CACHE_OBJECT (image, res, NULL);
5099 MonoReflectionModule*
5100 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5102 static MonoClass *System_Reflection_Module;
5103 MonoReflectionModule *res;
5104 MonoTableInfo *table;
5105 guint32 cols [MONO_FILE_SIZE];
5107 guint32 i, name_idx;
5110 if (!System_Reflection_Module)
5111 System_Reflection_Module = mono_class_from_name (
5112 mono_defaults.corlib, "System.Reflection", "Module");
5113 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5115 table = &image->tables [MONO_TABLE_FILE];
5116 g_assert (table_index < table->rows);
5117 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5120 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5121 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5123 /* Check whenever the row has a corresponding row in the moduleref table */
5124 table = &image->tables [MONO_TABLE_MODULEREF];
5125 for (i = 0; i < table->rows; ++i) {
5126 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5127 val = mono_metadata_string_heap (image, name_idx);
5128 if (strcmp (val, name) == 0)
5129 res->image = image->modules [i];
5132 res->fqname = mono_string_new (domain, name);
5133 res->name = mono_string_new (domain, name);
5134 res->scopename = mono_string_new (domain, name);
5135 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5136 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5142 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5144 if ((t1->type != t2->type) ||
5145 (t1->byref != t2->byref))
5149 case MONO_TYPE_VOID:
5150 case MONO_TYPE_BOOLEAN:
5151 case MONO_TYPE_CHAR:
5162 case MONO_TYPE_STRING:
5165 case MONO_TYPE_OBJECT:
5166 case MONO_TYPE_TYPEDBYREF:
5168 case MONO_TYPE_VALUETYPE:
5169 case MONO_TYPE_CLASS:
5170 case MONO_TYPE_SZARRAY:
5171 return t1->data.klass == t2->data.klass;
5173 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5174 case MONO_TYPE_ARRAY:
5175 if (t1->data.array->rank != t2->data.array->rank)
5177 return t1->data.array->eklass == t2->data.array->eklass;
5178 case MONO_TYPE_GENERICINST: {
5180 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5182 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5184 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5185 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5191 case MONO_TYPE_MVAR:
5192 return t1->data.generic_param == t2->data.generic_param;
5194 g_error ("implement type compare for %0x!", t1->type);
5202 mymono_metadata_type_hash (MonoType *t1)
5208 hash |= t1->byref << 6; /* do not collide with t1->type values */
5210 case MONO_TYPE_VALUETYPE:
5211 case MONO_TYPE_CLASS:
5212 case MONO_TYPE_SZARRAY:
5213 /* check if the distribution is good enough */
5214 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5216 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5221 static MonoReflectionGenericInst*
5222 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5224 static MonoClass *System_Reflection_MonoGenericInst;
5225 MonoReflectionGenericInst *res;
5226 MonoGenericInst *ginst;
5229 if (!System_Reflection_MonoGenericInst) {
5230 System_Reflection_MonoGenericInst = mono_class_from_name (
5231 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5232 g_assert (System_Reflection_MonoGenericInst);
5235 ginst = geninst->data.generic_inst;
5236 gklass = mono_class_from_mono_type (ginst->generic_type);
5238 mono_class_init (ginst->klass);
5240 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5242 res->type.type = geninst;
5243 if (gklass->wastypebuilder && gklass->reflection_info)
5244 res->generic_type = gklass->reflection_info;
5246 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5252 * mono_type_get_object:
5253 * @domain: an app domain
5256 * Return an System.MonoType object representing the type @type.
5259 mono_type_get_object (MonoDomain *domain, MonoType *type)
5261 MonoReflectionType *res;
5262 MonoClass *klass = mono_class_from_mono_type (type);
5264 mono_domain_lock (domain);
5265 if (!domain->type_hash)
5266 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5267 (GCompareFunc)mymono_metadata_type_equal);
5268 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5269 mono_domain_unlock (domain);
5272 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5273 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5274 mono_g_hash_table_insert (domain->type_hash, type, res);
5275 mono_domain_unlock (domain);
5278 if (klass->reflection_info && !klass->wastypebuilder) {
5279 /* g_assert_not_reached (); */
5280 /* should this be considered an error condition? */
5282 mono_domain_unlock (domain);
5283 return klass->reflection_info;
5286 mono_class_init (klass);
5287 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5289 mono_g_hash_table_insert (domain->type_hash, type, res);
5290 mono_domain_unlock (domain);
5295 * mono_method_get_object:
5296 * @domain: an app domain
5298 * @refclass: the reflected type (can be NULL)
5300 * Return an System.Reflection.MonoMethod object representing the method @method.
5302 MonoReflectionMethod*
5303 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5306 * We use the same C representation for methods and constructors, but the type
5307 * name in C# is different.
5311 MonoReflectionMethod *ret;
5314 refclass = method->klass;
5316 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5317 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5318 cname = "MonoCMethod";
5320 cname = "MonoMethod";
5321 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5323 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5324 ret->method = method;
5325 ret->name = mono_string_new (domain, method->name);
5326 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5327 CACHE_OBJECT (method, ret, refclass);
5332 * mono_field_get_object:
5333 * @domain: an app domain
5337 * Return an System.Reflection.MonoField object representing the field @field
5340 MonoReflectionField*
5341 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5343 MonoReflectionField *res;
5346 CHECK_OBJECT (MonoReflectionField *, field, klass);
5347 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5348 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5351 res->name = mono_string_new (domain, field->name);
5352 if (field->generic_info)
5353 res->attrs = field->generic_info->generic_type->attrs;
5355 res->attrs = field->type->attrs;
5356 res->type = mono_type_get_object (domain, field->type);
5357 CACHE_OBJECT (field, res, klass);
5362 * mono_property_get_object:
5363 * @domain: an app domain
5365 * @property: a property
5367 * Return an System.Reflection.MonoProperty object representing the property @property
5370 MonoReflectionProperty*
5371 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5373 MonoReflectionProperty *res;
5376 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5377 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5378 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5380 res->property = property;
5381 CACHE_OBJECT (property, res, klass);
5386 * mono_event_get_object:
5387 * @domain: an app domain
5391 * Return an System.Reflection.MonoEvent object representing the event @event
5394 MonoReflectionEvent*
5395 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5397 MonoReflectionEvent *res;
5400 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5401 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5402 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5405 CACHE_OBJECT (event, res, klass);
5410 * mono_param_get_objects:
5411 * @domain: an app domain
5414 * Return an System.Reflection.ParameterInfo array object representing the parameters
5415 * in the method @method.
5418 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5420 static MonoClass *System_Reflection_ParameterInfo;
5421 MonoArray *res = NULL;
5422 MonoReflectionMethod *member = NULL;
5423 MonoReflectionParameter *param = NULL;
5424 char **names, **blobs = NULL;
5425 MonoObject *dbnull = mono_get_dbnull_object (domain);
5426 MonoMarshalSpec **mspecs;
5429 if (!System_Reflection_ParameterInfo)
5430 System_Reflection_ParameterInfo = mono_class_from_name (
5431 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5433 if (!method->signature->param_count)
5434 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5436 /* Note: the cache is based on the address of the signature into the method
5437 * since we already cache MethodInfos with the method as keys.
5439 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5441 member = mono_method_get_object (domain, method, NULL);
5442 names = g_new (char *, method->signature->param_count);
5443 mono_method_get_param_names (method, (const char **) names);
5445 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5446 mono_method_get_marshal_info (method, mspecs);
5448 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5449 for (i = 0; i < method->signature->param_count; ++i) {
5450 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5451 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5452 param->MemberImpl = (MonoObject*)member;
5453 param->NameImpl = mono_string_new (domain, names [i]);
5454 param->PositionImpl = i;
5455 param->AttrsImpl = method->signature->params [i]->attrs;
5457 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5458 param->DefaultValueImpl = dbnull;
5460 MonoType *type = param->ClassImpl->type;
5463 blobs = g_new0 (char *, method->signature->param_count);
5464 get_default_param_value_blobs (method, blobs);
5467 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5469 if (!param->DefaultValueImpl) {
5470 param->DefaultValueImpl = dbnull;
5475 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5477 mono_array_set (res, gpointer, i, param);
5482 for (i = method->signature->param_count; i >= 0; i--)
5484 mono_metadata_free_marshal_spec (mspecs [i]);
5487 CACHE_OBJECT (&(method->signature), res, NULL);
5492 * mono_method_body_get_object:
5493 * @domain: an app domain
5496 * Return an System.Reflection.MethodBody object representing the method @method.
5498 MonoReflectionMethodBody*
5499 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5501 static MonoClass *System_Reflection_MethodBody = NULL;
5502 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5503 MonoReflectionMethodBody *ret;
5504 MonoMethodNormal *mn;
5505 MonoMethodHeader *header;
5508 if (!System_Reflection_MethodBody)
5509 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5510 if (!System_Reflection_LocalVariableInfo)
5511 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5513 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5515 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5516 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5518 mn = (MonoMethodNormal *)method;
5519 header = mono_method_get_header (method);
5521 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5522 /* FIXME: Other fields */
5523 ret->init_locals = header->init_locals;
5524 ret->max_stack = header->max_stack;
5525 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5526 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5527 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5528 for (i = 0; i < header->num_locals; ++i) {
5529 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5530 info->local_type = mono_type_get_object (domain, header->locals [i]);
5531 info->is_pinned = header->locals [i]->pinned;
5532 info->local_index = 0;
5535 CACHE_OBJECT (method, ret, NULL);
5540 mono_get_dbnull_object (MonoDomain *domain)
5544 static MonoClassField *dbnull_value_field = NULL;
5546 if (!dbnull_value_field) {
5547 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5548 mono_class_init (klass);
5549 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5550 g_assert (dbnull_value_field);
5552 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5559 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5561 guint32 param_index, i, lastp, crow = 0;
5562 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5565 MonoClass *klass = method->klass;
5566 MonoImage *image = klass->image;
5567 MonoMethodSignature *methodsig = method->signature;
5569 MonoTableInfo *constt;
5570 MonoTableInfo *methodt;
5571 MonoTableInfo *paramt;
5573 if (!methodsig->param_count)
5576 if (klass->generic_inst) {
5577 return; /* FIXME - ??? */
5580 mono_class_init (klass);
5582 if (klass->image->dynamic) {
5583 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5584 if (aux && aux->param_defaults)
5585 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5589 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5590 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5591 constt = &image->tables [MONO_TABLE_CONSTANT];
5593 for (i = 0; i < klass->method.count; ++i) {
5594 if (method == klass->methods [i]) {
5595 idx = klass->method.first + i;
5600 g_assert (idx != -1);
5602 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5603 if (idx + 1 < methodt->rows)
5604 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5606 lastp = paramt->rows + 1;
5608 for (i = param_index; i < lastp; ++i) {
5611 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5612 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5614 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5617 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5622 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5623 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5630 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5639 klass = mono_class_from_mono_type (type);
5640 if (klass->valuetype) {
5641 object = mono_object_new (domain, klass);
5642 retval = ((gchar *) object + sizeof (MonoObject));
5647 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5654 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5658 memset (assembly, 0, sizeof (MonoAssemblyName));
5660 assembly->culture = "";
5661 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5663 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5666 while (*p == ' ' || *p == ',') {
5675 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5677 assembly->major = strtoul (p, &s, 10);
5678 if (s == p || *s != '.')
5681 assembly->minor = strtoul (p, &s, 10);
5682 if (s == p || *s != '.')
5685 assembly->build = strtoul (p, &s, 10);
5686 if (s == p || *s != '.')
5689 assembly->revision = strtoul (p, &s, 10);
5693 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5695 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5696 assembly->culture = "";
5699 assembly->culture = p;
5700 while (*p && *p != ',') {
5704 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5706 if (strncmp (p, "null", 4) == 0) {
5711 while (*p && *p != ',') {
5714 len = (p - start + 1);
5715 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5716 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5717 g_strlcpy (assembly->public_key_token, start, len);
5720 while (*p && *p != ',')
5724 while (*p == ' ' || *p == ',') {
5738 * mono_reflection_parse_type:
5741 * Parse a type name as accepted by the GetType () method and output the info
5742 * extracted in the info structure.
5743 * the name param will be mangled, so, make a copy before passing it to this function.
5744 * The fields in info will be valid until the memory pointed to by name is valid.
5745 * Returns 0 on parse error.
5746 * See also mono_type_get_name () below.
5749 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5751 char *start, *p, *w, *last_point, *startn;
5752 int in_modifiers = 0;
5753 int isbyref = 0, rank;
5755 start = p = w = name;
5757 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5758 info->name = info->name_space = NULL;
5759 info->nested = NULL;
5760 info->modifiers = NULL;
5762 /* last_point separates the namespace from the name */
5768 *p = 0; /* NULL terminate the name */
5770 info->nested = g_list_append (info->nested, startn);
5771 /* we have parsed the nesting namespace + name */
5775 info->name_space = start;
5777 info->name = last_point + 1;
5779 info->name_space = (char *)"";
5805 info->name_space = start;
5807 info->name = last_point + 1;
5809 info->name_space = (char *)"";
5816 if (isbyref) /* only one level allowed by the spec */
5819 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5823 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5834 else if (*p != '*') /* '*' means unknown lower bound */
5840 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5852 return 0; /* missing assembly name */
5853 if (!assembly_name_to_aname (&info->assembly, p))
5860 if (info->assembly.name)
5863 *w = 0; /* terminate class name */
5864 if (!info->name || !*info->name)
5866 /* add other consistency checks */
5871 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5878 image = mono_defaults.corlib;
5881 klass = mono_class_from_name_case (image, info->name_space, info->name);
5883 klass = mono_class_from_name (image, info->name_space, info->name);
5886 for (mod = info->nested; mod; mod = mod->next) {
5889 mono_class_init (klass);
5890 nested = klass->nested_classes;
5893 klass = nested->data;
5895 if (g_strcasecmp (klass->name, mod->data) == 0)
5898 if (strcmp (klass->name, mod->data) == 0)
5902 nested = nested->next;
5909 mono_class_init (klass);
5910 for (mod = info->modifiers; mod; mod = mod->next) {
5911 modval = GPOINTER_TO_UINT (mod->data);
5912 if (!modval) { /* byref: must be last modifier */
5913 return &klass->this_arg;
5914 } else if (modval == -1) {
5915 klass = mono_ptr_class_get (&klass->byval_arg);
5916 } else { /* array rank */
5917 klass = mono_array_class_get (klass, modval);
5919 mono_class_init (klass);
5922 return &klass->byval_arg;
5926 * mono_reflection_get_type:
5927 * @image: a metadata context
5928 * @info: type description structure
5929 * @ignorecase: flag for case-insensitive string compares
5930 * @type_resolve: whenever type resolve was already tried
5932 * Build a MonoType from the type description in @info.
5937 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5940 MonoReflectionAssembly *assembly;
5944 type = mono_reflection_get_type_internal (image, info, ignorecase);
5947 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5954 *type_resolve = TRUE;
5957 /* Reconstruct the type name */
5958 fullName = g_string_new ("");
5959 if (info->name_space && (info->name_space [0] != '\0'))
5960 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5962 g_string_printf (fullName, info->name);
5963 for (mod = info->nested; mod; mod = mod->next)
5964 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5966 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5968 if (assembly->assembly->dynamic) {
5969 /* Enumerate all modules */
5970 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5974 if (abuilder->modules) {
5975 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5976 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5977 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5983 if (!type && abuilder->loaded_modules) {
5984 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5985 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5986 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5993 type = mono_reflection_get_type_internal (assembly->assembly->image,
5996 g_string_free (fullName, TRUE);
6001 * mono_reflection_type_from_name:
6003 * @image: a metadata context (can be NULL).
6005 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6006 * it defaults to get the type from @image or, if @image is NULL or loading
6007 * from it fails, uses corlib.
6011 mono_reflection_type_from_name (char *name, MonoImage *image)
6014 MonoTypeNameParse info;
6015 MonoAssembly *assembly;
6017 gboolean type_resolve = FALSE;
6019 /* Make a copy since parse_type modifies its argument */
6020 tmp = g_strdup (name);
6022 /*g_print ("requested type %s\n", str);*/
6023 if (!mono_reflection_parse_type (tmp, &info)) {
6025 g_list_free (info.modifiers);
6026 g_list_free (info.nested);
6030 if (info.assembly.name) {
6031 assembly = mono_assembly_loaded (&info.assembly);
6033 /* then we must load the assembly ourselve - see #60439 */
6034 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6037 g_list_free (info.modifiers);
6038 g_list_free (info.nested);
6042 image = assembly->image;
6043 } else if (image == NULL) {
6044 image = mono_defaults.corlib;
6047 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6048 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6049 image = mono_defaults.corlib;
6050 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6054 g_list_free (info.modifiers);
6055 g_list_free (info.nested);
6060 * mono_reflection_get_token:
6062 * Return the metadata token of OBJ which should be an object
6063 * representing a metadata element.
6066 mono_reflection_get_token (MonoObject *obj)
6071 klass = obj->vtable->klass;
6073 if (strcmp (klass->name, "MethodBuilder") == 0) {
6074 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6076 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6077 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6078 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6080 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6081 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6082 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6083 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6084 if (tb->generic_params) {
6085 g_assert_not_reached ();
6087 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6089 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6090 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6091 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6092 } else if (strcmp (klass->name, "MonoType") == 0) {
6093 MonoReflectionType *tb = (MonoReflectionType *)obj;
6094 token = mono_class_from_mono_type (tb->type)->type_token;
6095 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6096 strcmp (klass->name, "MonoMethod") == 0) {
6097 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6098 if (m->method->signature->is_inflated) {
6099 g_assert_not_reached ();
6100 } else if (m->method->signature->generic_param_count) {
6101 g_assert_not_reached ();
6102 } else if (m->method->klass->generic_inst) {
6103 g_assert_not_reached ();
6105 token = m->method->token;
6107 } else if (strcmp (klass->name, "MonoField") == 0) {
6108 MonoReflectionField *f = (MonoReflectionField*)obj;
6110 token = mono_class_get_field_token (f->field);
6111 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6112 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6114 token = mono_class_get_property_token (p->property);
6115 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6116 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6118 token = mono_class_get_event_token (p->event);
6119 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6120 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6122 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6123 } else if (strcmp (klass->name, "Module") == 0) {
6124 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6127 } else if (strcmp (klass->name, "Assembly") == 0) {
6128 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6130 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6131 MonoException *ex = mono_get_exception_not_implemented (msg);
6133 mono_raise_exception (ex);
6140 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6142 int slen, type = t->type;
6147 case MONO_TYPE_BOOLEAN: {
6148 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6153 case MONO_TYPE_CHAR:
6155 case MONO_TYPE_I2: {
6156 guint16 *val = g_malloc (sizeof (guint16));
6161 #if SIZEOF_VOID_P == 4
6167 case MONO_TYPE_I4: {
6168 guint32 *val = g_malloc (sizeof (guint32));
6173 #if SIZEOF_VOID_P == 8
6174 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6179 case MONO_TYPE_I8: {
6180 guint64 *val = g_malloc (sizeof (guint64));
6185 case MONO_TYPE_VALUETYPE:
6186 if (t->data.klass->enumtype) {
6187 type = t->data.klass->enum_basetype->type;
6190 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6193 case MONO_TYPE_STRING:
6194 if (*p == (char)0xFF) {
6198 slen = mono_metadata_decode_value (p, &p);
6200 return mono_string_new_len (mono_domain_get (), p, slen);
6201 case MONO_TYPE_CLASS: {
6204 if (*p == (char)0xFF) {
6209 slen = mono_metadata_decode_value (p, &p);
6210 n = g_memdup (p, slen + 1);
6212 t = mono_reflection_type_from_name (n, image);
6214 g_warning ("Cannot load type '%s'", n);
6218 return mono_type_get_object (mono_domain_get (), t);
6222 case MONO_TYPE_OBJECT: {
6225 MonoClass *subc = NULL;
6230 } else if (subt == 0x0E) {
6231 type = MONO_TYPE_STRING;
6233 } else if (subt == 0x55) {
6236 slen = mono_metadata_decode_value (p, &p);
6237 n = g_memdup (p, slen + 1);
6239 t = mono_reflection_type_from_name (n, image);
6241 g_warning ("Cannot load type '%s'", n);
6244 subc = mono_class_from_mono_type (t);
6245 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6246 MonoType simple_type = {{0}};
6247 simple_type.type = subt;
6248 subc = mono_class_from_mono_type (&simple_type);
6250 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6252 val = load_cattr_value (image, &subc->byval_arg, p, end);
6253 obj = mono_object_new (mono_domain_get (), subc);
6254 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6258 case MONO_TYPE_SZARRAY: {
6260 guint32 i, alen, basetype;
6263 if (alen == 0xffffffff) {
6267 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6268 basetype = t->data.klass->byval_arg.type;
6273 case MONO_TYPE_BOOLEAN:
6274 for (i = 0; i < alen; i++) {
6275 MonoBoolean val = *p++;
6276 mono_array_set (arr, MonoBoolean, i, val);
6279 case MONO_TYPE_CHAR:
6282 for (i = 0; i < alen; i++) {
6283 guint16 val = read16 (p);
6284 mono_array_set (arr, guint16, i, val);
6291 for (i = 0; i < alen; i++) {
6292 guint32 val = read32 (p);
6293 mono_array_set (arr, guint32, i, val);
6300 for (i = 0; i < alen; i++) {
6301 guint64 val = read64 (p);
6302 mono_array_set (arr, guint64, i, val);
6306 case MONO_TYPE_CLASS:
6307 case MONO_TYPE_OBJECT:
6308 case MONO_TYPE_STRING:
6309 for (i = 0; i < alen; i++) {
6310 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6311 mono_array_set (arr, gpointer, i, item);
6315 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6321 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6327 type_is_reference (MonoType *type)
6329 switch (type->type) {
6330 case MONO_TYPE_BOOLEAN:
6331 case MONO_TYPE_CHAR:
6344 case MONO_TYPE_VALUETYPE:
6352 free_param_data (MonoMethodSignature *sig, void **params) {
6354 for (i = 0; i < sig->param_count; ++i) {
6355 if (!type_is_reference (sig->params [i]))
6356 g_free (params [i]);
6361 * Find the method index in the metadata methodDef table.
6362 * Later put these three helper methods in metadata and export them.
6365 find_method_index (MonoMethod *method) {
6366 MonoClass *klass = method->klass;
6369 for (i = 0; i < klass->method.count; ++i) {
6370 if (method == klass->methods [i])
6371 return klass->method.first + 1 + i;
6377 * Find the field index in the metadata FieldDef table.
6380 find_field_index (MonoClass *klass, MonoClassField *field) {
6383 for (i = 0; i < klass->field.count; ++i) {
6384 if (field == &klass->fields [i])
6385 return klass->field.first + 1 + i;
6391 * Find the property index in the metadata Property table.
6394 find_property_index (MonoClass *klass, MonoProperty *property) {
6397 for (i = 0; i < klass->property.count; ++i) {
6398 if (property == &klass->properties [i])
6399 return klass->property.first + 1 + i;
6405 * Find the event index in the metadata Event table.
6408 find_event_index (MonoClass *klass, MonoEvent *event) {
6411 for (i = 0; i < klass->event.count; ++i) {
6412 if (event == &klass->events [i])
6413 return klass->event.first + 1 + i;
6419 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6421 const char *p = data;
6423 guint32 i, j, num_named;
6427 mono_class_init (method->klass);
6430 attr = mono_object_new (mono_domain_get (), method->klass);
6431 mono_runtime_invoke (method, attr, NULL, NULL);
6435 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6438 /*g_print ("got attr %s\n", method->klass->name);*/
6440 params = g_new (void*, method->signature->param_count);
6444 for (i = 0; i < method->signature->param_count; ++i) {
6445 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6449 attr = mono_object_new (mono_domain_get (), method->klass);
6450 mono_runtime_invoke (method, attr, params, NULL);
6451 free_param_data (method->signature, params);
6453 num_named = read16 (named);
6455 for (j = 0; j < num_named; j++) {
6457 char *name, named_type, data_type;
6458 named_type = *named++;
6459 data_type = *named++; /* type of data */
6460 if (data_type == 0x55) {
6463 type_len = mono_metadata_decode_blob_size (named, &named);
6464 type_name = g_malloc (type_len + 1);
6465 memcpy (type_name, named, type_len);
6466 type_name [type_len] = 0;
6468 /* FIXME: lookup the type and check type consistency */
6469 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6470 /* this seems to be the type of the element of the array */
6471 /* g_print ("skipping 0x%02x after prop\n", *named); */
6474 name_len = mono_metadata_decode_blob_size (named, &named);
6475 name = g_malloc (name_len + 1);
6476 memcpy (name, named, name_len);
6477 name [name_len] = 0;
6479 if (named_type == 0x53) {
6480 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6481 void *val = load_cattr_value (image, field->type, named, &named);
6482 mono_field_set_value (attr, field, val);
6483 if (!type_is_reference (field->type))
6485 } else if (named_type == 0x54) {
6488 MonoType *prop_type;
6490 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6491 /* can we have more that 1 arg in a custom attr named property? */
6492 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6493 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6494 mono_property_set_value (prop, attr, pparams, NULL);
6495 if (!type_is_reference (prop_type))
6496 g_free (pparams [0]);
6505 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6512 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6513 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6514 for (i = 0; i < cinfo->num_attrs; ++i) {
6515 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6516 mono_array_set (result, gpointer, i, attr);
6522 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6524 guint32 mtoken, i, len;
6525 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6527 MonoCustomAttrInfo *ainfo;
6528 GList *tmp, *list = NULL;
6531 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6533 i = mono_metadata_custom_attrs_from_index (image, idx);
6537 while (i < ca->rows) {
6538 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6540 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6543 len = g_list_length (list);
6546 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6547 ainfo->num_attrs = len;
6548 ainfo->image = image;
6549 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6550 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6551 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6552 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6553 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6554 mtoken |= MONO_TOKEN_METHOD_DEF;
6556 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6557 mtoken |= MONO_TOKEN_MEMBER_REF;
6560 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6563 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6564 if (!ainfo->attrs [i].ctor)
6565 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6566 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6567 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6568 ainfo->attrs [i].data = data;
6576 mono_custom_attrs_from_method (MonoMethod *method)
6578 MonoCustomAttrInfo *cinfo;
6581 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6583 idx = find_method_index (method);
6584 idx <<= MONO_CUSTOM_ATTR_BITS;
6585 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6586 return mono_custom_attrs_from_index (method->klass->image, idx);
6590 mono_custom_attrs_from_class (MonoClass *klass)
6592 MonoCustomAttrInfo *cinfo;
6595 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6597 idx = mono_metadata_token_index (klass->type_token);
6598 idx <<= MONO_CUSTOM_ATTR_BITS;
6599 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6600 return mono_custom_attrs_from_index (klass->image, idx);
6604 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6606 MonoCustomAttrInfo *cinfo;
6609 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6611 idx = 1; /* there is only one assembly */
6612 idx <<= MONO_CUSTOM_ATTR_BITS;
6613 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6614 return mono_custom_attrs_from_index (assembly->image, idx);
6617 static MonoCustomAttrInfo*
6618 mono_custom_attrs_from_module (MonoImage *image)
6620 MonoCustomAttrInfo *cinfo;
6623 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6625 idx = 1; /* there is only one module */
6626 idx <<= MONO_CUSTOM_ATTR_BITS;
6627 idx |= MONO_CUSTOM_ATTR_MODULE;
6628 return mono_custom_attrs_from_index (image, idx);
6632 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6634 MonoCustomAttrInfo *cinfo;
6637 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6639 idx = find_property_index (klass, property);
6640 idx <<= MONO_CUSTOM_ATTR_BITS;
6641 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6642 return mono_custom_attrs_from_index (klass->image, idx);
6646 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6648 MonoCustomAttrInfo *cinfo;
6651 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6653 idx = find_event_index (klass, event);
6654 idx <<= MONO_CUSTOM_ATTR_BITS;
6655 idx |= MONO_CUSTOM_ATTR_EVENT;
6656 return mono_custom_attrs_from_index (klass->image, idx);
6660 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6662 MonoCustomAttrInfo *cinfo;
6665 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6667 idx = find_field_index (klass, field);
6668 idx <<= MONO_CUSTOM_ATTR_BITS;
6669 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6670 return mono_custom_attrs_from_index (klass->image, idx);
6674 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6677 guint32 i, idx, method_index;
6678 guint32 param_list, param_last, param_pos, found;
6680 MonoReflectionMethodAux *aux;
6682 if (method->klass->image->dynamic) {
6683 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6684 if (!aux || !aux->param_cattr)
6686 return aux->param_cattr [param];
6689 image = method->klass->image;
6690 method_index = find_method_index (method);
6691 ca = &image->tables [MONO_TABLE_METHOD];
6693 if (method->klass->generic_inst || method->klass->generic_container ||
6694 method->signature->generic_param_count) {
6695 /* FIXME FIXME FIXME */
6699 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6700 if (method_index == ca->rows) {
6701 ca = &image->tables [MONO_TABLE_PARAM];
6702 param_last = ca->rows + 1;
6704 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6705 ca = &image->tables [MONO_TABLE_PARAM];
6708 for (i = param_list; i < param_last; ++i) {
6709 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6710 if (param_pos == param) {
6718 idx <<= MONO_CUSTOM_ATTR_BITS;
6719 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6720 return mono_custom_attrs_from_index (image, idx);
6724 * mono_reflection_get_custom_attrs:
6725 * @obj: a reflection object handle
6727 * Return an array with all the custom attributes defined of the
6728 * reflection handle @obj. The objects are fully build.
6731 mono_reflection_get_custom_attrs (MonoObject *obj)
6735 MonoCustomAttrInfo *cinfo = NULL;
6737 MONO_ARCH_SAVE_REGS;
6739 klass = obj->vtable->klass;
6740 if (klass == mono_defaults.monotype_class) {
6741 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6742 klass = mono_class_from_mono_type (rtype->type);
6743 cinfo = mono_custom_attrs_from_class (klass);
6744 } else if (strcmp ("Assembly", klass->name) == 0) {
6745 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6746 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6747 } else if (strcmp ("Module", klass->name) == 0) {
6748 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6749 cinfo = mono_custom_attrs_from_module (module->image);
6750 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6751 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6752 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6753 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6754 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6755 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6756 } else if (strcmp ("MonoField", klass->name) == 0) {
6757 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6758 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6759 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6760 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6761 cinfo = mono_custom_attrs_from_method (rmethod->method);
6762 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6763 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6764 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6765 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6766 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6767 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6768 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6769 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6770 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6771 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6772 } else { /* handle other types here... */
6773 g_error ("get custom attrs not yet supported for %s", klass->name);
6777 result = mono_custom_attrs_construct (cinfo);
6779 mono_custom_attrs_free (cinfo);
6781 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6782 result = mono_array_new (mono_domain_get (), klass, 0);
6788 static MonoMethodSignature*
6789 parameters_to_signature (MonoArray *parameters) {
6790 MonoMethodSignature *sig;
6793 count = parameters? mono_array_length (parameters): 0;
6795 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6796 sig->param_count = count;
6797 sig->sentinelpos = -1; /* FIXME */
6798 for (i = 0; i < count; ++i) {
6799 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6800 sig->params [i] = pt->type;
6805 static MonoMethodSignature*
6806 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6807 MonoMethodSignature *sig;
6809 sig = parameters_to_signature (ctor->parameters);
6810 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6811 sig->ret = &mono_defaults.void_class->byval_arg;
6815 static MonoMethodSignature*
6816 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6817 MonoMethodSignature *sig;
6819 sig = parameters_to_signature (method->parameters);
6820 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6821 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6822 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6826 static MonoMethodSignature*
6827 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6828 MonoMethodSignature *sig;
6830 sig = parameters_to_signature (method->parameters);
6831 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6832 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6833 sig->generic_param_count = 0;
6838 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6840 MonoClass *klass = mono_object_class (prop);
6841 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6842 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6843 *name = mono_string_to_utf8 (pb->name);
6844 *type = pb->type->type;
6846 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6847 *name = g_strdup (p->property->name);
6848 if (p->property->get)
6849 *type = p->property->get->signature->ret;
6851 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6856 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6858 MonoClass *klass = mono_object_class (field);
6859 if (strcmp (klass->name, "FieldBuilder") == 0) {
6860 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6861 *name = mono_string_to_utf8 (fb->name);
6862 *type = fb->type->type;
6864 MonoReflectionField *f = (MonoReflectionField *)field;
6865 *name = g_strdup (f->field->name);
6866 *type = f->field->type;
6871 * Encode a value in a custom attribute stream of bytes.
6872 * The value to encode is either supplied as an object in argument val
6873 * (valuetypes are boxed), or as a pointer to the data in the
6875 * @type represents the type of the value
6876 * @buffer is the start of the buffer
6877 * @p the current position in the buffer
6878 * @buflen contains the size of the buffer and is used to return the new buffer size
6879 * if this needs to be realloced.
6880 * @retbuffer and @retp return the start and the position of the buffer
6883 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6885 MonoTypeEnum simple_type;
6887 if ((p-buffer) + 10 >= *buflen) {
6890 newbuf = g_realloc (buffer, *buflen);
6891 p = newbuf + (p-buffer);
6895 argval = ((char*)arg + sizeof (MonoObject));
6896 simple_type = type->type;
6898 switch (simple_type) {
6899 case MONO_TYPE_BOOLEAN:
6904 case MONO_TYPE_CHAR:
6907 swap_with_size (p, argval, 2, 1);
6913 swap_with_size (p, argval, 4, 1);
6919 swap_with_size (p, argval, 8, 1);
6922 case MONO_TYPE_VALUETYPE:
6923 if (type->data.klass->enumtype) {
6924 simple_type = type->data.klass->enum_basetype->type;
6927 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6930 case MONO_TYPE_STRING: {
6937 str = mono_string_to_utf8 ((MonoString*)arg);
6938 slen = strlen (str);
6939 if ((p-buffer) + 10 + slen >= *buflen) {
6943 newbuf = g_realloc (buffer, *buflen);
6944 p = newbuf + (p-buffer);
6947 mono_metadata_encode_value (slen, p, &p);
6948 memcpy (p, str, slen);
6953 case MONO_TYPE_CLASS: {
6961 k = mono_object_class (arg);
6962 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6963 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6964 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6966 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6967 slen = strlen (str);
6968 if ((p-buffer) + 10 + slen >= *buflen) {
6972 newbuf = g_realloc (buffer, *buflen);
6973 p = newbuf + (p-buffer);
6976 mono_metadata_encode_value (slen, p, &p);
6977 memcpy (p, str, slen);
6982 case MONO_TYPE_SZARRAY: {
6984 MonoClass *eclass, *arg_eclass;
6987 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6990 len = mono_array_length ((MonoArray*)arg);
6992 *p++ = (len >> 8) & 0xff;
6993 *p++ = (len >> 16) & 0xff;
6994 *p++ = (len >> 24) & 0xff;
6996 *retbuffer = buffer;
6997 eclass = type->data.klass;
6998 arg_eclass = mono_object_class (arg)->element_class;
6999 if (eclass->valuetype && arg_eclass->valuetype) {
7000 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7001 int elsize = mono_class_array_element_size (eclass);
7002 for (i = 0; i < len; ++i) {
7003 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7007 for (i = 0; i < len; ++i) {
7008 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7013 /* it may be a boxed value or a Type */
7014 case MONO_TYPE_OBJECT: {
7015 MonoClass *klass = mono_object_class (arg);
7019 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7022 } else if (klass->enumtype) {
7024 } else if (klass == mono_defaults.string_class) {
7025 simple_type = MONO_TYPE_STRING;
7028 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7029 *p++ = simple_type = klass->byval_arg.type;
7032 g_error ("unhandled type in custom attr");
7034 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7035 slen = strlen (str);
7036 if ((p-buffer) + 10 + slen >= *buflen) {
7040 newbuf = g_realloc (buffer, *buflen);
7041 p = newbuf + (p-buffer);
7044 mono_metadata_encode_value (slen, p, &p);
7045 memcpy (p, str, slen);
7048 simple_type = klass->enum_basetype->type;
7052 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7055 *retbuffer = buffer;
7059 * mono_reflection_get_custom_attrs_blob:
7060 * @ctor: custom attribute constructor
7061 * @ctorArgs: arguments o the constructor
7067 * Creates the blob of data that needs to be saved in the metadata and that represents
7068 * the custom attributed described by @ctor, @ctorArgs etc.
7069 * Returns: a Byte array representing the blob of data.
7072 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7075 MonoMethodSignature *sig;
7080 MONO_ARCH_SAVE_REGS;
7082 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7083 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7085 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7087 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7089 p = buffer = g_malloc (buflen);
7090 /* write the prolog */
7093 for (i = 0; i < sig->param_count; ++i) {
7094 arg = mono_array_get (ctorArgs, MonoObject*, i);
7095 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7099 i += mono_array_length (properties);
7101 i += mono_array_length (fields);
7103 *p++ = (i >> 8) & 0xff;
7106 for (i = 0; i < mono_array_length (properties); ++i) {
7111 prop = mono_array_get (properties, gpointer, i);
7112 get_prop_name_and_type (prop, &pname, &ptype);
7113 *p++ = 0x54; /* PROPERTY signature */
7115 /* Preallocate a large enough buffer */
7116 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7117 char *str = type_get_qualified_name (ptype, NULL);
7123 len += strlen (pname);
7125 if ((p-buffer) + 20 + len >= buflen) {
7129 newbuf = g_realloc (buffer, buflen);
7130 p = newbuf + (p-buffer);
7134 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7135 char *str = type_get_qualified_name (ptype, NULL);
7136 int slen = strlen (str);
7140 * This seems to be optional...
7143 mono_metadata_encode_value (slen, p, &p);
7144 memcpy (p, str, slen);
7148 mono_metadata_encode_value (ptype->type, p, &p);
7149 if (ptype->type == MONO_TYPE_SZARRAY)
7150 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7152 len = strlen (pname);
7153 mono_metadata_encode_value (len, p, &p);
7154 memcpy (p, pname, len);
7156 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7163 for (i = 0; i < mono_array_length (fields); ++i) {
7168 field = mono_array_get (fields, gpointer, i);
7169 get_field_name_and_type (field, &fname, &ftype);
7170 *p++ = 0x53; /* FIELD signature */
7171 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7172 char *str = type_get_qualified_name (ftype, NULL);
7173 int slen = strlen (str);
7174 if ((p-buffer) + 10 + slen >= buflen) {
7178 newbuf = g_realloc (buffer, buflen);
7179 p = newbuf + (p-buffer);
7184 * This seems to be optional...
7187 mono_metadata_encode_value (slen, p, &p);
7188 memcpy (p, str, slen);
7192 mono_metadata_encode_value (ftype->type, p, &p);
7193 if (ftype->type == MONO_TYPE_SZARRAY)
7194 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7196 len = strlen (fname);
7197 mono_metadata_encode_value (len, p, &p);
7198 memcpy (p, fname, len);
7200 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7205 g_assert (p - buffer <= buflen);
7206 buflen = p - buffer;
7207 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7208 p = mono_array_addr (result, char, 0);
7209 memcpy (p, buffer, buflen);
7211 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7217 * mono_reflection_setup_internal_class:
7218 * @tb: a TypeBuilder object
7220 * Creates a MonoClass that represents the TypeBuilder.
7221 * This is a trick that lets us simplify a lot of reflection code
7222 * (and will allow us to support Build and Run assemblies easier).
7225 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7227 MonoClass *klass, *parent;
7229 MONO_ARCH_SAVE_REGS;
7232 /* check so we can compile corlib correctly */
7233 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7234 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7235 parent = tb->parent->type->data.klass;
7237 parent = my_mono_class_from_mono_type (tb->parent->type);
7243 /* the type has already being created: it means we just have to change the parent */
7244 if (tb->type.type) {
7245 klass = mono_class_from_mono_type (tb->type.type);
7246 klass->parent = NULL;
7247 /* fool mono_class_setup_parent */
7248 g_free (klass->supertypes);
7249 klass->supertypes = NULL;
7250 mono_class_setup_parent (klass, parent);
7251 mono_class_setup_mono_type (klass);
7255 klass = g_new0 (MonoClass, 1);
7257 klass->image = &tb->module->dynamic_image->image;
7259 klass->inited = 1; /* we lie to the runtime */
7260 klass->name = mono_string_to_utf8 (tb->name);
7261 klass->name_space = mono_string_to_utf8 (tb->nspace);
7262 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7263 klass->flags = tb->attrs;
7265 klass->element_class = klass;
7266 klass->reflection_info = tb; /* need to pin. */
7268 /* Put into cache so mono_class_get () will find it */
7269 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7271 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7272 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7274 if (parent != NULL) {
7275 mono_class_setup_parent (klass, parent);
7276 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7277 const char *old_n = klass->name;
7278 /* trick to get relative numbering right when compiling corlib */
7279 klass->name = "BuildingObject";
7280 mono_class_setup_parent (klass, mono_defaults.object_class);
7281 klass->name = old_n;
7284 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7285 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7286 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7287 klass->instance_size = sizeof (MonoObject);
7288 klass->size_inited = 1;
7289 mono_class_setup_vtable (klass, NULL, 0);
7292 mono_class_setup_mono_type (klass);
7294 mono_class_setup_supertypes (klass);
7297 * FIXME: handle interfaces.
7300 tb->type.type = &klass->byval_arg;
7302 if (tb->nesting_type) {
7303 g_assert (tb->nesting_type->type);
7304 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7307 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7311 * mono_reflection_setup_generic_class:
7312 * @tb: a TypeBuilder object
7314 * Setup the generic class before adding the first generic parameter.
7317 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7321 MONO_ARCH_SAVE_REGS;
7323 klass = my_mono_class_from_mono_type (tb->type.type);
7324 if (tb->generic_container)
7327 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7328 tb->generic_container->klass = klass;
7330 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7331 tb->generic_container->context->container = tb->generic_container;
7335 * mono_reflection_create_generic_class:
7336 * @tb: a TypeBuilder object
7338 * Creates the generic class after all generic parameters have been added.
7341 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7346 MONO_ARCH_SAVE_REGS;
7348 klass = my_mono_class_from_mono_type (tb->type.type);
7350 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7352 if (klass->generic_container || (count == 0))
7355 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7357 klass->generic_container = tb->generic_container;
7359 klass->generic_container->type_argc = count;
7360 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7362 for (i = 0; i < count; i++) {
7363 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7364 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7365 g_assert (klass->generic_container->type_params [i].owner);
7370 * mono_reflection_create_internal_class:
7371 * @tb: a TypeBuilder object
7373 * Actually create the MonoClass that is associated with the TypeBuilder.
7376 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7380 MONO_ARCH_SAVE_REGS;
7382 klass = my_mono_class_from_mono_type (tb->type.type);
7384 if (klass->enumtype && klass->enum_basetype == NULL) {
7385 MonoReflectionFieldBuilder *fb;
7388 g_assert (tb->fields != NULL);
7389 g_assert (mono_array_length (tb->fields) >= 1);
7391 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7393 klass->enum_basetype = fb->type->type;
7394 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7395 if (!klass->element_class)
7396 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7399 * get the element_class from the current corlib.
7401 ec = default_class_from_mono_type (klass->enum_basetype);
7402 klass->instance_size = ec->instance_size;
7403 klass->size_inited = 1;
7405 * this is almost safe to do with enums and it's needed to be able
7406 * to create objects of the enum type (for use in SetConstant).
7408 /* FIXME: Does this mean enums can't have method overrides ? */
7409 mono_class_setup_vtable (klass, NULL, 0);
7413 static MonoMarshalSpec*
7414 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7415 MonoReflectionMarshal *minfo)
7417 MonoMarshalSpec *res;
7419 res = g_new0 (MonoMarshalSpec, 1);
7420 res->native = minfo->type;
7422 switch (minfo->type) {
7423 case MONO_NATIVE_LPARRAY:
7424 res->data.array_data.elem_type = minfo->eltype;
7425 res->data.array_data.param_num = 0; /* Not yet */
7426 res->data.array_data.num_elem = minfo->count;
7429 case MONO_NATIVE_BYVALTSTR:
7430 case MONO_NATIVE_BYVALARRAY:
7431 res->data.array_data.num_elem = minfo->count;
7434 case MONO_NATIVE_CUSTOM:
7435 if (minfo->marshaltyperef)
7436 res->data.custom_data.custom_name =
7437 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7439 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7449 MonoReflectionMarshal*
7450 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7451 MonoMarshalSpec *spec)
7453 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7454 MonoReflectionMarshal *minfo;
7457 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7458 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7459 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7460 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7463 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7464 minfo->type = spec->native;
7466 switch (minfo->type) {
7467 case MONO_NATIVE_LPARRAY:
7468 minfo->eltype = spec->data.array_data.elem_type;
7469 minfo->count = spec->data.array_data.num_elem;
7472 case MONO_NATIVE_BYVALTSTR:
7473 case MONO_NATIVE_BYVALARRAY:
7474 minfo->count = spec->data.array_data.num_elem;
7477 case MONO_NATIVE_CUSTOM:
7478 if (spec->data.custom_data.custom_name) {
7479 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7481 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7483 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7485 if (spec->data.custom_data.cookie)
7486 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7497 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7498 ReflectionMethodBuilder *rmb,
7499 MonoMethodSignature *sig)
7502 MonoMethodNormal *pm;
7503 MonoMarshalSpec **specs;
7504 MonoReflectionMethodAux *method_aux;
7507 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7508 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7509 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7511 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7513 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7515 pm = (MonoMethodNormal*)m;
7518 m->flags = rmb->attrs;
7519 m->iflags = rmb->iattrs;
7520 m->name = mono_string_to_utf8 (rmb->name);
7524 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7526 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7527 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7530 m->signature->pinvoke = 1;
7531 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7532 m->signature->pinvoke = 1;
7534 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7536 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7537 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7539 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7541 if (klass->image->dynamic)
7542 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7545 } else if (!m->klass->dummy &&
7546 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7547 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7548 MonoMethodHeader *header;
7550 gint32 max_stack, i;
7551 gint32 num_locals = 0;
7552 gint32 num_clauses = 0;
7556 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7557 code_size = rmb->ilgen->code_len;
7558 max_stack = rmb->ilgen->max_stack;
7559 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7560 if (rmb->ilgen->ex_handlers)
7561 num_clauses = method_count_clauses (rmb->ilgen);
7564 code = mono_array_addr (rmb->code, guint8, 0);
7565 code_size = mono_array_length (rmb->code);
7566 /* we probably need to run a verifier on the code... */
7576 header = g_malloc0 (sizeof (MonoMethodHeader) +
7577 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7578 header->code_size = code_size;
7579 header->code = g_malloc (code_size);
7580 memcpy ((char*)header->code, code, code_size);
7581 header->max_stack = max_stack;
7582 header->init_locals = rmb->init_locals;
7583 header->num_locals = num_locals;
7585 for (i = 0; i < num_locals; ++i) {
7586 MonoReflectionLocalBuilder *lb =
7587 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7589 header->locals [i] = g_new0 (MonoType, 1);
7590 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7593 header->num_clauses = num_clauses;
7595 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7596 rmb->ilgen, num_clauses);
7599 pm->header = header;
7602 if (rmb->generic_params) {
7603 int count = mono_array_length (rmb->generic_params);
7604 MonoGenericContainer *container;
7606 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7607 container->type_argc = count;
7608 container->type_params = g_new0 (MonoGenericParam, count);
7610 for (i = 0; i < count; i++) {
7611 MonoReflectionGenericParam *gp =
7612 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7614 container->type_params [i] = *gp->type.type->data.generic_param;
7619 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7622 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7624 for (i = 0; i < rmb->nrefs; ++i)
7625 mw->data = g_list_append (mw->data, rmb->refs [i]);
7630 /* Parameter info */
7633 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7634 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7635 for (i = 0; i <= m->signature->param_count; ++i) {
7636 MonoReflectionParamBuilder *pb;
7637 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7639 m->signature->params [i - 1]->attrs = pb->attrs;
7641 if (pb->def_value) {
7642 MonoDynamicImage *assembly;
7643 guint32 idx, def_type, len;
7647 if (!method_aux->param_defaults)
7648 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7649 assembly = (MonoDynamicImage*)klass->image;
7650 idx = encode_constant (assembly, pb->def_value, &def_type);
7651 /* Copy the data from the blob since it might get realloc-ed */
7652 p = assembly->blob.data + idx;
7653 len = mono_metadata_decode_blob_size (p, &p2);
7655 method_aux->param_defaults [i] = g_malloc (len);
7656 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7660 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7662 if (!method_aux->param_cattr)
7663 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7664 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7670 /* Parameter marshalling */
7673 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7674 MonoReflectionParamBuilder *pb;
7675 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7676 if (pb->marshal_info) {
7678 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7679 specs [pb->position] =
7680 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7684 if (specs != NULL) {
7686 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7687 method_aux->param_marshall = specs;
7690 if (klass->image->dynamic && method_aux)
7691 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7697 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7699 ReflectionMethodBuilder rmb;
7700 MonoMethodSignature *sig;
7702 sig = ctor_builder_to_signature (mb);
7704 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7706 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7707 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7709 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7710 /* ilgen is no longer needed */
7718 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7720 ReflectionMethodBuilder rmb;
7721 MonoMethodSignature *sig;
7723 sig = method_builder_to_signature (mb);
7725 reflection_methodbuilder_from_method_builder (&rmb, mb);
7727 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7728 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7730 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7731 /* ilgen is no longer needed */
7737 static MonoClassField*
7738 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7740 MonoClassField *field;
7747 field = g_new0 (MonoClassField, 1);
7749 field->name = mono_string_to_utf8 (fb->name);
7751 /* FIXME: handle type modifiers */
7752 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7753 field->type->attrs = fb->attrs;
7755 field->type = fb->type->type;
7757 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7758 field->data = mono_array_addr (fb->rva_data, char, 0);
7759 if (fb->offset != -1)
7760 field->offset = fb->offset;
7761 field->parent = klass;
7763 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7765 if (fb->def_value) {
7766 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7767 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7768 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7769 /* Copy the data from the blob since it might get realloc-ed */
7770 p = assembly->blob.data + idx;
7771 len = mono_metadata_decode_blob_size (p, &p2);
7773 field->data = g_malloc (len);
7774 memcpy ((gpointer)field->data, p, len);
7781 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7783 MonoClass *klass, *gklass;
7784 MonoReflectionTypeBuilder *tb = NULL;
7785 MonoGenericInst *ginst, *cached;
7790 klass = mono_class_from_mono_type (type->type);
7791 if (!klass->generic_container && !klass->generic_inst &&
7792 !(klass->nested_in && klass->nested_in->generic_container))
7795 mono_loader_lock ();
7797 domain = mono_object_domain (type);
7799 ginst = g_new0 (MonoGenericInst, 1);
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 if (klass->generic_inst) {
7812 MonoGenericInst *kginst = klass->generic_inst;
7813 MonoGenericInst *oginst = ginst;
7815 oginst->context = g_new0 (MonoGenericContext, 1);
7816 oginst->context->ginst = oginst;
7818 ginst = g_new0 (MonoGenericInst, 1);
7820 ginst->type_argc = kginst->type_argc;
7821 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7823 for (i = 0; i < ginst->type_argc; i++) {
7824 MonoType *t = kginst->type_argv [i];
7826 t = mono_class_inflate_generic_type (t, oginst->context);
7828 if (!ginst->is_open)
7829 ginst->is_open = mono_class_is_open_constructed_type (t);
7831 ginst->type_argv [i] = t;
7834 ginst->generic_type = kginst->generic_type;
7837 geninst = g_new0 (MonoType, 1);
7838 geninst->type = MONO_TYPE_GENERICINST;
7840 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7843 mono_loader_unlock ();
7844 geninst->data.generic_inst = cached;
7848 gklass = mono_class_from_mono_type (ginst->generic_type);
7849 g_assert ((ginst->container = gklass->generic_container) != NULL);
7851 geninst->data.generic_inst = ginst;
7853 ginst->context = g_new0 (MonoGenericContext, 1);
7854 ginst->context->ginst = ginst;
7856 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7857 tb = (MonoReflectionTypeBuilder *) type;
7859 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7860 ginst->is_dynamic = TRUE;
7861 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7862 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7863 MonoReflectionType *rgt = rgi->generic_type;
7865 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7866 tb = (MonoReflectionTypeBuilder *) rgt;
7868 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7869 ginst->is_dynamic = TRUE;
7871 icount = klass->interface_count;
7874 ginst->ifaces = g_new0 (MonoType *, icount);
7875 ginst->count_ifaces = icount;
7877 for (i = 0; i < icount; i++) {
7878 MonoReflectionType *itype;
7881 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7883 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7884 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7885 if (!ginst->ifaces [i])
7886 ginst->ifaces [i] = itype->type;
7889 mono_class_create_generic (ginst);
7891 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7893 mono_loader_unlock ();
7899 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7901 MonoClass *klass, *pklass = NULL;
7902 MonoReflectionType *parent = NULL;
7904 MonoReflectionTypeBuilder *tb = NULL;
7905 MonoGenericInst *ginst;
7908 domain = mono_object_domain (type);
7909 klass = mono_class_from_mono_type (type->type);
7911 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7912 tb = (MonoReflectionTypeBuilder *) type;
7915 parent = tb->parent;
7916 pklass = mono_class_from_mono_type (parent->type);
7919 pklass = klass->parent;
7921 parent = mono_type_get_object (domain, &pklass->byval_arg);
7922 else if (klass->generic_inst && klass->generic_inst->parent) {
7923 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7924 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7928 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7932 ginst = geninst->data.generic_inst;
7934 if (pklass && pklass->generic_inst)
7935 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7940 MonoReflectionMethod*
7941 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7943 MonoMethod *method, *inflated;
7944 MonoReflectionMethodBuilder *mb = NULL;
7945 MonoGenericMethod *gmethod;
7946 MonoGenericContext *context;
7949 MONO_ARCH_SAVE_REGS;
7950 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7951 MonoReflectionTypeBuilder *tb;
7954 mb = (MonoReflectionMethodBuilder *) rmethod;
7955 tb = (MonoReflectionTypeBuilder *) mb->type;
7956 klass = mono_class_from_mono_type (tb->type.type);
7958 method = methodbuilder_to_mono_method (klass, mb);
7960 method = rmethod->method;
7963 count = method->signature->generic_param_count;
7964 if (count != mono_array_length (types))
7967 gmethod = g_new0 (MonoGenericMethod, 1);
7968 gmethod->mtype_argc = count;
7969 gmethod->mtype_argv = g_new0 (MonoType *, count);
7970 for (i = 0; i < count; i++) {
7971 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7972 gmethod->mtype_argv [i] = garg->type;
7975 gmethod->reflection_info = rmethod;
7977 context = g_new0 (MonoGenericContext, 1);
7978 context->ginst = method->klass->generic_inst;
7979 context->gmethod = gmethod;
7981 inflated = mono_class_inflate_generic_method (method, context, NULL);
7983 return mono_method_get_object (
7984 mono_object_domain (rmethod), inflated, NULL);
7988 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7990 MonoGenericMethod *gmethod;
7991 MonoGenericInst *ginst;
7992 MonoGenericContext *context;
7995 ginst = type->type.type->data.generic_inst;
7997 gmethod = g_new0 (MonoGenericMethod, 1);
7998 gmethod->reflection_info = obj;
8000 gmethod->mtype_argc = method->signature->generic_param_count;
8001 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
8003 for (i = 0; i < gmethod->mtype_argc; i++) {
8004 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8005 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8007 g_assert (gparam->pklass);
8008 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8011 context = g_new0 (MonoGenericContext, 1);
8012 context->ginst = ginst;
8013 context->gmethod = gmethod;
8015 return mono_class_inflate_generic_method (method, context, ginst->klass);
8019 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8024 klass = mono_class_from_mono_type (type->type.type);
8026 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8027 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8028 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8029 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8030 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8031 method = ((MonoReflectionMethod *) obj)->method;
8033 method = NULL; /* prevent compiler warning */
8034 g_assert_not_reached ();
8037 return inflate_mono_method (type, method, obj);
8041 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8042 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8044 MonoGenericInst *ginst;
8045 MonoDynamicGenericInst *dginst;
8046 MonoClass *klass, *gklass, *pklass;
8049 MONO_ARCH_SAVE_REGS;
8051 klass = mono_class_from_mono_type (type->type.type);
8052 ginst = type->type.type->data.generic_inst;
8054 if (ginst->initialized)
8057 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8059 gklass = mono_class_from_mono_type (ginst->generic_type);
8060 mono_class_init (gklass);
8063 pklass = mono_class_from_mono_type (ginst->parent);
8065 pklass = gklass->parent;
8067 mono_class_setup_parent (klass, pklass);
8069 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8070 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8071 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8072 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8073 dginst->count_events = events ? mono_array_length (events) : 0;
8075 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8076 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8077 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8078 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8079 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8081 for (i = 0; i < dginst->count_methods; i++) {
8082 MonoObject *obj = mono_array_get (methods, gpointer, i);
8084 dginst->methods [i] = inflate_method (type, obj);
8087 for (i = 0; i < dginst->count_ctors; i++) {
8088 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8090 dginst->ctors [i] = inflate_method (type, obj);
8093 for (i = 0; i < dginst->count_fields; i++) {
8094 MonoObject *obj = mono_array_get (fields, gpointer, i);
8095 MonoClassField *field;
8096 MonoInflatedField *ifield;
8098 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8099 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8100 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8101 field = ((MonoReflectionField *) obj)->field;
8103 field = NULL; /* prevent compiler warning */
8104 g_assert_not_reached ();
8107 ifield = g_new0 (MonoInflatedField, 1);
8108 ifield->generic_type = field->type;
8109 ifield->reflection_info = obj;
8111 dginst->fields [i] = *field;
8112 dginst->fields [i].generic_info = ifield;
8113 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8116 for (i = 0; i < dginst->count_properties; i++) {
8117 MonoObject *obj = mono_array_get (properties, gpointer, i);
8118 MonoProperty *property = &dginst->properties [i];
8120 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8121 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8123 property->parent = klass;
8124 property->attrs = pb->attrs;
8125 property->name = mono_string_to_utf8 (pb->name);
8127 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8129 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8130 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8131 *property = *((MonoReflectionProperty *) obj)->property;
8134 property->get = inflate_mono_method (type, property->get, NULL);
8136 property->set = inflate_mono_method (type, property->set, NULL);
8138 g_assert_not_reached ();
8141 for (i = 0; i < dginst->count_events; i++) {
8142 MonoObject *obj = mono_array_get (events, gpointer, i);
8143 MonoEvent *event = &dginst->events [i];
8145 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8146 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8148 event->parent = klass;
8149 event->attrs = eb->attrs;
8150 event->name = mono_string_to_utf8 (eb->name);
8152 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8153 if (eb->remove_method)
8154 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8155 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8156 *event = *((MonoReflectionEvent *) obj)->event;
8159 event->add = inflate_mono_method (type, event->add, NULL);
8161 event->remove = inflate_mono_method (type, event->remove, NULL);
8163 g_assert_not_reached ();
8166 ginst->initialized = TRUE;
8170 ensure_runtime_vtable (MonoClass *klass)
8172 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8173 int i, num, j, onum;
8174 MonoMethod **overrides;
8176 if (!tb || klass->wastypebuilder)
8179 ensure_runtime_vtable (klass->parent);
8181 num = tb->ctors? mono_array_length (tb->ctors): 0;
8182 num += tb->num_methods;
8183 klass->method.count = num;
8184 klass->methods = g_new (MonoMethod*, num);
8185 num = tb->ctors? mono_array_length (tb->ctors): 0;
8186 for (i = 0; i < num; ++i)
8187 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8188 num = tb->num_methods;
8190 for (i = 0; i < num; ++i)
8191 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8193 if (tb->interfaces) {
8194 klass->interface_count = mono_array_length (tb->interfaces);
8195 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8196 for (i = 0; i < klass->interface_count; ++i) {
8197 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8198 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8202 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8203 for (i = 0; i < klass->method.count; ++i)
8204 klass->methods [i]->slot = i;
8209 for (i = 0; i < tb->num_methods; ++i) {
8210 MonoReflectionMethodBuilder *mb =
8211 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8212 if (mb->override_method)
8217 overrides = g_new0 (MonoMethod*, onum * 2);
8221 for (i = 0; i < tb->num_methods; ++i) {
8222 MonoReflectionMethodBuilder *mb =
8223 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8224 if (mb->override_method) {
8225 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8226 overrides [onum * 2] =
8227 mb->override_method->method;
8228 overrides [onum * 2 + 1] =
8231 g_assert (mb->mhandle);
8238 mono_class_setup_vtable (klass, overrides, onum);
8243 typebuilder_setup_fields (MonoClass *klass)
8245 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8246 MonoReflectionFieldBuilder *fb;
8247 MonoClassField *field;
8252 klass->field.count = tb->num_fields;
8253 klass->field.first = 0;
8254 klass->field.last = klass->field.count;
8256 if (!klass->field.count)
8259 klass->fields = g_new0 (MonoClassField, klass->field.count);
8261 for (i = 0; i < klass->field.count; ++i) {
8262 fb = mono_array_get (tb->fields, gpointer, i);
8263 field = &klass->fields [i];
8264 field->name = mono_string_to_utf8 (fb->name);
8266 /* FIXME: handle type modifiers */
8267 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8268 field->type->attrs = fb->attrs;
8270 field->type = fb->type->type;
8272 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8273 field->data = mono_array_addr (fb->rva_data, char, 0);
8274 if (fb->offset != -1)
8275 field->offset = fb->offset;
8276 field->parent = klass;
8278 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8280 if (fb->def_value) {
8281 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8282 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8283 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8284 /* Copy the data from the blob since it might get realloc-ed */
8285 p = assembly->blob.data + idx;
8286 len = mono_metadata_decode_blob_size (p, &p2);
8288 field->data = g_malloc (len);
8289 memcpy ((gpointer)field->data, p, len);
8292 mono_class_layout_fields (klass);
8296 typebuilder_setup_properties (MonoClass *klass)
8298 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8299 MonoReflectionPropertyBuilder *pb;
8302 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8303 klass->property.first = 0;
8304 klass->property.last = klass->property.count;
8306 klass->properties = g_new0 (MonoProperty, klass->property.count);
8307 for (i = 0; i < klass->property.count; ++i) {
8308 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8309 klass->properties [i].parent = klass;
8310 klass->properties [i].attrs = pb->attrs;
8311 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8313 klass->properties [i].get = pb->get_method->mhandle;
8315 klass->properties [i].set = pb->set_method->mhandle;
8319 MonoReflectionEvent *
8320 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8322 MonoEvent *event = g_new0 (MonoEvent, 1);
8326 klass = my_mono_class_from_mono_type (tb->type.type);
8328 event->parent = klass;
8329 event->attrs = eb->attrs;
8330 event->name = mono_string_to_utf8 (eb->name);
8332 event->add = eb->add_method->mhandle;
8333 if (eb->remove_method)
8334 event->remove = eb->remove_method->mhandle;
8335 if (eb->raise_method)
8336 event->raise = eb->raise_method->mhandle;
8338 if (eb->other_methods) {
8339 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8340 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8341 MonoReflectionMethodBuilder *mb =
8342 mono_array_get (eb->other_methods,
8343 MonoReflectionMethodBuilder*, j);
8344 event->other [j] = mb->mhandle;
8348 return mono_event_get_object (mono_object_domain (tb), klass, event);
8352 typebuilder_setup_events (MonoClass *klass)
8354 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8355 MonoReflectionEventBuilder *eb;
8358 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8359 klass->event.first = 0;
8360 klass->event.last = klass->event.count;
8362 klass->events = g_new0 (MonoEvent, klass->event.count);
8363 for (i = 0; i < klass->event.count; ++i) {
8364 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8365 klass->events [i].parent = klass;
8366 klass->events [i].attrs = eb->attrs;
8367 klass->events [i].name = mono_string_to_utf8 (eb->name);
8369 klass->events [i].add = eb->add_method->mhandle;
8370 if (eb->remove_method)
8371 klass->events [i].remove = eb->remove_method->mhandle;
8372 if (eb->raise_method)
8373 klass->events [i].raise = eb->raise_method->mhandle;
8375 if (eb->other_methods) {
8376 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8377 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8378 MonoReflectionMethodBuilder *mb =
8379 mono_array_get (eb->other_methods,
8380 MonoReflectionMethodBuilder*, j);
8381 klass->events [i].other [j] = mb->mhandle;
8388 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8391 MonoReflectionType* res;
8394 MONO_ARCH_SAVE_REGS;
8396 klass = my_mono_class_from_mono_type (tb->type.type);
8398 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8401 * Fields to set in klass:
8402 * the various flags: delegate/unicode/contextbound etc.
8404 klass->flags = tb->attrs;
8406 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8407 /* No need to fully construct the type */
8408 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8410 /* enums are done right away */
8411 if (!klass->enumtype)
8412 ensure_runtime_vtable (klass);
8415 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8416 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8417 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8421 /* fields and object layout */
8422 if (klass->parent) {
8423 if (!klass->parent->size_inited)
8424 mono_class_init (klass->parent);
8425 klass->instance_size += klass->parent->instance_size;
8426 klass->class_size += klass->parent->class_size;
8427 klass->min_align = klass->parent->min_align;
8429 klass->instance_size = sizeof (MonoObject);
8430 klass->min_align = 1;
8433 /* FIXME: handle packing_size and instance_size */
8434 typebuilder_setup_fields (klass);
8436 typebuilder_setup_properties (klass);
8438 typebuilder_setup_events (klass);
8440 klass->wastypebuilder = TRUE;
8442 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8443 g_assert (res != (MonoReflectionType*)tb);
8448 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8450 MonoGenericParam *param;
8453 MONO_ARCH_SAVE_REGS;
8455 param = g_new0 (MonoGenericParam, 1);
8457 if (gparam->mbuilder) {
8458 if (!gparam->mbuilder->generic_container)
8459 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8460 param->owner = gparam->mbuilder->generic_container;
8461 } else if (gparam->tbuilder) {
8462 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8463 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8468 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8469 if (gparam->index >= count)
8472 container = nesting->generic_container;
8473 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8476 g_assert (container);
8477 param->owner = container;
8480 param->method = NULL;
8481 param->name = mono_string_to_utf8 (gparam->name);
8482 param->num = gparam->index;
8484 image = &gparam->tbuilder->module->dynamic_image->image;
8485 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8487 param->pklass->reflection_info = gparam;
8489 gparam->type.type = g_new0 (MonoType, 1);
8490 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8491 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8492 gparam->type.type->data.generic_param = param;
8496 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8498 MonoDynamicImage *assembly = sig->module->dynamic_image;
8499 guint32 na = mono_array_length (sig->arguments);
8504 MONO_ARCH_SAVE_REGS;
8506 p = buf = g_malloc (10 + na * 10);
8508 mono_metadata_encode_value (0x07, p, &p);
8509 mono_metadata_encode_value (na, p, &p);
8510 for (i = 0; i < na; ++i) {
8511 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8512 encode_reflection_type (assembly, type, p, &p);
8516 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8517 p = mono_array_addr (result, char, 0);
8518 memcpy (p, buf, buflen);
8525 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8527 MonoDynamicImage *assembly = sig->module->dynamic_image;
8528 guint32 na = mono_array_length (sig->arguments);
8533 MONO_ARCH_SAVE_REGS;
8535 p = buf = g_malloc (10 + na * 10);
8537 mono_metadata_encode_value (0x06, p, &p);
8538 for (i = 0; i < na; ++i) {
8539 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8540 encode_reflection_type (assembly, type, p, &p);
8544 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8545 p = mono_array_addr (result, char, 0);
8546 memcpy (p, buf, buflen);
8553 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8555 ReflectionMethodBuilder rmb;
8556 MonoMethodSignature *sig;
8559 sig = dynamic_method_to_signature (mb);
8561 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8564 * Resolve references.
8566 rmb.nrefs = mb->nrefs;
8567 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8568 for (i = 0; i < mb->nrefs; ++i) {
8569 gpointer ref = resolve_object (mb->module->image,
8570 mono_array_get (mb->refs, MonoObject*, i));
8573 mono_raise_exception (mono_get_exception_type_load (NULL));
8580 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8584 /* ilgen is no longer needed */
8589 * mono_reflection_lookup_dynamic_token:
8591 * Finish the Builder object pointed to by TOKEN and return the corresponding
8592 * runtime structure.
8595 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8597 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8600 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8603 return resolve_object (image, obj);
8607 resolve_object (MonoImage *image, MonoObject *obj)
8609 gpointer result = NULL;
8611 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8612 result = mono_string_intern ((MonoString*)obj);
8614 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8615 MonoReflectionType *tb = (MonoReflectionType*)obj;
8616 result = mono_class_from_mono_type (tb->type);
8618 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8619 result = ((MonoReflectionMethod*)obj)->method;
8621 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8622 result = ((MonoReflectionMethod*)obj)->method;
8624 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8625 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8626 result = mb->mhandle;
8628 /* Type is not yet created */
8629 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8631 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8634 * Hopefully this has been filled in by calling CreateType() on the
8638 * TODO: This won't work if the application finishes another
8639 * TypeBuilder instance instead of this one.
8641 result = mb->mhandle;
8643 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8644 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8646 result = cb->mhandle;
8648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8650 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8651 result = cb->mhandle;
8653 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8654 result = ((MonoReflectionField*)obj)->field;
8656 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8657 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8658 result = fb->handle;
8661 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8663 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8664 result = fb->handle;
8666 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8667 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8670 klass = tb->type.type->data.klass;
8671 if (klass->wastypebuilder) {
8672 /* Already created */
8676 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8677 result = tb->type.type->data.klass;
8680 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8681 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8682 MonoMethodSignature *sig;
8685 if (helper->arguments)
8686 nargs = mono_array_length (helper->arguments);
8690 sig = mono_metadata_signature_alloc (image, nargs);
8691 sig->explicit_this = helper->call_conv & 64;
8692 sig->hasthis = helper->call_conv & 32;
8694 if (helper->call_conv == 0) /* unmanaged */
8695 sig->call_convention = helper->unmanaged_call_conv - 1;
8697 if (helper->call_conv & 0x02)
8698 sig->call_convention = MONO_CALL_VARARG;
8700 sig->call_convention = MONO_CALL_DEFAULT;
8702 sig->param_count = nargs;
8703 /* TODO: Copy type ? */
8704 sig->ret = helper->return_type->type;
8705 for (i = 0; i < nargs; ++i) {
8706 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8707 sig->params [i] = rt->type;
8712 g_print (obj->vtable->klass->name);
8713 g_assert_not_reached ();