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 stream_data_align (&assembly->code);
939 /* check for exceptions, maxstack, locals */
940 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
942 if (code_size < 64 && !(code_size & 1)) {
943 flags = (code_size << 2) | 0x2;
944 } else if (code_size < 32 && (code_size & 1)) {
945 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
949 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
953 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
954 return assembly->text_rva + idx;
958 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
960 * FIXME: need to set also the header size in fat_flags.
961 * (and more sects and init locals flags)
965 fat_flags |= METHOD_HEADER_MORE_SECTS;
967 fat_flags |= METHOD_HEADER_INIT_LOCALS;
968 fat_header [0] = fat_flags;
969 fat_header [1] = (header_size / 4 ) << 4;
970 shortp = (guint16*)(fat_header + 2);
971 *shortp = GUINT16_TO_LE (max_stack);
972 intp = (guint32*)(fat_header + 4);
973 *intp = GUINT32_TO_LE (code_size);
974 intp = (guint32*)(fat_header + 8);
975 *intp = GUINT32_TO_LE (local_sig);
976 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
977 /* add to the fixup todo list */
978 if (mb->ilgen && mb->ilgen->num_token_fixups)
979 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
983 unsigned char sheader [4];
984 MonoExceptionClause clause;
985 MonoILExceptionInfo * ex_info;
986 MonoILExceptionBlock * ex_block;
989 stream_data_align (&assembly->code);
990 /* always use fat format for now */
991 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
992 num_exception *= sizeof (MonoExceptionClause);
993 num_exception += 4; /* include the size of the header */
994 sheader [1] = num_exception & 0xff;
995 sheader [2] = (num_exception >> 8) & 0xff;
996 sheader [3] = (num_exception >> 16) & 0xff;
997 mono_image_add_stream_data (&assembly->code, sheader, 4);
998 /* fat header, so we are already aligned */
1000 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1001 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1002 if (ex_info->handlers) {
1003 int finally_start = ex_info->start + ex_info->len;
1004 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1005 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1006 clause.flags = GUINT32_TO_LE (ex_block->type);
1007 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1008 /* need fault, too, probably */
1009 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1010 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1012 clause.try_len = GUINT32_TO_LE (ex_info->len);
1013 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1014 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1015 finally_start = ex_block->start + ex_block->len;
1016 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1017 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1018 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1019 /*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",
1020 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);*/
1021 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1024 g_error ("No clauses for ex info block %d", i);
1028 return assembly->text_rva + idx;
1032 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1035 MonoDynamicTable *table;
1038 table = &assembly->tables [table_idx];
1040 g_assert (col < table->columns);
1042 values = table->values + table->columns;
1043 for (i = 1; i <= table->rows; ++i) {
1044 if (values [col] == token)
1046 values += table->columns;
1051 static GHashTable *dynamic_custom_attrs = NULL;
1053 static MonoCustomAttrInfo*
1054 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1057 MonoCustomAttrInfo *ainfo;
1058 MonoReflectionCustomAttr *cattr;
1062 /* FIXME: check in assembly the Run flag is set */
1064 count = mono_array_length (cattrs);
1066 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1068 ainfo->image = image;
1069 ainfo->num_attrs = count;
1070 for (i = 0; i < count; ++i) {
1071 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1072 ainfo->attrs [i].ctor = cattr->ctor->method;
1073 /* FIXME: might want to memdup the data here */
1074 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1075 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1082 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1084 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1089 if (!dynamic_custom_attrs)
1090 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1092 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1093 ainfo->cached = TRUE;
1097 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1099 /* they are cached, so we don't free them */
1100 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1106 * idx is the table index of the object
1107 * type is one of MONO_CUSTOM_ATTR_*
1110 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1112 MonoDynamicTable *table;
1113 MonoReflectionCustomAttr *cattr;
1115 guint32 count, i, token;
1117 char *p = blob_size;
1119 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1122 count = mono_array_length (cattrs);
1123 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1124 table->rows += count;
1125 alloc_table (table, table->rows);
1126 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1127 idx <<= MONO_CUSTOM_ATTR_BITS;
1129 for (i = 0; i < count; ++i) {
1130 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1131 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1132 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1133 type = mono_metadata_token_index (token);
1134 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1135 switch (mono_metadata_token_table (token)) {
1136 case MONO_TABLE_METHOD:
1137 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1139 case MONO_TABLE_MEMBERREF:
1140 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1143 g_warning ("got wrong token in custom attr");
1146 values [MONO_CUSTOM_ATTR_TYPE] = type;
1148 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1149 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1150 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1151 values += MONO_CUSTOM_ATTR_SIZE;
1157 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1159 MonoDynamicTable *table;
1161 guint32 count, i, idx;
1162 MonoReflectionPermissionSet *perm;
1167 count = mono_array_length (permissions);
1168 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1169 table->rows += count;
1170 alloc_table (table, table->rows);
1172 for (i = 0; i < mono_array_length (permissions); ++i) {
1173 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1175 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1177 idx = mono_metadata_token_index (parent_token);
1178 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1179 switch (mono_metadata_token_table (parent_token)) {
1180 case MONO_TABLE_TYPEDEF:
1181 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1183 case MONO_TABLE_METHOD:
1184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1186 case MONO_TABLE_ASSEMBLY:
1187 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1190 g_assert_not_reached ();
1193 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1194 values [MONO_DECL_SECURITY_PARENT] = idx;
1195 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1202 * Fill in the MethodDef and ParamDef tables for a method.
1203 * This is used for both normal methods and constructors.
1206 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1208 MonoDynamicTable *table;
1213 /* room in this table is already allocated */
1214 table = &assembly->tables [MONO_TABLE_METHOD];
1215 *mb->table_idx = table->next_idx ++;
1216 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1217 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1218 name = mono_string_to_utf8 (mb->name);
1219 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1221 values [MONO_METHOD_FLAGS] = mb->attrs;
1222 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1223 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1224 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1226 table = &assembly->tables [MONO_TABLE_PARAM];
1227 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1229 mono_image_add_decl_security (assembly,
1230 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1233 MonoDynamicTable *mtable;
1236 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1237 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1240 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1241 if (mono_array_get (mb->pinfo, gpointer, i))
1244 table->rows += count;
1245 alloc_table (table, table->rows);
1246 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1247 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1248 MonoReflectionParamBuilder *pb;
1249 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1250 values [MONO_PARAM_FLAGS] = pb->attrs;
1251 values [MONO_PARAM_SEQUENCE] = i;
1252 if (pb->name != NULL) {
1253 name = mono_string_to_utf8 (pb->name);
1254 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1257 values [MONO_PARAM_NAME] = 0;
1259 values += MONO_PARAM_SIZE;
1260 if (pb->marshal_info) {
1262 alloc_table (mtable, mtable->rows);
1263 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1264 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1265 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1267 pb->table_idx = table->next_idx++;
1268 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1269 guint32 field_type = 0;
1270 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1272 alloc_table (mtable, mtable->rows);
1273 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1274 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1275 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1276 mvalues [MONO_CONSTANT_TYPE] = field_type;
1277 mvalues [MONO_CONSTANT_PADDING] = 0;
1285 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mb->rtype;
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = mb->generic_params;
1291 rmb->opt_types = NULL;
1292 rmb->pinfo = mb->pinfo;
1293 rmb->attrs = mb->attrs;
1294 rmb->iattrs = mb->iattrs;
1295 rmb->call_conv = mb->call_conv;
1296 rmb->code = mb->code;
1297 rmb->type = mb->type;
1298 rmb->name = mb->name;
1299 rmb->table_idx = &mb->table_idx;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = mb->return_modreq;
1302 rmb->return_modopt = mb->return_modopt;
1303 rmb->param_modreq = mb->param_modreq;
1304 rmb->param_modopt = mb->param_modopt;
1305 rmb->permissions = mb->permissions;
1306 rmb->mhandle = mb->mhandle;
1311 rmb->charset = rmb->charset & 0xf;
1312 rmb->lasterr = rmb->charset & 0x40;
1313 rmb->native_cc = rmb->native_cc;
1314 rmb->dllentry = mb->dllentry;
1320 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1322 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1324 rmb->ilgen = mb->ilgen;
1325 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1326 rmb->parameters = mb->parameters;
1327 rmb->generic_params = NULL;
1328 rmb->opt_types = NULL;
1329 rmb->pinfo = mb->pinfo;
1330 rmb->attrs = mb->attrs;
1331 rmb->iattrs = mb->iattrs;
1332 rmb->call_conv = mb->call_conv;
1334 rmb->type = mb->type;
1335 rmb->name = mono_string_new (mono_domain_get (), name);
1336 rmb->table_idx = &mb->table_idx;
1337 rmb->init_locals = mb->init_locals;
1338 rmb->return_modreq = NULL;
1339 rmb->return_modopt = NULL;
1340 rmb->param_modreq = mb->param_modreq;
1341 rmb->param_modopt = mb->param_modopt;
1342 rmb->permissions = mb->permissions;
1343 rmb->mhandle = mb->mhandle;
1349 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = NULL;
1355 rmb->opt_types = NULL;
1357 rmb->attrs = mb->attrs;
1359 rmb->call_conv = mb->call_conv;
1362 rmb->name = mb->name;
1363 rmb->table_idx = NULL;
1364 rmb->init_locals = mb->init_locals;
1365 rmb->return_modreq = NULL;
1366 rmb->return_modopt = NULL;
1367 rmb->param_modreq = NULL;
1368 rmb->param_modopt = NULL;
1369 rmb->permissions = NULL;
1370 rmb->mhandle = mb->mhandle;
1376 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1378 MonoDynamicTable *table;
1381 ReflectionMethodBuilder rmb;
1384 reflection_methodbuilder_from_method_builder (&rmb, mb);
1386 mono_image_basic_method (&rmb, assembly);
1388 if (mb->dll) { /* It's a P/Invoke method */
1390 int charset = mb->charset & 0xf;
1391 int lasterr = mb->charset & 0x40;
1392 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1394 alloc_table (table, table->rows);
1395 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1396 /* map CharSet values to on-disk values */
1398 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1399 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1400 name = mono_string_to_utf8 (mb->dllentry);
1401 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1403 name = mono_string_to_utf8 (mb->dll);
1404 moduleref = string_heap_insert (&assembly->sheap, name);
1406 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1407 table = &assembly->tables [MONO_TABLE_MODULEREF];
1409 alloc_table (table, table->rows);
1410 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1411 values [MONO_IMPLMAP_SCOPE] = table->rows;
1415 if (mb->override_method) {
1416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1418 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1420 alloc_table (table, table->rows);
1421 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1422 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1423 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1425 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1426 switch (mono_metadata_token_table (tok)) {
1427 case MONO_TABLE_MEMBERREF:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1430 case MONO_TABLE_METHOD:
1431 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1434 g_assert_not_reached ();
1436 values [MONO_METHODIMPL_DECLARATION] = tok;
1439 if (mb->generic_params) {
1440 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1441 table->rows += mono_array_length (mb->generic_params);
1442 alloc_table (table, table->rows);
1443 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1444 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1446 mono_image_get_generic_param_info (
1447 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1454 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1456 ReflectionMethodBuilder rmb;
1458 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1460 mono_image_basic_method (&rmb, assembly);
1464 type_get_fully_qualified_name (MonoType *type) {
1465 char *name, *result;
1469 name = mono_type_get_name (type);
1470 klass = my_mono_class_from_mono_type (type);
1471 ta = klass->image->assembly;
1473 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1474 name, ta->aname.name,
1475 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1476 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1477 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1483 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1487 klass = my_mono_class_from_mono_type (type);
1489 return mono_type_get_name (type);
1490 ta = klass->image->assembly;
1491 if (ta == ass || klass->image == mono_defaults.corlib)
1492 return mono_type_get_name (type);
1494 return type_get_fully_qualified_name (type);
1498 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1500 char blob_size [64];
1501 char *b = blob_size;
1506 if (!assembly->save)
1509 p = buf = g_malloc (64);
1511 mono_metadata_encode_value (0x06, p, &p);
1512 /* encode custom attributes before the type */
1513 encode_type (assembly, type, p, &p);
1514 g_assert (p-buf < 64);
1515 mono_metadata_encode_value (p-buf, b, &b);
1516 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1522 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1524 char blob_size [64];
1525 char *b = blob_size;
1530 p = buf = g_malloc (64);
1532 mono_metadata_encode_value (0x06, p, &p);
1533 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1534 /* encode custom attributes before the type */
1535 encode_reflection_type (assembly, fb->type, p, &p);
1536 g_assert (p-buf < 64);
1537 mono_metadata_encode_value (p-buf, b, &b);
1538 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1544 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1545 char blob_size [64];
1546 char *b = blob_size;
1549 guint32 idx = 0, len = 0, dummy = 0;
1551 p = buf = g_malloc (64);
1553 *ret_type = MONO_TYPE_CLASS;
1555 box_val = (char*)&dummy;
1557 box_val = ((char*)val) + sizeof (MonoObject);
1558 *ret_type = val->vtable->klass->byval_arg.type;
1561 switch (*ret_type) {
1562 case MONO_TYPE_BOOLEAN:
1567 case MONO_TYPE_CHAR:
1582 case MONO_TYPE_VALUETYPE:
1583 if (val->vtable->klass->enumtype) {
1584 *ret_type = val->vtable->klass->enum_basetype->type;
1587 g_error ("we can't encode valuetypes");
1588 case MONO_TYPE_CLASS:
1590 case MONO_TYPE_STRING: {
1591 MonoString *str = (MonoString*)val;
1592 /* there is no signature */
1593 len = str->length * 2;
1594 mono_metadata_encode_value (len, b, &b);
1595 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1597 char *swapped = g_malloc (2 * mono_string_length (str));
1598 const char *p = (const char*)mono_string_chars (str);
1600 swap_with_size (swapped, p, 2, mono_string_length (str));
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1605 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1612 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1615 /* there is no signature */
1616 mono_metadata_encode_value (len, b, &b);
1617 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1618 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1619 swap_with_size (blob_size, box_val, len, 1);
1620 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1630 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1631 char blob_size [64];
1632 char *b = blob_size;
1633 char *p, *buf, *str;
1634 guint32 idx, len, bufsize = 256;
1636 p = buf = g_malloc (bufsize);
1638 switch (minfo->type) {
1639 case MONO_NATIVE_BYVALTSTR:
1640 case MONO_NATIVE_BYVALARRAY:
1641 mono_metadata_encode_value (minfo->type, p, &p);
1642 mono_metadata_encode_value (minfo->count, p, &p);
1644 case MONO_NATIVE_LPARRAY:
1645 mono_metadata_encode_value (minfo->type, p, &p);
1646 if (minfo->eltype || (minfo->count > 0)) {
1647 mono_metadata_encode_value (minfo->eltype, p, &p);
1648 if (minfo->count > 0) {
1649 mono_metadata_encode_value (0, p, &p);
1650 mono_metadata_encode_value (minfo->count, p, &p);
1654 case MONO_NATIVE_CUSTOM:
1655 mono_metadata_encode_value (minfo->type, p, &p);
1657 str = mono_string_to_utf8 (minfo->guid);
1659 mono_metadata_encode_value (len, p, &p);
1660 memcpy (p, str, len);
1664 mono_metadata_encode_value (0, p, &p);
1666 if (minfo->marshaltype) {
1667 str = mono_string_to_utf8 (minfo->marshaltype);
1669 mono_metadata_encode_value (len, p, &p);
1670 if (p + len >= buf + bufsize) {
1673 buf = g_realloc (buf, bufsize);
1676 memcpy (p, str, len);
1680 mono_metadata_encode_value (0, p, &p);
1682 if (minfo->marshaltyperef) {
1683 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1685 mono_metadata_encode_value (len, p, &p);
1686 if (p + len >= buf + bufsize) {
1689 buf = g_realloc (buf, bufsize);
1692 memcpy (p, str, len);
1696 mono_metadata_encode_value (0, p, &p);
1698 if (minfo->mcookie) {
1699 str = mono_string_to_utf8 (minfo->mcookie);
1701 mono_metadata_encode_value (len, p, &p);
1702 if (p + len >= buf + bufsize) {
1705 buf = g_realloc (buf, bufsize);
1708 memcpy (p, str, len);
1712 mono_metadata_encode_value (0, p, &p);
1716 mono_metadata_encode_value (minfo->type, p, &p);
1720 mono_metadata_encode_value (len, b, &b);
1721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1727 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1729 MonoDynamicTable *table;
1733 /* maybe this fixup should be done in the C# code */
1734 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1735 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1736 table = &assembly->tables [MONO_TABLE_FIELD];
1737 fb->table_idx = table->next_idx ++;
1738 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1739 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1740 name = mono_string_to_utf8 (fb->name);
1741 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1743 values [MONO_FIELD_FLAGS] = fb->attrs;
1744 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1746 if (fb->offset != -1) {
1747 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1751 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1752 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1754 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1755 guint32 field_type = 0;
1756 table = &assembly->tables [MONO_TABLE_CONSTANT];
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1760 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1761 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1762 values [MONO_CONSTANT_TYPE] = field_type;
1763 values [MONO_CONSTANT_PADDING] = 0;
1765 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1767 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1769 alloc_table (table, table->rows);
1770 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1771 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1773 * We store it in the code section because it's simpler for now.
1776 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1778 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1779 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1781 if (fb->marshal_info) {
1782 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1784 alloc_table (table, table->rows);
1785 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1786 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1787 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1792 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1796 char *b = blob_size;
1797 guint32 nparams = 0;
1798 MonoReflectionMethodBuilder *mb = fb->get_method;
1799 MonoReflectionMethodBuilder *smb = fb->set_method;
1800 guint32 idx, i, size;
1802 if (mb && mb->parameters)
1803 nparams = mono_array_length (mb->parameters);
1804 if (!mb && smb && smb->parameters)
1805 nparams = mono_array_length (smb->parameters) - 1;
1806 size = 24 + nparams * 10;
1807 buf = p = g_malloc (size);
1810 mono_metadata_encode_value (nparams, p, &p);
1812 encode_reflection_type (assembly, mb->rtype, p, &p);
1813 for (i = 0; i < nparams; ++i) {
1814 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1815 encode_reflection_type (assembly, pt, p, &p);
1818 /* the property type is the last param */
1819 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1820 for (i = 0; i < nparams; ++i) {
1821 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1822 encode_reflection_type (assembly, pt, p, &p);
1826 g_assert (p - buf < size);
1827 mono_metadata_encode_value (p-buf, b, &b);
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1834 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1836 MonoDynamicTable *table;
1839 guint num_methods = 0;
1843 * we need to set things in the following tables:
1844 * PROPERTYMAP (info already filled in _get_type_info ())
1845 * PROPERTY (rows already preallocated in _get_type_info ())
1846 * METHOD (method info already done with the generic method code)
1849 table = &assembly->tables [MONO_TABLE_PROPERTY];
1850 pb->table_idx = table->next_idx ++;
1851 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1852 name = mono_string_to_utf8 (pb->name);
1853 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1855 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1856 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1858 /* FIXME: we still don't handle 'other' methods */
1859 if (pb->get_method) num_methods ++;
1860 if (pb->set_method) num_methods ++;
1862 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1863 table->rows += num_methods;
1864 alloc_table (table, table->rows);
1866 if (pb->get_method) {
1867 semaidx = table->next_idx ++;
1868 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1869 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1870 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1871 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1873 if (pb->set_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1883 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1885 MonoDynamicTable *table;
1888 guint num_methods = 0;
1892 * we need to set things in the following tables:
1893 * EVENTMAP (info already filled in _get_type_info ())
1894 * EVENT (rows already preallocated in _get_type_info ())
1895 * METHOD (method info already done with the generic method code)
1898 table = &assembly->tables [MONO_TABLE_EVENT];
1899 eb->table_idx = table->next_idx ++;
1900 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1901 name = mono_string_to_utf8 (eb->name);
1902 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1904 values [MONO_EVENT_FLAGS] = eb->attrs;
1905 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1908 * FIXME: we still don't handle 'other' methods
1910 if (eb->add_method) num_methods ++;
1911 if (eb->remove_method) num_methods ++;
1912 if (eb->raise_method) num_methods ++;
1914 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1915 table->rows += num_methods;
1916 alloc_table (table, table->rows);
1918 if (eb->add_method) {
1919 semaidx = table->next_idx ++;
1920 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1921 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1922 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1923 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1925 if (eb->remove_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->raise_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1942 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1944 static MonoClass *NewConstraintAttr;
1945 static MonoMethod *NewConstraintAttr_ctor;
1946 MonoDynamicTable *table;
1948 guint32 token, type;
1949 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1952 if (!NewConstraintAttr)
1953 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1954 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1955 g_assert (NewConstraintAttr);
1957 if (!NewConstraintAttr_ctor) {
1960 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1961 MonoMethod *m = NewConstraintAttr->methods [i];
1963 if (strcmp (m->name, ".ctor"))
1966 NewConstraintAttr_ctor = m;
1970 g_assert (NewConstraintAttr_ctor);
1973 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1975 alloc_table (table, table->rows);
1977 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1978 owner <<= MONO_CUSTOM_ATTR_BITS;
1979 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1980 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1982 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1984 type = mono_metadata_token_index (token);
1985 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1986 switch (mono_metadata_token_table (token)) {
1987 case MONO_TABLE_METHOD:
1988 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1990 case MONO_TABLE_MEMBERREF:
1991 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1994 g_warning ("got wrong token in custom attr");
1997 values [MONO_CUSTOM_ATTR_TYPE] = type;
1999 buf = p = g_malloc (1);
2000 mono_metadata_encode_value (4, p, &p);
2001 g_assert (p-buf == 1);
2003 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2005 values += MONO_CUSTOM_ATTR_SIZE;
2010 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2013 guint32 num_constraints, i;
2017 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2018 num_constraints = gparam->iface_constraints ?
2019 mono_array_length (gparam->iface_constraints) : 0;
2020 table->rows += num_constraints;
2021 if (gparam->base_type)
2023 alloc_table (table, table->rows);
2025 if (gparam->base_type) {
2026 table_idx = table->next_idx ++;
2027 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2029 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2030 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2031 assembly, gparam->base_type->type);
2034 for (i = 0; i < num_constraints; i++) {
2035 MonoReflectionType *constraint = mono_array_get (
2036 gparam->iface_constraints, gpointer, i);
2038 table_idx = table->next_idx ++;
2039 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2041 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2042 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2043 assembly, constraint->type);
2046 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2047 encode_new_constraint (assembly, owner);
2051 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2053 GenericParamTableEntry *entry;
2056 * The GenericParam table must be sorted according to the `owner' field.
2057 * We need to do this sorting prior to writing the GenericParamConstraint
2058 * table, since we have to use the final GenericParam table indices there
2059 * and they must also be sorted.
2062 entry = g_new0 (GenericParamTableEntry, 1);
2063 entry->owner = owner;
2064 entry->gparam = gparam;
2066 g_ptr_array_add (assembly->gen_params, entry);
2070 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2072 MonoDynamicTable *table;
2073 MonoGenericParam *param;
2077 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2078 table_idx = table->next_idx ++;
2079 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2081 param = entry->gparam->type.type->data.generic_param;
2083 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2084 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2085 values [MONO_GENERICPARAM_NUMBER] = param->num;
2086 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2087 values [MONO_GENERICPARAM_KIND] = 0;
2089 encode_constraints (entry->gparam, table_idx, assembly);
2093 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2095 MonoDynamicTable *table;
2098 guint32 cols [MONO_ASSEMBLY_SIZE];
2102 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2105 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2106 table = &assembly->tables [MONO_TABLE_MODULEREF];
2107 token = table->next_idx ++;
2109 alloc_table (table, table->rows);
2110 values = table->values + token * MONO_MODULEREF_SIZE;
2111 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2113 token <<= MONO_RESOLTION_SCOPE_BITS;
2114 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2115 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2120 if (image->assembly->dynamic)
2122 memset (cols, 0, sizeof (cols));
2124 /* image->assembly->image is the manifest module */
2125 image = image->assembly->image;
2126 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2129 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2130 token = table->next_idx ++;
2132 alloc_table (table, table->rows);
2133 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2134 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2135 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2136 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2137 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2138 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2139 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2140 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2141 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2143 if (strcmp ("", image->assembly->aname.culture)) {
2144 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2145 image->assembly->aname.culture);
2148 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2149 guchar pubtoken [9];
2151 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2152 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2154 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2156 token <<= MONO_RESOLTION_SCOPE_BITS;
2157 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2158 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2163 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2165 MonoDynamicTable *table;
2171 char *b = blob_size;
2173 switch (type->type) {
2174 case MONO_TYPE_FNPTR:
2176 case MONO_TYPE_SZARRAY:
2177 case MONO_TYPE_ARRAY:
2179 case MONO_TYPE_MVAR:
2180 case MONO_TYPE_GENERICINST:
2181 encode_type (assembly, type, p, &p);
2183 case MONO_TYPE_CLASS:
2184 case MONO_TYPE_VALUETYPE: {
2185 MonoClass *k = mono_class_from_mono_type (type);
2186 if (!k || !k->generic_inst)
2188 encode_generic_inst (assembly, k->generic_inst, p, &p);
2195 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2196 if (assembly->save) {
2197 g_assert (p-sig < 128);
2198 mono_metadata_encode_value (p-sig, b, &b);
2199 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2200 alloc_table (table, table->rows + 1);
2201 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2202 values [MONO_TYPESPEC_SIGNATURE] = token;
2205 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2206 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2212 * Despite the name, we handle also TypeSpec (with the above helper).
2215 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2217 MonoDynamicTable *table;
2219 guint32 token, scope, enclosing;
2222 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2225 token = create_typespec (assembly, type);
2228 klass = my_mono_class_from_mono_type (type);
2230 klass = mono_class_from_mono_type (type);
2233 * If it's in the same module and not a generic type parameter:
2235 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2236 (type->type != MONO_TYPE_MVAR)) {
2237 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2238 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2239 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2243 if (klass->nested_in) {
2244 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2245 /* get the typeref idx of the enclosing type */
2246 enclosing >>= MONO_TYPEDEFORREF_BITS;
2247 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2249 scope = resolution_scope_from_image (assembly, klass->image);
2251 table = &assembly->tables [MONO_TABLE_TYPEREF];
2252 if (assembly->save) {
2253 alloc_table (table, table->rows + 1);
2254 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2255 values [MONO_TYPEREF_SCOPE] = scope;
2256 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2257 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2259 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2260 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2262 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2267 * Insert a memberef row into the metadata: the token that point to the memberref
2268 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2269 * mono_image_get_fieldref_token()).
2270 * The sig param is an index to an already built signature.
2273 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2275 MonoDynamicTable *table;
2277 guint32 token, pclass;
2280 parent = mono_image_typedef_or_ref (assembly, type);
2281 switch (parent & MONO_TYPEDEFORREF_MASK) {
2282 case MONO_TYPEDEFORREF_TYPEREF:
2283 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2285 case MONO_TYPEDEFORREF_TYPESPEC:
2286 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2288 case MONO_TYPEDEFORREF_TYPEDEF:
2289 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2292 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2295 /* extract the index */
2296 parent >>= MONO_TYPEDEFORREF_BITS;
2298 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2300 if (assembly->save) {
2301 alloc_table (table, table->rows + 1);
2302 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2303 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2304 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2305 values [MONO_MEMBERREF_SIGNATURE] = sig;
2308 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2315 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2318 MonoMethodSignature *sig;
2320 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2325 * A methodref signature can't contain an unmanaged calling convention.
2327 sig = mono_metadata_signature_dup (method->signature);
2328 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2329 sig->call_convention = MONO_CALL_DEFAULT;
2330 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2331 method->name, method_encode_signature (assembly, sig));
2333 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2338 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2339 const gchar *name, guint32 sig)
2341 MonoDynamicTable *table;
2345 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2347 if (assembly->save) {
2348 alloc_table (table, table->rows + 1);
2349 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2350 values [MONO_MEMBERREF_CLASS] = original;
2351 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2352 values [MONO_MEMBERREF_SIGNATURE] = sig;
2355 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2362 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2365 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2371 reflection_methodbuilder_from_method_builder (&rmb, mb);
2373 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2374 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2375 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2380 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2383 ReflectionMethodBuilder rmb;
2385 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2389 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2391 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2392 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2393 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2398 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2403 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2406 g_assert (f->field->parent);
2407 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2408 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2409 f->field->name, fieldref_encode_signature (assembly, type));
2410 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2420 guint32 nparams = gmethod->mtype_argc;
2421 guint32 size = 10 + nparams * 10;
2424 char *b = blob_size;
2426 if (!assembly->save)
2429 p = buf = g_malloc (size);
2431 * FIXME: vararg, explicit_this, differenc call_conv values...
2433 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2434 mono_metadata_encode_value (nparams, p, &p);
2436 for (i = 0; i < nparams; i++)
2437 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2440 g_assert (p - buf < size);
2441 mono_metadata_encode_value (p-buf, b, &b);
2442 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2450 MonoDynamicTable *table;
2452 guint32 token, mtoken = 0, sig;
2453 MonoMethodInflated *imethod;
2454 MonoMethod *declaring;
2456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2458 g_assert (method->signature->is_inflated);
2459 imethod = (MonoMethodInflated *) method;
2460 declaring = imethod->declaring;
2462 sig = method_encode_signature (assembly, declaring->signature);
2463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2465 if (!declaring->signature->generic_param_count)
2468 switch (mono_metadata_token_table (mtoken)) {
2469 case MONO_TABLE_MEMBERREF:
2470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2472 case MONO_TABLE_METHOD:
2473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2476 g_assert_not_reached ();
2479 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2481 if (assembly->save) {
2482 alloc_table (table, table->rows + 1);
2483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2484 values [MONO_METHODSPEC_METHOD] = mtoken;
2485 values [MONO_METHODSPEC_SIGNATURE] = sig;
2488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2497 MonoMethodInflated *imethod;
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2504 g_assert (m->signature->is_inflated);
2505 imethod = (MonoMethodInflated *) m;
2507 if (imethod->declaring->signature->generic_param_count) {
2508 token = method_encode_methodspec (assembly, m);
2510 guint32 sig = method_encode_signature (
2511 assembly, imethod->declaring->signature);
2512 token = mono_image_get_memberref_token (
2513 assembly, &m->klass->byval_arg, m->name, sig);
2516 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2526 sig = method_encode_signature (assembly, imethod->declaring->signature);
2527 token = mono_image_get_memberref_token (
2528 assembly, &m->klass->byval_arg, m->name, sig);
2534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2536 MonoDynamicTable *table;
2543 char *b = blob_size;
2547 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2548 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2549 * Because of this, we must not insert it into the `typeref' hash table.
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2556 g_assert (tb->generic_params);
2557 klass = mono_class_from_mono_type (tb->type.type);
2559 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2560 encode_type (assembly, &klass->byval_arg, p, &p);
2562 count = mono_array_length (tb->generic_params);
2563 mono_metadata_encode_value (count, p, &p);
2564 for (i = 0; i < count; i++) {
2565 MonoReflectionGenericParam *gparam;
2567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2569 encode_type (assembly, gparam->type.type, p, &p);
2572 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2573 if (assembly->save) {
2574 g_assert (p-sig < 128);
2575 mono_metadata_encode_value (p-sig, b, &b);
2576 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2579 values [MONO_TYPESPEC_SIGNATURE] = token;
2582 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2591 MonoDynamicTable *table;
2594 guint32 token, pclass, parent, sig;
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2601 klass = mono_class_from_mono_type (fb->typeb->type);
2602 name = mono_string_to_utf8 (fb->name);
2604 sig = fieldref_encode_signature (assembly, fb->type->type);
2606 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2609 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610 parent >>= MONO_TYPEDEFORREF_BITS;
2612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2614 if (assembly->save) {
2615 alloc_table (table, table->rows + 1);
2616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619 values [MONO_MEMBERREF_SIGNATURE] = sig;
2622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2624 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2637 char *b = blob_size;
2639 if (!assembly->save)
2643 g_assert (helper->type == 2);
2645 if (helper->arguments)
2646 nargs = mono_array_length (helper->arguments);
2650 size = 10 + (nargs * 10);
2652 p = buf = g_malloc (size);
2654 /* Encode calling convention */
2655 /* Change Any to Standard */
2656 if ((helper->call_conv & 0x03) == 0x03)
2657 helper->call_conv = 0x01;
2658 /* explicit_this implies has_this */
2659 if (helper->call_conv & 0x40)
2660 helper->call_conv &= 0x20;
2662 if (helper->call_conv == 0) { /* Unmanaged */
2663 *p = helper->unmanaged_call_conv - 1;
2666 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2667 if (helper->call_conv & 0x02) /* varargs */
2672 mono_metadata_encode_value (nargs, p, &p);
2673 encode_reflection_type (assembly, helper->return_type, p, &p);
2674 for (i = 0; i < nargs; ++i) {
2675 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2676 encode_reflection_type (assembly, pt, p, &p);
2679 g_assert (p - buf < size);
2680 mono_metadata_encode_value (p-buf, b, &b);
2681 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2688 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2691 MonoDynamicTable *table;
2694 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2695 idx = table->next_idx ++;
2697 alloc_table (table, table->rows);
2698 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2700 values [MONO_STAND_ALONE_SIGNATURE] =
2701 mono_reflection_encode_sighelper (assembly, helper);
2707 reflection_cc_to_file (int call_conv) {
2708 switch (call_conv & 0x3) {
2710 case 1: return MONO_CALL_DEFAULT;
2711 case 2: return MONO_CALL_VARARG;
2713 g_assert_not_reached ();
2720 MonoMethodSignature *sig;
2726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2731 MonoMethodSignature *sig;
2734 name = mono_string_to_utf8 (m->name);
2735 nparams = mono_array_length (m->parameters);
2736 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2738 sig->sentinelpos = -1;
2739 sig->call_convention = reflection_cc_to_file (m->call_conv);
2740 sig->param_count = nparams;
2741 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2742 for (i = 0; i < nparams; ++i) {
2743 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2744 sig->params [i] = t->type;
2747 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2749 if (strcmp (name, am->name) == 0 &&
2750 mono_metadata_type_equal (am->parent, m->parent->type) &&
2751 mono_metadata_signature_equal (am->sig, sig)) {
2754 m->table_idx = am->token & 0xffffff;
2758 am = g_new0 (ArrayMethod, 1);
2761 am->parent = m->parent->type;
2762 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2763 method_encode_signature (assembly, sig));
2764 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2765 m->table_idx = am->token & 0xffffff;
2770 * Insert into the metadata tables all the info about the TypeBuilder tb.
2771 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2774 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2776 MonoDynamicTable *table;
2778 int i, is_object = 0, is_system = 0;
2781 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2782 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2783 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2784 n = mono_string_to_utf8 (tb->name);
2785 if (strcmp (n, "Object") == 0)
2787 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2789 n = mono_string_to_utf8 (tb->nspace);
2790 if (strcmp (n, "System") == 0)
2792 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2794 if (tb->parent && !(is_system && is_object) &&
2795 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2796 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2798 values [MONO_TYPEDEF_EXTENDS] = 0;
2800 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2801 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2804 * if we have explicitlayout or sequentiallayouts, output data in the
2805 * ClassLayout table.
2807 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2808 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2809 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2811 alloc_table (table, table->rows);
2812 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2813 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2814 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2815 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2818 /* handle interfaces */
2819 if (tb->interfaces) {
2820 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2822 table->rows += mono_array_length (tb->interfaces);
2823 alloc_table (table, table->rows);
2824 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2825 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2826 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2827 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2828 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2829 values += MONO_INTERFACEIMPL_SIZE;
2835 table = &assembly->tables [MONO_TABLE_FIELD];
2836 table->rows += tb->num_fields;
2837 alloc_table (table, table->rows);
2838 for (i = 0; i < tb->num_fields; ++i)
2839 mono_image_get_field_info (
2840 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2843 /* handle constructors */
2845 table = &assembly->tables [MONO_TABLE_METHOD];
2846 table->rows += mono_array_length (tb->ctors);
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2849 mono_image_get_ctor_info (domain,
2850 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2853 /* handle methods */
2855 table = &assembly->tables [MONO_TABLE_METHOD];
2856 table->rows += tb->num_methods;
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < tb->num_methods; ++i)
2859 mono_image_get_method_info (
2860 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2863 /* Do the same with properties etc.. */
2864 if (tb->events && mono_array_length (tb->events)) {
2865 table = &assembly->tables [MONO_TABLE_EVENT];
2866 table->rows += mono_array_length (tb->events);
2867 alloc_table (table, table->rows);
2868 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2870 alloc_table (table, table->rows);
2871 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2872 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2873 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2874 for (i = 0; i < mono_array_length (tb->events); ++i)
2875 mono_image_get_event_info (
2876 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2878 if (tb->properties && mono_array_length (tb->properties)) {
2879 table = &assembly->tables [MONO_TABLE_PROPERTY];
2880 table->rows += mono_array_length (tb->properties);
2881 alloc_table (table, table->rows);
2882 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2884 alloc_table (table, table->rows);
2885 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2886 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2887 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2888 for (i = 0; i < mono_array_length (tb->properties); ++i)
2889 mono_image_get_property_info (
2890 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2893 /* handle generic parameters */
2894 if (tb->generic_params) {
2895 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2896 table->rows += mono_array_length (tb->generic_params);
2897 alloc_table (table, table->rows);
2898 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2899 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2901 mono_image_get_generic_param_info (
2902 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2906 mono_image_add_decl_security (assembly,
2907 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2910 MonoDynamicTable *ntable;
2912 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2913 ntable->rows += mono_array_length (tb->subtypes);
2914 alloc_table (ntable, ntable->rows);
2915 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2917 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2918 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2920 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2921 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2922 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2923 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2924 mono_string_to_utf8 (tb->name), tb->table_idx,
2925 ntable->next_idx, ntable->rows);*/
2926 values += MONO_NESTED_CLASS_SIZE;
2933 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2937 g_ptr_array_add (types, type);
2939 if (!type->subtypes)
2942 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2943 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2944 collect_types (types, subtype);
2949 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2951 if ((*type1)->table_idx < (*type2)->table_idx)
2954 if ((*type1)->table_idx > (*type2)->table_idx)
2961 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2966 for (i = 0; i < mono_array_length (pinfo); ++i) {
2967 MonoReflectionParamBuilder *pb;
2968 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2971 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2976 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2979 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2981 for (i = 0; i < tb->num_fields; ++i) {
2982 MonoReflectionFieldBuilder* fb;
2983 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2984 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2988 for (i = 0; i < mono_array_length (tb->events); ++i) {
2989 MonoReflectionEventBuilder* eb;
2990 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2991 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2994 if (tb->properties) {
2995 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2996 MonoReflectionPropertyBuilder* pb;
2997 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2998 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3002 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3003 MonoReflectionCtorBuilder* cb;
3004 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3005 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3006 params_add_cattrs (assembly, cb->pinfo);
3011 for (i = 0; i < tb->num_methods; ++i) {
3012 MonoReflectionMethodBuilder* mb;
3013 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3014 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3015 params_add_cattrs (assembly, mb->pinfo);
3020 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3021 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3026 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3031 /* no types in the module */
3035 for (i = 0; i < mb->num_types; ++i)
3036 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3040 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3042 MonoDynamicTable *table;
3046 char *b = blob_size;
3049 table = &assembly->tables [MONO_TABLE_FILE];
3051 alloc_table (table, table->rows);
3052 values = table->values + table->next_idx * MONO_FILE_SIZE;
3053 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3054 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3055 if (module->image->dynamic) {
3056 /* This depends on the fact that the main module is emitted last */
3057 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3058 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3061 path = g_strdup (module->image->name);
3063 mono_sha1_get_digest_from_file (path, hash);
3066 mono_metadata_encode_value (20, b, &b);
3067 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3068 mono_image_add_stream_data (&assembly->blob, hash, 20);
3073 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3079 table = &assembly->tables [MONO_TABLE_MODULE];
3080 mb->table_idx = table->next_idx ++;
3081 name = mono_string_to_utf8 (mb->module.name);
3082 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3084 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3088 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3093 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3094 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3096 MonoDynamicTable *table;
3100 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3101 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3104 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3106 alloc_table (table, table->rows);
3107 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3109 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3110 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3111 if (klass->nested_in)
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3114 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3115 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3116 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3118 res = table->next_idx;
3122 /* Emit nested types */
3123 if (klass->nested_classes) {
3126 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3127 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3134 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3135 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3140 klass = mono_class_from_mono_type (tb->type.type);
3142 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3144 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3145 parent_index, assembly);
3149 * We need to do this ourselves since klass->nested_classes is not set up.
3152 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3153 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3158 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3159 guint32 module_index, MonoDynamicImage *assembly)
3161 MonoImage *image = module->image;
3165 t = &image->tables [MONO_TABLE_TYPEDEF];
3167 for (i = 0; i < t->rows; ++i) {
3168 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3170 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3171 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3175 #define align_pointer(base,p)\
3177 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3179 (p) += 4 - (__diff & 3);\
3183 compare_semantics (const void *a, const void *b)
3185 const guint32 *a_values = a;
3186 const guint32 *b_values = b;
3187 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3190 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3194 compare_custom_attrs (const void *a, const void *b)
3196 const guint32 *a_values = a;
3197 const guint32 *b_values = b;
3199 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3203 compare_field_marshal (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3208 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3212 compare_nested (const void *a, const void *b)
3214 const guint32 *a_values = a;
3215 const guint32 *b_values = b;
3217 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3221 compare_genericparam (const void *a, const void *b)
3223 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3224 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3226 return (*a_entry)->owner - (*b_entry)->owner;
3230 compare_declsecurity_attrs (const void *a, const void *b)
3232 const guint32 *a_values = a;
3233 const guint32 *b_values = b;
3235 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3239 pad_heap (MonoDynamicStream *sh)
3241 if (sh->index & 3) {
3242 int sz = 4 - (sh->index & 3);
3243 memset (sh->data + sh->index, 0, sz);
3250 MonoDynamicStream *stream;
3254 * build_compressed_metadata() fills in the blob of data that represents the
3255 * raw metadata as it will be saved in the PE file. The five streams are output
3256 * and the metadata tables are comnpressed from the guint32 array representation,
3257 * to the compressed on-disk format.
3260 build_compressed_metadata (MonoDynamicImage *assembly)
3262 MonoDynamicTable *table;
3264 guint64 valid_mask = 0;
3265 guint64 sorted_mask;
3266 guint32 heapt_size = 0;
3267 guint32 meta_size = 256; /* allow for header and other stuff */
3268 guint32 table_offset;
3269 guint32 ntables = 0;
3275 struct StreamDesc stream_desc [5];
3277 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3278 for (i = 0; i < assembly->gen_params->len; i++){
3279 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3280 write_generic_param_entry (assembly, entry);
3283 stream_desc [0].name = "#~";
3284 stream_desc [0].stream = &assembly->tstream;
3285 stream_desc [1].name = "#Strings";
3286 stream_desc [1].stream = &assembly->sheap;
3287 stream_desc [2].name = "#US";
3288 stream_desc [2].stream = &assembly->us;
3289 stream_desc [3].name = "#Blob";
3290 stream_desc [3].stream = &assembly->blob;
3291 stream_desc [4].name = "#GUID";
3292 stream_desc [4].stream = &assembly->guid;
3294 /* tables that are sorted */
3295 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3296 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3297 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3298 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3299 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3300 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3302 /* Compute table sizes */
3303 /* the MonoImage has already been created in mono_image_basic_init() */
3304 meta = &assembly->image;
3306 /* sizes should be multiple of 4 */
3307 pad_heap (&assembly->blob);
3308 pad_heap (&assembly->guid);
3309 pad_heap (&assembly->sheap);
3310 pad_heap (&assembly->us);
3312 /* Setup the info used by compute_sizes () */
3313 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3314 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3315 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3317 meta_size += assembly->blob.index;
3318 meta_size += assembly->guid.index;
3319 meta_size += assembly->sheap.index;
3320 meta_size += assembly->us.index;
3322 for (i=0; i < 64; ++i)
3323 meta->tables [i].rows = assembly->tables [i].rows;
3325 for (i = 0; i < 64; i++){
3326 if (meta->tables [i].rows == 0)
3328 valid_mask |= (guint64)1 << i;
3330 meta->tables [i].row_size = mono_metadata_compute_size (
3331 meta, i, &meta->tables [i].size_bitfield);
3332 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3334 heapt_size += 24; /* #~ header size */
3335 heapt_size += ntables * 4;
3336 /* make multiple of 4 */
3339 meta_size += heapt_size;
3340 meta->raw_metadata = g_malloc0 (meta_size);
3341 p = meta->raw_metadata;
3342 /* the metadata signature */
3343 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3344 /* version numbers and 4 bytes reserved */
3345 int16val = (guint16*)p;
3346 *int16val++ = GUINT16_TO_LE (1);
3347 *int16val = GUINT16_TO_LE (1);
3349 /* version string */
3350 int32val = (guint32*)p;
3351 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3353 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3354 p += GUINT32_FROM_LE (*int32val);
3355 align_pointer (meta->raw_metadata, p);
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3358 *int16val = GUINT16_TO_LE (5); /* number of streams */
3362 * write the stream info.
3364 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3365 table_offset += 3; table_offset &= ~3;
3367 assembly->tstream.index = heapt_size;
3368 for (i = 0; i < 5; ++i) {
3369 int32val = (guint32*)p;
3370 stream_desc [i].stream->offset = table_offset;
3371 *int32val++ = GUINT32_TO_LE (table_offset);
3372 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3373 table_offset += GUINT32_FROM_LE (*int32val);
3374 table_offset += 3; table_offset &= ~3;
3376 strcpy (p, stream_desc [i].name);
3377 p += strlen (stream_desc [i].name) + 1;
3378 align_pointer (meta->raw_metadata, p);
3381 * now copy the data, the table stream header and contents goes first.
3383 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3384 p = meta->raw_metadata + assembly->tstream.offset;
3385 int32val = (guint32*)p;
3386 *int32val = GUINT32_TO_LE (0); /* reserved */
3389 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3390 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3391 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3392 *p++ = 1; /* version */
3395 *p++ = 1; /* version */
3399 if (meta->idx_string_wide)
3401 if (meta->idx_guid_wide)
3403 if (meta->idx_blob_wide)
3406 *p++ = 0; /* reserved */
3407 int64val = (guint64*)p;
3408 *int64val++ = GUINT64_TO_LE (valid_mask);
3409 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3411 int32val = (guint32*)p;
3412 for (i = 0; i < 64; i++){
3413 if (meta->tables [i].rows == 0)
3415 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3417 p = (unsigned char*)int32val;
3419 /* sort the tables that still need sorting */
3420 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3422 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3423 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3425 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3426 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3428 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3429 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3431 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3432 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3433 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3435 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3437 /* compress the tables */
3438 for (i = 0; i < 64; i++){
3441 guint32 bitfield = meta->tables [i].size_bitfield;
3442 if (!meta->tables [i].rows)
3444 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3445 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3446 meta->tables [i].base = p;
3447 for (row = 1; row <= meta->tables [i].rows; ++row) {
3448 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3449 for (col = 0; col < assembly->tables [i].columns; ++col) {
3450 switch (mono_metadata_table_size (bitfield, col)) {
3452 *p++ = values [col];
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3459 *p++ = values [col] & 0xff;
3460 *p++ = (values [col] >> 8) & 0xff;
3461 *p++ = (values [col] >> 16) & 0xff;
3462 *p++ = (values [col] >> 24) & 0xff;
3465 g_assert_not_reached ();
3469 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3472 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3473 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3474 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3475 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3476 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3478 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 * Some tables in metadata need to be sorted according to some criteria, but
3483 * when methods and fields are first created with reflection, they may be assigned a token
3484 * that doesn't correspond to the final token they will get assigned after the sorting.
3485 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3486 * with the reflection objects that represent them. Once all the tables are set up, the
3487 * reflection objects will contains the correct table index. fixup_method() will fixup the
3488 * tokens for the method with ILGenerator @ilgen.
3491 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3492 guint32 code_idx = GPOINTER_TO_UINT (value);
3493 MonoReflectionILTokenInfo *iltoken;
3494 MonoReflectionFieldBuilder *field;
3495 MonoReflectionCtorBuilder *ctor;
3496 MonoReflectionMethodBuilder *method;
3497 MonoReflectionTypeBuilder *tb;
3498 MonoReflectionArrayMethod *am;
3500 unsigned char *target;
3502 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3503 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3504 target = assembly->code.data + code_idx + iltoken->code_pos;
3505 switch (target [3]) {
3506 case MONO_TABLE_FIELD:
3507 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3508 field = (MonoReflectionFieldBuilder *)iltoken->member;
3509 idx = field->table_idx;
3510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3511 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3512 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3514 g_assert_not_reached ();
3517 case MONO_TABLE_METHOD:
3518 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3519 method = (MonoReflectionMethodBuilder *)iltoken->member;
3520 idx = method->table_idx;
3521 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3522 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3523 idx = ctor->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3525 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3526 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3527 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3529 g_assert_not_reached ();
3532 case MONO_TABLE_TYPEDEF:
3533 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3534 g_assert_not_reached ();
3535 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3536 idx = tb->table_idx;
3538 case MONO_TABLE_MEMBERREF:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3540 am = (MonoReflectionArrayMethod*)iltoken->member;
3541 idx = am->table_idx;
3542 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3543 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3544 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3545 g_assert (m->klass->generic_inst);
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3550 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3551 g_assert (f->generic_info);
3553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3556 g_assert_not_reached ();
3559 case MONO_TABLE_METHODSPEC:
3560 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3561 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3562 g_assert (m->signature->generic_param_count);
3565 g_assert_not_reached ();
3569 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3571 target [0] = idx & 0xff;
3572 target [1] = (idx >> 8) & 0xff;
3573 target [2] = (idx >> 16) & 0xff;
3580 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3581 * value is not known when the table is emitted.
3584 fixup_cattrs (MonoDynamicImage *assembly)
3586 MonoDynamicTable *table;
3588 guint32 type, i, idx, token;
3591 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3593 for (i = 0; i < table->rows; ++i) {
3594 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3596 type = values [MONO_CUSTOM_ATTR_TYPE];
3597 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3598 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3599 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3600 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3603 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3604 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3605 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3606 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3613 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3615 MonoDynamicTable *table;
3619 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3621 alloc_table (table, table->rows);
3622 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3623 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3624 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3625 name = mono_string_to_utf8 (rsrc->name);
3626 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3628 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3633 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3635 MonoDynamicTable *table;
3639 char *b = blob_size;
3641 guint32 idx, offset;
3643 if (rsrc->filename) {
3644 name = mono_string_to_utf8 (rsrc->filename);
3645 sname = g_path_get_basename (name);
3647 table = &assembly->tables [MONO_TABLE_FILE];
3649 alloc_table (table, table->rows);
3650 values = table->values + table->next_idx * MONO_FILE_SIZE;
3651 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3652 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3655 mono_sha1_get_digest_from_file (name, hash);
3656 mono_metadata_encode_value (20, b, &b);
3657 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3658 mono_image_add_stream_data (&assembly->blob, hash, 20);
3660 idx = table->next_idx++;
3662 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3665 offset = mono_array_length (rsrc->data);
3666 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3667 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3668 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3669 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3673 * The entry should be emitted into the MANIFESTRESOURCE table of
3674 * the main module, but that needs to reference the FILE table
3675 * which isn't emitted yet.
3682 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3686 set_version_from_string (MonoString *version, guint32 *values)
3688 gchar *ver, *p, *str;
3691 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3692 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3693 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3694 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3697 ver = str = mono_string_to_utf8 (version);
3698 for (i = 0; i < 4; ++i) {
3699 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3705 /* handle Revision and Build */
3715 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3719 char *b = blob_size;
3724 len = mono_array_length (pkey);
3725 mono_metadata_encode_value (len, b, &b);
3726 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3727 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3729 /* need to get the actual value from the key type... */
3730 assembly->strong_name_size = 128;
3731 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3737 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3739 MonoDynamicTable *table;
3740 MonoDynamicImage *assembly;
3741 MonoReflectionAssemblyBuilder *assemblyb;
3746 guint32 module_index;
3748 assemblyb = moduleb->assemblyb;
3749 assembly = moduleb->dynamic_image;
3750 domain = mono_object_domain (assemblyb);
3752 /* Emit ASSEMBLY table */
3753 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3754 alloc_table (table, 1);
3755 values = table->values + MONO_ASSEMBLY_SIZE;
3756 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3757 name = mono_string_to_utf8 (assemblyb->name);
3758 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3760 if (assemblyb->culture) {
3761 name = mono_string_to_utf8 (assemblyb->culture);
3762 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3765 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3767 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3768 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3769 set_version_from_string (assemblyb->version, values);
3771 /* Emit FILE + EXPORTED_TYPE table */
3773 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3775 MonoReflectionModuleBuilder *file_module =
3776 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3777 if (file_module != moduleb) {
3778 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3780 if (file_module->types) {
3781 for (j = 0; j < file_module->num_types; ++j) {
3782 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3783 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3788 if (assemblyb->loaded_modules) {
3789 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3790 MonoReflectionModule *file_module =
3791 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3792 mono_image_fill_file_table (domain, file_module, assembly);
3794 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3798 /* Emit MANIFESTRESOURCE table */
3800 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3802 MonoReflectionModuleBuilder *file_module =
3803 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3804 /* The table for the main module is emitted later */
3805 if (file_module != moduleb) {
3807 if (file_module->resources) {
3808 int len = mono_array_length (file_module->resources);
3809 for (j = 0; j < len; ++j) {
3810 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3811 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3819 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3820 * for the modulebuilder @moduleb.
3821 * At the end of the process, method and field tokens are fixed up and the
3822 * on-disk compressed metadata representation is created.
3825 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3827 MonoDynamicTable *table;
3828 MonoDynamicImage *assembly;
3829 MonoReflectionAssemblyBuilder *assemblyb;
3834 assemblyb = moduleb->assemblyb;
3835 assembly = moduleb->dynamic_image;
3836 domain = mono_object_domain (assemblyb);
3838 if (assembly->text_rva)
3841 assembly->text_rva = START_TEXT_RVA;
3843 if (moduleb->is_main) {
3844 mono_image_emit_manifest (moduleb);
3847 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3848 table->rows = 1; /* .<Module> */
3850 alloc_table (table, table->rows);
3852 * Set the first entry.
3854 values = table->values + table->columns;
3855 values [MONO_TYPEDEF_FLAGS] = 0;
3856 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3857 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3858 values [MONO_TYPEDEF_EXTENDS] = 0;
3859 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3860 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3863 * handle global methods
3864 * FIXME: test what to do when global methods are defined in multiple modules.
3866 if (moduleb->global_methods) {
3867 table = &assembly->tables [MONO_TABLE_METHOD];
3868 table->rows += mono_array_length (moduleb->global_methods);
3869 alloc_table (table, table->rows);
3870 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3871 mono_image_get_method_info (
3872 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3874 if (moduleb->global_fields) {
3875 table = &assembly->tables [MONO_TABLE_FIELD];
3876 table->rows += mono_array_length (moduleb->global_fields);
3877 alloc_table (table, table->rows);
3878 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3879 mono_image_get_field_info (
3880 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3883 table = &assembly->tables [MONO_TABLE_MODULE];
3884 alloc_table (table, 1);
3885 mono_image_fill_module_table (domain, moduleb, assembly);
3889 /* Collect all types into a list sorted by their table_idx */
3890 GPtrArray *types = g_ptr_array_new ();
3893 for (i = 0; i < moduleb->num_types; ++i) {
3894 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3895 collect_types (types, type);
3898 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows += types->len;
3901 alloc_table (table, table->rows);
3903 for (i = 0; i < types->len; ++i) {
3904 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3905 mono_image_get_type_info (domain, type, assembly);
3907 g_ptr_array_free (types, TRUE);
3911 * table->rows is already set above and in mono_image_fill_module_table.
3913 /* add all the custom attributes at the end, once all the indexes are stable */
3914 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3916 /* CAS assembly permissions */
3917 if (assemblyb->permissions_minimum)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3919 if (assemblyb->permissions_optional)
3920 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3921 if (assemblyb->permissions_refused)
3922 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3924 module_add_cattrs (assembly, moduleb);
3927 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3928 fixup_cattrs (assembly);
3932 * mono_image_insert_string:
3933 * @module: module builder object
3936 * Insert @str into the user string stream of @module.
3939 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3941 MonoDynamicImage *assembly;
3946 MONO_ARCH_SAVE_REGS;
3948 if (!module->dynamic_image)
3949 mono_image_module_basic_init (module);
3951 assembly = module->dynamic_image;
3953 if (assembly->save) {
3954 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3955 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3956 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3958 char *swapped = g_malloc (2 * mono_string_length (str));
3959 const char *p = (const char*)mono_string_chars (str);
3961 swap_with_size (swapped, p, 2, mono_string_length (str));
3962 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3966 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3968 mono_image_add_stream_data (&assembly->us, "", 1);
3970 idx = assembly->us.index ++;
3973 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3975 return MONO_TOKEN_STRING | idx;
3979 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3984 klass = obj->vtable->klass;
3985 if (strcmp (klass->name, "MonoMethod") == 0) {
3986 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3987 MonoMethodSignature *sig, *old;
3988 guint32 sig_token, parent;
3991 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3993 nargs = mono_array_length (opt_param_types);
3994 old = method->signature;
3995 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3997 sig->hasthis = old->hasthis;
3998 sig->explicit_this = old->explicit_this;
3999 sig->call_convention = old->call_convention;
4000 sig->generic_param_count = old->generic_param_count;
4001 sig->param_count = old->param_count + nargs;
4002 sig->sentinelpos = old->param_count;
4003 sig->ret = old->ret;
4005 for (i = 0; i < old->param_count; i++)
4006 sig->params [i] = old->params [i];
4008 for (i = 0; i < nargs; i++) {
4009 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4010 sig->params [old->param_count + i] = rt->type;
4013 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4014 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4015 parent >>= MONO_TYPEDEFORREF_BITS;
4017 parent <<= MONO_MEMBERREF_PARENT_BITS;
4018 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4020 sig_token = method_encode_signature (assembly, sig);
4021 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4022 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4024 ReflectionMethodBuilder rmb;
4025 guint32 parent, sig;
4027 reflection_methodbuilder_from_method_builder (&rmb, mb);
4028 rmb.opt_types = opt_param_types;
4030 sig = method_builder_encode_signature (assembly, &rmb);
4032 parent = mono_image_create_token (assembly, obj, TRUE);
4033 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4035 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4036 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4038 token = mono_image_get_varargs_method_token (
4039 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4041 g_error ("requested method token for %s\n", klass->name);
4048 * mono_image_create_token:
4049 * @assembly: a dynamic assembly
4052 * Get a token to insert in the IL code stream for the given MemberInfo.
4053 * @obj can be one of:
4054 * ConstructorBuilder
4064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4069 klass = obj->vtable->klass;
4070 if (strcmp (klass->name, "MethodBuilder") == 0) {
4071 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4073 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4074 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4076 token = mono_image_get_methodbuilder_token (assembly, mb);
4077 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4078 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4079 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4081 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4082 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4084 token = mono_image_get_ctorbuilder_token (assembly, mb);
4085 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4086 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4087 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4088 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4089 if (tb->generic_params) {
4090 token = mono_image_get_generic_field_token (assembly, fb);
4092 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4094 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4095 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4096 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4097 } else if (strcmp (klass->name, "MonoType") == 0 ||
4098 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4099 MonoReflectionType *tb = (MonoReflectionType *)obj;
4100 token = mono_metadata_token_from_dor (
4101 mono_image_typedef_or_ref (assembly, tb->type));
4102 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4103 MonoReflectionType *tb = (MonoReflectionType *)obj;
4104 token = mono_metadata_token_from_dor (
4105 mono_image_typedef_or_ref (assembly, tb->type));
4106 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4107 strcmp (klass->name, "MonoMethod") == 0) {
4108 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4109 if (m->method->signature->is_inflated) {
4110 if (create_methodspec)
4111 token = mono_image_get_methodspec_token (assembly, m->method);
4113 token = mono_image_get_inflated_method_token (assembly, m->method);
4114 } else if (m->method->signature->generic_param_count) {
4115 g_assert_not_reached ();
4116 } else if ((m->method->klass->image == &assembly->image) &&
4117 !m->method->klass->generic_inst) {
4118 static guint32 method_table_idx = 0xffffff;
4119 if (m->method->klass->wastypebuilder) {
4120 /* we use the same token as the one that was assigned
4121 * to the Methodbuilder.
4122 * FIXME: do the equivalent for Fields.
4124 token = m->method->token;
4127 * Each token should have a unique index, but the indexes are
4128 * assigned by managed code, so we don't know about them. An
4129 * easy solution is to count backwards...
4131 method_table_idx --;
4132 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4135 token = mono_image_get_methodref_token (assembly, m->method);
4137 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4138 } else if (strcmp (klass->name, "MonoField") == 0) {
4139 MonoReflectionField *f = (MonoReflectionField *)obj;
4140 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4141 static guint32 field_table_idx = 0xffffff;
4143 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4145 token = mono_image_get_fieldref_token (assembly, f);
4147 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4148 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4149 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4150 token = mono_image_get_array_token (assembly, m);
4151 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4152 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4153 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4155 g_error ("requested token for %s\n", klass->name);
4158 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4164 guint32 import_lookup_table;
4168 guint32 import_address_table_rva;
4176 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4178 static MonoDynamicImage*
4179 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4181 static const guchar entrycode [16] = {0xff, 0x25, 0};
4182 MonoDynamicImage *image;
4185 const char *version = mono_get_runtime_version ();
4188 image = GC_MALLOC (sizeof (MonoDynamicImage));
4190 image = g_new0 (MonoDynamicImage, 1);
4193 /* keep in sync with image.c */
4194 image->image.name = assembly_name;
4195 image->image.assembly_name = image->image.name; /* they may be different */
4196 image->image.module_name = module_name;
4197 image->image.version = g_strdup (version);
4198 image->image.dynamic = TRUE;
4200 image->image.references = g_new0 (MonoAssembly*, 1);
4201 image->image.references [0] = NULL;
4203 mono_image_init (&image->image);
4205 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4206 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4207 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4208 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4209 image->handleref = g_hash_table_new (NULL, NULL);
4210 image->tokens = mono_g_hash_table_new (NULL, NULL);
4211 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4212 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4213 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4214 image->gen_params = g_ptr_array_new ();
4216 string_heap_init (&image->sheap);
4217 mono_image_add_stream_data (&image->us, "", 1);
4218 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4219 /* import tables... */
4220 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4221 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4222 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4223 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4225 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4226 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4227 stream_data_align (&image->code);
4229 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4231 for (i=0; i < 64; ++i) {
4232 image->tables [i].next_idx = 1;
4233 image->tables [i].columns = table_sizes [i];
4236 image->image.assembly = (MonoAssembly*)assembly;
4237 image->run = assembly->run;
4238 image->save = assembly->save;
4239 image->pe_kind = 0x1; /* ILOnly */
4240 image->machine = 0x14c; /* I386 */
4246 * mono_image_basic_init:
4247 * @assembly: an assembly builder object
4249 * Create the MonoImage that represents the assembly builder and setup some
4250 * of the helper hash table and the basic metadata streams.
4253 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4255 MonoDynamicAssembly *assembly;
4256 MonoDynamicImage *image;
4258 MONO_ARCH_SAVE_REGS;
4260 if (assemblyb->dynamic_assembly)
4264 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4266 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4269 assembly->assembly.dynamic = TRUE;
4270 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4271 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4272 if (assemblyb->culture)
4273 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4275 assembly->assembly.aname.culture = g_strdup ("");
4277 assembly->run = assemblyb->access != 2;
4278 assembly->save = assemblyb->access != 1;
4280 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4281 image->initial_image = TRUE;
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 assembly->pe_kind = assemblyb->pe_kind;
4581 assembly->machine = assemblyb->machine;
4582 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4583 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4585 /* already created */
4586 if (assembly->pefile.index)
4589 mono_image_build_metadata (mb);
4591 if (mb->is_main && assemblyb->resources) {
4592 int len = mono_array_length (assemblyb->resources);
4593 for (i = 0; i < len; ++i)
4594 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4597 if (mb->resources) {
4598 int len = mono_array_length (mb->resources);
4599 for (i = 0; i < len; ++i)
4600 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4603 build_compressed_metadata (assembly);
4606 assembly_add_win32_resources (assembly, assemblyb);
4608 nsections = calc_section_size (assembly);
4610 pefile = &assembly->pefile;
4612 /* The DOS header and stub */
4613 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4614 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4616 /* the dotnet header */
4617 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4619 /* the section tables */
4620 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4622 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4623 virtual_offset = VIRT_ALIGN;
4626 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4627 if (!assembly->sections [i].size)
4630 file_offset += FILE_ALIGN - 1;
4631 file_offset &= ~(FILE_ALIGN - 1);
4632 virtual_offset += VIRT_ALIGN - 1;
4633 virtual_offset &= ~(VIRT_ALIGN - 1);
4635 assembly->sections [i].offset = file_offset;
4636 assembly->sections [i].rva = virtual_offset;
4638 file_offset += assembly->sections [i].size;
4639 virtual_offset += assembly->sections [i].size;
4640 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4643 file_offset += FILE_ALIGN - 1;
4644 file_offset &= ~(FILE_ALIGN - 1);
4645 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4647 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4649 /* back-patch info */
4650 msdos = (MonoMSDOSHeader*)pefile->data;
4651 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4652 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4653 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4655 header = (MonoDotNetHeader*)(pefile->data + header_start);
4656 header->pesig [0] = 'P';
4657 header->pesig [1] = 'E';
4659 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4660 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4661 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4662 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4663 if (assemblyb->pekind == 1) {
4665 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4668 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4671 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4673 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4674 header->pe.pe_major = 6;
4675 header->pe.pe_minor = 0;
4676 size = assembly->sections [MONO_SECTION_TEXT].size;
4677 size += FILE_ALIGN - 1;
4678 size &= ~(FILE_ALIGN - 1);
4679 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4680 size = assembly->sections [MONO_SECTION_RSRC].size;
4681 size += FILE_ALIGN - 1;
4682 size &= ~(FILE_ALIGN - 1);
4683 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4684 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4685 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4686 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4687 /* pe_rva_entry_point always at the beginning of the text section */
4688 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4690 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4691 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4692 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4693 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4694 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4695 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4696 size = section_start;
4697 size += FILE_ALIGN - 1;
4698 size &= ~(FILE_ALIGN - 1);
4699 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4701 size += VIRT_ALIGN - 1;
4702 size &= ~(VIRT_ALIGN - 1);
4703 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4706 // Translate the PEFileKind value to the value expected by the Windows loader
4712 // PEFileKinds.Dll == 1
4713 // PEFileKinds.ConsoleApplication == 2
4714 // PEFileKinds.WindowApplication == 3
4717 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4718 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4720 if (assemblyb->pekind == 3)
4725 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4727 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4728 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4729 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4730 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4731 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4732 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4734 /* fill data directory entries */
4736 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4737 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4739 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4740 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4742 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4743 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4744 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4745 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4746 /* patch imported function RVA name */
4747 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4748 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4750 /* the import table */
4751 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4752 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4753 /* patch imported dll RVA name and other entries in the dir */
4754 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4755 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4756 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4757 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4758 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4759 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4761 p = (assembly->code.data + assembly->ilt_offset);
4762 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4763 *p++ = (value) & 0xff;
4764 *p++ = (value >> 8) & (0xff);
4765 *p++ = (value >> 16) & (0xff);
4766 *p++ = (value >> 24) & (0xff);
4768 /* the CLI header info */
4769 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4770 cli_header->ch_size = GUINT32_FROM_LE (72);
4771 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4772 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4773 if (assemblyb->entry_point) {
4774 guint32 table_idx = 0;
4775 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4776 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4777 table_idx = methodb->table_idx;
4779 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4781 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4783 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4785 /* The embedded managed resources */
4786 text_offset = assembly->text_rva + assembly->code.index;
4787 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4788 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4789 text_offset += assembly->resources.index;
4790 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4791 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4792 text_offset += assembly->meta_size;
4793 if (assembly->strong_name_size) {
4794 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4795 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4796 text_offset += assembly->strong_name_size;
4799 /* write the section tables and section content */
4800 section = (MonoSectionTable*)(pefile->data + section_start);
4801 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4802 static const char *section_names [] = {
4803 ".text", ".rsrc", ".reloc"
4805 if (!assembly->sections [i].size)
4807 strcpy (section->st_name, section_names [i]);
4808 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4809 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4810 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4811 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4812 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4813 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4814 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4816 case MONO_SECTION_TEXT:
4817 /* patch entry point */
4818 p = (assembly->code.data + 2);
4819 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4820 *p++ = (value) & 0xff;
4821 *p++ = (value >> 8) & 0xff;
4822 *p++ = (value >> 16) & 0xff;
4823 *p++ = (value >> 24) & 0xff;
4825 text_offset = assembly->sections [i].offset;
4826 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4827 text_offset += assembly->code.index;
4828 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4829 text_offset += assembly->resources.index;
4830 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4831 text_offset += assembly->meta_size;
4832 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4834 g_free (assembly->image.raw_metadata);
4836 case MONO_SECTION_RELOC:
4837 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4838 *rva = GUINT32_FROM_LE (assembly->text_rva);
4840 *rva = GUINT32_FROM_LE (12);
4842 data16 = (guint16*)rva;
4844 * the entrypoint is always at the start of the text section
4845 * 3 is IMAGE_REL_BASED_HIGHLOW
4846 * 2 is patch_size_rva - text_rva
4848 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4850 *data16 = 0; /* terminate */
4852 case MONO_SECTION_RSRC:
4853 if (assembly->win32_res) {
4854 text_offset = assembly->sections [i].offset;
4856 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4857 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4859 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4863 g_assert_not_reached ();
4868 /* check that the file is properly padded */
4871 FILE *f = fopen ("mypetest.exe", "w");
4872 fwrite (pefile->data, pefile->index, 1, f);
4878 MonoReflectionModule *
4879 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4883 MonoImageOpenStatus status;
4884 MonoDynamicAssembly *assembly;
4885 guint32 module_count;
4886 MonoImage **new_modules;
4888 name = mono_string_to_utf8 (fileName);
4890 image = mono_image_open (name, &status);
4893 if (status == MONO_IMAGE_ERROR_ERRNO)
4894 exc = mono_get_exception_file_not_found (fileName);
4896 exc = mono_get_exception_bad_image_format (name);
4898 mono_raise_exception (exc);
4903 assembly = ab->dynamic_assembly;
4904 image->assembly = (MonoAssembly*)assembly;
4906 module_count = image->assembly->image->module_count;
4907 new_modules = g_new0 (MonoImage *, module_count + 1);
4909 if (image->assembly->image->modules)
4910 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4911 new_modules [module_count] = image;
4913 g_free (image->assembly->image->modules);
4914 image->assembly->image->modules = new_modules;
4915 image->assembly->image->module_count ++;
4917 mono_assembly_load_references (image, &status);
4919 mono_image_close (image);
4920 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4923 return mono_module_get_object (mono_domain_get (), image);
4927 * We need to return always the same object for MethodInfo, FieldInfo etc..
4928 * but we need to consider the reflected type.
4929 * type uses a different hash, since it uses custom hash/equal functions.
4934 MonoClass *refclass;
4938 reflected_equal (gconstpointer a, gconstpointer b) {
4939 const ReflectedEntry *ea = a;
4940 const ReflectedEntry *eb = b;
4942 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4946 reflected_hash (gconstpointer a) {
4947 const ReflectedEntry *ea = a;
4948 return GPOINTER_TO_UINT (ea->item);
4951 #define CHECK_OBJECT(t,p,k) \
4957 mono_domain_lock (domain); \
4958 if (!domain->refobject_hash) \
4959 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4960 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4961 mono_domain_unlock (domain); \
4967 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4969 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4972 #define CACHE_OBJECT(p,o,k) \
4974 ReflectedEntry *e = ALLOC_REFENTRY; \
4976 e->refclass = (k); \
4977 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4978 mono_domain_unlock (domain); \
4982 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4984 /* this is done only once */
4985 mono_domain_lock (domain);
4986 CACHE_OBJECT (assembly, res, NULL);
4990 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4992 /* this is done only once */
4993 mono_domain_lock (domain);
4994 CACHE_OBJECT (module, res, NULL);
4998 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5000 MonoDynamicImage *image = moduleb->dynamic_image;
5001 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5004 * FIXME: we already created an image in mono_image_basic_init (), but
5005 * we don't know which module it belongs to, since that is only
5006 * determined at assembly save time.
5008 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5009 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5011 moduleb->module.image = &image->image;
5012 moduleb->dynamic_image = image;
5013 register_module (mono_object_domain (moduleb), moduleb, image);
5018 * mono_assembly_get_object:
5019 * @domain: an app domain
5020 * @assembly: an assembly
5022 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5024 MonoReflectionAssembly*
5025 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5027 static MonoClass *System_Reflection_Assembly;
5028 MonoReflectionAssembly *res;
5030 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5031 if (!System_Reflection_Assembly)
5032 System_Reflection_Assembly = mono_class_from_name (
5033 mono_defaults.corlib, "System.Reflection", "Assembly");
5034 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5035 res->assembly = assembly;
5036 CACHE_OBJECT (assembly, res, NULL);
5042 MonoReflectionModule*
5043 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5045 static MonoClass *System_Reflection_Module;
5046 MonoReflectionModule *res;
5048 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5049 if (!System_Reflection_Module)
5050 System_Reflection_Module = mono_class_from_name (
5051 mono_defaults.corlib, "System.Reflection", "Module");
5052 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5055 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5057 res->fqname = mono_string_new (domain, image->name);
5058 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5059 res->scopename = mono_string_new (domain, image->module_name);
5061 if (image->assembly->image == image) {
5062 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5065 g_assert (image->assembly->image->modules);
5067 for (i = 0; i < image->assembly->image->module_count; i++) {
5068 if (image->assembly->image->modules [i] == image)
5069 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5071 g_assert (res->token);
5074 mono_image_addref (image);
5076 CACHE_OBJECT (image, res, NULL);
5080 MonoReflectionModule*
5081 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5083 static MonoClass *System_Reflection_Module;
5084 MonoReflectionModule *res;
5085 MonoTableInfo *table;
5086 guint32 cols [MONO_FILE_SIZE];
5088 guint32 i, name_idx;
5091 if (!System_Reflection_Module)
5092 System_Reflection_Module = mono_class_from_name (
5093 mono_defaults.corlib, "System.Reflection", "Module");
5094 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5096 table = &image->tables [MONO_TABLE_FILE];
5097 g_assert (table_index < table->rows);
5098 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5101 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5102 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5104 /* Check whenever the row has a corresponding row in the moduleref table */
5105 table = &image->tables [MONO_TABLE_MODULEREF];
5106 for (i = 0; i < table->rows; ++i) {
5107 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5108 val = mono_metadata_string_heap (image, name_idx);
5109 if (strcmp (val, name) == 0)
5110 res->image = image->modules [i];
5113 res->fqname = mono_string_new (domain, name);
5114 res->name = mono_string_new (domain, name);
5115 res->scopename = mono_string_new (domain, name);
5116 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5117 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5123 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5125 if ((t1->type != t2->type) ||
5126 (t1->byref != t2->byref))
5130 case MONO_TYPE_VOID:
5131 case MONO_TYPE_BOOLEAN:
5132 case MONO_TYPE_CHAR:
5143 case MONO_TYPE_STRING:
5146 case MONO_TYPE_OBJECT:
5147 case MONO_TYPE_TYPEDBYREF:
5149 case MONO_TYPE_VALUETYPE:
5150 case MONO_TYPE_CLASS:
5151 case MONO_TYPE_SZARRAY:
5152 return t1->data.klass == t2->data.klass;
5154 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5155 case MONO_TYPE_ARRAY:
5156 if (t1->data.array->rank != t2->data.array->rank)
5158 return t1->data.array->eklass == t2->data.array->eklass;
5159 case MONO_TYPE_GENERICINST: {
5161 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5163 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5165 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5166 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5172 case MONO_TYPE_MVAR:
5173 return t1->data.generic_param == t2->data.generic_param;
5175 g_error ("implement type compare for %0x!", t1->type);
5183 mymono_metadata_type_hash (MonoType *t1)
5189 hash |= t1->byref << 6; /* do not collide with t1->type values */
5191 case MONO_TYPE_VALUETYPE:
5192 case MONO_TYPE_CLASS:
5193 case MONO_TYPE_SZARRAY:
5194 /* check if the distribution is good enough */
5195 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5197 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5202 static MonoReflectionGenericInst*
5203 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5205 static MonoClass *System_Reflection_MonoGenericInst;
5206 MonoReflectionGenericInst *res;
5207 MonoGenericInst *ginst;
5210 if (!System_Reflection_MonoGenericInst) {
5211 System_Reflection_MonoGenericInst = mono_class_from_name (
5212 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5213 g_assert (System_Reflection_MonoGenericInst);
5216 ginst = geninst->data.generic_inst;
5217 gklass = mono_class_from_mono_type (ginst->generic_type);
5219 mono_class_init (ginst->klass);
5221 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5223 res->type.type = geninst;
5224 if (gklass->wastypebuilder && gklass->reflection_info)
5225 res->generic_type = gklass->reflection_info;
5227 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5233 * mono_type_get_object:
5234 * @domain: an app domain
5237 * Return an System.MonoType object representing the type @type.
5240 mono_type_get_object (MonoDomain *domain, MonoType *type)
5242 MonoReflectionType *res;
5243 MonoClass *klass = mono_class_from_mono_type (type);
5245 mono_domain_lock (domain);
5246 if (!domain->type_hash)
5247 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5248 (GCompareFunc)mymono_metadata_type_equal);
5249 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5250 mono_domain_unlock (domain);
5253 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5254 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5255 mono_g_hash_table_insert (domain->type_hash, type, res);
5256 mono_domain_unlock (domain);
5259 if (klass->reflection_info && !klass->wastypebuilder) {
5260 /* g_assert_not_reached (); */
5261 /* should this be considered an error condition? */
5263 mono_domain_unlock (domain);
5264 return klass->reflection_info;
5267 mono_class_init (klass);
5268 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5270 mono_g_hash_table_insert (domain->type_hash, type, res);
5271 mono_domain_unlock (domain);
5276 * mono_method_get_object:
5277 * @domain: an app domain
5279 * @refclass: the reflected type (can be NULL)
5281 * Return an System.Reflection.MonoMethod object representing the method @method.
5283 MonoReflectionMethod*
5284 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5287 * We use the same C representation for methods and constructors, but the type
5288 * name in C# is different.
5292 MonoReflectionMethod *ret;
5295 refclass = method->klass;
5297 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5298 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5299 cname = "MonoCMethod";
5301 cname = "MonoMethod";
5302 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5304 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5305 ret->method = method;
5306 ret->name = mono_string_new (domain, method->name);
5307 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5308 CACHE_OBJECT (method, ret, refclass);
5313 * mono_field_get_object:
5314 * @domain: an app domain
5318 * Return an System.Reflection.MonoField object representing the field @field
5321 MonoReflectionField*
5322 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5324 MonoReflectionField *res;
5327 CHECK_OBJECT (MonoReflectionField *, field, klass);
5328 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5329 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5332 res->name = mono_string_new (domain, field->name);
5333 if (field->generic_info)
5334 res->attrs = field->generic_info->generic_type->attrs;
5336 res->attrs = field->type->attrs;
5337 res->type = mono_type_get_object (domain, field->type);
5338 CACHE_OBJECT (field, res, klass);
5343 * mono_property_get_object:
5344 * @domain: an app domain
5346 * @property: a property
5348 * Return an System.Reflection.MonoProperty object representing the property @property
5351 MonoReflectionProperty*
5352 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5354 MonoReflectionProperty *res;
5357 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5358 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5359 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5361 res->property = property;
5362 CACHE_OBJECT (property, res, klass);
5367 * mono_event_get_object:
5368 * @domain: an app domain
5372 * Return an System.Reflection.MonoEvent object representing the event @event
5375 MonoReflectionEvent*
5376 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5378 MonoReflectionEvent *res;
5381 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5382 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5383 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5386 CACHE_OBJECT (event, res, klass);
5391 * mono_param_get_objects:
5392 * @domain: an app domain
5395 * Return an System.Reflection.ParameterInfo array object representing the parameters
5396 * in the method @method.
5399 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5401 static MonoClass *System_Reflection_ParameterInfo;
5402 MonoArray *res = NULL;
5403 MonoReflectionMethod *member = NULL;
5404 MonoReflectionParameter *param = NULL;
5405 char **names, **blobs = NULL;
5406 MonoObject *dbnull = mono_get_dbnull_object (domain);
5407 MonoMarshalSpec **mspecs;
5410 if (!System_Reflection_ParameterInfo)
5411 System_Reflection_ParameterInfo = mono_class_from_name (
5412 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5414 if (!method->signature->param_count)
5415 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5417 /* Note: the cache is based on the address of the signature into the method
5418 * since we already cache MethodInfos with the method as keys.
5420 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5422 member = mono_method_get_object (domain, method, NULL);
5423 names = g_new (char *, method->signature->param_count);
5424 mono_method_get_param_names (method, (const char **) names);
5426 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5427 mono_method_get_marshal_info (method, mspecs);
5429 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5430 for (i = 0; i < method->signature->param_count; ++i) {
5431 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5432 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5433 param->MemberImpl = (MonoObject*)member;
5434 param->NameImpl = mono_string_new (domain, names [i]);
5435 param->PositionImpl = i;
5436 param->AttrsImpl = method->signature->params [i]->attrs;
5438 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5439 param->DefaultValueImpl = dbnull;
5441 MonoType *type = param->ClassImpl->type;
5444 blobs = g_new0 (char *, method->signature->param_count);
5445 get_default_param_value_blobs (method, blobs);
5448 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5450 if (!param->DefaultValueImpl) {
5451 param->DefaultValueImpl = dbnull;
5456 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5458 mono_array_set (res, gpointer, i, param);
5463 for (i = method->signature->param_count; i >= 0; i--)
5465 mono_metadata_free_marshal_spec (mspecs [i]);
5468 CACHE_OBJECT (&(method->signature), res, NULL);
5473 * mono_method_body_get_object:
5474 * @domain: an app domain
5477 * Return an System.Reflection.MethodBody object representing the method @method.
5479 MonoReflectionMethodBody*
5480 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5482 static MonoClass *System_Reflection_MethodBody = NULL;
5484 MonoReflectionMethodBody *ret;
5485 MonoMethodNormal *mn;
5486 MonoMethodHeader *header;
5488 if (!System_Reflection_MethodBody)
5489 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5491 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5493 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5494 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5496 mn = (MonoMethodNormal *)method;
5497 header = mn->header;
5499 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5500 /* FIXME: Other fields */
5501 ret->init_locals = header->init_locals;
5502 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5503 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5504 CACHE_OBJECT (method, ret, NULL);
5509 mono_get_dbnull_object (MonoDomain *domain)
5513 static MonoClassField *dbnull_value_field = NULL;
5515 if (!dbnull_value_field) {
5516 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5517 mono_class_init (klass);
5518 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5519 g_assert (dbnull_value_field);
5521 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5528 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5530 guint32 param_index, i, lastp, crow = 0;
5531 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5534 MonoClass *klass = method->klass;
5535 MonoImage *image = klass->image;
5536 MonoMethodSignature *methodsig = method->signature;
5538 MonoTableInfo *constt;
5539 MonoTableInfo *methodt;
5540 MonoTableInfo *paramt;
5542 if (!methodsig->param_count)
5545 if (klass->generic_inst) {
5546 return; /* FIXME - ??? */
5549 mono_class_init (klass);
5551 if (klass->image->dynamic) {
5552 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5553 if (aux && aux->param_defaults)
5554 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5558 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5559 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5560 constt = &image->tables [MONO_TABLE_CONSTANT];
5562 for (i = 0; i < klass->method.count; ++i) {
5563 if (method == klass->methods [i]) {
5564 idx = klass->method.first + i;
5569 g_assert (idx != -1);
5571 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5572 if (idx + 1 < methodt->rows)
5573 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5575 lastp = paramt->rows + 1;
5577 for (i = param_index; i < lastp; ++i) {
5580 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5581 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5583 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5586 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5591 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5592 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5599 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5608 klass = mono_class_from_mono_type (type);
5609 if (klass->valuetype) {
5610 object = mono_object_new (domain, klass);
5611 retval = ((gchar *) object + sizeof (MonoObject));
5616 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5623 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5627 memset (assembly, 0, sizeof (MonoAssemblyName));
5629 assembly->culture = "";
5630 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5632 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5635 while (*p == ' ' || *p == ',') {
5644 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5646 assembly->major = strtoul (p, &s, 10);
5647 if (s == p || *s != '.')
5650 assembly->minor = strtoul (p, &s, 10);
5651 if (s == p || *s != '.')
5654 assembly->build = strtoul (p, &s, 10);
5655 if (s == p || *s != '.')
5658 assembly->revision = strtoul (p, &s, 10);
5662 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5664 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5665 assembly->culture = "";
5668 assembly->culture = p;
5669 while (*p && *p != ',') {
5673 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5675 if (strncmp (p, "null", 4) == 0) {
5680 while (*p && *p != ',') {
5683 len = (p - start + 1);
5684 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5685 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5686 g_strlcpy (assembly->public_key_token, start, len);
5689 while (*p && *p != ',')
5693 while (*p == ' ' || *p == ',') {
5707 * mono_reflection_parse_type:
5710 * Parse a type name as accepted by the GetType () method and output the info
5711 * extracted in the info structure.
5712 * the name param will be mangled, so, make a copy before passing it to this function.
5713 * The fields in info will be valid until the memory pointed to by name is valid.
5714 * Returns 0 on parse error.
5715 * See also mono_type_get_name () below.
5718 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5720 char *start, *p, *w, *last_point, *startn;
5721 int in_modifiers = 0;
5722 int isbyref = 0, rank;
5724 start = p = w = name;
5726 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5727 info->name = info->name_space = NULL;
5728 info->nested = NULL;
5729 info->modifiers = NULL;
5731 /* last_point separates the namespace from the name */
5737 *p = 0; /* NULL terminate the name */
5739 info->nested = g_list_append (info->nested, startn);
5740 /* we have parsed the nesting namespace + name */
5744 info->name_space = start;
5746 info->name = last_point + 1;
5748 info->name_space = (char *)"";
5774 info->name_space = start;
5776 info->name = last_point + 1;
5778 info->name_space = (char *)"";
5785 if (isbyref) /* only one level allowed by the spec */
5788 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5792 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5803 else if (*p != '*') /* '*' means unknown lower bound */
5809 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5821 return 0; /* missing assembly name */
5822 if (!assembly_name_to_aname (&info->assembly, p))
5829 if (info->assembly.name)
5832 *w = 0; /* terminate class name */
5833 if (!info->name || !*info->name)
5835 /* add other consistency checks */
5840 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5847 image = mono_defaults.corlib;
5850 klass = mono_class_from_name_case (image, info->name_space, info->name);
5852 klass = mono_class_from_name (image, info->name_space, info->name);
5855 for (mod = info->nested; mod; mod = mod->next) {
5858 mono_class_init (klass);
5859 nested = klass->nested_classes;
5862 klass = nested->data;
5864 if (g_strcasecmp (klass->name, mod->data) == 0)
5867 if (strcmp (klass->name, mod->data) == 0)
5871 nested = nested->next;
5878 mono_class_init (klass);
5879 for (mod = info->modifiers; mod; mod = mod->next) {
5880 modval = GPOINTER_TO_UINT (mod->data);
5881 if (!modval) { /* byref: must be last modifier */
5882 return &klass->this_arg;
5883 } else if (modval == -1) {
5884 klass = mono_ptr_class_get (&klass->byval_arg);
5885 } else { /* array rank */
5886 klass = mono_array_class_get (klass, modval);
5888 mono_class_init (klass);
5891 return &klass->byval_arg;
5895 * mono_reflection_get_type:
5896 * @image: a metadata context
5897 * @info: type description structure
5898 * @ignorecase: flag for case-insensitive string compares
5899 * @type_resolve: whenever type resolve was already tried
5901 * Build a MonoType from the type description in @info.
5906 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5909 MonoReflectionAssembly *assembly;
5913 type = mono_reflection_get_type_internal (image, info, ignorecase);
5916 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5919 /* FIXME: Enabling this causes regressions (#65577) */
5925 *type_resolve = TRUE;
5929 /* Reconstruct the type name */
5930 fullName = g_string_new ("");
5931 if (info->name_space && (info->name_space [0] != '\0'))
5932 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5934 g_string_printf (fullName, info->name);
5935 for (mod = info->nested; mod; mod = mod->next)
5936 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5938 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5939 if (assembly && (!image || (assembly->assembly->image == image))) {
5941 if (assembly->assembly->dynamic) {
5942 /* Enumerate all modules */
5943 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5947 if (abuilder->modules) {
5948 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5949 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5950 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5956 if (!type && abuilder->loaded_modules) {
5957 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5958 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5959 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5966 type = mono_reflection_get_type_internal (assembly->assembly->image,
5969 g_string_free (fullName, TRUE);
5974 * mono_reflection_type_from_name:
5976 * @image: a metadata context (can be NULL).
5978 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5979 * it defaults to get the type from @image or, if @image is NULL or loading
5980 * from it fails, uses corlib.
5984 mono_reflection_type_from_name (char *name, MonoImage *image)
5987 MonoTypeNameParse info;
5988 MonoAssembly *assembly;
5990 gboolean type_resolve = FALSE;
5992 /* Make a copy since parse_type modifies its argument */
5993 tmp = g_strdup (name);
5995 /*g_print ("requested type %s\n", str);*/
5996 if (!mono_reflection_parse_type (tmp, &info)) {
5998 g_list_free (info.modifiers);
5999 g_list_free (info.nested);
6003 if (info.assembly.name) {
6004 assembly = mono_assembly_loaded (&info.assembly);
6006 /* then we must load the assembly ourselve - see #60439 */
6007 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6010 g_list_free (info.modifiers);
6011 g_list_free (info.nested);
6015 image = assembly->image;
6016 } else if (image == NULL) {
6017 image = mono_defaults.corlib;
6020 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6021 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6022 image = mono_defaults.corlib;
6023 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6027 g_list_free (info.modifiers);
6028 g_list_free (info.nested);
6033 * mono_reflection_get_token:
6035 * Return the metadata token of OBJ which should be an object
6036 * representing a metadata element.
6039 mono_reflection_get_token (MonoObject *obj)
6044 klass = obj->vtable->klass;
6046 if (strcmp (klass->name, "MethodBuilder") == 0) {
6047 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6049 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6050 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6051 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6053 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6054 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6055 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6056 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6057 if (tb->generic_params) {
6058 g_assert_not_reached ();
6060 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6062 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6063 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6064 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6065 } else if (strcmp (klass->name, "MonoType") == 0) {
6066 MonoReflectionType *tb = (MonoReflectionType *)obj;
6067 token = mono_class_from_mono_type (tb->type)->type_token;
6068 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6069 strcmp (klass->name, "MonoMethod") == 0) {
6070 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6071 if (m->method->signature->is_inflated) {
6072 g_assert_not_reached ();
6073 } else if (m->method->signature->generic_param_count) {
6074 g_assert_not_reached ();
6075 } else if (m->method->klass->generic_inst) {
6076 g_assert_not_reached ();
6078 token = m->method->token;
6080 } else if (strcmp (klass->name, "MonoField") == 0) {
6081 MonoReflectionField *f = (MonoReflectionField*)obj;
6083 token = mono_class_get_field_token (f->field);
6084 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6085 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6087 token = mono_class_get_property_token (p->property);
6088 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6089 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6091 token = mono_class_get_event_token (p->event);
6092 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6093 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6095 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6096 } else if (strcmp (klass->name, "Module") == 0) {
6097 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6100 } else if (strcmp (klass->name, "Assembly") == 0) {
6101 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6103 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6104 MonoException *ex = mono_get_exception_not_implemented (msg);
6106 mono_raise_exception (ex);
6113 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6115 int slen, type = t->type;
6120 case MONO_TYPE_BOOLEAN: {
6121 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6126 case MONO_TYPE_CHAR:
6128 case MONO_TYPE_I2: {
6129 guint16 *val = g_malloc (sizeof (guint16));
6134 #if SIZEOF_VOID_P == 4
6140 case MONO_TYPE_I4: {
6141 guint32 *val = g_malloc (sizeof (guint32));
6146 #if SIZEOF_VOID_P == 8
6147 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6152 case MONO_TYPE_I8: {
6153 guint64 *val = g_malloc (sizeof (guint64));
6158 case MONO_TYPE_VALUETYPE:
6159 if (t->data.klass->enumtype) {
6160 type = t->data.klass->enum_basetype->type;
6163 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6166 case MONO_TYPE_STRING:
6167 if (*p == (char)0xFF) {
6171 slen = mono_metadata_decode_value (p, &p);
6173 return mono_string_new_len (mono_domain_get (), p, slen);
6174 case MONO_TYPE_CLASS: {
6177 if (*p == (char)0xFF) {
6182 slen = mono_metadata_decode_value (p, &p);
6183 n = g_memdup (p, slen + 1);
6185 t = mono_reflection_type_from_name (n, image);
6187 g_warning ("Cannot load type '%s'", n);
6191 return mono_type_get_object (mono_domain_get (), t);
6195 case MONO_TYPE_OBJECT: {
6198 MonoClass *subc = NULL;
6203 } else if (subt == 0x0E) {
6204 type = MONO_TYPE_STRING;
6206 } else if (subt == 0x55) {
6209 slen = mono_metadata_decode_value (p, &p);
6210 n = g_memdup (p, slen + 1);
6212 t = mono_reflection_type_from_name (n, image);
6214 g_warning ("Cannot load type '%s'", n);
6217 subc = mono_class_from_mono_type (t);
6218 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6219 MonoType simple_type = {{0}};
6220 simple_type.type = subt;
6221 subc = mono_class_from_mono_type (&simple_type);
6223 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6225 val = load_cattr_value (image, &subc->byval_arg, p, end);
6226 obj = mono_object_new (mono_domain_get (), subc);
6227 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6231 case MONO_TYPE_SZARRAY: {
6233 guint32 i, alen, basetype;
6236 if (alen == 0xffffffff) {
6240 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6241 basetype = t->data.klass->byval_arg.type;
6246 case MONO_TYPE_BOOLEAN:
6247 for (i = 0; i < alen; i++) {
6248 MonoBoolean val = *p++;
6249 mono_array_set (arr, MonoBoolean, i, val);
6252 case MONO_TYPE_CHAR:
6255 for (i = 0; i < alen; i++) {
6256 guint16 val = read16 (p);
6257 mono_array_set (arr, guint16, i, val);
6264 for (i = 0; i < alen; i++) {
6265 guint32 val = read32 (p);
6266 mono_array_set (arr, guint32, i, val);
6273 for (i = 0; i < alen; i++) {
6274 guint64 val = read64 (p);
6275 mono_array_set (arr, guint64, i, val);
6279 case MONO_TYPE_CLASS:
6280 case MONO_TYPE_OBJECT:
6281 case MONO_TYPE_STRING:
6282 for (i = 0; i < alen; i++) {
6283 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6284 mono_array_set (arr, gpointer, i, item);
6288 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6294 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6300 type_is_reference (MonoType *type)
6302 switch (type->type) {
6303 case MONO_TYPE_BOOLEAN:
6304 case MONO_TYPE_CHAR:
6317 case MONO_TYPE_VALUETYPE:
6325 free_param_data (MonoMethodSignature *sig, void **params) {
6327 for (i = 0; i < sig->param_count; ++i) {
6328 if (!type_is_reference (sig->params [i]))
6329 g_free (params [i]);
6334 * Find the method index in the metadata methodDef table.
6335 * Later put these three helper methods in metadata and export them.
6338 find_method_index (MonoMethod *method) {
6339 MonoClass *klass = method->klass;
6342 for (i = 0; i < klass->method.count; ++i) {
6343 if (method == klass->methods [i])
6344 return klass->method.first + 1 + i;
6350 * Find the field index in the metadata FieldDef table.
6353 find_field_index (MonoClass *klass, MonoClassField *field) {
6356 for (i = 0; i < klass->field.count; ++i) {
6357 if (field == &klass->fields [i])
6358 return klass->field.first + 1 + i;
6364 * Find the property index in the metadata Property table.
6367 find_property_index (MonoClass *klass, MonoProperty *property) {
6370 for (i = 0; i < klass->property.count; ++i) {
6371 if (property == &klass->properties [i])
6372 return klass->property.first + 1 + i;
6378 * Find the event index in the metadata Event table.
6381 find_event_index (MonoClass *klass, MonoEvent *event) {
6384 for (i = 0; i < klass->event.count; ++i) {
6385 if (event == &klass->events [i])
6386 return klass->event.first + 1 + i;
6392 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6394 const char *p = data;
6396 guint32 i, j, num_named;
6400 mono_class_init (method->klass);
6403 attr = mono_object_new (mono_domain_get (), method->klass);
6404 mono_runtime_invoke (method, attr, NULL, NULL);
6408 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6411 /*g_print ("got attr %s\n", method->klass->name);*/
6413 params = g_new (void*, method->signature->param_count);
6417 for (i = 0; i < method->signature->param_count; ++i) {
6418 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6422 attr = mono_object_new (mono_domain_get (), method->klass);
6423 mono_runtime_invoke (method, attr, params, NULL);
6424 free_param_data (method->signature, params);
6426 num_named = read16 (named);
6428 for (j = 0; j < num_named; j++) {
6430 char *name, named_type, data_type;
6431 named_type = *named++;
6432 data_type = *named++; /* type of data */
6433 if (data_type == 0x55) {
6436 type_len = mono_metadata_decode_blob_size (named, &named);
6437 type_name = g_malloc (type_len + 1);
6438 memcpy (type_name, named, type_len);
6439 type_name [type_len] = 0;
6441 /* FIXME: lookup the type and check type consistency */
6442 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6443 /* this seems to be the type of the element of the array */
6444 /* g_print ("skipping 0x%02x after prop\n", *named); */
6447 name_len = mono_metadata_decode_blob_size (named, &named);
6448 name = g_malloc (name_len + 1);
6449 memcpy (name, named, name_len);
6450 name [name_len] = 0;
6452 if (named_type == 0x53) {
6453 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6454 void *val = load_cattr_value (image, field->type, named, &named);
6455 mono_field_set_value (attr, field, val);
6456 if (!type_is_reference (field->type))
6458 } else if (named_type == 0x54) {
6461 MonoType *prop_type;
6463 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6464 /* can we have more that 1 arg in a custom attr named property? */
6465 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6466 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6467 mono_property_set_value (prop, attr, pparams, NULL);
6468 if (!type_is_reference (prop_type))
6469 g_free (pparams [0]);
6478 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6485 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6486 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6487 for (i = 0; i < cinfo->num_attrs; ++i) {
6488 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6489 mono_array_set (result, gpointer, i, attr);
6495 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6497 guint32 mtoken, i, len;
6498 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6500 MonoCustomAttrInfo *ainfo;
6501 GList *tmp, *list = NULL;
6504 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6506 i = mono_metadata_custom_attrs_from_index (image, idx);
6510 while (i < ca->rows) {
6511 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6513 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6516 len = g_list_length (list);
6519 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6520 ainfo->num_attrs = len;
6521 ainfo->image = image;
6522 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6523 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6524 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6525 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6526 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6527 mtoken |= MONO_TOKEN_METHOD_DEF;
6529 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6530 mtoken |= MONO_TOKEN_MEMBER_REF;
6533 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6536 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6537 if (!ainfo->attrs [i].ctor)
6538 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6539 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6540 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6541 ainfo->attrs [i].data = data;
6549 mono_custom_attrs_from_method (MonoMethod *method)
6551 MonoCustomAttrInfo *cinfo;
6554 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6556 idx = find_method_index (method);
6557 idx <<= MONO_CUSTOM_ATTR_BITS;
6558 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6559 return mono_custom_attrs_from_index (method->klass->image, idx);
6563 mono_custom_attrs_from_class (MonoClass *klass)
6565 MonoCustomAttrInfo *cinfo;
6568 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6570 idx = mono_metadata_token_index (klass->type_token);
6571 idx <<= MONO_CUSTOM_ATTR_BITS;
6572 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6573 return mono_custom_attrs_from_index (klass->image, idx);
6577 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6579 MonoCustomAttrInfo *cinfo;
6582 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6584 idx = 1; /* there is only one assembly */
6585 idx <<= MONO_CUSTOM_ATTR_BITS;
6586 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6587 return mono_custom_attrs_from_index (assembly->image, idx);
6590 static MonoCustomAttrInfo*
6591 mono_custom_attrs_from_module (MonoImage *image)
6593 MonoCustomAttrInfo *cinfo;
6596 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6598 idx = 1; /* there is only one module */
6599 idx <<= MONO_CUSTOM_ATTR_BITS;
6600 idx |= MONO_CUSTOM_ATTR_MODULE;
6601 return mono_custom_attrs_from_index (image, idx);
6605 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6607 MonoCustomAttrInfo *cinfo;
6610 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6612 idx = find_property_index (klass, property);
6613 idx <<= MONO_CUSTOM_ATTR_BITS;
6614 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6615 return mono_custom_attrs_from_index (klass->image, idx);
6619 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6621 MonoCustomAttrInfo *cinfo;
6624 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6626 idx = find_event_index (klass, event);
6627 idx <<= MONO_CUSTOM_ATTR_BITS;
6628 idx |= MONO_CUSTOM_ATTR_EVENT;
6629 return mono_custom_attrs_from_index (klass->image, idx);
6633 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6635 MonoCustomAttrInfo *cinfo;
6638 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6640 idx = find_field_index (klass, field);
6641 idx <<= MONO_CUSTOM_ATTR_BITS;
6642 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6643 return mono_custom_attrs_from_index (klass->image, idx);
6647 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6650 guint32 i, idx, method_index;
6651 guint32 param_list, param_last, param_pos, found;
6653 MonoReflectionMethodAux *aux;
6655 if (method->klass->image->dynamic) {
6656 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6657 if (!aux || !aux->param_cattr)
6659 return aux->param_cattr [param];
6662 image = method->klass->image;
6663 method_index = find_method_index (method);
6664 ca = &image->tables [MONO_TABLE_METHOD];
6666 if (method->klass->generic_inst || method->klass->generic_container ||
6667 method->signature->generic_param_count) {
6668 /* FIXME FIXME FIXME */
6672 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6673 if (method_index == ca->rows) {
6674 ca = &image->tables [MONO_TABLE_PARAM];
6675 param_last = ca->rows + 1;
6677 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6678 ca = &image->tables [MONO_TABLE_PARAM];
6681 for (i = param_list; i < param_last; ++i) {
6682 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6683 if (param_pos == param) {
6691 idx <<= MONO_CUSTOM_ATTR_BITS;
6692 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6693 return mono_custom_attrs_from_index (image, idx);
6697 * mono_reflection_get_custom_attrs:
6698 * @obj: a reflection object handle
6700 * Return an array with all the custom attributes defined of the
6701 * reflection handle @obj. The objects are fully build.
6704 mono_reflection_get_custom_attrs (MonoObject *obj)
6708 MonoCustomAttrInfo *cinfo = NULL;
6710 MONO_ARCH_SAVE_REGS;
6712 klass = obj->vtable->klass;
6713 if (klass == mono_defaults.monotype_class) {
6714 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6715 klass = mono_class_from_mono_type (rtype->type);
6716 cinfo = mono_custom_attrs_from_class (klass);
6717 } else if (strcmp ("Assembly", klass->name) == 0) {
6718 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6719 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6720 } else if (strcmp ("Module", klass->name) == 0) {
6721 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6722 cinfo = mono_custom_attrs_from_module (module->image);
6723 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6724 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6725 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6726 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6727 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6728 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6729 } else if (strcmp ("MonoField", klass->name) == 0) {
6730 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6731 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6732 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6733 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6734 cinfo = mono_custom_attrs_from_method (rmethod->method);
6735 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6736 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6737 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6738 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6739 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6740 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6741 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6742 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6743 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6744 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6745 } else { /* handle other types here... */
6746 g_error ("get custom attrs not yet supported for %s", klass->name);
6750 result = mono_custom_attrs_construct (cinfo);
6752 mono_custom_attrs_free (cinfo);
6754 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6755 result = mono_array_new (mono_domain_get (), klass, 0);
6761 static MonoMethodSignature*
6762 parameters_to_signature (MonoArray *parameters) {
6763 MonoMethodSignature *sig;
6766 count = parameters? mono_array_length (parameters): 0;
6768 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6769 sig->param_count = count;
6770 sig->sentinelpos = -1; /* FIXME */
6771 for (i = 0; i < count; ++i) {
6772 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6773 sig->params [i] = pt->type;
6778 static MonoMethodSignature*
6779 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6780 MonoMethodSignature *sig;
6782 sig = parameters_to_signature (ctor->parameters);
6783 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6784 sig->ret = &mono_defaults.void_class->byval_arg;
6788 static MonoMethodSignature*
6789 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6790 MonoMethodSignature *sig;
6792 sig = parameters_to_signature (method->parameters);
6793 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6794 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6795 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6799 static MonoMethodSignature*
6800 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6801 MonoMethodSignature *sig;
6803 sig = parameters_to_signature (method->parameters);
6804 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6805 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6806 sig->generic_param_count = 0;
6811 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6813 MonoClass *klass = mono_object_class (prop);
6814 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6815 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6816 *name = mono_string_to_utf8 (pb->name);
6817 *type = pb->type->type;
6819 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6820 *name = g_strdup (p->property->name);
6821 if (p->property->get)
6822 *type = p->property->get->signature->ret;
6824 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6829 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6831 MonoClass *klass = mono_object_class (field);
6832 if (strcmp (klass->name, "FieldBuilder") == 0) {
6833 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6834 *name = mono_string_to_utf8 (fb->name);
6835 *type = fb->type->type;
6837 MonoReflectionField *f = (MonoReflectionField *)field;
6838 *name = g_strdup (f->field->name);
6839 *type = f->field->type;
6844 * Encode a value in a custom attribute stream of bytes.
6845 * The value to encode is either supplied as an object in argument val
6846 * (valuetypes are boxed), or as a pointer to the data in the
6848 * @type represents the type of the value
6849 * @buffer is the start of the buffer
6850 * @p the current position in the buffer
6851 * @buflen contains the size of the buffer and is used to return the new buffer size
6852 * if this needs to be realloced.
6853 * @retbuffer and @retp return the start and the position of the buffer
6856 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6858 MonoTypeEnum simple_type;
6860 if ((p-buffer) + 10 >= *buflen) {
6863 newbuf = g_realloc (buffer, *buflen);
6864 p = newbuf + (p-buffer);
6868 argval = ((char*)arg + sizeof (MonoObject));
6869 simple_type = type->type;
6871 switch (simple_type) {
6872 case MONO_TYPE_BOOLEAN:
6877 case MONO_TYPE_CHAR:
6880 swap_with_size (p, argval, 2, 1);
6886 swap_with_size (p, argval, 4, 1);
6892 swap_with_size (p, argval, 8, 1);
6895 case MONO_TYPE_VALUETYPE:
6896 if (type->data.klass->enumtype) {
6897 simple_type = type->data.klass->enum_basetype->type;
6900 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6903 case MONO_TYPE_STRING: {
6910 str = mono_string_to_utf8 ((MonoString*)arg);
6911 slen = strlen (str);
6912 if ((p-buffer) + 10 + slen >= *buflen) {
6916 newbuf = g_realloc (buffer, *buflen);
6917 p = newbuf + (p-buffer);
6920 mono_metadata_encode_value (slen, p, &p);
6921 memcpy (p, str, slen);
6926 case MONO_TYPE_CLASS: {
6934 k = mono_object_class (arg);
6935 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6936 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6937 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6939 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6940 slen = strlen (str);
6941 if ((p-buffer) + 10 + slen >= *buflen) {
6945 newbuf = g_realloc (buffer, *buflen);
6946 p = newbuf + (p-buffer);
6949 mono_metadata_encode_value (slen, p, &p);
6950 memcpy (p, str, slen);
6955 case MONO_TYPE_SZARRAY: {
6957 MonoClass *eclass, *arg_eclass;
6960 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6963 len = mono_array_length ((MonoArray*)arg);
6965 *p++ = (len >> 8) & 0xff;
6966 *p++ = (len >> 16) & 0xff;
6967 *p++ = (len >> 24) & 0xff;
6969 *retbuffer = buffer;
6970 eclass = type->data.klass;
6971 arg_eclass = mono_object_class (arg)->element_class;
6972 if (eclass->valuetype && arg_eclass->valuetype) {
6973 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6974 int elsize = mono_class_array_element_size (eclass);
6975 for (i = 0; i < len; ++i) {
6976 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6980 for (i = 0; i < len; ++i) {
6981 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6986 /* it may be a boxed value or a Type */
6987 case MONO_TYPE_OBJECT: {
6988 MonoClass *klass = mono_object_class (arg);
6992 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6995 } else if (klass->enumtype) {
6997 } else if (klass == mono_defaults.string_class) {
6998 simple_type = MONO_TYPE_STRING;
7001 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7002 *p++ = simple_type = klass->byval_arg.type;
7005 g_error ("unhandled type in custom attr");
7007 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7008 slen = strlen (str);
7009 if ((p-buffer) + 10 + slen >= *buflen) {
7013 newbuf = g_realloc (buffer, *buflen);
7014 p = newbuf + (p-buffer);
7017 mono_metadata_encode_value (slen, p, &p);
7018 memcpy (p, str, slen);
7021 simple_type = klass->enum_basetype->type;
7025 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7028 *retbuffer = buffer;
7032 * mono_reflection_get_custom_attrs_blob:
7033 * @ctor: custom attribute constructor
7034 * @ctorArgs: arguments o the constructor
7040 * Creates the blob of data that needs to be saved in the metadata and that represents
7041 * the custom attributed described by @ctor, @ctorArgs etc.
7042 * Returns: a Byte array representing the blob of data.
7045 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7048 MonoMethodSignature *sig;
7053 MONO_ARCH_SAVE_REGS;
7055 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7056 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7058 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7060 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7062 p = buffer = g_malloc (buflen);
7063 /* write the prolog */
7066 for (i = 0; i < sig->param_count; ++i) {
7067 arg = mono_array_get (ctorArgs, MonoObject*, i);
7068 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7072 i += mono_array_length (properties);
7074 i += mono_array_length (fields);
7076 *p++ = (i >> 8) & 0xff;
7079 for (i = 0; i < mono_array_length (properties); ++i) {
7084 prop = mono_array_get (properties, gpointer, i);
7085 get_prop_name_and_type (prop, &pname, &ptype);
7086 *p++ = 0x54; /* PROPERTY signature */
7088 /* Preallocate a large enough buffer */
7089 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7090 char *str = type_get_qualified_name (ptype, NULL);
7096 len += strlen (pname);
7098 if ((p-buffer) + 20 + len >= buflen) {
7102 newbuf = g_realloc (buffer, buflen);
7103 p = newbuf + (p-buffer);
7107 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7108 char *str = type_get_qualified_name (ptype, NULL);
7109 int slen = strlen (str);
7113 * This seems to be optional...
7116 mono_metadata_encode_value (slen, p, &p);
7117 memcpy (p, str, slen);
7121 mono_metadata_encode_value (ptype->type, p, &p);
7122 if (ptype->type == MONO_TYPE_SZARRAY)
7123 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7125 len = strlen (pname);
7126 mono_metadata_encode_value (len, p, &p);
7127 memcpy (p, pname, len);
7129 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7136 for (i = 0; i < mono_array_length (fields); ++i) {
7141 field = mono_array_get (fields, gpointer, i);
7142 get_field_name_and_type (field, &fname, &ftype);
7143 *p++ = 0x53; /* FIELD signature */
7144 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7145 char *str = type_get_qualified_name (ftype, NULL);
7146 int slen = strlen (str);
7147 if ((p-buffer) + 10 + slen >= buflen) {
7151 newbuf = g_realloc (buffer, buflen);
7152 p = newbuf + (p-buffer);
7157 * This seems to be optional...
7160 mono_metadata_encode_value (slen, p, &p);
7161 memcpy (p, str, slen);
7165 mono_metadata_encode_value (ftype->type, p, &p);
7166 if (ftype->type == MONO_TYPE_SZARRAY)
7167 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7169 len = strlen (fname);
7170 mono_metadata_encode_value (len, p, &p);
7171 memcpy (p, fname, len);
7173 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7178 g_assert (p - buffer <= buflen);
7179 buflen = p - buffer;
7180 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7181 p = mono_array_addr (result, char, 0);
7182 memcpy (p, buffer, buflen);
7184 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7190 * mono_reflection_setup_internal_class:
7191 * @tb: a TypeBuilder object
7193 * Creates a MonoClass that represents the TypeBuilder.
7194 * This is a trick that lets us simplify a lot of reflection code
7195 * (and will allow us to support Build and Run assemblies easier).
7198 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7200 MonoClass *klass, *parent;
7202 MONO_ARCH_SAVE_REGS;
7205 /* check so we can compile corlib correctly */
7206 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7207 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7208 parent = tb->parent->type->data.klass;
7210 parent = my_mono_class_from_mono_type (tb->parent->type);
7216 /* the type has already being created: it means we just have to change the parent */
7217 if (tb->type.type) {
7218 klass = mono_class_from_mono_type (tb->type.type);
7219 klass->parent = NULL;
7220 /* fool mono_class_setup_parent */
7221 g_free (klass->supertypes);
7222 klass->supertypes = NULL;
7223 mono_class_setup_parent (klass, parent);
7224 mono_class_setup_mono_type (klass);
7228 klass = g_new0 (MonoClass, 1);
7230 klass->image = &tb->module->dynamic_image->image;
7232 klass->inited = 1; /* we lie to the runtime */
7233 klass->name = mono_string_to_utf8 (tb->name);
7234 klass->name_space = mono_string_to_utf8 (tb->nspace);
7235 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7236 klass->flags = tb->attrs;
7238 klass->element_class = klass;
7239 klass->reflection_info = tb; /* need to pin. */
7241 /* Put into cache so mono_class_get () will find it */
7242 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7244 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7245 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7247 if (parent != NULL) {
7248 mono_class_setup_parent (klass, parent);
7249 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7250 const char *old_n = klass->name;
7251 /* trick to get relative numbering right when compiling corlib */
7252 klass->name = "BuildingObject";
7253 mono_class_setup_parent (klass, mono_defaults.object_class);
7254 klass->name = old_n;
7257 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7258 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7259 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7260 klass->instance_size = sizeof (MonoObject);
7261 klass->size_inited = 1;
7262 mono_class_setup_vtable (klass, NULL, 0);
7265 mono_class_setup_mono_type (klass);
7267 mono_class_setup_supertypes (klass);
7270 * FIXME: handle interfaces.
7273 tb->type.type = &klass->byval_arg;
7275 if (tb->nesting_type) {
7276 g_assert (tb->nesting_type->type);
7277 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7280 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7284 * mono_reflection_setup_generic_class:
7285 * @tb: a TypeBuilder object
7287 * Setup the generic class before adding the first generic parameter.
7290 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7293 MonoGenericContainer *container;
7296 MONO_ARCH_SAVE_REGS;
7298 klass = my_mono_class_from_mono_type (tb->type.type);
7299 if (tb->generic_container)
7302 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7303 tb->generic_container->klass = klass;
7307 * mono_reflection_create_generic_class:
7308 * @tb: a TypeBuilder object
7310 * Creates the generic class after all generic parameters have been added.
7313 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7318 MONO_ARCH_SAVE_REGS;
7320 klass = my_mono_class_from_mono_type (tb->type.type);
7322 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7324 if (klass->generic_container || (count == 0))
7327 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7329 klass->generic_container = tb->generic_container;
7331 klass->generic_container->type_argc = count;
7332 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7334 for (i = 0; i < count; i++) {
7335 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7336 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7337 g_assert (klass->generic_container->type_params [i].owner);
7342 * mono_reflection_create_internal_class:
7343 * @tb: a TypeBuilder object
7345 * Actually create the MonoClass that is associated with the TypeBuilder.
7348 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7352 MONO_ARCH_SAVE_REGS;
7354 klass = my_mono_class_from_mono_type (tb->type.type);
7356 if (klass->enumtype && klass->enum_basetype == NULL) {
7357 MonoReflectionFieldBuilder *fb;
7360 g_assert (tb->fields != NULL);
7361 g_assert (mono_array_length (tb->fields) >= 1);
7363 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7365 klass->enum_basetype = fb->type->type;
7366 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7367 if (!klass->element_class)
7368 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7371 * get the element_class from the current corlib.
7373 ec = default_class_from_mono_type (klass->enum_basetype);
7374 klass->instance_size = ec->instance_size;
7375 klass->size_inited = 1;
7377 * this is almost safe to do with enums and it's needed to be able
7378 * to create objects of the enum type (for use in SetConstant).
7380 /* FIXME: Does this mean enums can't have method overrides ? */
7381 mono_class_setup_vtable (klass, NULL, 0);
7385 static MonoMarshalSpec*
7386 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7387 MonoReflectionMarshal *minfo)
7389 MonoMarshalSpec *res;
7391 res = g_new0 (MonoMarshalSpec, 1);
7392 res->native = minfo->type;
7394 switch (minfo->type) {
7395 case MONO_NATIVE_LPARRAY:
7396 res->data.array_data.elem_type = minfo->eltype;
7397 res->data.array_data.param_num = 0; /* Not yet */
7398 res->data.array_data.num_elem = minfo->count;
7401 case MONO_NATIVE_BYVALTSTR:
7402 case MONO_NATIVE_BYVALARRAY:
7403 res->data.array_data.num_elem = minfo->count;
7406 case MONO_NATIVE_CUSTOM:
7407 if (minfo->marshaltyperef)
7408 res->data.custom_data.custom_name =
7409 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7411 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7421 MonoReflectionMarshal*
7422 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7423 MonoMarshalSpec *spec)
7425 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7426 MonoReflectionMarshal *minfo;
7429 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7430 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7431 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7432 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7435 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7436 minfo->type = spec->native;
7438 switch (minfo->type) {
7439 case MONO_NATIVE_LPARRAY:
7440 minfo->eltype = spec->data.array_data.elem_type;
7441 minfo->count = spec->data.array_data.num_elem;
7444 case MONO_NATIVE_BYVALTSTR:
7445 case MONO_NATIVE_BYVALARRAY:
7446 minfo->count = spec->data.array_data.num_elem;
7449 case MONO_NATIVE_CUSTOM:
7450 if (spec->data.custom_data.custom_name) {
7451 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7453 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7455 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7457 if (spec->data.custom_data.cookie)
7458 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7469 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7470 ReflectionMethodBuilder *rmb,
7471 MonoMethodSignature *sig)
7474 MonoMethodNormal *pm;
7475 MonoMarshalSpec **specs;
7476 MonoReflectionMethodAux *method_aux;
7479 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7480 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7481 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7483 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7485 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7487 pm = (MonoMethodNormal*)m;
7490 m->flags = rmb->attrs;
7491 m->iflags = rmb->iattrs;
7492 m->name = mono_string_to_utf8 (rmb->name);
7496 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7498 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7499 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7502 m->signature->pinvoke = 1;
7503 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7504 m->signature->pinvoke = 1;
7506 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7508 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7509 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7511 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7513 if (klass->image->dynamic)
7514 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7517 } else if (!m->klass->dummy &&
7518 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7519 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7520 MonoMethodHeader *header;
7522 gint32 max_stack, i;
7523 gint32 num_locals = 0;
7524 gint32 num_clauses = 0;
7528 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7529 code_size = rmb->ilgen->code_len;
7530 max_stack = rmb->ilgen->max_stack;
7531 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7532 if (rmb->ilgen->ex_handlers)
7533 num_clauses = method_count_clauses (rmb->ilgen);
7536 code = mono_array_addr (rmb->code, guint8, 0);
7537 code_size = mono_array_length (rmb->code);
7538 /* we probably need to run a verifier on the code... */
7548 header = g_malloc0 (sizeof (MonoMethodHeader) +
7549 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7550 header->code_size = code_size;
7551 header->code = g_malloc (code_size);
7552 memcpy ((char*)header->code, code, code_size);
7553 header->max_stack = max_stack;
7554 header->init_locals = rmb->init_locals;
7555 header->num_locals = num_locals;
7557 for (i = 0; i < num_locals; ++i) {
7558 MonoReflectionLocalBuilder *lb =
7559 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7561 header->locals [i] = g_new0 (MonoType, 1);
7562 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7565 header->num_clauses = num_clauses;
7567 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7568 rmb->ilgen, num_clauses);
7571 pm->header = header;
7574 if (rmb->generic_params) {
7575 int count = mono_array_length (rmb->generic_params);
7576 MonoGenericContainer *container;
7578 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7579 container->type_argc = count;
7580 container->type_params = g_new0 (MonoGenericParam, count);
7582 for (i = 0; i < count; i++) {
7583 MonoReflectionGenericParam *gp =
7584 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7586 container->type_params [i] = *gp->type.type->data.generic_param;
7591 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7594 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7596 for (i = 0; i < rmb->nrefs; ++i)
7597 mw->data = g_list_append (mw->data, rmb->refs [i]);
7602 /* Parameter info */
7605 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7606 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7607 for (i = 0; i <= m->signature->param_count; ++i) {
7608 MonoReflectionParamBuilder *pb;
7609 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7611 m->signature->params [i - 1]->attrs = pb->attrs;
7613 if (pb->def_value) {
7614 MonoDynamicImage *assembly;
7615 guint32 idx, def_type, len;
7619 if (!method_aux->param_defaults)
7620 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7621 assembly = (MonoDynamicImage*)klass->image;
7622 idx = encode_constant (assembly, pb->def_value, &def_type);
7623 /* Copy the data from the blob since it might get realloc-ed */
7624 p = assembly->blob.data + idx;
7625 len = mono_metadata_decode_blob_size (p, &p2);
7627 method_aux->param_defaults [i] = g_malloc (len);
7628 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7632 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7634 if (!method_aux->param_cattr)
7635 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7636 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7642 /* Parameter marshalling */
7645 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7646 MonoReflectionParamBuilder *pb;
7647 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7648 if (pb->marshal_info) {
7650 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7651 specs [pb->position] =
7652 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7656 if (specs != NULL) {
7658 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7659 method_aux->param_marshall = specs;
7662 if (klass->image->dynamic && method_aux)
7663 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7669 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7671 ReflectionMethodBuilder rmb;
7672 MonoMethodSignature *sig;
7674 sig = ctor_builder_to_signature (mb);
7676 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7678 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7679 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7681 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7682 /* ilgen is no longer needed */
7690 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7692 ReflectionMethodBuilder rmb;
7693 MonoMethodSignature *sig;
7695 sig = method_builder_to_signature (mb);
7697 reflection_methodbuilder_from_method_builder (&rmb, mb);
7699 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7700 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7702 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7703 /* ilgen is no longer needed */
7709 static MonoClassField*
7710 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7712 MonoClassField *field;
7719 field = g_new0 (MonoClassField, 1);
7721 field->name = mono_string_to_utf8 (fb->name);
7723 /* FIXME: handle type modifiers */
7724 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7725 field->type->attrs = fb->attrs;
7727 field->type = fb->type->type;
7729 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7730 field->data = mono_array_addr (fb->rva_data, char, 0);
7731 if (fb->offset != -1)
7732 field->offset = fb->offset;
7733 field->parent = klass;
7735 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7737 if (fb->def_value) {
7738 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7739 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7740 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7741 /* Copy the data from the blob since it might get realloc-ed */
7742 p = assembly->blob.data + idx;
7743 len = mono_metadata_decode_blob_size (p, &p2);
7745 field->data = g_malloc (len);
7746 memcpy ((gpointer)field->data, p, len);
7753 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7755 MonoClass *klass, *gklass;
7756 MonoReflectionTypeBuilder *tb = NULL;
7757 MonoGenericInst *ginst, *cached;
7762 klass = mono_class_from_mono_type (type->type);
7763 if (!klass->generic_container && !klass->generic_inst &&
7764 !(klass->nested_in && klass->nested_in->generic_container))
7767 mono_loader_lock ();
7769 domain = mono_object_domain (type);
7771 ginst = g_new0 (MonoGenericInst, 1);
7773 if (!klass->generic_inst) {
7774 ginst->type_argc = type_argc;
7775 ginst->type_argv = types;
7777 for (i = 0; i < ginst->type_argc; ++i) {
7778 if (!ginst->is_open)
7779 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7782 ginst->generic_type = &klass->byval_arg;
7784 MonoGenericInst *kginst = klass->generic_inst;
7786 ginst->type_argc = kginst->type_argc;
7787 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7789 for (i = 0; i < ginst->type_argc; i++) {
7790 MonoType *t = kginst->type_argv [i];
7792 if (t->type == MONO_TYPE_VAR)
7793 t = types [t->data.generic_param->num];
7795 if (!ginst->is_open)
7796 ginst->is_open = mono_class_is_open_constructed_type (t);
7798 ginst->type_argv [i] = t;
7801 ginst->generic_type = kginst->generic_type;
7804 geninst = g_new0 (MonoType, 1);
7805 geninst->type = MONO_TYPE_GENERICINST;
7807 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7810 mono_loader_unlock ();
7811 geninst->data.generic_inst = cached;
7815 gklass = mono_class_from_mono_type (ginst->generic_type);
7816 g_assert ((ginst->container = gklass->generic_container) != NULL);
7818 geninst->data.generic_inst = ginst;
7820 ginst->context = g_new0 (MonoGenericContext, 1);
7821 ginst->context->ginst = ginst;
7823 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7824 tb = (MonoReflectionTypeBuilder *) type;
7826 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7827 ginst->is_dynamic = TRUE;
7828 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7829 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7830 MonoReflectionType *rgt = rgi->generic_type;
7832 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7833 tb = (MonoReflectionTypeBuilder *) rgt;
7835 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7836 ginst->is_dynamic = TRUE;
7838 icount = klass->interface_count;
7841 ginst->ifaces = g_new0 (MonoType *, icount);
7842 ginst->count_ifaces = icount;
7844 for (i = 0; i < icount; i++) {
7845 MonoReflectionType *itype;
7848 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7850 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7851 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7852 if (!ginst->ifaces [i])
7853 ginst->ifaces [i] = itype->type;
7856 mono_class_create_generic (ginst);
7858 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7860 mono_loader_unlock ();
7866 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7868 MonoClass *klass, *pklass = NULL;
7869 MonoReflectionType *parent = NULL;
7871 MonoReflectionTypeBuilder *tb = NULL;
7872 MonoGenericInst *ginst;
7875 domain = mono_object_domain (type);
7876 klass = mono_class_from_mono_type (type->type);
7878 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7879 tb = (MonoReflectionTypeBuilder *) type;
7882 parent = tb->parent;
7883 pklass = mono_class_from_mono_type (parent->type);
7886 pklass = klass->parent;
7888 parent = mono_type_get_object (domain, &pklass->byval_arg);
7889 else if (klass->generic_inst && klass->generic_inst->parent) {
7890 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7891 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7895 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7899 ginst = geninst->data.generic_inst;
7901 if (pklass && pklass->generic_inst)
7902 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7907 MonoReflectionMethod*
7908 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7910 MonoMethod *method, *inflated;
7911 MonoReflectionMethodBuilder *mb = NULL;
7912 MonoGenericMethod *gmethod;
7913 MonoGenericContext *context;
7916 MONO_ARCH_SAVE_REGS;
7917 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7918 MonoReflectionTypeBuilder *tb;
7921 mb = (MonoReflectionMethodBuilder *) rmethod;
7922 tb = (MonoReflectionTypeBuilder *) mb->type;
7923 klass = mono_class_from_mono_type (tb->type.type);
7925 method = methodbuilder_to_mono_method (klass, mb);
7927 method = rmethod->method;
7930 count = method->signature->generic_param_count;
7931 if (count != mono_array_length (types))
7934 gmethod = g_new0 (MonoGenericMethod, 1);
7935 gmethod->mtype_argc = count;
7936 gmethod->mtype_argv = g_new0 (MonoType *, count);
7937 for (i = 0; i < count; i++) {
7938 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7939 gmethod->mtype_argv [i] = garg->type;
7942 gmethod->reflection_info = rmethod;
7944 context = g_new0 (MonoGenericContext, 1);
7945 context->ginst = method->klass->generic_inst;
7946 context->gmethod = gmethod;
7948 inflated = mono_class_inflate_generic_method (method, context, NULL);
7950 return mono_method_get_object (
7951 mono_object_domain (rmethod), inflated, NULL);
7955 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7957 MonoGenericMethod *gmethod;
7958 MonoGenericInst *ginst;
7959 MonoGenericContext *context;
7962 ginst = type->type.type->data.generic_inst;
7964 gmethod = g_new0 (MonoGenericMethod, 1);
7965 gmethod->reflection_info = obj;
7967 gmethod->mtype_argc = method->signature->generic_param_count;
7968 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7970 for (i = 0; i < gmethod->mtype_argc; i++) {
7971 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7972 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7974 g_assert (gparam->pklass);
7975 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7978 context = g_new0 (MonoGenericContext, 1);
7979 context->ginst = ginst;
7980 context->gmethod = gmethod;
7982 return mono_class_inflate_generic_method (method, context, ginst->klass);
7986 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7991 klass = mono_class_from_mono_type (type->type.type);
7993 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7994 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7995 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7996 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7997 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7998 method = ((MonoReflectionMethod *) obj)->method;
8000 method = NULL; /* prevent compiler warning */
8001 g_assert_not_reached ();
8004 return inflate_mono_method (type, method, obj);
8008 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8009 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8011 MonoGenericInst *ginst;
8012 MonoDynamicGenericInst *dginst;
8013 MonoClass *klass, *gklass, *pklass;
8016 MONO_ARCH_SAVE_REGS;
8018 klass = mono_class_from_mono_type (type->type.type);
8019 ginst = type->type.type->data.generic_inst;
8021 if (ginst->initialized)
8024 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8026 gklass = mono_class_from_mono_type (ginst->generic_type);
8027 mono_class_init (gklass);
8030 pklass = mono_class_from_mono_type (ginst->parent);
8032 pklass = gklass->parent;
8034 mono_class_setup_parent (klass, pklass);
8036 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8037 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8038 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8039 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8040 dginst->count_events = events ? mono_array_length (events) : 0;
8042 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8043 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8044 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8045 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8046 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8048 for (i = 0; i < dginst->count_methods; i++) {
8049 MonoObject *obj = mono_array_get (methods, gpointer, i);
8051 dginst->methods [i] = inflate_method (type, obj);
8054 for (i = 0; i < dginst->count_ctors; i++) {
8055 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8057 dginst->ctors [i] = inflate_method (type, obj);
8060 for (i = 0; i < dginst->count_fields; i++) {
8061 MonoObject *obj = mono_array_get (fields, gpointer, i);
8062 MonoClassField *field;
8063 MonoInflatedField *ifield;
8065 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8066 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8067 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8068 field = ((MonoReflectionField *) obj)->field;
8070 field = NULL; /* prevent compiler warning */
8071 g_assert_not_reached ();
8074 ifield = g_new0 (MonoInflatedField, 1);
8075 ifield->generic_type = field->type;
8076 ifield->reflection_info = obj;
8078 dginst->fields [i] = *field;
8079 dginst->fields [i].generic_info = ifield;
8080 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8083 for (i = 0; i < dginst->count_properties; i++) {
8084 MonoObject *obj = mono_array_get (properties, gpointer, i);
8085 MonoProperty *property = &dginst->properties [i];
8087 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8088 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8090 property->parent = klass;
8091 property->attrs = pb->attrs;
8092 property->name = mono_string_to_utf8 (pb->name);
8094 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8096 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8097 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8098 *property = *((MonoReflectionProperty *) obj)->property;
8101 property->get = inflate_mono_method (type, property->get, NULL);
8103 property->set = inflate_mono_method (type, property->set, NULL);
8105 g_assert_not_reached ();
8108 for (i = 0; i < dginst->count_events; i++) {
8109 MonoObject *obj = mono_array_get (events, gpointer, i);
8110 MonoEvent *event = &dginst->events [i];
8112 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8113 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8115 event->parent = klass;
8116 event->attrs = eb->attrs;
8117 event->name = mono_string_to_utf8 (eb->name);
8119 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8120 if (eb->remove_method)
8121 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8122 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8123 *event = *((MonoReflectionEvent *) obj)->event;
8126 event->add = inflate_mono_method (type, event->add, NULL);
8128 event->remove = inflate_mono_method (type, event->remove, NULL);
8130 g_assert_not_reached ();
8133 ginst->initialized = TRUE;
8137 ensure_runtime_vtable (MonoClass *klass)
8139 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8140 int i, num, j, onum;
8141 MonoMethod **overrides;
8143 if (!tb || klass->wastypebuilder)
8146 ensure_runtime_vtable (klass->parent);
8148 num = tb->ctors? mono_array_length (tb->ctors): 0;
8149 num += tb->num_methods;
8150 klass->method.count = num;
8151 klass->methods = g_new (MonoMethod*, num);
8152 num = tb->ctors? mono_array_length (tb->ctors): 0;
8153 for (i = 0; i < num; ++i)
8154 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8155 num = tb->num_methods;
8157 for (i = 0; i < num; ++i)
8158 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8160 klass->wastypebuilder = TRUE;
8161 if (tb->interfaces) {
8162 klass->interface_count = mono_array_length (tb->interfaces);
8163 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8164 for (i = 0; i < klass->interface_count; ++i) {
8165 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8166 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8170 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8171 for (i = 0; i < klass->method.count; ++i)
8172 klass->methods [i]->slot = i;
8177 for (i = 0; i < tb->num_methods; ++i) {
8178 MonoReflectionMethodBuilder *mb =
8179 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8180 if (mb->override_method)
8185 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8189 for (i = 0; i < tb->num_methods; ++i) {
8190 MonoReflectionMethodBuilder *mb =
8191 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8192 if (mb->override_method) {
8193 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8194 overrides [onum * 2] =
8195 mb->override_method->method;
8196 overrides [onum * 2 + 1] =
8199 g_assert (mb->mhandle);
8206 mono_class_setup_vtable (klass, overrides, onum);
8210 typebuilder_setup_fields (MonoClass *klass)
8212 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8213 MonoReflectionFieldBuilder *fb;
8214 MonoClassField *field;
8219 klass->field.count = tb->num_fields;
8220 klass->field.first = 0;
8221 klass->field.last = klass->field.count;
8223 if (!klass->field.count)
8226 klass->fields = g_new0 (MonoClassField, klass->field.count);
8228 for (i = 0; i < klass->field.count; ++i) {
8229 fb = mono_array_get (tb->fields, gpointer, i);
8230 field = &klass->fields [i];
8231 field->name = mono_string_to_utf8 (fb->name);
8233 /* FIXME: handle type modifiers */
8234 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8235 field->type->attrs = fb->attrs;
8237 field->type = fb->type->type;
8239 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8240 field->data = mono_array_addr (fb->rva_data, char, 0);
8241 if (fb->offset != -1)
8242 field->offset = fb->offset;
8243 field->parent = klass;
8245 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8247 if (fb->def_value) {
8248 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8249 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8250 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8251 /* Copy the data from the blob since it might get realloc-ed */
8252 p = assembly->blob.data + idx;
8253 len = mono_metadata_decode_blob_size (p, &p2);
8255 field->data = g_malloc (len);
8256 memcpy ((gpointer)field->data, p, len);
8259 mono_class_layout_fields (klass);
8263 typebuilder_setup_properties (MonoClass *klass)
8265 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8266 MonoReflectionPropertyBuilder *pb;
8269 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8270 klass->property.first = 0;
8271 klass->property.last = klass->property.count;
8273 klass->properties = g_new0 (MonoProperty, klass->property.count);
8274 for (i = 0; i < klass->property.count; ++i) {
8275 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8276 klass->properties [i].parent = klass;
8277 klass->properties [i].attrs = pb->attrs;
8278 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8280 klass->properties [i].get = pb->get_method->mhandle;
8282 klass->properties [i].set = pb->set_method->mhandle;
8286 MonoReflectionEvent *
8287 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8289 MonoEvent *event = g_new0 (MonoEvent, 1);
8293 klass = my_mono_class_from_mono_type (tb->type.type);
8295 event->parent = klass;
8296 event->attrs = eb->attrs;
8297 event->name = mono_string_to_utf8 (eb->name);
8299 event->add = eb->add_method->mhandle;
8300 if (eb->remove_method)
8301 event->remove = eb->remove_method->mhandle;
8302 if (eb->raise_method)
8303 event->raise = eb->raise_method->mhandle;
8305 if (eb->other_methods) {
8306 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8307 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8308 MonoReflectionMethodBuilder *mb =
8309 mono_array_get (eb->other_methods,
8310 MonoReflectionMethodBuilder*, j);
8311 event->other [j] = mb->mhandle;
8315 return mono_event_get_object (mono_object_domain (tb), klass, event);
8319 typebuilder_setup_events (MonoClass *klass)
8321 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8322 MonoReflectionEventBuilder *eb;
8325 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8326 klass->event.first = 0;
8327 klass->event.last = klass->event.count;
8329 klass->events = g_new0 (MonoEvent, klass->event.count);
8330 for (i = 0; i < klass->event.count; ++i) {
8331 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8332 klass->events [i].parent = klass;
8333 klass->events [i].attrs = eb->attrs;
8334 klass->events [i].name = mono_string_to_utf8 (eb->name);
8336 klass->events [i].add = eb->add_method->mhandle;
8337 if (eb->remove_method)
8338 klass->events [i].remove = eb->remove_method->mhandle;
8339 if (eb->raise_method)
8340 klass->events [i].raise = eb->raise_method->mhandle;
8342 if (eb->other_methods) {
8343 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8344 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8345 MonoReflectionMethodBuilder *mb =
8346 mono_array_get (eb->other_methods,
8347 MonoReflectionMethodBuilder*, j);
8348 klass->events [i].other [j] = mb->mhandle;
8355 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8358 MonoReflectionType* res;
8361 MONO_ARCH_SAVE_REGS;
8363 klass = my_mono_class_from_mono_type (tb->type.type);
8365 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8368 * Fields to set in klass:
8369 * the various flags: delegate/unicode/contextbound etc.
8371 klass->flags = tb->attrs;
8373 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8374 /* No need to fully construct the type */
8375 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8377 /* enums are done right away */
8378 if (!klass->enumtype)
8379 ensure_runtime_vtable (klass);
8382 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8383 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8384 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8388 /* fields and object layout */
8389 if (klass->parent) {
8390 if (!klass->parent->size_inited)
8391 mono_class_init (klass->parent);
8392 klass->instance_size += klass->parent->instance_size;
8393 klass->class_size += klass->parent->class_size;
8394 klass->min_align = klass->parent->min_align;
8396 klass->instance_size = sizeof (MonoObject);
8397 klass->min_align = 1;
8400 /* FIXME: handle packing_size and instance_size */
8401 typebuilder_setup_fields (klass);
8403 typebuilder_setup_properties (klass);
8405 typebuilder_setup_events (klass);
8407 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8408 /* with enums res == tb: need to fix that. */
8409 if (!klass->enumtype)
8410 g_assert (res != (MonoReflectionType*)tb);
8415 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8417 MonoGenericParam *param;
8420 MONO_ARCH_SAVE_REGS;
8422 param = g_new0 (MonoGenericParam, 1);
8424 if (gparam->mbuilder) {
8425 if (!gparam->mbuilder->generic_container)
8426 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8427 param->owner = gparam->mbuilder->generic_container;
8428 } else if (gparam->tbuilder) {
8429 MonoReflectionTypeBuilder *nesting = gparam->tbuilder->nesting_type;
8430 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8435 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8436 if (gparam->index >= count)
8439 container = nesting->generic_container;
8440 nesting = nesting->nesting_type;
8443 g_assert (container);
8444 param->owner = container;
8447 param->method = NULL;
8448 param->name = mono_string_to_utf8 (gparam->name);
8449 param->num = gparam->index;
8451 image = &gparam->tbuilder->module->dynamic_image->image;
8452 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8454 param->pklass->reflection_info = gparam;
8456 gparam->type.type = g_new0 (MonoType, 1);
8457 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8458 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8459 gparam->type.type->data.generic_param = param;
8463 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8465 MonoDynamicImage *assembly = sig->module->dynamic_image;
8466 guint32 na = mono_array_length (sig->arguments);
8471 MONO_ARCH_SAVE_REGS;
8473 p = buf = g_malloc (10 + na * 10);
8475 mono_metadata_encode_value (0x07, p, &p);
8476 mono_metadata_encode_value (na, p, &p);
8477 for (i = 0; i < na; ++i) {
8478 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8479 encode_reflection_type (assembly, type, p, &p);
8483 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8484 p = mono_array_addr (result, char, 0);
8485 memcpy (p, buf, buflen);
8492 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8494 MonoDynamicImage *assembly = sig->module->dynamic_image;
8495 guint32 na = mono_array_length (sig->arguments);
8500 MONO_ARCH_SAVE_REGS;
8502 p = buf = g_malloc (10 + na * 10);
8504 mono_metadata_encode_value (0x06, p, &p);
8505 for (i = 0; i < na; ++i) {
8506 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8507 encode_reflection_type (assembly, type, p, &p);
8511 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8512 p = mono_array_addr (result, char, 0);
8513 memcpy (p, buf, buflen);
8520 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8522 ReflectionMethodBuilder rmb;
8523 MonoMethodSignature *sig;
8526 sig = dynamic_method_to_signature (mb);
8528 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8531 * Resolve references.
8533 rmb.nrefs = mb->nrefs;
8534 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8535 for (i = 0; i < mb->nrefs; ++i) {
8536 gpointer ref = resolve_object (mb->module->image,
8537 mono_array_get (mb->refs, MonoObject*, i));
8540 mono_raise_exception (mono_get_exception_type_load (NULL));
8547 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8551 /* ilgen is no longer needed */
8556 * mono_reflection_lookup_dynamic_token:
8558 * Finish the Builder object pointed to by TOKEN and return the corresponding
8559 * runtime structure.
8562 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8564 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8567 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8570 return resolve_object (image, obj);
8574 resolve_object (MonoImage *image, MonoObject *obj)
8576 gpointer result = NULL;
8578 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8579 result = mono_string_intern ((MonoString*)obj);
8581 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8582 MonoReflectionType *tb = (MonoReflectionType*)obj;
8583 result = mono_class_from_mono_type (tb->type);
8585 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8586 result = ((MonoReflectionMethod*)obj)->method;
8588 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8589 result = ((MonoReflectionMethod*)obj)->method;
8591 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8592 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8593 result = mb->mhandle;
8595 /* Type is not yet created */
8596 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8598 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8601 * Hopefully this has been filled in by calling CreateType() on the
8605 * TODO: This won't work if the application finishes another
8606 * TypeBuilder instance instead of this one.
8608 result = mb->mhandle;
8610 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8611 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8613 result = cb->mhandle;
8615 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8617 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8618 result = cb->mhandle;
8620 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8621 result = ((MonoReflectionField*)obj)->field;
8623 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8624 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8625 result = fb->handle;
8628 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8630 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8631 result = fb->handle;
8633 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8634 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8637 klass = tb->type.type->data.klass;
8638 if (klass->wastypebuilder) {
8639 /* Already created */
8643 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8644 result = tb->type.type->data.klass;
8647 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8648 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8649 MonoMethodSignature *sig;
8652 if (helper->arguments)
8653 nargs = mono_array_length (helper->arguments);
8657 sig = mono_metadata_signature_alloc (image, nargs);
8658 sig->explicit_this = helper->call_conv & 64;
8659 sig->hasthis = helper->call_conv & 32;
8661 if (helper->call_conv == 0) /* unmanaged */
8662 sig->call_convention = helper->unmanaged_call_conv - 1;
8664 if (helper->call_conv & 0x02)
8665 sig->call_convention = MONO_CALL_VARARG;
8667 sig->call_convention = MONO_CALL_DEFAULT;
8669 sig->param_count = nargs;
8670 /* TODO: Copy type ? */
8671 sig->ret = helper->return_type->type;
8672 for (i = 0; i < nargs; ++i) {
8673 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8674 sig->params [i] = rt->type;
8679 g_print (obj->vtable->klass->name);
8680 g_assert_not_reached ();