2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
160 alloc_table (MonoDynamicTable *table, guint nrows)
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows) {
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
169 table->alloc_rows *= 2;
173 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
175 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
180 make_room_in_stream (MonoDynamicStream *stream, int size)
182 while (stream->alloc_size <= size) {
183 if (stream->alloc_size < 4096)
184 stream->alloc_size = 4096;
186 stream->alloc_size *= 2;
189 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
191 stream->data = ALLOC_ATOMIC (stream->alloc_size);
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
199 gpointer oldkey, oldval;
201 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202 return GPOINTER_TO_UINT (oldval);
204 len = strlen (str) + 1;
206 if (idx + len > sh->alloc_size)
207 make_room_in_stream (sh, idx + len);
210 * We strdup the string even if we already copy them in sh->data
211 * so that the string pointers in the hash remain valid even if
212 * we need to realloc sh->data. We may want to avoid that later.
214 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215 memcpy (sh->data + idx, str, len);
221 string_heap_init (MonoDynamicStream *sh)
224 sh->alloc_size = 4096;
225 sh->data = ALLOC_ATOMIC (4096);
226 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227 string_heap_insert (sh, "");
230 #if 0 /* never used */
232 string_heap_free (MonoDynamicStream *sh)
234 FREE_ATOMIC (sh->data);
235 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236 g_hash_table_destroy (sh->hash);
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memcpy (stream->data + stream->index, data, len);
248 stream->index += len;
250 * align index? Not without adding an additional param that controls it since
251 * we may store a blob value in pieces.
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
260 if (stream->alloc_size < stream->index + len)
261 make_room_in_stream (stream, stream->index + len);
262 memset (stream->data + stream->index, 0, len);
264 stream->index += len;
269 stream_data_align (MonoDynamicStream *stream)
272 guint32 count = stream->index % 4;
274 /* we assume the stream data will be aligned */
276 mono_image_add_stream_data (stream, buf, 4 - count);
280 mono_blob_entry_hash (const char* str)
284 len = mono_metadata_decode_blob_size (str, &str);
288 for (str += 1; str < end; str++)
289 h = (h << 5) - h + *str;
297 mono_blob_entry_equal (const char *str1, const char *str2) {
301 len = mono_metadata_decode_blob_size (str1, &end1);
302 len2 = mono_metadata_decode_blob_size (str2, &end2);
305 return memcmp (end1, end2, len) == 0;
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
313 gpointer oldkey, oldval;
315 copy = ALLOC_ATOMIC (s1+s2);
316 memcpy (copy, b1, s1);
317 memcpy (copy + s1, b2, s2);
318 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
320 idx = GPOINTER_TO_UINT (oldval);
322 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323 mono_image_add_stream_data (&assembly->blob, b2, s2);
324 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
330 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331 * dest may be misaligned.
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
338 for (elem = 0; elem < nelem; ++elem) {
364 g_assert_not_reached ();
370 memcpy (dest, val, len * nelem);
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
379 guint32 idx = 0, len;
381 len = str->length * 2;
382 mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
385 char *swapped = g_malloc (2 * mono_string_length (str));
386 const char *p = (const char*)mono_string_chars (str);
388 swap_with_size (swapped, p, 2, mono_string_length (str));
389 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
393 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
398 /* modified version needed to handle building corlib */
400 my_mono_class_from_mono_type (MonoType *type) {
401 switch (type->type) {
402 case MONO_TYPE_ARRAY:
404 case MONO_TYPE_SZARRAY:
405 case MONO_TYPE_GENERICINST:
406 return mono_class_from_mono_type (type);
409 g_assert (type->data.generic_param->pklass);
410 return type->data.generic_param->pklass;
412 /* should be always valid when we reach this case... */
413 return type->data.klass;
418 default_class_from_mono_type (MonoType *type)
420 switch (type->type) {
421 case MONO_TYPE_OBJECT:
422 return mono_defaults.object_class;
424 return mono_defaults.void_class;
425 case MONO_TYPE_BOOLEAN:
426 return mono_defaults.boolean_class;
428 return mono_defaults.char_class;
430 return mono_defaults.sbyte_class;
432 return mono_defaults.byte_class;
434 return mono_defaults.int16_class;
436 return mono_defaults.uint16_class;
438 return mono_defaults.int32_class;
440 return mono_defaults.uint32_class;
442 return mono_defaults.int_class;
444 return mono_defaults.uint_class;
446 return mono_defaults.int64_class;
448 return mono_defaults.uint64_class;
450 return mono_defaults.single_class;
452 return mono_defaults.double_class;
453 case MONO_TYPE_STRING:
454 return mono_defaults.string_class;
456 g_warning ("implement me 0x%02x\n", type->type);
457 g_assert_not_reached ();
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
469 g_assert_not_reached ();
473 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474 encode_type (assembly, ginst->generic_type, p, &p);
475 mono_metadata_encode_value (ginst->type_argc, p, &p);
476 for (i = 0; i < ginst->type_argc; ++i)
477 encode_type (assembly, ginst->type_argv [i], p, &p);
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
486 g_assert_not_reached ();
491 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
495 case MONO_TYPE_BOOLEAN:
509 case MONO_TYPE_STRING:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_TYPEDBYREF:
512 mono_metadata_encode_value (type->type, p, &p);
515 mono_metadata_encode_value (type->type, p, &p);
516 encode_type (assembly, type->data.type, p, &p);
518 case MONO_TYPE_SZARRAY:
519 mono_metadata_encode_value (type->type, p, &p);
520 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
522 case MONO_TYPE_VALUETYPE:
523 case MONO_TYPE_CLASS: {
524 MonoClass *k = mono_class_from_mono_type (type);
525 mono_metadata_encode_value (type->type, p, &p);
527 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528 * otherwise two typerefs could point to the same type, leading to
529 * verification errors.
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
534 case MONO_TYPE_ARRAY:
535 mono_metadata_encode_value (type->type, p, &p);
536 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537 mono_metadata_encode_value (type->data.array->rank, p, &p);
538 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539 mono_metadata_encode_value (0, p, &p);
541 case MONO_TYPE_GENERICINST:
542 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
546 mono_metadata_encode_value (type->type, p, &p);
547 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
550 g_error ("need to encode type %x", type->type);
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
559 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
563 encode_type (assembly, type->type, p, endbuf);
567 g_assert_not_reached ();
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
577 for (i = 0; i < mono_array_length (modreq); ++i) {
578 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_REQD;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
585 for (i = 0; i < mono_array_length (modopt); ++i) {
586 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587 *p = MONO_TYPE_CMOD_OPT;
589 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
602 g_assert_not_reached ();
605 size += 1 + type_get_signature_size (ginst->generic_type);
607 for (i = 0; i < ginst->type_argc; ++i)
608 size += type_get_signature_size (ginst->type_argv [i]);
614 type_get_signature_size (MonoType *type)
619 g_assert_not_reached ();
627 case MONO_TYPE_BOOLEAN:
641 case MONO_TYPE_STRING:
642 case MONO_TYPE_OBJECT:
643 case MONO_TYPE_TYPEDBYREF:
646 return size + 1 + type_get_signature_size (type->data.type);
647 case MONO_TYPE_SZARRAY:
648 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS:
652 case MONO_TYPE_ARRAY:
653 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654 case MONO_TYPE_GENERICINST:
655 return size + generic_inst_get_signature_size (type->data.generic_inst);
660 g_error ("need to encode type %x", type->type);
666 method_get_signature_size (MonoMethodSignature *sig)
671 size = type_get_signature_size (sig->ret);
672 for (i = 0; i < sig->param_count; i++)
673 size += type_get_signature_size (sig->params [i]);
675 if (sig->generic_param_count)
677 if (sig->sentinelpos >= 0)
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
689 guint32 nparams = sig->param_count;
690 guint32 size = 11 + method_get_signature_size (sig);
698 p = buf = g_malloc (size);
700 * FIXME: vararg, explicit_this, differenc call_conv values...
702 *p = sig->call_convention;
704 *p |= 0x20; /* hasthis */
705 if (sig->generic_param_count)
706 *p |= 0x10; /* generic */
708 if (sig->generic_param_count)
709 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710 mono_metadata_encode_value (nparams, p, &p);
711 encode_type (assembly, sig->ret, p, &p);
712 for (i = 0; i < nparams; ++i) {
713 if (i == sig->sentinelpos)
714 *p++ = MONO_TYPE_SENTINEL;
715 encode_type (assembly, sig->params [i], p, &p);
718 g_assert (p - buf < size);
719 mono_metadata_encode_value (p-buf, b, &b);
720 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
729 * FIXME: reuse code from method_encode_signature().
734 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
735 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737 guint32 size = 21 + nparams * 20 + notypes * 20;
742 p = buf = g_malloc (size);
743 /* LAMESPEC: all the call conv spec is foobared */
744 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745 if (mb->call_conv & 2)
746 *p |= 0x5; /* vararg */
747 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748 *p |= 0x20; /* hasthis */
750 *p |= 0x10; /* generic */
753 mono_metadata_encode_value (ngparams, p, &p);
754 mono_metadata_encode_value (nparams + notypes, p, &p);
755 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756 encode_reflection_type (assembly, mb->rtype, p, &p);
757 for (i = 0; i < nparams; ++i) {
758 MonoArray *modreq = NULL;
759 MonoArray *modopt = NULL;
760 MonoReflectionType *pt;
762 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
771 *p++ = MONO_TYPE_SENTINEL;
772 for (i = 0; i < notypes; ++i) {
773 MonoReflectionType *pt;
775 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776 encode_reflection_type (assembly, pt, p, &p);
780 g_assert (p - buf < size);
781 mono_metadata_encode_value (p-buf, b, &b);
782 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
790 MonoDynamicTable *table;
793 guint32 idx, sig_idx, size;
794 guint nl = mono_array_length (ilgen->locals);
801 p = buf = g_malloc (size);
802 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803 idx = table->next_idx ++;
805 alloc_table (table, table->rows);
806 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
808 mono_metadata_encode_value (0x07, p, &p);
809 mono_metadata_encode_value (nl, p, &p);
810 for (i = 0; i < nl; ++i) {
811 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
814 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
816 encode_reflection_type (assembly, lb->type, p, &p);
818 g_assert (p - buf < size);
819 mono_metadata_encode_value (p-buf, b, &b);
820 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
823 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
829 method_count_clauses (MonoReflectionILGen *ilgen)
831 guint32 num_clauses = 0;
834 MonoILExceptionInfo *ex_info;
835 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 if (ex_info->handlers)
838 num_clauses += mono_array_length (ex_info->handlers);
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
849 MonoExceptionClause *clauses;
850 MonoExceptionClause *clause;
851 MonoILExceptionInfo *ex_info;
852 MonoILExceptionBlock *ex_block;
853 guint32 finally_start;
854 int i, j, clause_index;;
856 clauses = g_new0 (MonoExceptionClause, num_clauses);
859 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861 finally_start = ex_info->start + ex_info->len;
862 g_assert (ex_info->handlers);
863 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865 clause = &(clauses [clause_index]);
867 clause->flags = ex_block->type;
868 clause->try_offset = ex_info->start;
870 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871 clause->try_len = finally_start - ex_info->start;
873 clause->try_len = ex_info->len;
874 clause->handler_offset = ex_block->start;
875 clause->handler_len = ex_block->len;
876 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878 if (ex_block->extype) {
879 mono_g_hash_table_insert (assembly->tokens,
880 GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
882 finally_start = ex_block->start + ex_block->len;
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
898 gint32 num_locals = 0;
899 gint32 num_exception = 0;
902 char fat_header [12];
905 guint32 local_sig = 0;
906 guint32 header_size = 12;
909 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
914 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
916 code = mb->ilgen->code;
917 code_size = mb->ilgen->code_len;
918 max_stack = mb->ilgen->max_stack;
919 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920 if (mb->ilgen->ex_handlers)
921 num_exception = method_count_clauses (mb->ilgen);
925 char *name = mono_string_to_utf8 (mb->name);
926 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
930 mono_raise_exception (exception);
933 code_size = mono_array_length (code);
934 max_stack = 8; /* we probably need to run a verifier on the code... */
937 /* check for exceptions, maxstack, locals */
938 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
940 if (code_size < 64 && !(code_size & 1)) {
941 flags = (code_size << 2) | 0x2;
942 } else if (code_size < 32 && (code_size & 1)) {
943 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
947 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
948 /* add to the fixup todo list */
949 if (mb->ilgen && mb->ilgen->num_token_fixups)
950 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
951 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
952 return assembly->text_rva + idx;
956 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
958 * FIXME: need to set also the header size in fat_flags.
959 * (and more sects and init locals flags)
963 fat_flags |= METHOD_HEADER_MORE_SECTS;
965 fat_flags |= METHOD_HEADER_INIT_LOCALS;
966 fat_header [0] = fat_flags;
967 fat_header [1] = (header_size / 4 ) << 4;
968 shortp = (guint16*)(fat_header + 2);
969 *shortp = GUINT16_TO_LE (max_stack);
970 intp = (guint32*)(fat_header + 4);
971 *intp = GUINT32_TO_LE (code_size);
972 intp = (guint32*)(fat_header + 8);
973 *intp = GUINT32_TO_LE (local_sig);
974 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
975 /* add to the fixup todo list */
976 if (mb->ilgen && mb->ilgen->num_token_fixups)
977 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
979 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
981 unsigned char sheader [4];
982 MonoExceptionClause clause;
983 MonoILExceptionInfo * ex_info;
984 MonoILExceptionBlock * ex_block;
987 stream_data_align (&assembly->code);
988 /* always use fat format for now */
989 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
990 num_exception *= sizeof (MonoExceptionClause);
991 num_exception += 4; /* include the size of the header */
992 sheader [1] = num_exception & 0xff;
993 sheader [2] = (num_exception >> 8) & 0xff;
994 sheader [3] = (num_exception >> 16) & 0xff;
995 mono_image_add_stream_data (&assembly->code, sheader, 4);
996 /* fat header, so we are already aligned */
998 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
999 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1000 if (ex_info->handlers) {
1001 int finally_start = ex_info->start + ex_info->len;
1002 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1003 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1004 clause.flags = GUINT32_TO_LE (ex_block->type);
1005 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1006 /* need fault, too, probably */
1007 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1008 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1010 clause.try_len = GUINT32_TO_LE (ex_info->len);
1011 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1012 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1013 finally_start = ex_block->start + ex_block->len;
1014 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1015 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1016 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1017 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1018 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1019 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1022 g_error ("No clauses for ex info block %d", i);
1026 return assembly->text_rva + idx;
1030 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1033 MonoDynamicTable *table;
1036 table = &assembly->tables [table_idx];
1038 g_assert (col < table->columns);
1040 values = table->values + table->columns;
1041 for (i = 1; i <= table->rows; ++i) {
1042 if (values [col] == token)
1044 values += table->columns;
1049 static GHashTable *dynamic_custom_attrs = NULL;
1051 static MonoCustomAttrInfo*
1052 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1055 MonoCustomAttrInfo *ainfo;
1056 MonoReflectionCustomAttr *cattr;
1060 /* FIXME: check in assembly the Run flag is set */
1062 count = mono_array_length (cattrs);
1064 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1066 ainfo->image = image;
1067 ainfo->num_attrs = count;
1068 for (i = 0; i < count; ++i) {
1069 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1070 ainfo->attrs [i].ctor = cattr->ctor->method;
1071 /* FIXME: might want to memdup the data here */
1072 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1073 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1080 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1082 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1087 if (!dynamic_custom_attrs)
1088 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1090 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1091 ainfo->cached = TRUE;
1095 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1097 /* they are cached, so we don't free them */
1098 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1104 * idx is the table index of the object
1105 * type is one of MONO_CUSTOM_ATTR_*
1108 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1110 MonoDynamicTable *table;
1111 MonoReflectionCustomAttr *cattr;
1113 guint32 count, i, token;
1115 char *p = blob_size;
1117 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1120 count = mono_array_length (cattrs);
1121 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1122 table->rows += count;
1123 alloc_table (table, table->rows);
1124 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1125 idx <<= MONO_CUSTOM_ATTR_BITS;
1127 for (i = 0; i < count; ++i) {
1128 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1129 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1130 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1131 type = mono_metadata_token_index (token);
1132 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1133 switch (mono_metadata_token_table (token)) {
1134 case MONO_TABLE_METHOD:
1135 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1137 case MONO_TABLE_MEMBERREF:
1138 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1141 g_warning ("got wrong token in custom attr");
1144 values [MONO_CUSTOM_ATTR_TYPE] = type;
1146 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1147 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1148 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1149 values += MONO_CUSTOM_ATTR_SIZE;
1155 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1157 MonoDynamicTable *table;
1159 guint32 count, i, idx;
1160 MonoReflectionPermissionSet *perm;
1165 count = mono_array_length (permissions);
1166 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1167 table->rows += count;
1168 alloc_table (table, table->rows);
1170 for (i = 0; i < mono_array_length (permissions); ++i) {
1171 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1173 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1175 idx = mono_metadata_token_index (parent_token);
1176 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1177 switch (mono_metadata_token_table (parent_token)) {
1178 case MONO_TABLE_TYPEDEF:
1179 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1181 case MONO_TABLE_METHOD:
1182 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1184 case MONO_TABLE_ASSEMBLY:
1185 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1188 g_assert_not_reached ();
1191 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1192 values [MONO_DECL_SECURITY_PARENT] = idx;
1193 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1200 * Fill in the MethodDef and ParamDef tables for a method.
1201 * This is used for both normal methods and constructors.
1204 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1206 MonoDynamicTable *table;
1211 /* room in this table is already allocated */
1212 table = &assembly->tables [MONO_TABLE_METHOD];
1213 *mb->table_idx = table->next_idx ++;
1214 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1215 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1216 name = mono_string_to_utf8 (mb->name);
1217 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1219 values [MONO_METHOD_FLAGS] = mb->attrs;
1220 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1221 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1222 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1224 table = &assembly->tables [MONO_TABLE_PARAM];
1225 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1227 mono_image_add_decl_security (assembly,
1228 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1231 MonoDynamicTable *mtable;
1234 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1235 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1238 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1239 if (mono_array_get (mb->pinfo, gpointer, i))
1242 table->rows += count;
1243 alloc_table (table, table->rows);
1244 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1245 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1246 MonoReflectionParamBuilder *pb;
1247 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1248 values [MONO_PARAM_FLAGS] = pb->attrs;
1249 values [MONO_PARAM_SEQUENCE] = i;
1250 if (pb->name != NULL) {
1251 name = mono_string_to_utf8 (pb->name);
1252 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1255 values [MONO_PARAM_NAME] = 0;
1257 values += MONO_PARAM_SIZE;
1258 if (pb->marshal_info) {
1260 alloc_table (mtable, mtable->rows);
1261 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1262 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1263 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1265 pb->table_idx = table->next_idx++;
1266 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1267 guint32 field_type = 0;
1268 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1270 alloc_table (mtable, mtable->rows);
1271 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1272 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1273 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1274 mvalues [MONO_CONSTANT_TYPE] = field_type;
1275 mvalues [MONO_CONSTANT_PADDING] = 0;
1283 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1285 rmb->ilgen = mb->ilgen;
1286 rmb->rtype = mb->rtype;
1287 rmb->parameters = mb->parameters;
1288 rmb->generic_params = mb->generic_params;
1289 rmb->opt_types = NULL;
1290 rmb->pinfo = mb->pinfo;
1291 rmb->attrs = mb->attrs;
1292 rmb->iattrs = mb->iattrs;
1293 rmb->call_conv = mb->call_conv;
1294 rmb->code = mb->code;
1295 rmb->type = mb->type;
1296 rmb->name = mb->name;
1297 rmb->table_idx = &mb->table_idx;
1298 rmb->init_locals = mb->init_locals;
1299 rmb->return_modreq = mb->return_modreq;
1300 rmb->return_modopt = mb->return_modopt;
1301 rmb->param_modreq = mb->param_modreq;
1302 rmb->param_modopt = mb->param_modopt;
1303 rmb->permissions = mb->permissions;
1304 rmb->mhandle = mb->mhandle;
1309 rmb->charset = rmb->charset & 0xf;
1310 rmb->lasterr = rmb->charset & 0x40;
1311 rmb->native_cc = rmb->native_cc;
1312 rmb->dllentry = mb->dllentry;
1318 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1320 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1322 rmb->ilgen = mb->ilgen;
1323 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1324 rmb->parameters = mb->parameters;
1325 rmb->generic_params = NULL;
1326 rmb->opt_types = NULL;
1327 rmb->pinfo = mb->pinfo;
1328 rmb->attrs = mb->attrs;
1329 rmb->iattrs = mb->iattrs;
1330 rmb->call_conv = mb->call_conv;
1332 rmb->type = mb->type;
1333 rmb->name = mono_string_new (mono_domain_get (), name);
1334 rmb->table_idx = &mb->table_idx;
1335 rmb->init_locals = mb->init_locals;
1336 rmb->return_modreq = NULL;
1337 rmb->return_modopt = NULL;
1338 rmb->param_modreq = mb->param_modreq;
1339 rmb->param_modopt = mb->param_modopt;
1340 rmb->permissions = mb->permissions;
1341 rmb->mhandle = mb->mhandle;
1347 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1349 rmb->ilgen = mb->ilgen;
1350 rmb->rtype = mb->rtype;
1351 rmb->parameters = mb->parameters;
1352 rmb->generic_params = NULL;
1353 rmb->opt_types = NULL;
1355 rmb->attrs = mb->attrs;
1357 rmb->call_conv = mb->call_conv;
1360 rmb->name = mb->name;
1361 rmb->table_idx = NULL;
1362 rmb->init_locals = mb->init_locals;
1363 rmb->return_modreq = NULL;
1364 rmb->return_modopt = NULL;
1365 rmb->param_modreq = NULL;
1366 rmb->param_modopt = NULL;
1367 rmb->permissions = NULL;
1368 rmb->mhandle = mb->mhandle;
1374 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1376 MonoDynamicTable *table;
1379 ReflectionMethodBuilder rmb;
1382 reflection_methodbuilder_from_method_builder (&rmb, mb);
1384 mono_image_basic_method (&rmb, assembly);
1386 if (mb->dll) { /* It's a P/Invoke method */
1388 int charset = mb->charset & 0xf;
1389 int lasterr = mb->charset & 0x40;
1390 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1392 alloc_table (table, table->rows);
1393 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1394 /* map CharSet values to on-disk values */
1396 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1397 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1398 name = mono_string_to_utf8 (mb->dllentry);
1399 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1401 name = mono_string_to_utf8 (mb->dll);
1402 moduleref = string_heap_insert (&assembly->sheap, name);
1404 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1405 table = &assembly->tables [MONO_TABLE_MODULEREF];
1407 alloc_table (table, table->rows);
1408 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1409 values [MONO_IMPLMAP_SCOPE] = table->rows;
1413 if (mb->override_method) {
1414 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1416 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1418 alloc_table (table, table->rows);
1419 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1420 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1421 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1423 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1424 switch (mono_metadata_token_table (tok)) {
1425 case MONO_TABLE_MEMBERREF:
1426 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1428 case MONO_TABLE_METHOD:
1429 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1432 g_assert_not_reached ();
1434 values [MONO_METHODIMPL_DECLARATION] = tok;
1437 if (mb->generic_params) {
1438 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1439 table->rows += mono_array_length (mb->generic_params);
1440 alloc_table (table, table->rows);
1441 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1442 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1444 mono_image_get_generic_param_info (
1445 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1452 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1454 ReflectionMethodBuilder rmb;
1456 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1458 mono_image_basic_method (&rmb, assembly);
1462 type_get_fully_qualified_name (MonoType *type) {
1463 char *name, *result;
1467 name = mono_type_get_name (type);
1468 klass = my_mono_class_from_mono_type (type);
1469 ta = klass->image->assembly;
1471 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1472 name, ta->aname.name,
1473 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1474 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1475 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1481 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1485 klass = my_mono_class_from_mono_type (type);
1487 return mono_type_get_name (type);
1488 ta = klass->image->assembly;
1489 if (ta == ass || klass->image == mono_defaults.corlib)
1490 return mono_type_get_name (type);
1492 return type_get_fully_qualified_name (type);
1496 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1498 char blob_size [64];
1499 char *b = blob_size;
1504 if (!assembly->save)
1507 p = buf = g_malloc (64);
1509 mono_metadata_encode_value (0x06, p, &p);
1510 /* encode custom attributes before the type */
1511 encode_type (assembly, type, p, &p);
1512 g_assert (p-buf < 64);
1513 mono_metadata_encode_value (p-buf, b, &b);
1514 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1520 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1522 char blob_size [64];
1523 char *b = blob_size;
1528 p = buf = g_malloc (64);
1530 mono_metadata_encode_value (0x06, p, &p);
1531 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1532 /* encode custom attributes before the type */
1533 encode_reflection_type (assembly, fb->type, p, &p);
1534 g_assert (p-buf < 64);
1535 mono_metadata_encode_value (p-buf, b, &b);
1536 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1542 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1543 char blob_size [64];
1544 char *b = blob_size;
1547 guint32 idx = 0, len = 0, dummy = 0;
1549 p = buf = g_malloc (64);
1551 *ret_type = MONO_TYPE_CLASS;
1553 box_val = (char*)&dummy;
1555 box_val = ((char*)val) + sizeof (MonoObject);
1556 *ret_type = val->vtable->klass->byval_arg.type;
1559 switch (*ret_type) {
1560 case MONO_TYPE_BOOLEAN:
1565 case MONO_TYPE_CHAR:
1580 case MONO_TYPE_VALUETYPE:
1581 if (val->vtable->klass->enumtype) {
1582 *ret_type = val->vtable->klass->enum_basetype->type;
1585 g_error ("we can't encode valuetypes");
1586 case MONO_TYPE_CLASS:
1588 case MONO_TYPE_STRING: {
1589 MonoString *str = (MonoString*)val;
1590 /* there is no signature */
1591 len = str->length * 2;
1592 mono_metadata_encode_value (len, b, &b);
1593 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1595 char *swapped = g_malloc (2 * mono_string_length (str));
1596 const char *p = (const char*)mono_string_chars (str);
1598 swap_with_size (swapped, p, 2, mono_string_length (str));
1599 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1603 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1610 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1613 /* there is no signature */
1614 mono_metadata_encode_value (len, b, &b);
1615 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1616 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1617 swap_with_size (blob_size, box_val, len, 1);
1618 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1620 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1628 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1629 char blob_size [64];
1630 char *b = blob_size;
1631 char *p, *buf, *str;
1632 guint32 idx, len, bufsize = 256;
1634 p = buf = g_malloc (bufsize);
1636 switch (minfo->type) {
1637 case MONO_NATIVE_BYVALTSTR:
1638 case MONO_NATIVE_BYVALARRAY:
1639 mono_metadata_encode_value (minfo->type, p, &p);
1640 mono_metadata_encode_value (minfo->count, p, &p);
1642 case MONO_NATIVE_LPARRAY:
1643 mono_metadata_encode_value (minfo->type, p, &p);
1644 if (minfo->eltype || (minfo->count > 0)) {
1645 mono_metadata_encode_value (minfo->eltype, p, &p);
1646 if (minfo->count > 0) {
1647 mono_metadata_encode_value (0, p, &p);
1648 mono_metadata_encode_value (minfo->count, p, &p);
1652 case MONO_NATIVE_CUSTOM:
1653 mono_metadata_encode_value (minfo->type, p, &p);
1655 str = mono_string_to_utf8 (minfo->guid);
1657 mono_metadata_encode_value (len, p, &p);
1658 memcpy (p, str, len);
1662 mono_metadata_encode_value (0, p, &p);
1664 if (minfo->marshaltype) {
1665 str = mono_string_to_utf8 (minfo->marshaltype);
1667 mono_metadata_encode_value (len, p, &p);
1668 if (p + len >= buf + bufsize) {
1671 buf = g_realloc (buf, bufsize);
1674 memcpy (p, str, len);
1678 mono_metadata_encode_value (0, p, &p);
1680 if (minfo->marshaltyperef) {
1681 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1683 mono_metadata_encode_value (len, p, &p);
1684 if (p + len >= buf + bufsize) {
1687 buf = g_realloc (buf, bufsize);
1690 memcpy (p, str, len);
1694 mono_metadata_encode_value (0, p, &p);
1696 if (minfo->mcookie) {
1697 str = mono_string_to_utf8 (minfo->mcookie);
1699 mono_metadata_encode_value (len, p, &p);
1700 if (p + len >= buf + bufsize) {
1703 buf = g_realloc (buf, bufsize);
1706 memcpy (p, str, len);
1710 mono_metadata_encode_value (0, p, &p);
1714 mono_metadata_encode_value (minfo->type, p, &p);
1718 mono_metadata_encode_value (len, b, &b);
1719 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1725 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1727 MonoDynamicTable *table;
1731 /* maybe this fixup should be done in the C# code */
1732 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1733 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1734 table = &assembly->tables [MONO_TABLE_FIELD];
1735 fb->table_idx = table->next_idx ++;
1736 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1737 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1738 name = mono_string_to_utf8 (fb->name);
1739 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1741 values [MONO_FIELD_FLAGS] = fb->attrs;
1742 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1744 if (fb->offset != -1) {
1745 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1747 alloc_table (table, table->rows);
1748 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1749 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1750 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1752 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1753 guint32 field_type = 0;
1754 table = &assembly->tables [MONO_TABLE_CONSTANT];
1756 alloc_table (table, table->rows);
1757 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1758 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1759 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1760 values [MONO_CONSTANT_TYPE] = field_type;
1761 values [MONO_CONSTANT_PADDING] = 0;
1763 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1765 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1767 alloc_table (table, table->rows);
1768 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1769 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1771 * We store it in the code section because it's simpler for now.
1774 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1776 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1777 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1779 if (fb->marshal_info) {
1780 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1782 alloc_table (table, table->rows);
1783 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1784 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1785 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1790 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1794 char *b = blob_size;
1795 guint32 nparams = 0;
1796 MonoReflectionMethodBuilder *mb = fb->get_method;
1797 MonoReflectionMethodBuilder *smb = fb->set_method;
1798 guint32 idx, i, size;
1800 if (mb && mb->parameters)
1801 nparams = mono_array_length (mb->parameters);
1802 if (!mb && smb && smb->parameters)
1803 nparams = mono_array_length (smb->parameters) - 1;
1804 size = 24 + nparams * 10;
1805 buf = p = g_malloc (size);
1808 mono_metadata_encode_value (nparams, p, &p);
1810 encode_reflection_type (assembly, mb->rtype, p, &p);
1811 for (i = 0; i < nparams; ++i) {
1812 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1813 encode_reflection_type (assembly, pt, p, &p);
1816 /* the property type is the last param */
1817 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1818 for (i = 0; i < nparams; ++i) {
1819 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1820 encode_reflection_type (assembly, pt, p, &p);
1824 g_assert (p - buf < size);
1825 mono_metadata_encode_value (p-buf, b, &b);
1826 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1832 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1834 MonoDynamicTable *table;
1837 guint num_methods = 0;
1841 * we need to set things in the following tables:
1842 * PROPERTYMAP (info already filled in _get_type_info ())
1843 * PROPERTY (rows already preallocated in _get_type_info ())
1844 * METHOD (method info already done with the generic method code)
1847 table = &assembly->tables [MONO_TABLE_PROPERTY];
1848 pb->table_idx = table->next_idx ++;
1849 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1850 name = mono_string_to_utf8 (pb->name);
1851 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1853 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1854 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1856 /* FIXME: we still don't handle 'other' methods */
1857 if (pb->get_method) num_methods ++;
1858 if (pb->set_method) num_methods ++;
1860 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1861 table->rows += num_methods;
1862 alloc_table (table, table->rows);
1864 if (pb->get_method) {
1865 semaidx = table->next_idx ++;
1866 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1867 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1868 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1869 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1871 if (pb->set_method) {
1872 semaidx = table->next_idx ++;
1873 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1874 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1875 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1876 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1881 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1883 MonoDynamicTable *table;
1886 guint num_methods = 0;
1890 * we need to set things in the following tables:
1891 * EVENTMAP (info already filled in _get_type_info ())
1892 * EVENT (rows already preallocated in _get_type_info ())
1893 * METHOD (method info already done with the generic method code)
1896 table = &assembly->tables [MONO_TABLE_EVENT];
1897 eb->table_idx = table->next_idx ++;
1898 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1899 name = mono_string_to_utf8 (eb->name);
1900 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1902 values [MONO_EVENT_FLAGS] = eb->attrs;
1903 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1906 * FIXME: we still don't handle 'other' methods
1908 if (eb->add_method) num_methods ++;
1909 if (eb->remove_method) num_methods ++;
1910 if (eb->raise_method) num_methods ++;
1912 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1913 table->rows += num_methods;
1914 alloc_table (table, table->rows);
1916 if (eb->add_method) {
1917 semaidx = table->next_idx ++;
1918 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1919 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1920 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1921 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1923 if (eb->remove_method) {
1924 semaidx = table->next_idx ++;
1925 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1926 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1927 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1928 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1930 if (eb->raise_method) {
1931 semaidx = table->next_idx ++;
1932 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1933 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1934 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1935 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1940 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1942 static MonoClass *NewConstraintAttr;
1943 static MonoMethod *NewConstraintAttr_ctor;
1944 MonoDynamicTable *table;
1946 guint32 token, type;
1947 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1950 if (!NewConstraintAttr)
1951 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1952 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1953 g_assert (NewConstraintAttr);
1955 if (!NewConstraintAttr_ctor) {
1958 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1959 MonoMethod *m = NewConstraintAttr->methods [i];
1961 if (strcmp (m->name, ".ctor"))
1964 NewConstraintAttr_ctor = m;
1968 g_assert (NewConstraintAttr_ctor);
1971 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1973 alloc_table (table, table->rows);
1975 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1976 owner <<= MONO_CUSTOM_ATTR_BITS;
1977 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1978 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1980 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1982 type = mono_metadata_token_index (token);
1983 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1984 switch (mono_metadata_token_table (token)) {
1985 case MONO_TABLE_METHOD:
1986 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1988 case MONO_TABLE_MEMBERREF:
1989 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1992 g_warning ("got wrong token in custom attr");
1995 values [MONO_CUSTOM_ATTR_TYPE] = type;
1997 buf = p = g_malloc (1);
1998 mono_metadata_encode_value (4, p, &p);
1999 g_assert (p-buf == 1);
2001 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2003 values += MONO_CUSTOM_ATTR_SIZE;
2008 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2010 MonoDynamicTable *table;
2011 guint32 num_constraints, i;
2015 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2016 num_constraints = gparam->iface_constraints ?
2017 mono_array_length (gparam->iface_constraints) : 0;
2018 table->rows += num_constraints;
2019 if (gparam->base_type)
2021 alloc_table (table, table->rows);
2023 if (gparam->base_type) {
2024 table_idx = table->next_idx ++;
2025 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2027 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2028 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2029 assembly, gparam->base_type->type);
2032 for (i = 0; i < num_constraints; i++) {
2033 MonoReflectionType *constraint = mono_array_get (
2034 gparam->iface_constraints, gpointer, i);
2036 table_idx = table->next_idx ++;
2037 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2039 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2040 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2041 assembly, constraint->type);
2044 if (gparam->has_ctor_constraint)
2045 encode_new_constraint (assembly, owner);
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2051 GenericParamTableEntry *entry;
2054 * The GenericParam table must be sorted according to the `owner' field.
2055 * We need to do this sorting prior to writing the GenericParamConstraint
2056 * table, since we have to use the final GenericParam table indices there
2057 * and they must also be sorted.
2060 entry = g_new0 (GenericParamTableEntry, 1);
2061 entry->owner = owner;
2062 entry->gparam = gparam;
2064 g_ptr_array_add (assembly->gen_params, entry);
2068 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2070 MonoDynamicTable *table;
2071 MonoGenericParam *param;
2075 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2076 table_idx = table->next_idx ++;
2077 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2079 param = entry->gparam->type.type->data.generic_param;
2081 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2082 if (entry->gparam->has_value_type)
2083 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2084 else if (entry->gparam->has_reference_type)
2085 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2087 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2088 values [MONO_GENERICPARAM_NUMBER] = param->num;
2089 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090 values [MONO_GENERICPARAM_KIND] = 0;
2092 encode_constraints (entry->gparam, table_idx, assembly);
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2098 MonoDynamicTable *table;
2101 guint32 cols [MONO_ASSEMBLY_SIZE];
2105 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2108 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110 token = table->next_idx ++;
2112 alloc_table (table, table->rows);
2113 values = table->values + token * MONO_MODULEREF_SIZE;
2114 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2116 token <<= MONO_RESOLTION_SCOPE_BITS;
2117 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2123 if (image->assembly->dynamic)
2125 memset (cols, 0, sizeof (cols));
2127 /* image->assembly->image is the manifest module */
2128 image = image->assembly->image;
2129 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2132 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133 token = table->next_idx ++;
2135 alloc_table (table, table->rows);
2136 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2146 if (strcmp ("", image->assembly->aname.culture)) {
2147 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148 image->assembly->aname.culture);
2151 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152 guchar pubtoken [9];
2154 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2155 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2159 token <<= MONO_RESOLTION_SCOPE_BITS;
2160 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2168 MonoDynamicTable *table;
2174 char *b = blob_size;
2176 switch (type->type) {
2177 case MONO_TYPE_FNPTR:
2179 case MONO_TYPE_SZARRAY:
2180 case MONO_TYPE_ARRAY:
2182 case MONO_TYPE_MVAR:
2183 case MONO_TYPE_GENERICINST:
2184 encode_type (assembly, type, p, &p);
2186 case MONO_TYPE_CLASS:
2187 case MONO_TYPE_VALUETYPE: {
2188 MonoClass *k = mono_class_from_mono_type (type);
2189 if (!k || !k->generic_inst)
2191 encode_generic_inst (assembly, k->generic_inst, p, &p);
2198 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2199 if (assembly->save) {
2200 g_assert (p-sig < 128);
2201 mono_metadata_encode_value (p-sig, b, &b);
2202 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2203 alloc_table (table, table->rows + 1);
2204 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2205 values [MONO_TYPESPEC_SIGNATURE] = token;
2208 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2209 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2215 * Despite the name, we handle also TypeSpec (with the above helper).
2218 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2220 MonoDynamicTable *table;
2222 guint32 token, scope, enclosing;
2225 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2228 token = create_typespec (assembly, type);
2231 klass = my_mono_class_from_mono_type (type);
2233 klass = mono_class_from_mono_type (type);
2236 * If it's in the same module and not a generic type parameter:
2238 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2239 (type->type != MONO_TYPE_MVAR)) {
2240 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2246 if (klass->nested_in) {
2247 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2248 /* get the typeref idx of the enclosing type */
2249 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2252 scope = resolution_scope_from_image (assembly, klass->image);
2254 table = &assembly->tables [MONO_TABLE_TYPEREF];
2255 if (assembly->save) {
2256 alloc_table (table, table->rows + 1);
2257 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258 values [MONO_TYPEREF_SCOPE] = scope;
2259 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2262 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2265 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2270 * Insert a memberef row into the metadata: the token that point to the memberref
2271 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2272 * mono_image_get_fieldref_token()).
2273 * The sig param is an index to an already built signature.
2276 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2278 MonoDynamicTable *table;
2280 guint32 token, pclass;
2283 parent = mono_image_typedef_or_ref (assembly, type);
2284 switch (parent & MONO_TYPEDEFORREF_MASK) {
2285 case MONO_TYPEDEFORREF_TYPEREF:
2286 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2288 case MONO_TYPEDEFORREF_TYPESPEC:
2289 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2291 case MONO_TYPEDEFORREF_TYPEDEF:
2292 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2295 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2298 /* extract the index */
2299 parent >>= MONO_TYPEDEFORREF_BITS;
2301 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2303 if (assembly->save) {
2304 alloc_table (table, table->rows + 1);
2305 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2306 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2307 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2308 values [MONO_MEMBERREF_SIGNATURE] = sig;
2311 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2318 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2321 MonoMethodSignature *sig;
2323 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2328 * A methodref signature can't contain an unmanaged calling convention.
2330 sig = mono_metadata_signature_dup (method->signature);
2331 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2332 sig->call_convention = MONO_CALL_DEFAULT;
2333 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2334 method->name, method_encode_signature (assembly, sig));
2336 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2341 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2342 const gchar *name, guint32 sig)
2344 MonoDynamicTable *table;
2348 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2350 if (assembly->save) {
2351 alloc_table (table, table->rows + 1);
2352 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2353 values [MONO_MEMBERREF_CLASS] = original;
2354 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2355 values [MONO_MEMBERREF_SIGNATURE] = sig;
2358 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2365 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2368 ReflectionMethodBuilder rmb;
2370 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2374 reflection_methodbuilder_from_method_builder (&rmb, mb);
2376 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2377 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2378 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2383 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2386 ReflectionMethodBuilder rmb;
2388 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2392 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2394 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2395 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2396 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2401 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2406 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2409 g_assert (f->field->parent);
2410 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2411 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2412 f->field->name, fieldref_encode_signature (assembly, type));
2413 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2418 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2423 guint32 nparams = gmethod->mtype_argc;
2424 guint32 size = 10 + nparams * 10;
2427 char *b = blob_size;
2429 if (!assembly->save)
2432 p = buf = g_malloc (size);
2434 * FIXME: vararg, explicit_this, differenc call_conv values...
2436 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2437 mono_metadata_encode_value (nparams, p, &p);
2439 for (i = 0; i < nparams; i++)
2440 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2443 g_assert (p - buf < size);
2444 mono_metadata_encode_value (p-buf, b, &b);
2445 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2451 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2453 MonoDynamicTable *table;
2455 guint32 token, mtoken = 0, sig;
2456 MonoMethodInflated *imethod;
2457 MonoMethod *declaring;
2459 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2461 g_assert (method->signature->is_inflated);
2462 imethod = (MonoMethodInflated *) method;
2463 declaring = imethod->declaring;
2465 sig = method_encode_signature (assembly, declaring->signature);
2466 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2468 if (!declaring->signature->generic_param_count)
2471 switch (mono_metadata_token_table (mtoken)) {
2472 case MONO_TABLE_MEMBERREF:
2473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2475 case MONO_TABLE_METHOD:
2476 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2479 g_assert_not_reached ();
2482 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2484 if (assembly->save) {
2485 alloc_table (table, table->rows + 1);
2486 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2487 values [MONO_METHODSPEC_METHOD] = mtoken;
2488 values [MONO_METHODSPEC_SIGNATURE] = sig;
2491 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2498 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2500 MonoMethodInflated *imethod;
2503 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2507 g_assert (m->signature->is_inflated);
2508 imethod = (MonoMethodInflated *) m;
2510 if (imethod->declaring->signature->generic_param_count) {
2511 token = method_encode_methodspec (assembly, m);
2513 guint32 sig = method_encode_signature (
2514 assembly, imethod->declaring->signature);
2515 token = mono_image_get_memberref_token (
2516 assembly, &m->klass->byval_arg, m->name, sig);
2519 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2524 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2526 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2529 sig = method_encode_signature (assembly, imethod->declaring->signature);
2530 token = mono_image_get_memberref_token (
2531 assembly, &m->klass->byval_arg, m->name, sig);
2537 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2539 MonoDynamicTable *table;
2546 char *b = blob_size;
2550 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2551 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2552 * Because of this, we must not insert it into the `typeref' hash table.
2555 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2559 g_assert (tb->generic_params);
2560 klass = mono_class_from_mono_type (tb->type.type);
2562 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2563 encode_type (assembly, &klass->byval_arg, p, &p);
2565 count = mono_array_length (tb->generic_params);
2566 mono_metadata_encode_value (count, p, &p);
2567 for (i = 0; i < count; i++) {
2568 MonoReflectionGenericParam *gparam;
2570 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2572 encode_type (assembly, gparam->type.type, p, &p);
2575 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2576 if (assembly->save) {
2577 g_assert (p-sig < 128);
2578 mono_metadata_encode_value (p-sig, b, &b);
2579 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2580 alloc_table (table, table->rows + 1);
2581 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2582 values [MONO_TYPESPEC_SIGNATURE] = token;
2585 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2586 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2592 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2594 MonoDynamicTable *table;
2597 guint32 token, pclass, parent, sig;
2600 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2604 klass = mono_class_from_mono_type (fb->typeb->type);
2605 name = mono_string_to_utf8 (fb->name);
2607 sig = fieldref_encode_signature (assembly, fb->type->type);
2609 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2610 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2612 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2613 parent >>= MONO_TYPEDEFORREF_BITS;
2615 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2617 if (assembly->save) {
2618 alloc_table (table, table->rows + 1);
2619 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2620 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2621 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2622 values [MONO_MEMBERREF_SIGNATURE] = sig;
2625 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2627 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2632 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2640 char *b = blob_size;
2642 if (!assembly->save)
2646 g_assert (helper->type == 2);
2648 if (helper->arguments)
2649 nargs = mono_array_length (helper->arguments);
2653 size = 10 + (nargs * 10);
2655 p = buf = g_malloc (size);
2657 /* Encode calling convention */
2658 /* Change Any to Standard */
2659 if ((helper->call_conv & 0x03) == 0x03)
2660 helper->call_conv = 0x01;
2661 /* explicit_this implies has_this */
2662 if (helper->call_conv & 0x40)
2663 helper->call_conv &= 0x20;
2665 if (helper->call_conv == 0) { /* Unmanaged */
2666 *p = helper->unmanaged_call_conv - 1;
2669 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2670 if (helper->call_conv & 0x02) /* varargs */
2675 mono_metadata_encode_value (nargs, p, &p);
2676 encode_reflection_type (assembly, helper->return_type, p, &p);
2677 for (i = 0; i < nargs; ++i) {
2678 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2679 encode_reflection_type (assembly, pt, p, &p);
2682 g_assert (p - buf < size);
2683 mono_metadata_encode_value (p-buf, b, &b);
2684 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2691 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2694 MonoDynamicTable *table;
2697 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2698 idx = table->next_idx ++;
2700 alloc_table (table, table->rows);
2701 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2703 values [MONO_STAND_ALONE_SIGNATURE] =
2704 mono_reflection_encode_sighelper (assembly, helper);
2710 reflection_cc_to_file (int call_conv) {
2711 switch (call_conv & 0x3) {
2713 case 1: return MONO_CALL_DEFAULT;
2714 case 2: return MONO_CALL_VARARG;
2716 g_assert_not_reached ();
2723 MonoMethodSignature *sig;
2729 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2734 MonoMethodSignature *sig;
2737 name = mono_string_to_utf8 (m->name);
2738 nparams = mono_array_length (m->parameters);
2739 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2741 sig->sentinelpos = -1;
2742 sig->call_convention = reflection_cc_to_file (m->call_conv);
2743 sig->param_count = nparams;
2744 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2745 for (i = 0; i < nparams; ++i) {
2746 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2747 sig->params [i] = t->type;
2750 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2752 if (strcmp (name, am->name) == 0 &&
2753 mono_metadata_type_equal (am->parent, m->parent->type) &&
2754 mono_metadata_signature_equal (am->sig, sig)) {
2757 m->table_idx = am->token & 0xffffff;
2761 am = g_new0 (ArrayMethod, 1);
2764 am->parent = m->parent->type;
2765 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2766 method_encode_signature (assembly, sig));
2767 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2768 m->table_idx = am->token & 0xffffff;
2773 * Insert into the metadata tables all the info about the TypeBuilder tb.
2774 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2777 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2779 MonoDynamicTable *table;
2781 int i, is_object = 0, is_system = 0;
2784 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2785 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2786 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2787 n = mono_string_to_utf8 (tb->name);
2788 if (strcmp (n, "Object") == 0)
2790 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2792 n = mono_string_to_utf8 (tb->nspace);
2793 if (strcmp (n, "System") == 0)
2795 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2797 if (tb->parent && !(is_system && is_object) &&
2798 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2799 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2801 values [MONO_TYPEDEF_EXTENDS] = 0;
2803 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2804 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2807 * if we have explicitlayout or sequentiallayouts, output data in the
2808 * ClassLayout table.
2810 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2811 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2812 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2814 alloc_table (table, table->rows);
2815 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2816 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2817 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2818 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2821 /* handle interfaces */
2822 if (tb->interfaces) {
2823 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2825 table->rows += mono_array_length (tb->interfaces);
2826 alloc_table (table, table->rows);
2827 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2828 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2829 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2830 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2831 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2832 values += MONO_INTERFACEIMPL_SIZE;
2838 table = &assembly->tables [MONO_TABLE_FIELD];
2839 table->rows += tb->num_fields;
2840 alloc_table (table, table->rows);
2841 for (i = 0; i < tb->num_fields; ++i)
2842 mono_image_get_field_info (
2843 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2846 /* handle constructors */
2848 table = &assembly->tables [MONO_TABLE_METHOD];
2849 table->rows += mono_array_length (tb->ctors);
2850 alloc_table (table, table->rows);
2851 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2852 mono_image_get_ctor_info (domain,
2853 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2856 /* handle methods */
2858 table = &assembly->tables [MONO_TABLE_METHOD];
2859 table->rows += tb->num_methods;
2860 alloc_table (table, table->rows);
2861 for (i = 0; i < tb->num_methods; ++i)
2862 mono_image_get_method_info (
2863 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2866 /* Do the same with properties etc.. */
2867 if (tb->events && mono_array_length (tb->events)) {
2868 table = &assembly->tables [MONO_TABLE_EVENT];
2869 table->rows += mono_array_length (tb->events);
2870 alloc_table (table, table->rows);
2871 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2873 alloc_table (table, table->rows);
2874 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2875 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2876 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2877 for (i = 0; i < mono_array_length (tb->events); ++i)
2878 mono_image_get_event_info (
2879 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2881 if (tb->properties && mono_array_length (tb->properties)) {
2882 table = &assembly->tables [MONO_TABLE_PROPERTY];
2883 table->rows += mono_array_length (tb->properties);
2884 alloc_table (table, table->rows);
2885 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2887 alloc_table (table, table->rows);
2888 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2889 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2890 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2891 for (i = 0; i < mono_array_length (tb->properties); ++i)
2892 mono_image_get_property_info (
2893 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2896 /* handle generic parameters */
2897 if (tb->generic_params) {
2898 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2899 table->rows += mono_array_length (tb->generic_params);
2900 alloc_table (table, table->rows);
2901 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2902 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2904 mono_image_get_generic_param_info (
2905 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2909 mono_image_add_decl_security (assembly,
2910 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2913 MonoDynamicTable *ntable;
2915 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2916 ntable->rows += mono_array_length (tb->subtypes);
2917 alloc_table (ntable, ntable->rows);
2918 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2920 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2921 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2923 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2924 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2925 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2926 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2927 mono_string_to_utf8 (tb->name), tb->table_idx,
2928 ntable->next_idx, ntable->rows);*/
2929 values += MONO_NESTED_CLASS_SIZE;
2936 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2940 g_ptr_array_add (types, type);
2942 if (!type->subtypes)
2945 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2946 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2947 collect_types (types, subtype);
2952 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2954 if ((*type1)->table_idx < (*type2)->table_idx)
2957 if ((*type1)->table_idx > (*type2)->table_idx)
2964 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2969 for (i = 0; i < mono_array_length (pinfo); ++i) {
2970 MonoReflectionParamBuilder *pb;
2971 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2974 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2979 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2982 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2984 for (i = 0; i < tb->num_fields; ++i) {
2985 MonoReflectionFieldBuilder* fb;
2986 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2987 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2991 for (i = 0; i < mono_array_length (tb->events); ++i) {
2992 MonoReflectionEventBuilder* eb;
2993 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2994 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2997 if (tb->properties) {
2998 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2999 MonoReflectionPropertyBuilder* pb;
3000 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3001 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3005 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3006 MonoReflectionCtorBuilder* cb;
3007 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3008 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3009 params_add_cattrs (assembly, cb->pinfo);
3014 for (i = 0; i < tb->num_methods; ++i) {
3015 MonoReflectionMethodBuilder* mb;
3016 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3017 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3018 params_add_cattrs (assembly, mb->pinfo);
3023 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3024 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3029 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3032 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3034 /* no types in the module */
3038 for (i = 0; i < mb->num_types; ++i)
3039 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3043 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3045 MonoDynamicTable *table;
3049 char *b = blob_size;
3052 table = &assembly->tables [MONO_TABLE_FILE];
3054 alloc_table (table, table->rows);
3055 values = table->values + table->next_idx * MONO_FILE_SIZE;
3056 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3057 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3058 if (module->image->dynamic) {
3059 /* This depends on the fact that the main module is emitted last */
3060 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3061 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3064 path = g_strdup (module->image->name);
3066 mono_sha1_get_digest_from_file (path, hash);
3069 mono_metadata_encode_value (20, b, &b);
3070 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3071 mono_image_add_stream_data (&assembly->blob, hash, 20);
3076 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3078 MonoDynamicTable *table;
3082 table = &assembly->tables [MONO_TABLE_MODULE];
3083 mb->table_idx = table->next_idx ++;
3084 name = mono_string_to_utf8 (mb->module.name);
3085 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3087 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3090 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3091 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3092 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3096 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3097 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3099 MonoDynamicTable *table;
3103 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3104 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3107 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3109 alloc_table (table, table->rows);
3110 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3112 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3113 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3114 if (klass->nested_in)
3115 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3117 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3118 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3119 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3121 res = table->next_idx;
3125 /* Emit nested types */
3126 if (klass->nested_classes) {
3129 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3130 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3137 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3138 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3143 klass = mono_class_from_mono_type (tb->type.type);
3145 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3147 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3148 parent_index, assembly);
3152 * We need to do this ourselves since klass->nested_classes is not set up.
3155 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3156 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3161 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3162 guint32 module_index, MonoDynamicImage *assembly)
3164 MonoImage *image = module->image;
3168 t = &image->tables [MONO_TABLE_TYPEDEF];
3170 for (i = 0; i < t->rows; ++i) {
3171 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3173 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3174 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3178 #define align_pointer(base,p)\
3180 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3182 (p) += 4 - (__diff & 3);\
3186 compare_semantics (const void *a, const void *b)
3188 const guint32 *a_values = a;
3189 const guint32 *b_values = b;
3190 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3193 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3197 compare_custom_attrs (const void *a, const void *b)
3199 const guint32 *a_values = a;
3200 const guint32 *b_values = b;
3202 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3206 compare_field_marshal (const void *a, const void *b)
3208 const guint32 *a_values = a;
3209 const guint32 *b_values = b;
3211 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3215 compare_nested (const void *a, const void *b)
3217 const guint32 *a_values = a;
3218 const guint32 *b_values = b;
3220 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3224 compare_genericparam (const void *a, const void *b)
3226 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3227 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3229 return (*a_entry)->owner - (*b_entry)->owner;
3233 compare_declsecurity_attrs (const void *a, const void *b)
3235 const guint32 *a_values = a;
3236 const guint32 *b_values = b;
3238 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3242 pad_heap (MonoDynamicStream *sh)
3244 if (sh->index & 3) {
3245 int sz = 4 - (sh->index & 3);
3246 memset (sh->data + sh->index, 0, sz);
3253 MonoDynamicStream *stream;
3257 * build_compressed_metadata() fills in the blob of data that represents the
3258 * raw metadata as it will be saved in the PE file. The five streams are output
3259 * and the metadata tables are comnpressed from the guint32 array representation,
3260 * to the compressed on-disk format.
3263 build_compressed_metadata (MonoDynamicImage *assembly)
3265 MonoDynamicTable *table;
3267 guint64 valid_mask = 0;
3268 guint64 sorted_mask;
3269 guint32 heapt_size = 0;
3270 guint32 meta_size = 256; /* allow for header and other stuff */
3271 guint32 table_offset;
3272 guint32 ntables = 0;
3278 struct StreamDesc stream_desc [5];
3280 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3281 for (i = 0; i < assembly->gen_params->len; i++){
3282 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3283 write_generic_param_entry (assembly, entry);
3286 stream_desc [0].name = "#~";
3287 stream_desc [0].stream = &assembly->tstream;
3288 stream_desc [1].name = "#Strings";
3289 stream_desc [1].stream = &assembly->sheap;
3290 stream_desc [2].name = "#US";
3291 stream_desc [2].stream = &assembly->us;
3292 stream_desc [3].name = "#Blob";
3293 stream_desc [3].stream = &assembly->blob;
3294 stream_desc [4].name = "#GUID";
3295 stream_desc [4].stream = &assembly->guid;
3297 /* tables that are sorted */
3298 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3299 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3300 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3301 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3302 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3303 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3305 /* Compute table sizes */
3306 /* the MonoImage has already been created in mono_image_basic_init() */
3307 meta = &assembly->image;
3309 /* sizes should be multiple of 4 */
3310 pad_heap (&assembly->blob);
3311 pad_heap (&assembly->guid);
3312 pad_heap (&assembly->sheap);
3313 pad_heap (&assembly->us);
3315 /* Setup the info used by compute_sizes () */
3316 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3317 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3318 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3320 meta_size += assembly->blob.index;
3321 meta_size += assembly->guid.index;
3322 meta_size += assembly->sheap.index;
3323 meta_size += assembly->us.index;
3325 for (i=0; i < 64; ++i)
3326 meta->tables [i].rows = assembly->tables [i].rows;
3328 for (i = 0; i < 64; i++){
3329 if (meta->tables [i].rows == 0)
3331 valid_mask |= (guint64)1 << i;
3333 meta->tables [i].row_size = mono_metadata_compute_size (
3334 meta, i, &meta->tables [i].size_bitfield);
3335 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3337 heapt_size += 24; /* #~ header size */
3338 heapt_size += ntables * 4;
3339 /* make multiple of 4 */
3342 meta_size += heapt_size;
3343 meta->raw_metadata = g_malloc0 (meta_size);
3344 p = meta->raw_metadata;
3345 /* the metadata signature */
3346 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3347 /* version numbers and 4 bytes reserved */
3348 int16val = (guint16*)p;
3349 *int16val++ = GUINT16_TO_LE (1);
3350 *int16val = GUINT16_TO_LE (1);
3352 /* version string */
3353 int32val = (guint32*)p;
3354 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3356 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3357 p += GUINT32_FROM_LE (*int32val);
3358 align_pointer (meta->raw_metadata, p);
3359 int16val = (guint16*)p;
3360 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3361 *int16val = GUINT16_TO_LE (5); /* number of streams */
3365 * write the stream info.
3367 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3368 table_offset += 3; table_offset &= ~3;
3370 assembly->tstream.index = heapt_size;
3371 for (i = 0; i < 5; ++i) {
3372 int32val = (guint32*)p;
3373 stream_desc [i].stream->offset = table_offset;
3374 *int32val++ = GUINT32_TO_LE (table_offset);
3375 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3376 table_offset += GUINT32_FROM_LE (*int32val);
3377 table_offset += 3; table_offset &= ~3;
3379 strcpy (p, stream_desc [i].name);
3380 p += strlen (stream_desc [i].name) + 1;
3381 align_pointer (meta->raw_metadata, p);
3384 * now copy the data, the table stream header and contents goes first.
3386 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3387 p = meta->raw_metadata + assembly->tstream.offset;
3388 int32val = (guint32*)p;
3389 *int32val = GUINT32_TO_LE (0); /* reserved */
3392 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3393 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3394 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3395 *p++ = 1; /* version */
3398 *p++ = 1; /* version */
3402 if (meta->idx_string_wide)
3404 if (meta->idx_guid_wide)
3406 if (meta->idx_blob_wide)
3409 *p++ = 0; /* reserved */
3410 int64val = (guint64*)p;
3411 *int64val++ = GUINT64_TO_LE (valid_mask);
3412 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3414 int32val = (guint32*)p;
3415 for (i = 0; i < 64; i++){
3416 if (meta->tables [i].rows == 0)
3418 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3420 p = (unsigned char*)int32val;
3422 /* sort the tables that still need sorting */
3423 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3425 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3426 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3428 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3429 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3431 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3432 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3434 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3435 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3436 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3438 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3440 /* compress the tables */
3441 for (i = 0; i < 64; i++){
3444 guint32 bitfield = meta->tables [i].size_bitfield;
3445 if (!meta->tables [i].rows)
3447 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3448 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3449 meta->tables [i].base = p;
3450 for (row = 1; row <= meta->tables [i].rows; ++row) {
3451 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3452 for (col = 0; col < assembly->tables [i].columns; ++col) {
3453 switch (mono_metadata_table_size (bitfield, col)) {
3455 *p++ = values [col];
3458 *p++ = values [col] & 0xff;
3459 *p++ = (values [col] >> 8) & 0xff;
3462 *p++ = values [col] & 0xff;
3463 *p++ = (values [col] >> 8) & 0xff;
3464 *p++ = (values [col] >> 16) & 0xff;
3465 *p++ = (values [col] >> 24) & 0xff;
3468 g_assert_not_reached ();
3472 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3475 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3476 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3477 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3478 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3479 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3481 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3485 * Some tables in metadata need to be sorted according to some criteria, but
3486 * when methods and fields are first created with reflection, they may be assigned a token
3487 * that doesn't correspond to the final token they will get assigned after the sorting.
3488 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3489 * with the reflection objects that represent them. Once all the tables are set up, the
3490 * reflection objects will contains the correct table index. fixup_method() will fixup the
3491 * tokens for the method with ILGenerator @ilgen.
3494 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3495 guint32 code_idx = GPOINTER_TO_UINT (value);
3496 MonoReflectionILTokenInfo *iltoken;
3497 MonoReflectionFieldBuilder *field;
3498 MonoReflectionCtorBuilder *ctor;
3499 MonoReflectionMethodBuilder *method;
3500 MonoReflectionTypeBuilder *tb;
3501 MonoReflectionArrayMethod *am;
3503 unsigned char *target;
3505 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3506 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3507 target = assembly->code.data + code_idx + iltoken->code_pos;
3508 switch (target [3]) {
3509 case MONO_TABLE_FIELD:
3510 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3511 field = (MonoReflectionFieldBuilder *)iltoken->member;
3512 idx = field->table_idx;
3513 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3514 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3515 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3517 g_assert_not_reached ();
3520 case MONO_TABLE_METHOD:
3521 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3522 method = (MonoReflectionMethodBuilder *)iltoken->member;
3523 idx = method->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3525 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3526 idx = ctor->table_idx;
3527 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3528 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3529 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3530 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3532 g_assert_not_reached ();
3535 case MONO_TABLE_TYPEDEF:
3536 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3537 g_assert_not_reached ();
3538 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3539 idx = tb->table_idx;
3541 case MONO_TABLE_MEMBERREF:
3542 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3543 am = (MonoReflectionArrayMethod*)iltoken->member;
3544 idx = am->table_idx;
3545 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3546 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3547 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3548 g_assert (m->klass->generic_inst);
3550 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3553 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3554 g_assert (f->generic_info);
3556 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3559 g_assert_not_reached ();
3562 case MONO_TABLE_METHODSPEC:
3563 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3564 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3565 g_assert (m->signature->generic_param_count);
3568 g_assert_not_reached ();
3572 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3574 target [0] = idx & 0xff;
3575 target [1] = (idx >> 8) & 0xff;
3576 target [2] = (idx >> 16) & 0xff;
3583 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3584 * value is not known when the table is emitted.
3587 fixup_cattrs (MonoDynamicImage *assembly)
3589 MonoDynamicTable *table;
3591 guint32 type, i, idx, token;
3594 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3596 for (i = 0; i < table->rows; ++i) {
3597 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3599 type = values [MONO_CUSTOM_ATTR_TYPE];
3600 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3601 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3602 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3603 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3606 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3607 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3608 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3609 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3616 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3618 MonoDynamicTable *table;
3622 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3624 alloc_table (table, table->rows);
3625 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3626 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3627 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3628 name = mono_string_to_utf8 (rsrc->name);
3629 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3631 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3636 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3638 MonoDynamicTable *table;
3642 char *b = blob_size;
3644 guint32 idx, offset;
3646 if (rsrc->filename) {
3647 name = mono_string_to_utf8 (rsrc->filename);
3648 sname = g_path_get_basename (name);
3650 table = &assembly->tables [MONO_TABLE_FILE];
3652 alloc_table (table, table->rows);
3653 values = table->values + table->next_idx * MONO_FILE_SIZE;
3654 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3655 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3658 mono_sha1_get_digest_from_file (name, hash);
3659 mono_metadata_encode_value (20, b, &b);
3660 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3661 mono_image_add_stream_data (&assembly->blob, hash, 20);
3663 idx = table->next_idx++;
3665 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3668 offset = mono_array_length (rsrc->data);
3669 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3670 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3671 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3672 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3676 * The entry should be emitted into the MANIFESTRESOURCE table of
3677 * the main module, but that needs to reference the FILE table
3678 * which isn't emitted yet.
3685 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3689 set_version_from_string (MonoString *version, guint32 *values)
3691 gchar *ver, *p, *str;
3694 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3695 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3696 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3697 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3700 ver = str = mono_string_to_utf8 (version);
3701 for (i = 0; i < 4; ++i) {
3702 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3708 /* handle Revision and Build */
3718 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3722 char *b = blob_size;
3727 len = mono_array_length (pkey);
3728 mono_metadata_encode_value (len, b, &b);
3729 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3730 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3732 /* need to get the actual value from the key type... */
3733 assembly->strong_name_size = 128;
3734 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3740 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3742 MonoDynamicTable *table;
3743 MonoDynamicImage *assembly;
3744 MonoReflectionAssemblyBuilder *assemblyb;
3749 guint32 module_index;
3751 assemblyb = moduleb->assemblyb;
3752 assembly = moduleb->dynamic_image;
3753 domain = mono_object_domain (assemblyb);
3755 /* Emit ASSEMBLY table */
3756 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3757 alloc_table (table, 1);
3758 values = table->values + MONO_ASSEMBLY_SIZE;
3759 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3760 name = mono_string_to_utf8 (assemblyb->name);
3761 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3763 if (assemblyb->culture) {
3764 name = mono_string_to_utf8 (assemblyb->culture);
3765 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3768 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3770 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3771 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3772 set_version_from_string (assemblyb->version, values);
3774 /* Emit FILE + EXPORTED_TYPE table */
3776 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3778 MonoReflectionModuleBuilder *file_module =
3779 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3780 if (file_module != moduleb) {
3781 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3783 if (file_module->types) {
3784 for (j = 0; j < file_module->num_types; ++j) {
3785 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3786 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3791 if (assemblyb->loaded_modules) {
3792 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3793 MonoReflectionModule *file_module =
3794 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3795 mono_image_fill_file_table (domain, file_module, assembly);
3797 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3801 /* Emit MANIFESTRESOURCE table */
3803 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3805 MonoReflectionModuleBuilder *file_module =
3806 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3807 /* The table for the main module is emitted later */
3808 if (file_module != moduleb) {
3810 if (file_module->resources) {
3811 int len = mono_array_length (file_module->resources);
3812 for (j = 0; j < len; ++j) {
3813 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3814 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3822 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3823 * for the modulebuilder @moduleb.
3824 * At the end of the process, method and field tokens are fixed up and the
3825 * on-disk compressed metadata representation is created.
3828 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3830 MonoDynamicTable *table;
3831 MonoDynamicImage *assembly;
3832 MonoReflectionAssemblyBuilder *assemblyb;
3837 assemblyb = moduleb->assemblyb;
3838 assembly = moduleb->dynamic_image;
3839 domain = mono_object_domain (assemblyb);
3841 if (assembly->text_rva)
3844 assembly->text_rva = START_TEXT_RVA;
3846 if (moduleb->is_main) {
3847 mono_image_emit_manifest (moduleb);
3850 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3851 table->rows = 1; /* .<Module> */
3853 alloc_table (table, table->rows);
3855 * Set the first entry.
3857 values = table->values + table->columns;
3858 values [MONO_TYPEDEF_FLAGS] = 0;
3859 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3860 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3861 values [MONO_TYPEDEF_EXTENDS] = 0;
3862 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3863 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3866 * handle global methods
3867 * FIXME: test what to do when global methods are defined in multiple modules.
3869 if (moduleb->global_methods) {
3870 table = &assembly->tables [MONO_TABLE_METHOD];
3871 table->rows += mono_array_length (moduleb->global_methods);
3872 alloc_table (table, table->rows);
3873 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3874 mono_image_get_method_info (
3875 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3877 if (moduleb->global_fields) {
3878 table = &assembly->tables [MONO_TABLE_FIELD];
3879 table->rows += mono_array_length (moduleb->global_fields);
3880 alloc_table (table, table->rows);
3881 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3882 mono_image_get_field_info (
3883 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3886 table = &assembly->tables [MONO_TABLE_MODULE];
3887 alloc_table (table, 1);
3888 mono_image_fill_module_table (domain, moduleb, assembly);
3892 /* Collect all types into a list sorted by their table_idx */
3893 GPtrArray *types = g_ptr_array_new ();
3896 for (i = 0; i < moduleb->num_types; ++i) {
3897 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3898 collect_types (types, type);
3901 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3902 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3903 table->rows += types->len;
3904 alloc_table (table, table->rows);
3906 for (i = 0; i < types->len; ++i) {
3907 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3908 mono_image_get_type_info (domain, type, assembly);
3910 g_ptr_array_free (types, TRUE);
3914 * table->rows is already set above and in mono_image_fill_module_table.
3916 /* add all the custom attributes at the end, once all the indexes are stable */
3917 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3919 /* CAS assembly permissions */
3920 if (assemblyb->permissions_minimum)
3921 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3922 if (assemblyb->permissions_optional)
3923 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3924 if (assemblyb->permissions_refused)
3925 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3927 module_add_cattrs (assembly, moduleb);
3930 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3931 fixup_cattrs (assembly);
3935 * mono_image_insert_string:
3936 * @module: module builder object
3939 * Insert @str into the user string stream of @module.
3942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3944 MonoDynamicImage *assembly;
3949 MONO_ARCH_SAVE_REGS;
3951 if (!module->dynamic_image)
3952 mono_image_module_basic_init (module);
3954 assembly = module->dynamic_image;
3956 if (assembly->save) {
3957 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3958 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3959 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3961 char *swapped = g_malloc (2 * mono_string_length (str));
3962 const char *p = (const char*)mono_string_chars (str);
3964 swap_with_size (swapped, p, 2, mono_string_length (str));
3965 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3969 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3971 mono_image_add_stream_data (&assembly->us, "", 1);
3973 idx = assembly->us.index ++;
3976 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3978 return MONO_TOKEN_STRING | idx;
3982 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3987 klass = obj->vtable->klass;
3988 if (strcmp (klass->name, "MonoMethod") == 0) {
3989 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3990 MonoMethodSignature *sig, *old;
3991 guint32 sig_token, parent;
3994 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3996 nargs = mono_array_length (opt_param_types);
3997 old = method->signature;
3998 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4000 sig->hasthis = old->hasthis;
4001 sig->explicit_this = old->explicit_this;
4002 sig->call_convention = old->call_convention;
4003 sig->generic_param_count = old->generic_param_count;
4004 sig->param_count = old->param_count + nargs;
4005 sig->sentinelpos = old->param_count;
4006 sig->ret = old->ret;
4008 for (i = 0; i < old->param_count; i++)
4009 sig->params [i] = old->params [i];
4011 for (i = 0; i < nargs; i++) {
4012 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4013 sig->params [old->param_count + i] = rt->type;
4016 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4017 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4018 parent >>= MONO_TYPEDEFORREF_BITS;
4020 parent <<= MONO_MEMBERREF_PARENT_BITS;
4021 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4023 sig_token = method_encode_signature (assembly, sig);
4024 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4025 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4026 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4027 ReflectionMethodBuilder rmb;
4028 guint32 parent, sig;
4030 reflection_methodbuilder_from_method_builder (&rmb, mb);
4031 rmb.opt_types = opt_param_types;
4033 sig = method_builder_encode_signature (assembly, &rmb);
4035 parent = mono_image_create_token (assembly, obj, TRUE);
4036 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4038 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4039 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4041 token = mono_image_get_varargs_method_token (
4042 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4044 g_error ("requested method token for %s\n", klass->name);
4051 * mono_image_create_token:
4052 * @assembly: a dynamic assembly
4055 * Get a token to insert in the IL code stream for the given MemberInfo.
4056 * @obj can be one of:
4057 * ConstructorBuilder
4067 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4072 klass = obj->vtable->klass;
4073 if (strcmp (klass->name, "MethodBuilder") == 0) {
4074 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4076 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4077 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4079 token = mono_image_get_methodbuilder_token (assembly, mb);
4080 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4081 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4082 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4084 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4085 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4087 token = mono_image_get_ctorbuilder_token (assembly, mb);
4088 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4089 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4090 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4091 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4092 if (tb->generic_params) {
4093 token = mono_image_get_generic_field_token (assembly, fb);
4095 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4097 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4098 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4099 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4100 } else if (strcmp (klass->name, "MonoType") == 0 ||
4101 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4102 MonoReflectionType *tb = (MonoReflectionType *)obj;
4103 token = mono_metadata_token_from_dor (
4104 mono_image_typedef_or_ref (assembly, tb->type));
4105 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4106 MonoReflectionType *tb = (MonoReflectionType *)obj;
4107 token = mono_metadata_token_from_dor (
4108 mono_image_typedef_or_ref (assembly, tb->type));
4109 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4110 strcmp (klass->name, "MonoMethod") == 0) {
4111 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4112 if (m->method->signature->is_inflated) {
4113 if (create_methodspec)
4114 token = mono_image_get_methodspec_token (assembly, m->method);
4116 token = mono_image_get_inflated_method_token (assembly, m->method);
4117 } else if (m->method->signature->generic_param_count) {
4118 g_assert_not_reached ();
4119 } else if ((m->method->klass->image == &assembly->image) &&
4120 !m->method->klass->generic_inst) {
4121 static guint32 method_table_idx = 0xffffff;
4122 if (m->method->klass->wastypebuilder) {
4123 /* we use the same token as the one that was assigned
4124 * to the Methodbuilder.
4125 * FIXME: do the equivalent for Fields.
4127 token = m->method->token;
4130 * Each token should have a unique index, but the indexes are
4131 * assigned by managed code, so we don't know about them. An
4132 * easy solution is to count backwards...
4134 method_table_idx --;
4135 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4138 token = mono_image_get_methodref_token (assembly, m->method);
4140 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4141 } else if (strcmp (klass->name, "MonoField") == 0) {
4142 MonoReflectionField *f = (MonoReflectionField *)obj;
4143 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4144 static guint32 field_table_idx = 0xffffff;
4146 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4148 token = mono_image_get_fieldref_token (assembly, f);
4150 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4151 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4152 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4153 token = mono_image_get_array_token (assembly, m);
4154 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4155 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4156 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4158 g_error ("requested token for %s\n", klass->name);
4161 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4167 guint32 import_lookup_table;
4171 guint32 import_address_table_rva;
4179 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4181 static MonoDynamicImage*
4182 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4184 static const guchar entrycode [16] = {0xff, 0x25, 0};
4185 MonoDynamicImage *image;
4188 const char *version = mono_get_runtime_version ();
4191 image = GC_MALLOC (sizeof (MonoDynamicImage));
4193 image = g_new0 (MonoDynamicImage, 1);
4196 /* keep in sync with image.c */
4197 image->image.name = assembly_name;
4198 image->image.assembly_name = image->image.name; /* they may be different */
4199 image->image.module_name = module_name;
4200 image->image.version = g_strdup (version);
4201 image->image.dynamic = TRUE;
4203 image->image.references = g_new0 (MonoAssembly*, 1);
4204 image->image.references [0] = NULL;
4206 mono_image_init (&image->image);
4208 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4209 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4210 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4211 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4212 image->handleref = g_hash_table_new (NULL, NULL);
4213 image->tokens = mono_g_hash_table_new (NULL, NULL);
4214 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4215 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4216 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4217 image->gen_params = g_ptr_array_new ();
4219 string_heap_init (&image->sheap);
4220 mono_image_add_stream_data (&image->us, "", 1);
4221 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4222 /* import tables... */
4223 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4224 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4225 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4226 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4227 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4228 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4229 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4230 stream_data_align (&image->code);
4232 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4234 for (i=0; i < 64; ++i) {
4235 image->tables [i].next_idx = 1;
4236 image->tables [i].columns = table_sizes [i];
4239 image->image.assembly = (MonoAssembly*)assembly;
4240 image->run = assembly->run;
4241 image->save = assembly->save;
4247 * mono_image_basic_init:
4248 * @assembly: an assembly builder object
4250 * Create the MonoImage that represents the assembly builder and setup some
4251 * of the helper hash table and the basic metadata streams.
4254 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4256 MonoDynamicAssembly *assembly;
4257 MonoDynamicImage *image;
4259 MONO_ARCH_SAVE_REGS;
4261 if (assemblyb->dynamic_assembly)
4265 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4267 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4270 assembly->assembly.dynamic = TRUE;
4271 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4272 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4273 if (assemblyb->culture)
4274 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4276 assembly->assembly.aname.culture = g_strdup ("");
4278 assembly->run = assemblyb->access != 2;
4279 assembly->save = assemblyb->access != 1;
4281 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4282 assembly->assembly.aname.name = image->image.name;
4283 assembly->assembly.image = &image->image;
4285 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4286 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4290 calc_section_size (MonoDynamicImage *assembly)
4294 /* alignment constraints */
4295 assembly->code.index += 3;
4296 assembly->code.index &= ~3;
4297 assembly->meta_size += 3;
4298 assembly->meta_size &= ~3;
4299 assembly->resources.index += 3;
4300 assembly->resources.index &= ~3;
4302 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4303 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4306 if (assembly->win32_res) {
4307 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4309 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4310 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4314 assembly->sections [MONO_SECTION_RELOC].size = 12;
4315 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4325 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4329 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4331 ResTreeNode *t1 = (ResTreeNode*)a;
4332 ResTreeNode *t2 = (ResTreeNode*)b;
4334 return t1->id - t2->id;
4338 * resource_tree_create:
4340 * Organize the resources into a resource tree.
4342 static ResTreeNode *
4343 resource_tree_create (MonoArray *win32_resources)
4345 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4349 tree = g_new0 (ResTreeNode, 1);
4351 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4352 MonoReflectionWin32Resource *win32_res =
4353 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4357 lang_node = g_new0 (ResTreeNode, 1);
4358 lang_node->id = win32_res->lang_id;
4359 lang_node->win32_res = win32_res;
4361 /* Create type node if neccesary */
4363 for (l = tree->children; l; l = l->next)
4364 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4365 type_node = (ResTreeNode*)l->data;
4370 type_node = g_new0 (ResTreeNode, 1);
4371 type_node->id = win32_res->res_type;
4374 * The resource types have to be sorted otherwise
4375 * Windows Explorer can't display the version information.
4377 tree->children = g_slist_insert_sorted (tree->children,
4378 type_node, resource_tree_compare_by_id);
4381 /* Create res node if neccesary */
4383 for (l = type_node->children; l; l = l->next)
4384 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4385 res_node = (ResTreeNode*)l->data;
4390 res_node = g_new0 (ResTreeNode, 1);
4391 res_node->id = win32_res->res_id;
4392 type_node->children = g_slist_append (type_node->children, res_node);
4395 res_node->children = g_slist_append (res_node->children, lang_node);
4402 * resource_tree_encode:
4404 * Encode the resource tree into the format used in the PE file.
4407 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4410 MonoPEResourceDir dir;
4411 MonoPEResourceDirEntry dir_entry;
4412 MonoPEResourceDataEntry data_entry;
4416 * For the format of the resource directory, see the article
4417 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4421 memset (&dir, 0, sizeof (dir));
4422 memset (&dir_entry, 0, sizeof (dir_entry));
4423 memset (&data_entry, 0, sizeof (data_entry));
4425 g_assert (sizeof (dir) == 16);
4426 g_assert (sizeof (dir_entry) == 8);
4427 g_assert (sizeof (data_entry) == 16);
4429 node->offset = p - begin;
4431 /* IMAGE_RESOURCE_DIRECTORY */
4432 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4434 memcpy (p, &dir, sizeof (dir));
4437 /* Reserve space for entries */
4439 p += sizeof (dir_entry) * dir.res_id_entries;
4441 /* Write children */
4442 for (l = node->children; l; l = l->next) {
4443 ResTreeNode *child = (ResTreeNode*)l->data;
4445 if (child->win32_res) {
4447 child->offset = p - begin;
4449 /* IMAGE_RESOURCE_DATA_ENTRY */
4450 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4451 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4453 memcpy (p, &data_entry, sizeof (data_entry));
4454 p += sizeof (data_entry);
4456 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4457 p += data_entry.rde_size;
4459 resource_tree_encode (child, begin, p, &p);
4463 /* IMAGE_RESOURCE_ENTRY */
4464 for (l = node->children; l; l = l->next) {
4465 ResTreeNode *child = (ResTreeNode*)l->data;
4466 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4468 dir_entry.is_dir = child->win32_res ? 0 : 1;
4469 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4471 memcpy (entries, &dir_entry, sizeof (dir_entry));
4472 entries += sizeof (dir_entry);
4479 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4484 MonoReflectionWin32Resource *win32_res;
4487 if (!assemblyb->win32_resources)
4491 * Resources are stored in a three level tree inside the PE file.
4492 * - level one contains a node for each type of resource
4493 * - level two contains a node for each resource
4494 * - level three contains a node for each instance of a resource for a
4495 * specific language.
4498 tree = resource_tree_create (assemblyb->win32_resources);
4500 /* Estimate the size of the encoded tree */
4502 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4503 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4504 size += mono_array_length (win32_res->res_data);
4506 /* Directory structure */
4507 size += mono_array_length (assemblyb->win32_resources) * 256;
4508 p = buf = g_malloc (size);
4510 resource_tree_encode (tree, p, p, &p);
4512 g_assert (p - buf < size);
4514 assembly->win32_res = g_malloc (p - buf);
4515 assembly->win32_res_size = p - buf;
4516 memcpy (assembly->win32_res, buf, p - buf);
4522 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4524 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4527 p += sizeof (MonoPEResourceDir);
4528 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4529 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4530 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4531 if (dir_entry->is_dir) {
4532 fixup_resource_directory (res_section, child, rva);
4534 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4535 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4538 p += sizeof (MonoPEResourceDirEntry);
4543 * mono_image_create_pefile:
4544 * @mb: a module builder object
4546 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4547 * assembly->pefile where it can be easily retrieved later in chunks.
4550 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4551 MonoMSDOSHeader *msdos;
4552 MonoDotNetHeader *header;
4553 MonoSectionTable *section;
4554 MonoCLIHeader *cli_header;
4555 guint32 size, image_size, virtual_base, text_offset;
4556 guint32 header_start, section_start, file_offset, virtual_offset;
4557 MonoDynamicImage *assembly;
4558 MonoReflectionAssemblyBuilder *assemblyb;
4559 MonoDynamicStream *pefile;
4561 guint32 *rva, value;
4564 static const unsigned char msheader[] = {
4565 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4566 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4569 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4570 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4571 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4572 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4575 assemblyb = mb->assemblyb;
4577 mono_image_basic_init (assemblyb);
4578 assembly = mb->dynamic_image;
4580 /* already created */
4581 if (assembly->pefile.index)
4584 mono_image_build_metadata (mb);
4586 if (mb->is_main && assemblyb->resources) {
4587 int len = mono_array_length (assemblyb->resources);
4588 for (i = 0; i < len; ++i)
4589 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4592 if (mb->resources) {
4593 int len = mono_array_length (mb->resources);
4594 for (i = 0; i < len; ++i)
4595 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4598 build_compressed_metadata (assembly);
4601 assembly_add_win32_resources (assembly, assemblyb);
4603 nsections = calc_section_size (assembly);
4605 pefile = &assembly->pefile;
4607 /* The DOS header and stub */
4608 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4609 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4611 /* the dotnet header */
4612 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4614 /* the section tables */
4615 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4617 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4618 virtual_offset = VIRT_ALIGN;
4621 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4622 if (!assembly->sections [i].size)
4625 file_offset += FILE_ALIGN - 1;
4626 file_offset &= ~(FILE_ALIGN - 1);
4627 virtual_offset += VIRT_ALIGN - 1;
4628 virtual_offset &= ~(VIRT_ALIGN - 1);
4630 assembly->sections [i].offset = file_offset;
4631 assembly->sections [i].rva = virtual_offset;
4633 file_offset += assembly->sections [i].size;
4634 virtual_offset += assembly->sections [i].size;
4635 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4638 file_offset += FILE_ALIGN - 1;
4639 file_offset &= ~(FILE_ALIGN - 1);
4640 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4642 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4644 /* back-patch info */
4645 msdos = (MonoMSDOSHeader*)pefile->data;
4646 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4647 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4648 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4650 header = (MonoDotNetHeader*)(pefile->data + header_start);
4651 header->pesig [0] = 'P';
4652 header->pesig [1] = 'E';
4654 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4655 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4656 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4657 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4658 if (assemblyb->pekind == 1) {
4660 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4663 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4666 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4668 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4669 header->pe.pe_major = 6;
4670 header->pe.pe_minor = 0;
4671 size = assembly->sections [MONO_SECTION_TEXT].size;
4672 size += FILE_ALIGN - 1;
4673 size &= ~(FILE_ALIGN - 1);
4674 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4675 size = assembly->sections [MONO_SECTION_RSRC].size;
4676 size += FILE_ALIGN - 1;
4677 size &= ~(FILE_ALIGN - 1);
4678 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4679 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4680 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4681 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4682 /* pe_rva_entry_point always at the beginning of the text section */
4683 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4685 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4686 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4687 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4688 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4689 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4690 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4691 size = section_start;
4692 size += FILE_ALIGN - 1;
4693 size &= ~(FILE_ALIGN - 1);
4694 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4696 size += VIRT_ALIGN - 1;
4697 size &= ~(VIRT_ALIGN - 1);
4698 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4701 // Translate the PEFileKind value to the value expected by the Windows loader
4707 // PEFileKinds.Dll == 1
4708 // PEFileKinds.ConsoleApplication == 2
4709 // PEFileKinds.WindowApplication == 3
4712 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4713 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4715 if (assemblyb->pekind == 3)
4720 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4722 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4723 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4724 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4725 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4726 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4727 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4729 /* fill data directory entries */
4731 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4732 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4734 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4735 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4737 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4738 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4739 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4740 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4741 /* patch imported function RVA name */
4742 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4743 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4745 /* the import table */
4746 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4747 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4748 /* patch imported dll RVA name and other entries in the dir */
4749 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4750 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4751 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4752 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4753 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4754 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4756 p = (assembly->code.data + assembly->ilt_offset);
4757 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4758 *p++ = (value) & 0xff;
4759 *p++ = (value >> 8) & (0xff);
4760 *p++ = (value >> 16) & (0xff);
4761 *p++ = (value >> 24) & (0xff);
4763 /* the CLI header info */
4764 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4765 cli_header->ch_size = GUINT32_FROM_LE (72);
4766 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4767 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4768 if (assemblyb->entry_point) {
4769 guint32 table_idx = 0;
4770 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4771 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4772 table_idx = methodb->table_idx;
4774 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4776 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4778 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4780 /* The embedded managed resources */
4781 text_offset = assembly->text_rva + assembly->code.index;
4782 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4783 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4784 text_offset += assembly->resources.index;
4785 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4786 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4787 text_offset += assembly->meta_size;
4788 if (assembly->strong_name_size) {
4789 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4790 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4791 text_offset += assembly->strong_name_size;
4794 /* write the section tables and section content */
4795 section = (MonoSectionTable*)(pefile->data + section_start);
4796 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4797 static const char *section_names [] = {
4798 ".text", ".rsrc", ".reloc"
4800 if (!assembly->sections [i].size)
4802 strcpy (section->st_name, section_names [i]);
4803 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4804 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4805 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4806 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4807 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4808 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4809 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4811 case MONO_SECTION_TEXT:
4812 /* patch entry point */
4813 p = (assembly->code.data + 2);
4814 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4815 *p++ = (value) & 0xff;
4816 *p++ = (value >> 8) & 0xff;
4817 *p++ = (value >> 16) & 0xff;
4818 *p++ = (value >> 24) & 0xff;
4820 text_offset = assembly->sections [i].offset;
4821 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4822 text_offset += assembly->code.index;
4823 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4824 text_offset += assembly->resources.index;
4825 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4826 text_offset += assembly->meta_size;
4827 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4829 g_free (assembly->image.raw_metadata);
4831 case MONO_SECTION_RELOC:
4832 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4833 *rva = GUINT32_FROM_LE (assembly->text_rva);
4835 *rva = GUINT32_FROM_LE (12);
4837 data16 = (guint16*)rva;
4839 * the entrypoint is always at the start of the text section
4840 * 3 is IMAGE_REL_BASED_HIGHLOW
4841 * 2 is patch_size_rva - text_rva
4843 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4845 *data16 = 0; /* terminate */
4847 case MONO_SECTION_RSRC:
4848 if (assembly->win32_res) {
4849 text_offset = assembly->sections [i].offset;
4851 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4852 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4854 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4858 g_assert_not_reached ();
4863 /* check that the file is properly padded */
4866 FILE *f = fopen ("mypetest.exe", "w");
4867 fwrite (pefile->data, pefile->index, 1, f);
4873 MonoReflectionModule *
4874 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4878 MonoImageOpenStatus status;
4879 MonoDynamicAssembly *assembly;
4881 name = mono_string_to_utf8 (fileName);
4883 image = mono_image_open (name, &status);
4886 if (status == MONO_IMAGE_ERROR_ERRNO)
4887 exc = mono_get_exception_file_not_found (fileName);
4889 exc = mono_get_exception_bad_image_format (name);
4891 mono_raise_exception (exc);
4896 assembly = ab->dynamic_assembly;
4897 image->assembly = (MonoAssembly*)assembly;
4899 mono_assembly_load_references (image, &status);
4901 mono_image_close (image);
4902 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4905 return mono_module_get_object (mono_domain_get (), image);
4909 * We need to return always the same object for MethodInfo, FieldInfo etc..
4910 * but we need to consider the reflected type.
4911 * type uses a different hash, since it uses custom hash/equal functions.
4916 MonoClass *refclass;
4920 reflected_equal (gconstpointer a, gconstpointer b) {
4921 const ReflectedEntry *ea = a;
4922 const ReflectedEntry *eb = b;
4924 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4928 reflected_hash (gconstpointer a) {
4929 const ReflectedEntry *ea = a;
4930 return GPOINTER_TO_UINT (ea->item);
4933 #define CHECK_OBJECT(t,p,k) \
4939 mono_domain_lock (domain); \
4940 if (!domain->refobject_hash) \
4941 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4942 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4943 mono_domain_unlock (domain); \
4949 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4951 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4954 #define CACHE_OBJECT(p,o,k) \
4956 ReflectedEntry *e = ALLOC_REFENTRY; \
4958 e->refclass = (k); \
4959 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4960 mono_domain_unlock (domain); \
4964 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4966 /* this is done only once */
4967 mono_domain_lock (domain);
4968 CACHE_OBJECT (assembly, res, NULL);
4972 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4974 /* this is done only once */
4975 mono_domain_lock (domain);
4976 CACHE_OBJECT (module, res, NULL);
4980 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4982 MonoDynamicImage *image = moduleb->dynamic_image;
4983 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4986 * FIXME: we already created an image in mono_image_basic_init (), but
4987 * we don't know which module it belongs to, since that is only
4988 * determined at assembly save time.
4990 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4991 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4993 moduleb->module.image = &image->image;
4994 moduleb->dynamic_image = image;
4995 register_module (mono_object_domain (moduleb), moduleb, image);
5000 * mono_assembly_get_object:
5001 * @domain: an app domain
5002 * @assembly: an assembly
5004 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5006 MonoReflectionAssembly*
5007 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5009 static MonoClass *System_Reflection_Assembly;
5010 MonoReflectionAssembly *res;
5012 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5013 if (!System_Reflection_Assembly)
5014 System_Reflection_Assembly = mono_class_from_name (
5015 mono_defaults.corlib, "System.Reflection", "Assembly");
5016 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5017 res->assembly = assembly;
5018 CACHE_OBJECT (assembly, res, NULL);
5024 MonoReflectionModule*
5025 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5027 static MonoClass *System_Reflection_Module;
5028 MonoReflectionModule *res;
5030 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5031 if (!System_Reflection_Module)
5032 System_Reflection_Module = mono_class_from_name (
5033 mono_defaults.corlib, "System.Reflection", "Module");
5034 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5037 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5039 res->fqname = mono_string_new (domain, image->name);
5040 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5041 res->scopename = mono_string_new (domain, image->module_name);
5043 if (image->assembly->image == image) {
5044 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5047 g_assert (image->assembly->image->modules);
5049 while (image->assembly->image->modules [i]) {
5050 if (image->assembly->image->modules [i] == image)
5051 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5053 g_assert (res->token);
5056 mono_image_addref (image);
5058 CACHE_OBJECT (image, res, NULL);
5062 MonoReflectionModule*
5063 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5065 static MonoClass *System_Reflection_Module;
5066 MonoReflectionModule *res;
5067 MonoTableInfo *table;
5068 guint32 cols [MONO_FILE_SIZE];
5070 guint32 i, name_idx;
5073 if (!System_Reflection_Module)
5074 System_Reflection_Module = mono_class_from_name (
5075 mono_defaults.corlib, "System.Reflection", "Module");
5076 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5078 table = &image->tables [MONO_TABLE_FILE];
5079 g_assert (table_index < table->rows);
5080 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5083 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5084 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5086 /* Check whenever the row has a corresponding row in the moduleref table */
5087 table = &image->tables [MONO_TABLE_MODULEREF];
5088 for (i = 0; i < table->rows; ++i) {
5089 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5090 val = mono_metadata_string_heap (image, name_idx);
5091 if (strcmp (val, name) == 0)
5092 res->image = image->modules [i];
5095 res->fqname = mono_string_new (domain, name);
5096 res->name = mono_string_new (domain, name);
5097 res->scopename = mono_string_new (domain, name);
5098 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5099 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5105 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5107 if ((t1->type != t2->type) ||
5108 (t1->byref != t2->byref))
5112 case MONO_TYPE_VOID:
5113 case MONO_TYPE_BOOLEAN:
5114 case MONO_TYPE_CHAR:
5125 case MONO_TYPE_STRING:
5128 case MONO_TYPE_OBJECT:
5129 case MONO_TYPE_TYPEDBYREF:
5131 case MONO_TYPE_VALUETYPE:
5132 case MONO_TYPE_CLASS:
5133 case MONO_TYPE_SZARRAY:
5134 return t1->data.klass == t2->data.klass;
5136 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5137 case MONO_TYPE_ARRAY:
5138 if (t1->data.array->rank != t2->data.array->rank)
5140 return t1->data.array->eklass == t2->data.array->eklass;
5141 case MONO_TYPE_GENERICINST: {
5143 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5145 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5147 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5148 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5154 case MONO_TYPE_MVAR:
5155 return t1->data.generic_param == t2->data.generic_param;
5157 g_error ("implement type compare for %0x!", t1->type);
5165 mymono_metadata_type_hash (MonoType *t1)
5171 hash |= t1->byref << 6; /* do not collide with t1->type values */
5173 case MONO_TYPE_VALUETYPE:
5174 case MONO_TYPE_CLASS:
5175 case MONO_TYPE_SZARRAY:
5176 /* check if the distribution is good enough */
5177 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5179 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5184 static MonoReflectionGenericInst*
5185 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5187 static MonoClass *System_Reflection_MonoGenericInst;
5188 MonoReflectionGenericInst *res;
5189 MonoGenericInst *ginst;
5192 if (!System_Reflection_MonoGenericInst) {
5193 System_Reflection_MonoGenericInst = mono_class_from_name (
5194 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5195 g_assert (System_Reflection_MonoGenericInst);
5198 ginst = geninst->data.generic_inst;
5199 gklass = mono_class_from_mono_type (ginst->generic_type);
5201 mono_class_init (ginst->klass);
5203 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5205 res->type.type = geninst;
5206 if (gklass->wastypebuilder && gklass->reflection_info)
5207 res->generic_type = gklass->reflection_info;
5209 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5215 * mono_type_get_object:
5216 * @domain: an app domain
5219 * Return an System.MonoType object representing the type @type.
5222 mono_type_get_object (MonoDomain *domain, MonoType *type)
5224 MonoReflectionType *res;
5225 MonoClass *klass = mono_class_from_mono_type (type);
5227 mono_domain_lock (domain);
5228 if (!domain->type_hash)
5229 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5230 (GCompareFunc)mymono_metadata_type_equal);
5231 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5232 mono_domain_unlock (domain);
5235 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5236 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5237 mono_g_hash_table_insert (domain->type_hash, type, res);
5238 mono_domain_unlock (domain);
5241 if (klass->reflection_info && !klass->wastypebuilder) {
5242 /* g_assert_not_reached (); */
5243 /* should this be considered an error condition? */
5245 mono_domain_unlock (domain);
5246 return klass->reflection_info;
5249 mono_class_init (klass);
5250 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5252 mono_g_hash_table_insert (domain->type_hash, type, res);
5253 mono_domain_unlock (domain);
5258 * mono_method_get_object:
5259 * @domain: an app domain
5261 * @refclass: the reflected type (can be NULL)
5263 * Return an System.Reflection.MonoMethod object representing the method @method.
5265 MonoReflectionMethod*
5266 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5269 * We use the same C representation for methods and constructors, but the type
5270 * name in C# is different.
5274 MonoReflectionMethod *ret;
5277 refclass = method->klass;
5279 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5280 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5281 cname = "MonoCMethod";
5283 cname = "MonoMethod";
5284 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5286 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5287 ret->method = method;
5288 ret->name = mono_string_new (domain, method->name);
5289 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5290 CACHE_OBJECT (method, ret, refclass);
5295 * mono_field_get_object:
5296 * @domain: an app domain
5300 * Return an System.Reflection.MonoField object representing the field @field
5303 MonoReflectionField*
5304 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5306 MonoReflectionField *res;
5309 CHECK_OBJECT (MonoReflectionField *, field, klass);
5310 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5311 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5314 res->name = mono_string_new (domain, field->name);
5315 if (field->generic_info)
5316 res->attrs = field->generic_info->generic_type->attrs;
5318 res->attrs = field->type->attrs;
5319 res->type = mono_type_get_object (domain, field->type);
5320 CACHE_OBJECT (field, res, klass);
5325 * mono_property_get_object:
5326 * @domain: an app domain
5328 * @property: a property
5330 * Return an System.Reflection.MonoProperty object representing the property @property
5333 MonoReflectionProperty*
5334 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5336 MonoReflectionProperty *res;
5339 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5340 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5341 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5343 res->property = property;
5344 CACHE_OBJECT (property, res, klass);
5349 * mono_event_get_object:
5350 * @domain: an app domain
5354 * Return an System.Reflection.MonoEvent object representing the event @event
5357 MonoReflectionEvent*
5358 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5360 MonoReflectionEvent *res;
5363 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5364 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5365 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5368 CACHE_OBJECT (event, res, klass);
5373 * mono_param_get_objects:
5374 * @domain: an app domain
5377 * Return an System.Reflection.ParameterInfo array object representing the parameters
5378 * in the method @method.
5381 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5383 static MonoClass *System_Reflection_ParameterInfo;
5385 MonoArray *res = NULL;
5386 MonoReflectionMethod *member = NULL;
5387 MonoReflectionParameter *param = NULL;
5388 char **names, **blobs = NULL;
5389 MonoObject *dbnull = mono_get_dbnull_object (domain);
5392 if (!System_Reflection_ParameterInfo)
5393 System_Reflection_ParameterInfo = mono_class_from_name (
5394 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5396 if (!method->signature->param_count)
5397 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5399 /* Note: the cache is based on the address of the signature into the method
5400 * since we already cache MethodInfos with the method as keys.
5402 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5404 member = mono_method_get_object (domain, method, NULL);
5405 names = g_new (char *, method->signature->param_count);
5406 mono_method_get_param_names (method, (const char **) names);
5408 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5409 for (i = 0; i < method->signature->param_count; ++i) {
5410 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5411 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5412 param->MemberImpl = (MonoObject*)member;
5413 param->NameImpl = mono_string_new (domain, names [i]);
5414 param->PositionImpl = i;
5415 param->AttrsImpl = method->signature->params [i]->attrs;
5417 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5418 param->DefaultValueImpl = dbnull;
5420 MonoType *type = param->ClassImpl->type;
5423 blobs = g_new0 (char *, method->signature->param_count);
5424 get_default_param_value_blobs (method, blobs);
5427 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5429 if (!param->DefaultValueImpl) {
5430 param->DefaultValueImpl = dbnull;
5434 mono_array_set (res, gpointer, i, param);
5439 CACHE_OBJECT (&(method->signature), res, NULL);
5444 mono_get_dbnull_object (MonoDomain *domain)
5448 static MonoClassField *dbnull_value_field = NULL;
5450 if (!dbnull_value_field) {
5451 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5452 mono_class_init (klass);
5453 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5454 g_assert (dbnull_value_field);
5456 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5463 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5465 guint32 param_index, i, lastp, crow = 0;
5466 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5469 MonoClass *klass = method->klass;
5470 MonoImage *image = klass->image;
5471 MonoDomain *domain = mono_domain_get ();
5472 MonoMethodSignature *methodsig = method->signature;
5474 MonoTableInfo *constt;
5475 MonoTableInfo *methodt;
5476 MonoTableInfo *paramt;
5478 if (!methodsig->param_count)
5481 if (klass->generic_inst) {
5482 return; /* FIXME - ??? */
5485 mono_class_init (klass);
5487 if (klass->image->dynamic) {
5491 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5492 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5493 constt = &image->tables [MONO_TABLE_CONSTANT];
5495 for (i = 0; i < klass->method.count; ++i) {
5496 if (method == klass->methods [i]) {
5497 idx = klass->method.first + i;
5502 g_assert (idx != -1);
5504 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5505 if (idx + 1 < methodt->rows)
5506 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5508 lastp = paramt->rows + 1;
5510 for (i = param_index; i < lastp; ++i) {
5513 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5514 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5516 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5519 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5524 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5525 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5532 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5541 klass = mono_class_from_mono_type (type);
5542 if (klass->valuetype) {
5543 object = mono_object_new (domain, klass);
5544 retval = ((gchar *) object + sizeof (MonoObject));
5549 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5556 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5560 memset (assembly, 0, sizeof (MonoAssemblyName));
5562 assembly->culture = "";
5563 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5565 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5568 while (*p == ' ' || *p == ',') {
5577 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5579 assembly->major = strtoul (p, &s, 10);
5580 if (s == p || *s != '.')
5583 assembly->minor = strtoul (p, &s, 10);
5584 if (s == p || *s != '.')
5587 assembly->build = strtoul (p, &s, 10);
5588 if (s == p || *s != '.')
5591 assembly->revision = strtoul (p, &s, 10);
5595 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5597 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5598 assembly->culture = "";
5601 assembly->culture = p;
5602 while (*p && *p != ',') {
5606 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5608 if (strncmp (p, "null", 4) == 0) {
5613 while (*p && *p != ',') {
5616 len = (p - start + 1);
5617 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5618 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5619 g_strlcpy (assembly->public_key_token, start, len);
5622 while (*p && *p != ',')
5626 while (*p == ' ' || *p == ',') {
5640 * mono_reflection_parse_type:
5643 * Parse a type name as accepted by the GetType () method and output the info
5644 * extracted in the info structure.
5645 * the name param will be mangled, so, make a copy before passing it to this function.
5646 * The fields in info will be valid until the memory pointed to by name is valid.
5647 * Returns 0 on parse error.
5648 * See also mono_type_get_name () below.
5651 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5653 char *start, *p, *w, *last_point, *startn;
5654 int in_modifiers = 0;
5655 int isbyref = 0, rank;
5657 start = p = w = name;
5659 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5660 info->name = info->name_space = NULL;
5661 info->nested = NULL;
5662 info->modifiers = NULL;
5664 /* last_point separates the namespace from the name */
5670 *p = 0; /* NULL terminate the name */
5672 info->nested = g_list_append (info->nested, startn);
5673 /* we have parsed the nesting namespace + name */
5677 info->name_space = start;
5679 info->name = last_point + 1;
5681 info->name_space = (char *)"";
5707 info->name_space = start;
5709 info->name = last_point + 1;
5711 info->name_space = (char *)"";
5718 if (isbyref) /* only one level allowed by the spec */
5721 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5725 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5736 else if (*p != '*') /* '*' means unknown lower bound */
5742 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5754 return 0; /* missing assembly name */
5755 if (!assembly_name_to_aname (&info->assembly, p))
5762 if (info->assembly.name)
5765 *w = 0; /* terminate class name */
5766 if (!info->name || !*info->name)
5768 /* add other consistency checks */
5773 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5780 image = mono_defaults.corlib;
5783 klass = mono_class_from_name_case (image, info->name_space, info->name);
5785 klass = mono_class_from_name (image, info->name_space, info->name);
5788 for (mod = info->nested; mod; mod = mod->next) {
5791 mono_class_init (klass);
5792 nested = klass->nested_classes;
5795 klass = nested->data;
5797 if (g_strcasecmp (klass->name, mod->data) == 0)
5800 if (strcmp (klass->name, mod->data) == 0)
5804 nested = nested->next;
5811 mono_class_init (klass);
5812 for (mod = info->modifiers; mod; mod = mod->next) {
5813 modval = GPOINTER_TO_UINT (mod->data);
5814 if (!modval) { /* byref: must be last modifier */
5815 return &klass->this_arg;
5816 } else if (modval == -1) {
5817 klass = mono_ptr_class_get (&klass->byval_arg);
5818 } else { /* array rank */
5819 klass = mono_array_class_get (klass, modval);
5821 mono_class_init (klass);
5824 return &klass->byval_arg;
5828 * mono_reflection_get_type:
5829 * @image: a metadata context
5830 * @info: type description structure
5831 * @ignorecase: flag for case-insensitive string compares
5832 * @type_resolve: whenever type resolve was already tried
5834 * Build a MonoType from the type description in @info.
5839 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5842 MonoReflectionAssembly *assembly;
5846 type = mono_reflection_get_type_internal (image, info, ignorecase);
5849 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5852 /* FIXME: Enabling this causes regressions (#65577) */
5858 *type_resolve = TRUE;
5862 /* Reconstruct the type name */
5863 fullName = g_string_new ("");
5864 if (info->name_space && (info->name_space [0] != '\0'))
5865 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5867 g_string_printf (fullName, info->name);
5868 for (mod = info->nested; mod; mod = mod->next)
5869 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5871 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5872 if (assembly && (!image || (assembly->assembly->image == image))) {
5874 if (assembly->assembly->dynamic) {
5875 /* Enumerate all modules */
5876 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5880 if (abuilder->modules) {
5881 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5882 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5883 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5889 if (!type && abuilder->loaded_modules) {
5890 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5891 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5892 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5899 type = mono_reflection_get_type_internal (assembly->assembly->image,
5902 g_string_free (fullName, TRUE);
5907 * mono_reflection_type_from_name:
5909 * @image: a metadata context (can be NULL).
5911 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5912 * it defaults to get the type from @image or, if @image is NULL or loading
5913 * from it fails, uses corlib.
5917 mono_reflection_type_from_name (char *name, MonoImage *image)
5920 MonoTypeNameParse info;
5921 MonoAssembly *assembly;
5923 gboolean type_resolve = FALSE;
5925 /* Make a copy since parse_type modifies its argument */
5926 tmp = g_strdup (name);
5928 /*g_print ("requested type %s\n", str);*/
5929 if (!mono_reflection_parse_type (tmp, &info)) {
5931 g_list_free (info.modifiers);
5932 g_list_free (info.nested);
5936 if (info.assembly.name) {
5937 assembly = mono_assembly_loaded (&info.assembly);
5939 /* then we must load the assembly ourselve - see #60439 */
5940 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5943 g_list_free (info.modifiers);
5944 g_list_free (info.nested);
5948 image = assembly->image;
5949 } else if (image == NULL) {
5950 image = mono_defaults.corlib;
5953 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5954 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5955 image = mono_defaults.corlib;
5956 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5960 g_list_free (info.modifiers);
5961 g_list_free (info.nested);
5966 * mono_reflection_get_token:
5968 * Return the metadata token of OBJ which should be an object
5969 * representing a metadata element.
5972 mono_reflection_get_token (MonoObject *obj)
5977 klass = obj->vtable->klass;
5979 if (strcmp (klass->name, "MethodBuilder") == 0) {
5980 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5982 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5983 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5984 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5986 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5987 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5988 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5989 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5990 if (tb->generic_params) {
5991 g_assert_not_reached ();
5993 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5995 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5996 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5997 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5998 } else if (strcmp (klass->name, "MonoType") == 0) {
5999 MonoReflectionType *tb = (MonoReflectionType *)obj;
6000 token = mono_class_from_mono_type (tb->type)->type_token;
6001 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6002 strcmp (klass->name, "MonoMethod") == 0) {
6003 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6004 if (m->method->signature->is_inflated) {
6005 g_assert_not_reached ();
6006 } else if (m->method->signature->generic_param_count) {
6007 g_assert_not_reached ();
6008 } else if (m->method->klass->generic_inst) {
6009 g_assert_not_reached ();
6011 token = m->method->token;
6013 } else if (strcmp (klass->name, "MonoField") == 0) {
6014 MonoReflectionField *f = (MonoReflectionField*)obj;
6016 token = mono_class_get_field_token (f->field);
6017 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6018 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6020 token = mono_class_get_property_token (p->property);
6021 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6022 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6024 token = mono_class_get_event_token (p->event);
6025 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6026 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6028 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6029 } else if (strcmp (klass->name, "Module") == 0) {
6030 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6033 } else if (strcmp (klass->name, "Assembly") == 0) {
6034 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6036 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6037 MonoException *ex = mono_get_exception_not_implemented (msg);
6039 mono_raise_exception (ex);
6046 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6048 int slen, type = t->type;
6053 case MONO_TYPE_BOOLEAN: {
6054 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6059 case MONO_TYPE_CHAR:
6061 case MONO_TYPE_I2: {
6062 guint16 *val = g_malloc (sizeof (guint16));
6067 #if SIZEOF_VOID_P == 4
6073 case MONO_TYPE_I4: {
6074 guint32 *val = g_malloc (sizeof (guint32));
6079 #if SIZEOF_VOID_P == 8
6080 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6085 case MONO_TYPE_I8: {
6086 guint64 *val = g_malloc (sizeof (guint64));
6091 case MONO_TYPE_VALUETYPE:
6092 if (t->data.klass->enumtype) {
6093 type = t->data.klass->enum_basetype->type;
6096 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6099 case MONO_TYPE_STRING:
6100 if (*p == (char)0xFF) {
6104 slen = mono_metadata_decode_value (p, &p);
6106 return mono_string_new_len (mono_domain_get (), p, slen);
6107 case MONO_TYPE_CLASS: {
6110 if (*p == (char)0xFF) {
6115 slen = mono_metadata_decode_value (p, &p);
6116 n = g_memdup (p, slen + 1);
6118 t = mono_reflection_type_from_name (n, image);
6120 g_warning ("Cannot load type '%s'", n);
6124 return mono_type_get_object (mono_domain_get (), t);
6128 case MONO_TYPE_OBJECT: {
6131 MonoClass *subc = NULL;
6136 } else if (subt == 0x0E) {
6137 type = MONO_TYPE_STRING;
6139 } else if (subt == 0x55) {
6142 slen = mono_metadata_decode_value (p, &p);
6143 n = g_memdup (p, slen + 1);
6145 t = mono_reflection_type_from_name (n, image);
6147 g_warning ("Cannot load type '%s'", n);
6150 subc = mono_class_from_mono_type (t);
6151 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6152 MonoType simple_type = {{0}};
6153 simple_type.type = subt;
6154 subc = mono_class_from_mono_type (&simple_type);
6156 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6158 val = load_cattr_value (image, &subc->byval_arg, p, end);
6159 obj = mono_object_new (mono_domain_get (), subc);
6160 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6164 case MONO_TYPE_SZARRAY: {
6166 guint32 i, alen, basetype;
6169 if (alen == 0xffffffff) {
6173 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6174 basetype = t->data.klass->byval_arg.type;
6179 case MONO_TYPE_BOOLEAN:
6180 for (i = 0; i < alen; i++) {
6181 MonoBoolean val = *p++;
6182 mono_array_set (arr, MonoBoolean, i, val);
6185 case MONO_TYPE_CHAR:
6188 for (i = 0; i < alen; i++) {
6189 guint16 val = read16 (p);
6190 mono_array_set (arr, guint16, i, val);
6197 for (i = 0; i < alen; i++) {
6198 guint32 val = read32 (p);
6199 mono_array_set (arr, guint32, i, val);
6206 for (i = 0; i < alen; i++) {
6207 guint64 val = read64 (p);
6208 mono_array_set (arr, guint64, i, val);
6212 case MONO_TYPE_CLASS:
6213 case MONO_TYPE_OBJECT:
6214 case MONO_TYPE_STRING:
6215 for (i = 0; i < alen; i++) {
6216 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6217 mono_array_set (arr, gpointer, i, item);
6221 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6227 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6233 type_is_reference (MonoType *type)
6235 switch (type->type) {
6236 case MONO_TYPE_BOOLEAN:
6237 case MONO_TYPE_CHAR:
6250 case MONO_TYPE_VALUETYPE:
6258 free_param_data (MonoMethodSignature *sig, void **params) {
6260 for (i = 0; i < sig->param_count; ++i) {
6261 if (!type_is_reference (sig->params [i]))
6262 g_free (params [i]);
6267 * Find the method index in the metadata methodDef table.
6268 * Later put these three helper methods in metadata and export them.
6271 find_method_index (MonoMethod *method) {
6272 MonoClass *klass = method->klass;
6275 for (i = 0; i < klass->method.count; ++i) {
6276 if (method == klass->methods [i])
6277 return klass->method.first + 1 + i;
6283 * Find the field index in the metadata FieldDef table.
6286 find_field_index (MonoClass *klass, MonoClassField *field) {
6289 for (i = 0; i < klass->field.count; ++i) {
6290 if (field == &klass->fields [i])
6291 return klass->field.first + 1 + i;
6297 * Find the property index in the metadata Property table.
6300 find_property_index (MonoClass *klass, MonoProperty *property) {
6303 for (i = 0; i < klass->property.count; ++i) {
6304 if (property == &klass->properties [i])
6305 return klass->property.first + 1 + i;
6311 * Find the event index in the metadata Event table.
6314 find_event_index (MonoClass *klass, MonoEvent *event) {
6317 for (i = 0; i < klass->event.count; ++i) {
6318 if (event == &klass->events [i])
6319 return klass->event.first + 1 + i;
6325 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6327 const char *p = data;
6329 guint32 i, j, num_named;
6333 mono_class_init (method->klass);
6336 attr = mono_object_new (mono_domain_get (), method->klass);
6337 mono_runtime_invoke (method, attr, NULL, NULL);
6341 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6344 /*g_print ("got attr %s\n", method->klass->name);*/
6346 params = g_new (void*, method->signature->param_count);
6350 for (i = 0; i < method->signature->param_count; ++i) {
6351 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6355 attr = mono_object_new (mono_domain_get (), method->klass);
6356 mono_runtime_invoke (method, attr, params, NULL);
6357 free_param_data (method->signature, params);
6359 num_named = read16 (named);
6361 for (j = 0; j < num_named; j++) {
6363 char *name, named_type, data_type;
6364 named_type = *named++;
6365 data_type = *named++; /* type of data */
6366 if (data_type == 0x55) {
6369 type_len = mono_metadata_decode_blob_size (named, &named);
6370 type_name = g_malloc (type_len + 1);
6371 memcpy (type_name, named, type_len);
6372 type_name [type_len] = 0;
6374 /* FIXME: lookup the type and check type consistency */
6375 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6376 /* this seems to be the type of the element of the array */
6377 /* g_print ("skipping 0x%02x after prop\n", *named); */
6380 name_len = mono_metadata_decode_blob_size (named, &named);
6381 name = g_malloc (name_len + 1);
6382 memcpy (name, named, name_len);
6383 name [name_len] = 0;
6385 if (named_type == 0x53) {
6386 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6387 void *val = load_cattr_value (image, field->type, named, &named);
6388 mono_field_set_value (attr, field, val);
6389 if (!type_is_reference (field->type))
6391 } else if (named_type == 0x54) {
6394 MonoType *prop_type;
6396 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6397 /* can we have more that 1 arg in a custom attr named property? */
6398 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6399 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6400 mono_property_set_value (prop, attr, pparams, NULL);
6401 if (!type_is_reference (prop_type))
6402 g_free (pparams [0]);
6411 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6418 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6419 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6420 for (i = 0; i < cinfo->num_attrs; ++i) {
6421 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6422 mono_array_set (result, gpointer, i, attr);
6428 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6430 guint32 mtoken, i, len;
6431 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6433 MonoCustomAttrInfo *ainfo;
6434 GList *tmp, *list = NULL;
6437 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6439 i = mono_metadata_custom_attrs_from_index (image, idx);
6443 while (i < ca->rows) {
6444 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6446 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6449 len = g_list_length (list);
6452 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6453 ainfo->num_attrs = len;
6454 ainfo->image = image;
6455 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6456 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6457 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6458 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6459 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6460 mtoken |= MONO_TOKEN_METHOD_DEF;
6462 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6463 mtoken |= MONO_TOKEN_MEMBER_REF;
6466 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6469 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6470 if (!ainfo->attrs [i].ctor)
6471 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6472 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6473 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6474 ainfo->attrs [i].data = data;
6482 mono_custom_attrs_from_method (MonoMethod *method)
6484 MonoCustomAttrInfo *cinfo;
6487 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6489 idx = find_method_index (method);
6490 idx <<= MONO_CUSTOM_ATTR_BITS;
6491 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6492 return mono_custom_attrs_from_index (method->klass->image, idx);
6496 mono_custom_attrs_from_class (MonoClass *klass)
6498 MonoCustomAttrInfo *cinfo;
6501 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6503 idx = mono_metadata_token_index (klass->type_token);
6504 idx <<= MONO_CUSTOM_ATTR_BITS;
6505 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6506 return mono_custom_attrs_from_index (klass->image, idx);
6510 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6512 MonoCustomAttrInfo *cinfo;
6515 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6517 idx = 1; /* there is only one assembly */
6518 idx <<= MONO_CUSTOM_ATTR_BITS;
6519 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6520 return mono_custom_attrs_from_index (assembly->image, idx);
6523 static MonoCustomAttrInfo*
6524 mono_custom_attrs_from_module (MonoImage *image)
6526 MonoCustomAttrInfo *cinfo;
6529 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6531 idx = 1; /* there is only one module */
6532 idx <<= MONO_CUSTOM_ATTR_BITS;
6533 idx |= MONO_CUSTOM_ATTR_MODULE;
6534 return mono_custom_attrs_from_index (image, idx);
6538 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6540 MonoCustomAttrInfo *cinfo;
6543 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6545 idx = find_property_index (klass, property);
6546 idx <<= MONO_CUSTOM_ATTR_BITS;
6547 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6548 return mono_custom_attrs_from_index (klass->image, idx);
6552 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6554 MonoCustomAttrInfo *cinfo;
6557 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6559 idx = find_event_index (klass, event);
6560 idx <<= MONO_CUSTOM_ATTR_BITS;
6561 idx |= MONO_CUSTOM_ATTR_EVENT;
6562 return mono_custom_attrs_from_index (klass->image, idx);
6566 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6568 MonoCustomAttrInfo *cinfo;
6571 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6573 idx = find_field_index (klass, field);
6574 idx <<= MONO_CUSTOM_ATTR_BITS;
6575 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6576 return mono_custom_attrs_from_index (klass->image, idx);
6580 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6583 guint32 i, idx, method_index;
6584 guint32 param_list, param_last, param_pos, found;
6586 MonoReflectionMethodAux *aux;
6588 if (method->klass->image->dynamic) {
6589 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6590 if (!aux || !aux->param_cattr)
6592 return aux->param_cattr [param];
6595 image = method->klass->image;
6596 method_index = find_method_index (method);
6597 ca = &image->tables [MONO_TABLE_METHOD];
6599 if (method->klass->generic_inst || method->klass->gen_params ||
6600 method->signature->generic_param_count) {
6601 /* FIXME FIXME FIXME */
6605 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6606 if (method_index == ca->rows) {
6607 ca = &image->tables [MONO_TABLE_PARAM];
6608 param_last = ca->rows + 1;
6610 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6611 ca = &image->tables [MONO_TABLE_PARAM];
6614 for (i = param_list; i < param_last; ++i) {
6615 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6616 if (param_pos == param) {
6624 idx <<= MONO_CUSTOM_ATTR_BITS;
6625 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6626 return mono_custom_attrs_from_index (image, idx);
6630 * mono_reflection_get_custom_attrs:
6631 * @obj: a reflection object handle
6633 * Return an array with all the custom attributes defined of the
6634 * reflection handle @obj. The objects are fully build.
6637 mono_reflection_get_custom_attrs (MonoObject *obj)
6641 MonoCustomAttrInfo *cinfo = NULL;
6643 MONO_ARCH_SAVE_REGS;
6645 klass = obj->vtable->klass;
6646 if (klass == mono_defaults.monotype_class) {
6647 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6648 klass = mono_class_from_mono_type (rtype->type);
6649 cinfo = mono_custom_attrs_from_class (klass);
6650 } else if (strcmp ("Assembly", klass->name) == 0) {
6651 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6652 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6653 } else if (strcmp ("Module", klass->name) == 0) {
6654 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6655 cinfo = mono_custom_attrs_from_module (module->image);
6656 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6657 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6658 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6659 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6660 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6661 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6662 } else if (strcmp ("MonoField", klass->name) == 0) {
6663 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6664 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6665 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6666 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6667 cinfo = mono_custom_attrs_from_method (rmethod->method);
6668 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6669 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6670 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6671 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6672 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6673 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6674 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6675 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6676 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6677 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6678 } else { /* handle other types here... */
6679 g_error ("get custom attrs not yet supported for %s", klass->name);
6683 result = mono_custom_attrs_construct (cinfo);
6685 mono_custom_attrs_free (cinfo);
6687 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6688 result = mono_array_new (mono_domain_get (), klass, 0);
6694 static MonoMethodSignature*
6695 parameters_to_signature (MonoArray *parameters) {
6696 MonoMethodSignature *sig;
6699 count = parameters? mono_array_length (parameters): 0;
6701 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6702 sig->param_count = count;
6703 sig->sentinelpos = -1; /* FIXME */
6704 for (i = 0; i < count; ++i) {
6705 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6706 sig->params [i] = pt->type;
6711 static MonoMethodSignature*
6712 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6713 MonoMethodSignature *sig;
6715 sig = parameters_to_signature (ctor->parameters);
6716 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6717 sig->ret = &mono_defaults.void_class->byval_arg;
6721 static MonoMethodSignature*
6722 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6723 MonoMethodSignature *sig;
6725 sig = parameters_to_signature (method->parameters);
6726 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6727 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6728 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6732 static MonoMethodSignature*
6733 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6734 MonoMethodSignature *sig;
6736 sig = parameters_to_signature (method->parameters);
6737 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6738 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6739 sig->generic_param_count = 0;
6744 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6746 MonoClass *klass = mono_object_class (prop);
6747 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6748 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6749 *name = mono_string_to_utf8 (pb->name);
6750 *type = pb->type->type;
6752 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6753 *name = g_strdup (p->property->name);
6754 if (p->property->get)
6755 *type = p->property->get->signature->ret;
6757 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6762 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6764 MonoClass *klass = mono_object_class (field);
6765 if (strcmp (klass->name, "FieldBuilder") == 0) {
6766 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6767 *name = mono_string_to_utf8 (fb->name);
6768 *type = fb->type->type;
6770 MonoReflectionField *f = (MonoReflectionField *)field;
6771 *name = g_strdup (f->field->name);
6772 *type = f->field->type;
6777 * Encode a value in a custom attribute stream of bytes.
6778 * The value to encode is either supplied as an object in argument val
6779 * (valuetypes are boxed), or as a pointer to the data in the
6781 * @type represents the type of the value
6782 * @buffer is the start of the buffer
6783 * @p the current position in the buffer
6784 * @buflen contains the size of the buffer and is used to return the new buffer size
6785 * if this needs to be realloced.
6786 * @retbuffer and @retp return the start and the position of the buffer
6789 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6791 MonoTypeEnum simple_type;
6793 if ((p-buffer) + 10 >= *buflen) {
6796 newbuf = g_realloc (buffer, *buflen);
6797 p = newbuf + (p-buffer);
6801 argval = ((char*)arg + sizeof (MonoObject));
6802 simple_type = type->type;
6804 switch (simple_type) {
6805 case MONO_TYPE_BOOLEAN:
6810 case MONO_TYPE_CHAR:
6813 swap_with_size (p, argval, 2, 1);
6819 swap_with_size (p, argval, 4, 1);
6825 swap_with_size (p, argval, 8, 1);
6828 case MONO_TYPE_VALUETYPE:
6829 if (type->data.klass->enumtype) {
6830 simple_type = type->data.klass->enum_basetype->type;
6833 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6836 case MONO_TYPE_STRING: {
6843 str = mono_string_to_utf8 ((MonoString*)arg);
6844 slen = strlen (str);
6845 if ((p-buffer) + 10 + slen >= *buflen) {
6849 newbuf = g_realloc (buffer, *buflen);
6850 p = newbuf + (p-buffer);
6853 mono_metadata_encode_value (slen, p, &p);
6854 memcpy (p, str, slen);
6859 case MONO_TYPE_CLASS: {
6867 k = mono_object_class (arg);
6868 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6869 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6870 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6872 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6873 slen = strlen (str);
6874 if ((p-buffer) + 10 + slen >= *buflen) {
6878 newbuf = g_realloc (buffer, *buflen);
6879 p = newbuf + (p-buffer);
6882 mono_metadata_encode_value (slen, p, &p);
6883 memcpy (p, str, slen);
6888 case MONO_TYPE_SZARRAY: {
6890 MonoClass *eclass, *arg_eclass;
6893 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6896 len = mono_array_length ((MonoArray*)arg);
6898 *p++ = (len >> 8) & 0xff;
6899 *p++ = (len >> 16) & 0xff;
6900 *p++ = (len >> 24) & 0xff;
6902 *retbuffer = buffer;
6903 eclass = type->data.klass;
6904 arg_eclass = mono_object_class (arg)->element_class;
6905 if (eclass->valuetype && arg_eclass->valuetype) {
6906 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6907 int elsize = mono_class_array_element_size (eclass);
6908 for (i = 0; i < len; ++i) {
6909 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6913 for (i = 0; i < len; ++i) {
6914 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6919 /* it may be a boxed value or a Type */
6920 case MONO_TYPE_OBJECT: {
6921 MonoClass *klass = mono_object_class (arg);
6925 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6928 } else if (klass->enumtype) {
6930 } else if (klass == mono_defaults.string_class) {
6931 simple_type = MONO_TYPE_STRING;
6934 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6935 *p++ = simple_type = klass->byval_arg.type;
6938 g_error ("unhandled type in custom attr");
6940 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6941 slen = strlen (str);
6942 if ((p-buffer) + 10 + slen >= *buflen) {
6946 newbuf = g_realloc (buffer, *buflen);
6947 p = newbuf + (p-buffer);
6950 mono_metadata_encode_value (slen, p, &p);
6951 memcpy (p, str, slen);
6954 simple_type = klass->enum_basetype->type;
6958 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6961 *retbuffer = buffer;
6965 * mono_reflection_get_custom_attrs_blob:
6966 * @ctor: custom attribute constructor
6967 * @ctorArgs: arguments o the constructor
6973 * Creates the blob of data that needs to be saved in the metadata and that represents
6974 * the custom attributed described by @ctor, @ctorArgs etc.
6975 * Returns: a Byte array representing the blob of data.
6978 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6981 MonoMethodSignature *sig;
6986 MONO_ARCH_SAVE_REGS;
6988 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6989 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6991 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6993 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6995 p = buffer = g_malloc (buflen);
6996 /* write the prolog */
6999 for (i = 0; i < sig->param_count; ++i) {
7000 arg = mono_array_get (ctorArgs, MonoObject*, i);
7001 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7005 i += mono_array_length (properties);
7007 i += mono_array_length (fields);
7009 *p++ = (i >> 8) & 0xff;
7012 for (i = 0; i < mono_array_length (properties); ++i) {
7017 prop = mono_array_get (properties, gpointer, i);
7018 get_prop_name_and_type (prop, &pname, &ptype);
7019 *p++ = 0x54; /* PROPERTY signature */
7021 /* Preallocate a large enough buffer */
7022 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7023 char *str = type_get_qualified_name (ptype, NULL);
7029 len += strlen (pname);
7031 if ((p-buffer) + 20 + len >= buflen) {
7035 newbuf = g_realloc (buffer, buflen);
7036 p = newbuf + (p-buffer);
7040 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7041 char *str = type_get_qualified_name (ptype, NULL);
7042 int slen = strlen (str);
7046 * This seems to be optional...
7049 mono_metadata_encode_value (slen, p, &p);
7050 memcpy (p, str, slen);
7054 mono_metadata_encode_value (ptype->type, p, &p);
7055 if (ptype->type == MONO_TYPE_SZARRAY)
7056 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7058 len = strlen (pname);
7059 mono_metadata_encode_value (len, p, &p);
7060 memcpy (p, pname, len);
7062 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7069 for (i = 0; i < mono_array_length (fields); ++i) {
7074 field = mono_array_get (fields, gpointer, i);
7075 get_field_name_and_type (field, &fname, &ftype);
7076 *p++ = 0x53; /* FIELD signature */
7077 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7078 char *str = type_get_qualified_name (ftype, NULL);
7079 int slen = strlen (str);
7080 if ((p-buffer) + 10 + slen >= buflen) {
7084 newbuf = g_realloc (buffer, buflen);
7085 p = newbuf + (p-buffer);
7090 * This seems to be optional...
7093 mono_metadata_encode_value (slen, p, &p);
7094 memcpy (p, str, slen);
7098 mono_metadata_encode_value (ftype->type, p, &p);
7099 if (ftype->type == MONO_TYPE_SZARRAY)
7100 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7102 len = strlen (fname);
7103 mono_metadata_encode_value (len, p, &p);
7104 memcpy (p, fname, len);
7106 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7111 g_assert (p - buffer <= buflen);
7112 buflen = p - buffer;
7113 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7114 p = mono_array_addr (result, char, 0);
7115 memcpy (p, buffer, buflen);
7117 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7123 * mono_reflection_setup_internal_class:
7124 * @tb: a TypeBuilder object
7126 * Creates a MonoClass that represents the TypeBuilder.
7127 * This is a trick that lets us simplify a lot of reflection code
7128 * (and will allow us to support Build and Run assemblies easier).
7131 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7133 MonoClass *klass, *parent;
7135 MONO_ARCH_SAVE_REGS;
7138 /* check so we can compile corlib correctly */
7139 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7140 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7141 parent = tb->parent->type->data.klass;
7143 parent = my_mono_class_from_mono_type (tb->parent->type);
7149 /* the type has already being created: it means we just have to change the parent */
7150 if (tb->type.type) {
7151 klass = mono_class_from_mono_type (tb->type.type);
7152 klass->parent = NULL;
7153 /* fool mono_class_setup_parent */
7154 g_free (klass->supertypes);
7155 klass->supertypes = NULL;
7156 mono_class_setup_parent (klass, parent);
7157 mono_class_setup_mono_type (klass);
7161 klass = g_new0 (MonoClass, 1);
7163 klass->image = &tb->module->dynamic_image->image;
7165 klass->inited = 1; /* we lie to the runtime */
7166 klass->name = mono_string_to_utf8 (tb->name);
7167 klass->name_space = mono_string_to_utf8 (tb->nspace);
7168 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7169 klass->flags = tb->attrs;
7171 klass->element_class = klass;
7172 klass->reflection_info = tb; /* need to pin. */
7174 /* Put into cache so mono_class_get () will find it */
7175 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7177 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7178 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7180 if (parent != NULL) {
7181 mono_class_setup_parent (klass, parent);
7182 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7183 const char *old_n = klass->name;
7184 /* trick to get relative numbering right when compiling corlib */
7185 klass->name = "BuildingObject";
7186 mono_class_setup_parent (klass, mono_defaults.object_class);
7187 klass->name = old_n;
7190 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7191 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7192 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7193 klass->instance_size = sizeof (MonoObject);
7194 klass->size_inited = 1;
7195 mono_class_setup_vtable (klass, NULL, 0);
7198 mono_class_setup_mono_type (klass);
7200 mono_class_setup_supertypes (klass);
7203 * FIXME: handle interfaces.
7206 tb->type.type = &klass->byval_arg;
7208 if (tb->nesting_type) {
7209 g_assert (tb->nesting_type->type);
7210 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7213 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7217 * mono_reflection_setup_generic_class:
7218 * @tb: a TypeBuilder object
7220 * Setup the generic class after all generic parameters have been added.
7223 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7228 MONO_ARCH_SAVE_REGS;
7230 klass = my_mono_class_from_mono_type (tb->type.type);
7232 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7234 if (klass->gen_params || (count == 0))
7237 klass->num_gen_params = count;
7238 klass->gen_params = g_new0 (MonoGenericParam, count);
7240 for (i = 0; i < count; i++) {
7241 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7242 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7247 * mono_reflection_create_internal_class:
7248 * @tb: a TypeBuilder object
7250 * Actually create the MonoClass that is associated with the TypeBuilder.
7253 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7257 MONO_ARCH_SAVE_REGS;
7259 klass = my_mono_class_from_mono_type (tb->type.type);
7261 if (klass->enumtype && klass->enum_basetype == NULL) {
7262 MonoReflectionFieldBuilder *fb;
7265 g_assert (tb->fields != NULL);
7266 g_assert (mono_array_length (tb->fields) >= 1);
7268 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7270 klass->enum_basetype = fb->type->type;
7271 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7272 if (!klass->element_class)
7273 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7276 * get the element_class from the current corlib.
7278 ec = default_class_from_mono_type (klass->enum_basetype);
7279 klass->instance_size = ec->instance_size;
7280 klass->size_inited = 1;
7282 * this is almost safe to do with enums and it's needed to be able
7283 * to create objects of the enum type (for use in SetConstant).
7285 /* FIXME: Does this mean enums can't have method overrides ? */
7286 mono_class_setup_vtable (klass, NULL, 0);
7290 static MonoMarshalSpec*
7291 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7292 MonoReflectionMarshal *minfo)
7294 MonoMarshalSpec *res;
7296 res = g_new0 (MonoMarshalSpec, 1);
7297 res->native = minfo->type;
7299 switch (minfo->type) {
7300 case MONO_NATIVE_LPARRAY:
7301 res->data.array_data.elem_type = minfo->eltype;
7302 res->data.array_data.param_num = 0; /* Not yet */
7303 res->data.array_data.num_elem = minfo->count;
7306 case MONO_NATIVE_BYVALTSTR:
7307 case MONO_NATIVE_BYVALARRAY:
7308 res->data.array_data.num_elem = minfo->count;
7311 case MONO_NATIVE_CUSTOM:
7312 if (minfo->marshaltyperef)
7313 res->data.custom_data.custom_name =
7314 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7316 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7327 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7328 ReflectionMethodBuilder *rmb,
7329 MonoMethodSignature *sig)
7332 MonoMethodNormal *pm;
7333 MonoMarshalSpec **specs;
7334 MonoReflectionMethodAux *method_aux;
7337 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7338 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7339 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7341 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7343 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7345 pm = (MonoMethodNormal*)m;
7348 m->flags = rmb->attrs;
7349 m->iflags = rmb->iattrs;
7350 m->name = mono_string_to_utf8 (rmb->name);
7354 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7356 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7357 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7360 m->signature->pinvoke = 1;
7361 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7362 m->signature->pinvoke = 1;
7364 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7366 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7367 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7369 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7371 if (klass->image->dynamic)
7372 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7375 } else if (!m->klass->dummy &&
7376 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7377 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7378 MonoMethodHeader *header;
7380 gint32 max_stack, i;
7381 gint32 num_locals = 0;
7382 gint32 num_clauses = 0;
7386 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7387 code_size = rmb->ilgen->code_len;
7388 max_stack = rmb->ilgen->max_stack;
7389 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7390 if (rmb->ilgen->ex_handlers)
7391 num_clauses = method_count_clauses (rmb->ilgen);
7394 code = mono_array_addr (rmb->code, guint8, 0);
7395 code_size = mono_array_length (rmb->code);
7396 /* we probably need to run a verifier on the code... */
7406 header = g_malloc0 (sizeof (MonoMethodHeader) +
7407 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7408 header->code_size = code_size;
7409 header->code = g_malloc (code_size);
7410 memcpy ((char*)header->code, code, code_size);
7411 header->max_stack = max_stack;
7412 header->init_locals = rmb->init_locals;
7413 header->num_locals = num_locals;
7415 for (i = 0; i < num_locals; ++i) {
7416 MonoReflectionLocalBuilder *lb =
7417 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7419 header->locals [i] = g_new0 (MonoType, 1);
7420 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7423 header->num_clauses = num_clauses;
7425 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7426 rmb->ilgen, num_clauses);
7429 pm->header = header;
7432 if (rmb->generic_params) {
7433 int count = mono_array_length (rmb->generic_params);
7434 pm->gen_params = g_new0 (MonoGenericParam, count);
7435 for (i = 0; i < count; i++) {
7436 MonoReflectionGenericParam *gp =
7437 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7439 pm->gen_params [i] = *gp->type.type->data.generic_param;
7444 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7447 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7449 for (i = 0; i < rmb->nrefs; ++i)
7450 mw->data = g_list_append (mw->data, rmb->refs [i]);
7455 /* Parameter names */
7458 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7459 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7460 for (i = 0; i <= m->signature->param_count; ++i) {
7461 MonoReflectionParamBuilder *pb;
7462 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7464 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7466 if (!method_aux->param_cattr)
7467 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7468 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7474 /* Parameter marshalling */
7477 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7478 MonoReflectionParamBuilder *pb;
7479 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7480 if (pb->marshal_info) {
7482 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7483 specs [pb->position] =
7484 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7488 if (specs != NULL) {
7490 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7491 method_aux->param_marshall = specs;
7494 if (klass->image->dynamic && method_aux)
7495 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7501 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7503 ReflectionMethodBuilder rmb;
7504 MonoMethodSignature *sig;
7506 sig = ctor_builder_to_signature (mb);
7508 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7510 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7511 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7513 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7514 /* ilgen is no longer needed */
7522 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7524 ReflectionMethodBuilder rmb;
7525 MonoMethodSignature *sig;
7527 sig = method_builder_to_signature (mb);
7529 reflection_methodbuilder_from_method_builder (&rmb, mb);
7531 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7532 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7534 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7535 /* ilgen is no longer needed */
7541 static MonoClassField*
7542 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7544 MonoClassField *field;
7551 field = g_new0 (MonoClassField, 1);
7553 field->name = mono_string_to_utf8 (fb->name);
7555 /* FIXME: handle type modifiers */
7556 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7557 field->type->attrs = fb->attrs;
7559 field->type = fb->type->type;
7561 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7562 field->data = mono_array_addr (fb->rva_data, char, 0);
7563 if (fb->offset != -1)
7564 field->offset = fb->offset;
7565 field->parent = klass;
7567 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7569 if (fb->def_value) {
7570 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7571 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7572 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7573 /* Copy the data from the blob since it might get realloc-ed */
7574 p = assembly->blob.data + idx;
7575 len = mono_metadata_decode_blob_size (p, &p2);
7577 field->data = g_malloc (len);
7578 memcpy ((gpointer)field->data, p, len);
7585 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7588 MonoReflectionTypeBuilder *tb = NULL;
7589 MonoGenericInst *ginst, *cached;
7594 klass = mono_class_from_mono_type (type->type);
7595 if (!klass->gen_params && !klass->generic_inst &&
7596 !(klass->nested_in && klass->nested_in->gen_params))
7599 mono_loader_lock ();
7601 domain = mono_object_domain (type);
7603 ginst = g_new0 (MonoGenericInst, 1);
7605 if (!klass->generic_inst) {
7606 ginst->type_argc = type_argc;
7607 ginst->type_argv = types;
7609 for (i = 0; i < ginst->type_argc; ++i) {
7610 if (!ginst->is_open)
7611 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7614 ginst->generic_type = &klass->byval_arg;
7616 MonoGenericInst *kginst = klass->generic_inst;
7618 ginst->type_argc = kginst->type_argc;
7619 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7621 for (i = 0; i < ginst->type_argc; i++) {
7622 MonoType *t = kginst->type_argv [i];
7624 if (t->type == MONO_TYPE_VAR)
7625 t = types [t->data.generic_param->num];
7627 if (!ginst->is_open)
7628 ginst->is_open = mono_class_is_open_constructed_type (t);
7630 ginst->type_argv [i] = t;
7633 ginst->generic_type = kginst->generic_type;
7636 geninst = g_new0 (MonoType, 1);
7637 geninst->type = MONO_TYPE_GENERICINST;
7639 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7642 mono_loader_unlock ();
7643 geninst->data.generic_inst = cached;
7647 geninst->data.generic_inst = ginst;
7649 ginst->context = g_new0 (MonoGenericContext, 1);
7650 ginst->context->ginst = ginst;
7652 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7653 tb = (MonoReflectionTypeBuilder *) type;
7655 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7656 ginst->is_dynamic = TRUE;
7657 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7658 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7659 MonoReflectionType *rgt = rgi->generic_type;
7661 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7662 tb = (MonoReflectionTypeBuilder *) rgt;
7664 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7665 ginst->is_dynamic = TRUE;
7667 icount = klass->interface_count;
7670 ginst->ifaces = g_new0 (MonoType *, icount);
7671 ginst->count_ifaces = icount;
7673 for (i = 0; i < icount; i++) {
7674 MonoReflectionType *itype;
7677 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7679 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7680 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7681 if (!ginst->ifaces [i])
7682 ginst->ifaces [i] = itype->type;
7685 mono_class_create_generic (ginst);
7687 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7689 mono_loader_unlock ();
7695 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7697 MonoClass *klass, *pklass = NULL;
7698 MonoReflectionType *parent = NULL;
7700 MonoReflectionTypeBuilder *tb = NULL;
7701 MonoGenericInst *ginst;
7704 domain = mono_object_domain (type);
7705 klass = mono_class_from_mono_type (type->type);
7707 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7708 tb = (MonoReflectionTypeBuilder *) type;
7711 parent = tb->parent;
7712 pklass = mono_class_from_mono_type (parent->type);
7715 pklass = klass->parent;
7717 parent = mono_type_get_object (domain, &pklass->byval_arg);
7720 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7724 ginst = geninst->data.generic_inst;
7726 if (pklass && pklass->generic_inst)
7727 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7732 MonoReflectionMethod*
7733 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7735 MonoMethod *method, *inflated;
7736 MonoReflectionMethodBuilder *mb = NULL;
7737 MonoGenericMethod *gmethod;
7738 MonoGenericContext *context;
7741 MONO_ARCH_SAVE_REGS;
7742 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7743 MonoReflectionTypeBuilder *tb;
7746 mb = (MonoReflectionMethodBuilder *) rmethod;
7747 tb = (MonoReflectionTypeBuilder *) mb->type;
7748 klass = mono_class_from_mono_type (tb->type.type);
7750 method = methodbuilder_to_mono_method (klass, mb);
7752 method = rmethod->method;
7755 count = method->signature->generic_param_count;
7756 if (count != mono_array_length (types))
7759 gmethod = g_new0 (MonoGenericMethod, 1);
7760 gmethod->mtype_argc = count;
7761 gmethod->mtype_argv = g_new0 (MonoType *, count);
7762 for (i = 0; i < count; i++) {
7763 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7764 gmethod->mtype_argv [i] = garg->type;
7767 gmethod->reflection_info = rmethod;
7769 context = g_new0 (MonoGenericContext, 1);
7770 context->ginst = method->klass->generic_inst;
7771 context->gmethod = gmethod;
7773 inflated = mono_class_inflate_generic_method (method, context, NULL);
7775 return mono_method_get_object (
7776 mono_object_domain (rmethod), inflated, NULL);
7780 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7782 MonoGenericMethod *gmethod;
7783 MonoGenericInst *ginst;
7784 MonoGenericContext *context;
7787 ginst = type->type.type->data.generic_inst;
7789 gmethod = g_new0 (MonoGenericMethod, 1);
7790 gmethod->reflection_info = obj;
7792 gmethod->mtype_argc = method->signature->generic_param_count;
7793 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7795 for (i = 0; i < gmethod->mtype_argc; i++) {
7796 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7797 MonoGenericParam *gparam = &mn->gen_params [i];
7799 g_assert (gparam->pklass);
7800 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7803 context = g_new0 (MonoGenericContext, 1);
7804 context->ginst = ginst;
7805 context->gmethod = gmethod;
7807 return mono_class_inflate_generic_method (method, context, ginst->klass);
7811 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7816 klass = mono_class_from_mono_type (type->type.type);
7818 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7819 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7820 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7821 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7822 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7823 method = ((MonoReflectionMethod *) obj)->method;
7825 method = NULL; /* prevent compiler warning */
7826 g_assert_not_reached ();
7829 return inflate_mono_method (type, method, obj);
7833 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
7834 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7836 MonoGenericInst *ginst;
7837 MonoDynamicGenericInst *dginst;
7838 MonoClass *klass, *gklass, *pklass;
7841 MONO_ARCH_SAVE_REGS;
7843 klass = mono_class_from_mono_type (type->type.type);
7844 ginst = type->type.type->data.generic_inst;
7846 if (ginst->initialized)
7849 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7851 gklass = mono_class_from_mono_type (ginst->generic_type);
7852 mono_class_init (gklass);
7855 pklass = mono_class_from_mono_type (ginst->parent);
7857 pklass = gklass->parent;
7859 mono_class_setup_parent (klass, pklass);
7861 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7862 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7863 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7864 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7865 dginst->count_events = events ? mono_array_length (events) : 0;
7867 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7868 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7869 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7870 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7871 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7873 for (i = 0; i < dginst->count_methods; i++) {
7874 MonoObject *obj = mono_array_get (methods, gpointer, i);
7876 dginst->methods [i] = inflate_method (type, obj);
7879 for (i = 0; i < dginst->count_ctors; i++) {
7880 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7882 dginst->ctors [i] = inflate_method (type, obj);
7885 for (i = 0; i < dginst->count_fields; i++) {
7886 MonoObject *obj = mono_array_get (fields, gpointer, i);
7887 MonoClassField *field;
7888 MonoInflatedField *ifield;
7890 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7891 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7892 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7893 field = ((MonoReflectionField *) obj)->field;
7895 field = NULL; /* prevent compiler warning */
7896 g_assert_not_reached ();
7899 ifield = g_new0 (MonoInflatedField, 1);
7900 ifield->generic_type = field->type;
7901 ifield->reflection_info = obj;
7903 dginst->fields [i] = *field;
7904 dginst->fields [i].generic_info = ifield;
7905 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7908 for (i = 0; i < dginst->count_properties; i++) {
7909 MonoObject *obj = mono_array_get (properties, gpointer, i);
7910 MonoProperty *property = &dginst->properties [i];
7912 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7913 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7915 property->parent = klass;
7916 property->attrs = pb->attrs;
7917 property->name = mono_string_to_utf8 (pb->name);
7919 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7921 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7922 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7923 *property = *((MonoReflectionProperty *) obj)->property;
7926 property->get = inflate_mono_method (type, property->get, NULL);
7928 property->set = inflate_mono_method (type, property->set, NULL);
7930 g_assert_not_reached ();
7933 for (i = 0; i < dginst->count_events; i++) {
7934 MonoObject *obj = mono_array_get (events, gpointer, i);
7935 MonoEvent *event = &dginst->events [i];
7937 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7938 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7940 event->parent = klass;
7941 event->attrs = eb->attrs;
7942 event->name = mono_string_to_utf8 (eb->name);
7944 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7945 if (eb->remove_method)
7946 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7947 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7948 *event = *((MonoReflectionEvent *) obj)->event;
7951 event->add = inflate_mono_method (type, event->add, NULL);
7953 event->remove = inflate_mono_method (type, event->remove, NULL);
7955 g_assert_not_reached ();
7958 ginst->initialized = TRUE;
7962 ensure_runtime_vtable (MonoClass *klass)
7964 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7965 int i, num, j, onum;
7966 MonoMethod **overrides;
7968 if (!tb || klass->wastypebuilder)
7971 ensure_runtime_vtable (klass->parent);
7973 num = tb->ctors? mono_array_length (tb->ctors): 0;
7974 num += tb->num_methods;
7975 klass->method.count = num;
7976 klass->methods = g_new (MonoMethod*, num);
7977 num = tb->ctors? mono_array_length (tb->ctors): 0;
7978 for (i = 0; i < num; ++i)
7979 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7980 num = tb->num_methods;
7982 for (i = 0; i < num; ++i)
7983 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7985 klass->wastypebuilder = TRUE;
7986 if (tb->interfaces) {
7987 klass->interface_count = mono_array_length (tb->interfaces);
7988 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7989 for (i = 0; i < klass->interface_count; ++i) {
7990 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7991 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7995 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7996 for (i = 0; i < klass->method.count; ++i)
7997 klass->methods [i]->slot = i;
8002 for (i = 0; i < tb->num_methods; ++i) {
8003 MonoReflectionMethodBuilder *mb =
8004 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8005 if (mb->override_method)
8010 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8014 for (i = 0; i < tb->num_methods; ++i) {
8015 MonoReflectionMethodBuilder *mb =
8016 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8017 if (mb->override_method) {
8018 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8019 overrides [onum * 2] =
8020 mb->override_method->method;
8021 overrides [onum * 2 + 1] =
8024 g_assert (mb->mhandle);
8031 mono_class_setup_vtable (klass, overrides, onum);
8035 typebuilder_setup_fields (MonoClass *klass)
8037 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8038 MonoReflectionFieldBuilder *fb;
8039 MonoClassField *field;
8044 klass->field.count = tb->num_fields;
8045 klass->field.first = 0;
8046 klass->field.last = klass->field.count;
8048 if (!klass->field.count)
8051 klass->fields = g_new0 (MonoClassField, klass->field.count);
8053 for (i = 0; i < klass->field.count; ++i) {
8054 fb = mono_array_get (tb->fields, gpointer, i);
8055 field = &klass->fields [i];
8056 field->name = mono_string_to_utf8 (fb->name);
8058 /* FIXME: handle type modifiers */
8059 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8060 field->type->attrs = fb->attrs;
8062 field->type = fb->type->type;
8064 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8065 field->data = mono_array_addr (fb->rva_data, char, 0);
8066 if (fb->offset != -1)
8067 field->offset = fb->offset;
8068 field->parent = klass;
8070 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8072 if (fb->def_value) {
8073 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8074 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8075 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8076 /* Copy the data from the blob since it might get realloc-ed */
8077 p = assembly->blob.data + idx;
8078 len = mono_metadata_decode_blob_size (p, &p2);
8080 field->data = g_malloc (len);
8081 memcpy ((gpointer)field->data, p, len);
8084 mono_class_layout_fields (klass);
8088 typebuilder_setup_properties (MonoClass *klass)
8090 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8091 MonoReflectionPropertyBuilder *pb;
8094 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8095 klass->property.first = 0;
8096 klass->property.last = klass->property.count;
8098 klass->properties = g_new0 (MonoProperty, klass->property.count);
8099 for (i = 0; i < klass->property.count; ++i) {
8100 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8101 klass->properties [i].parent = klass;
8102 klass->properties [i].attrs = pb->attrs;
8103 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8105 klass->properties [i].get = pb->get_method->mhandle;
8107 klass->properties [i].set = pb->set_method->mhandle;
8111 MonoReflectionEvent *
8112 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8114 MonoEvent *event = g_new0 (MonoEvent, 1);
8118 klass = my_mono_class_from_mono_type (tb->type.type);
8120 event->parent = klass;
8121 event->attrs = eb->attrs;
8122 event->name = mono_string_to_utf8 (eb->name);
8124 event->add = eb->add_method->mhandle;
8125 if (eb->remove_method)
8126 event->remove = eb->remove_method->mhandle;
8127 if (eb->raise_method)
8128 event->raise = eb->raise_method->mhandle;
8130 if (eb->other_methods) {
8131 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8132 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8133 MonoReflectionMethodBuilder *mb =
8134 mono_array_get (eb->other_methods,
8135 MonoReflectionMethodBuilder*, j);
8136 event->other [j] = mb->mhandle;
8140 return mono_event_get_object (mono_object_domain (tb), klass, event);
8144 typebuilder_setup_events (MonoClass *klass)
8146 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8147 MonoReflectionEventBuilder *eb;
8150 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8151 klass->event.first = 0;
8152 klass->event.last = klass->event.count;
8154 klass->events = g_new0 (MonoEvent, klass->event.count);
8155 for (i = 0; i < klass->event.count; ++i) {
8156 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8157 klass->events [i].parent = klass;
8158 klass->events [i].attrs = eb->attrs;
8159 klass->events [i].name = mono_string_to_utf8 (eb->name);
8161 klass->events [i].add = eb->add_method->mhandle;
8162 if (eb->remove_method)
8163 klass->events [i].remove = eb->remove_method->mhandle;
8164 if (eb->raise_method)
8165 klass->events [i].raise = eb->raise_method->mhandle;
8167 if (eb->other_methods) {
8168 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8169 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8170 MonoReflectionMethodBuilder *mb =
8171 mono_array_get (eb->other_methods,
8172 MonoReflectionMethodBuilder*, j);
8173 klass->events [i].other [j] = mb->mhandle;
8180 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8183 MonoReflectionType* res;
8186 MONO_ARCH_SAVE_REGS;
8188 klass = my_mono_class_from_mono_type (tb->type.type);
8190 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8193 * Fields to set in klass:
8194 * the various flags: delegate/unicode/contextbound etc.
8196 klass->flags = tb->attrs;
8198 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8199 /* No need to fully construct the type */
8200 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8202 /* enums are done right away */
8203 if (!klass->enumtype)
8204 ensure_runtime_vtable (klass);
8207 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8208 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8209 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8213 /* fields and object layout */
8214 if (klass->parent) {
8215 if (!klass->parent->size_inited)
8216 mono_class_init (klass->parent);
8217 klass->instance_size += klass->parent->instance_size;
8218 klass->class_size += klass->parent->class_size;
8219 klass->min_align = klass->parent->min_align;
8221 klass->instance_size = sizeof (MonoObject);
8222 klass->min_align = 1;
8225 /* FIXME: handle packing_size and instance_size */
8226 typebuilder_setup_fields (klass);
8228 typebuilder_setup_properties (klass);
8230 typebuilder_setup_events (klass);
8232 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8233 /* with enums res == tb: need to fix that. */
8234 if (!klass->enumtype)
8235 g_assert (res != (MonoReflectionType*)tb);
8240 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8242 MonoGenericParam *param;
8245 MONO_ARCH_SAVE_REGS;
8247 param = g_new0 (MonoGenericParam, 1);
8249 param->method = NULL;
8250 param->name = mono_string_to_utf8 (gparam->name);
8251 param->num = gparam->index;
8253 image = &gparam->tbuilder->module->dynamic_image->image;
8254 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8256 param->pklass->reflection_info = gparam;
8258 gparam->type.type = g_new0 (MonoType, 1);
8259 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8260 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8261 gparam->type.type->data.generic_param = param;
8265 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8267 MonoDynamicImage *assembly = sig->module->dynamic_image;
8268 guint32 na = mono_array_length (sig->arguments);
8273 MONO_ARCH_SAVE_REGS;
8275 p = buf = g_malloc (10 + na * 10);
8277 mono_metadata_encode_value (0x07, p, &p);
8278 mono_metadata_encode_value (na, p, &p);
8279 for (i = 0; i < na; ++i) {
8280 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8281 encode_reflection_type (assembly, type, p, &p);
8285 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8286 p = mono_array_addr (result, char, 0);
8287 memcpy (p, buf, buflen);
8294 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8296 MonoDynamicImage *assembly = sig->module->dynamic_image;
8297 guint32 na = mono_array_length (sig->arguments);
8302 MONO_ARCH_SAVE_REGS;
8304 p = buf = g_malloc (10 + na * 10);
8306 mono_metadata_encode_value (0x06, p, &p);
8307 for (i = 0; i < na; ++i) {
8308 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8309 encode_reflection_type (assembly, type, p, &p);
8313 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8314 p = mono_array_addr (result, char, 0);
8315 memcpy (p, buf, buflen);
8322 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8324 ReflectionMethodBuilder rmb;
8325 MonoMethodSignature *sig;
8328 sig = dynamic_method_to_signature (mb);
8330 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8333 * Resolve references.
8335 rmb.nrefs = mb->nrefs;
8336 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8337 for (i = 0; i < mb->nrefs; ++i) {
8338 gpointer ref = resolve_object (mb->module->image,
8339 mono_array_get (mb->refs, MonoObject*, i));
8342 mono_raise_exception (mono_get_exception_type_load (NULL));
8349 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8353 /* ilgen is no longer needed */
8358 * mono_reflection_lookup_dynamic_token:
8360 * Finish the Builder object pointed to by TOKEN and return the corresponding
8361 * runtime structure.
8364 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8366 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8369 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8372 return resolve_object (image, obj);
8376 resolve_object (MonoImage *image, MonoObject *obj)
8378 gpointer result = NULL;
8380 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8381 result = mono_string_intern ((MonoString*)obj);
8383 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8384 MonoReflectionType *tb = (MonoReflectionType*)obj;
8385 result = mono_class_from_mono_type (tb->type);
8387 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8388 result = ((MonoReflectionMethod*)obj)->method;
8390 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8391 result = ((MonoReflectionMethod*)obj)->method;
8393 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8394 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8395 result = mb->mhandle;
8397 /* Type is not yet created */
8398 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8400 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8403 * Hopefully this has been filled in by calling CreateType() on the
8407 * TODO: This won't work if the application finishes another
8408 * TypeBuilder instance instead of this one.
8410 result = mb->mhandle;
8412 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8413 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8415 result = cb->mhandle;
8417 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8419 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8420 result = cb->mhandle;
8422 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8423 result = ((MonoReflectionField*)obj)->field;
8425 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8426 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8427 result = fb->handle;
8430 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8432 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8433 result = fb->handle;
8435 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8436 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8439 klass = tb->type.type->data.klass;
8440 if (klass->wastypebuilder) {
8441 /* Already created */
8445 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8446 result = tb->type.type->data.klass;
8449 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8450 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8451 MonoMethodSignature *sig;
8454 if (helper->arguments)
8455 nargs = mono_array_length (helper->arguments);
8459 sig = mono_metadata_signature_alloc (image, nargs);
8460 sig->explicit_this = helper->call_conv & 64;
8461 sig->hasthis = helper->call_conv & 32;
8463 if (helper->call_conv == 0) /* unmanaged */
8464 sig->call_convention = helper->unmanaged_call_conv - 1;
8466 if (helper->call_conv & 0x02)
8467 sig->call_convention = MONO_CALL_VARARG;
8469 sig->call_convention = MONO_CALL_DEFAULT;
8471 sig->param_count = nargs;
8472 /* TODO: Copy type ? */
8473 sig->ret = helper->return_type->type;
8474 for (i = 0; i < nargs; ++i) {
8475 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8476 sig->params [i] = rt->type;
8481 g_print (obj->vtable->klass->name);
8482 g_assert_not_reached ();