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, strlen (meta->version));
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++ = 1; /* 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 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224 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 entrypoint name */
4747 if (assemblyb->pekind == 1)
4748 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4750 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4751 /* patch imported function RVA name */
4752 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4753 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4755 /* the import table */
4756 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4757 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4758 /* patch imported dll RVA name and other entries in the dir */
4759 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4760 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4761 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4762 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4763 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4766 p = (assembly->code.data + assembly->ilt_offset);
4767 value = (assembly->text_rva + assembly->imp_names_offset);
4768 *p++ = (value) & 0xff;
4769 *p++ = (value >> 8) & (0xff);
4770 *p++ = (value >> 16) & (0xff);
4771 *p++ = (value >> 24) & (0xff);
4773 /* the CLI header info */
4774 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4775 cli_header->ch_size = GUINT32_FROM_LE (72);
4776 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4777 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4778 if (assemblyb->entry_point) {
4779 guint32 table_idx = 0;
4780 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4781 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4782 table_idx = methodb->table_idx;
4784 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4786 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4788 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4790 /* The embedded managed resources */
4791 text_offset = assembly->text_rva + assembly->code.index;
4792 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4793 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4794 text_offset += assembly->resources.index;
4795 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4796 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4797 text_offset += assembly->meta_size;
4798 if (assembly->strong_name_size) {
4799 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4800 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4801 text_offset += assembly->strong_name_size;
4804 /* write the section tables and section content */
4805 section = (MonoSectionTable*)(pefile->data + section_start);
4806 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4807 static const char *section_names [] = {
4808 ".text", ".rsrc", ".reloc"
4810 if (!assembly->sections [i].size)
4812 strcpy (section->st_name, section_names [i]);
4813 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4814 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4815 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4816 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4817 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4818 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4819 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4821 case MONO_SECTION_TEXT:
4822 /* patch entry point */
4823 p = (assembly->code.data + 2);
4824 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4825 *p++ = (value) & 0xff;
4826 *p++ = (value >> 8) & 0xff;
4827 *p++ = (value >> 16) & 0xff;
4828 *p++ = (value >> 24) & 0xff;
4830 text_offset = assembly->sections [i].offset;
4831 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4832 text_offset += assembly->code.index;
4833 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4834 text_offset += assembly->resources.index;
4835 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4836 text_offset += assembly->meta_size;
4837 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4839 g_free (assembly->image.raw_metadata);
4841 case MONO_SECTION_RELOC:
4842 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4843 *rva = GUINT32_FROM_LE (assembly->text_rva);
4845 *rva = GUINT32_FROM_LE (12);
4847 data16 = (guint16*)rva;
4849 * the entrypoint is always at the start of the text section
4850 * 3 is IMAGE_REL_BASED_HIGHLOW
4851 * 2 is patch_size_rva - text_rva
4853 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4855 *data16 = 0; /* terminate */
4857 case MONO_SECTION_RSRC:
4858 if (assembly->win32_res) {
4859 text_offset = assembly->sections [i].offset;
4861 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4862 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4864 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4868 g_assert_not_reached ();
4873 /* check that the file is properly padded */
4876 FILE *f = fopen ("mypetest.exe", "w");
4877 fwrite (pefile->data, pefile->index, 1, f);
4883 MonoReflectionModule *
4884 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4888 MonoImageOpenStatus status;
4889 MonoDynamicAssembly *assembly;
4890 guint32 module_count;
4891 MonoImage **new_modules;
4893 name = mono_string_to_utf8 (fileName);
4895 image = mono_image_open (name, &status);
4898 if (status == MONO_IMAGE_ERROR_ERRNO)
4899 exc = mono_get_exception_file_not_found (fileName);
4901 exc = mono_get_exception_bad_image_format (name);
4903 mono_raise_exception (exc);
4908 assembly = ab->dynamic_assembly;
4909 image->assembly = (MonoAssembly*)assembly;
4911 module_count = image->assembly->image->module_count;
4912 new_modules = g_new0 (MonoImage *, module_count + 1);
4914 if (image->assembly->image->modules)
4915 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4916 new_modules [module_count] = image;
4918 g_free (image->assembly->image->modules);
4919 image->assembly->image->modules = new_modules;
4920 image->assembly->image->module_count ++;
4922 mono_assembly_load_references (image, &status);
4924 mono_image_close (image);
4925 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4928 return mono_module_get_object (mono_domain_get (), image);
4932 * We need to return always the same object for MethodInfo, FieldInfo etc..
4933 * but we need to consider the reflected type.
4934 * type uses a different hash, since it uses custom hash/equal functions.
4939 MonoClass *refclass;
4943 reflected_equal (gconstpointer a, gconstpointer b) {
4944 const ReflectedEntry *ea = a;
4945 const ReflectedEntry *eb = b;
4947 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4951 reflected_hash (gconstpointer a) {
4952 const ReflectedEntry *ea = a;
4953 return GPOINTER_TO_UINT (ea->item);
4956 #define CHECK_OBJECT(t,p,k) \
4962 mono_domain_lock (domain); \
4963 if (!domain->refobject_hash) \
4964 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4965 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4966 mono_domain_unlock (domain); \
4972 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4974 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4977 #define CACHE_OBJECT(p,o,k) \
4979 ReflectedEntry *e = ALLOC_REFENTRY; \
4981 e->refclass = (k); \
4982 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4983 mono_domain_unlock (domain); \
4987 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4989 /* this is done only once */
4990 mono_domain_lock (domain);
4991 CACHE_OBJECT (assembly, res, NULL);
4995 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4997 /* this is done only once */
4998 mono_domain_lock (domain);
4999 CACHE_OBJECT (module, res, NULL);
5003 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5005 MonoDynamicImage *image = moduleb->dynamic_image;
5006 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5009 * FIXME: we already created an image in mono_image_basic_init (), but
5010 * we don't know which module it belongs to, since that is only
5011 * determined at assembly save time.
5013 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5014 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5016 moduleb->module.image = &image->image;
5017 moduleb->dynamic_image = image;
5018 register_module (mono_object_domain (moduleb), moduleb, image);
5023 * mono_assembly_get_object:
5024 * @domain: an app domain
5025 * @assembly: an assembly
5027 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5029 MonoReflectionAssembly*
5030 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5032 static MonoClass *System_Reflection_Assembly;
5033 MonoReflectionAssembly *res;
5035 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5036 if (!System_Reflection_Assembly)
5037 System_Reflection_Assembly = mono_class_from_name (
5038 mono_defaults.corlib, "System.Reflection", "Assembly");
5039 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5040 res->assembly = assembly;
5041 CACHE_OBJECT (assembly, res, NULL);
5047 MonoReflectionModule*
5048 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5050 static MonoClass *System_Reflection_Module;
5051 MonoReflectionModule *res;
5054 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5055 if (!System_Reflection_Module)
5056 System_Reflection_Module = mono_class_from_name (
5057 mono_defaults.corlib, "System.Reflection", "Module");
5058 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5061 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5063 res->fqname = mono_string_new (domain, image->name);
5064 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5065 res->scopename = mono_string_new (domain, image->module_name);
5069 if (image->assembly->image == image) {
5070 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5073 g_assert (image->assembly->image->modules);
5075 for (i = 0; i < image->assembly->image->module_count; i++) {
5076 if (image->assembly->image->modules [i] == image)
5077 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5079 g_assert (res->token);
5082 mono_image_addref (image);
5084 CACHE_OBJECT (image, res, NULL);
5088 MonoReflectionModule*
5089 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5091 static MonoClass *System_Reflection_Module;
5092 MonoReflectionModule *res;
5093 MonoTableInfo *table;
5094 guint32 cols [MONO_FILE_SIZE];
5096 guint32 i, name_idx;
5099 if (!System_Reflection_Module)
5100 System_Reflection_Module = mono_class_from_name (
5101 mono_defaults.corlib, "System.Reflection", "Module");
5102 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5104 table = &image->tables [MONO_TABLE_FILE];
5105 g_assert (table_index < table->rows);
5106 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5109 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5110 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5112 /* Check whenever the row has a corresponding row in the moduleref table */
5113 table = &image->tables [MONO_TABLE_MODULEREF];
5114 for (i = 0; i < table->rows; ++i) {
5115 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5116 val = mono_metadata_string_heap (image, name_idx);
5117 if (strcmp (val, name) == 0)
5118 res->image = image->modules [i];
5121 res->fqname = mono_string_new (domain, name);
5122 res->name = mono_string_new (domain, name);
5123 res->scopename = mono_string_new (domain, name);
5124 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5125 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5131 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5133 if ((t1->type != t2->type) ||
5134 (t1->byref != t2->byref))
5138 case MONO_TYPE_VOID:
5139 case MONO_TYPE_BOOLEAN:
5140 case MONO_TYPE_CHAR:
5151 case MONO_TYPE_STRING:
5154 case MONO_TYPE_OBJECT:
5155 case MONO_TYPE_TYPEDBYREF:
5157 case MONO_TYPE_VALUETYPE:
5158 case MONO_TYPE_CLASS:
5159 case MONO_TYPE_SZARRAY:
5160 return t1->data.klass == t2->data.klass;
5162 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5163 case MONO_TYPE_ARRAY:
5164 if (t1->data.array->rank != t2->data.array->rank)
5166 return t1->data.array->eklass == t2->data.array->eklass;
5167 case MONO_TYPE_GENERICINST: {
5169 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5171 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5173 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5174 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5180 case MONO_TYPE_MVAR:
5181 return t1->data.generic_param == t2->data.generic_param;
5183 g_error ("implement type compare for %0x!", t1->type);
5191 mymono_metadata_type_hash (MonoType *t1)
5197 hash |= t1->byref << 6; /* do not collide with t1->type values */
5199 case MONO_TYPE_VALUETYPE:
5200 case MONO_TYPE_CLASS:
5201 case MONO_TYPE_SZARRAY:
5202 /* check if the distribution is good enough */
5203 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5205 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5210 static MonoReflectionGenericInst*
5211 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5213 static MonoClass *System_Reflection_MonoGenericInst;
5214 MonoReflectionGenericInst *res;
5215 MonoGenericInst *ginst;
5218 if (!System_Reflection_MonoGenericInst) {
5219 System_Reflection_MonoGenericInst = mono_class_from_name (
5220 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5221 g_assert (System_Reflection_MonoGenericInst);
5224 ginst = geninst->data.generic_inst;
5225 gklass = mono_class_from_mono_type (ginst->generic_type);
5227 mono_class_init (ginst->klass);
5229 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5231 res->type.type = geninst;
5232 if (gklass->wastypebuilder && gklass->reflection_info)
5233 res->generic_type = gklass->reflection_info;
5235 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5241 * mono_type_get_object:
5242 * @domain: an app domain
5245 * Return an System.MonoType object representing the type @type.
5248 mono_type_get_object (MonoDomain *domain, MonoType *type)
5250 MonoReflectionType *res;
5251 MonoClass *klass = mono_class_from_mono_type (type);
5253 mono_domain_lock (domain);
5254 if (!domain->type_hash)
5255 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5256 (GCompareFunc)mymono_metadata_type_equal);
5257 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5258 mono_domain_unlock (domain);
5261 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5262 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5263 mono_g_hash_table_insert (domain->type_hash, type, res);
5264 mono_domain_unlock (domain);
5267 if (klass->reflection_info && !klass->wastypebuilder) {
5268 /* g_assert_not_reached (); */
5269 /* should this be considered an error condition? */
5271 mono_domain_unlock (domain);
5272 return klass->reflection_info;
5275 mono_class_init (klass);
5276 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5278 mono_g_hash_table_insert (domain->type_hash, type, res);
5279 mono_domain_unlock (domain);
5284 * mono_method_get_object:
5285 * @domain: an app domain
5287 * @refclass: the reflected type (can be NULL)
5289 * Return an System.Reflection.MonoMethod object representing the method @method.
5291 MonoReflectionMethod*
5292 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5295 * We use the same C representation for methods and constructors, but the type
5296 * name in C# is different.
5300 MonoReflectionMethod *ret;
5303 refclass = method->klass;
5305 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5306 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5307 cname = "MonoCMethod";
5309 cname = "MonoMethod";
5310 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5312 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5313 ret->method = method;
5314 ret->name = mono_string_new (domain, method->name);
5315 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5316 CACHE_OBJECT (method, ret, refclass);
5321 * mono_field_get_object:
5322 * @domain: an app domain
5326 * Return an System.Reflection.MonoField object representing the field @field
5329 MonoReflectionField*
5330 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5332 MonoReflectionField *res;
5335 CHECK_OBJECT (MonoReflectionField *, field, klass);
5336 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5337 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5340 res->name = mono_string_new (domain, field->name);
5341 if (field->generic_info)
5342 res->attrs = field->generic_info->generic_type->attrs;
5344 res->attrs = field->type->attrs;
5345 res->type = mono_type_get_object (domain, field->type);
5346 CACHE_OBJECT (field, res, klass);
5351 * mono_property_get_object:
5352 * @domain: an app domain
5354 * @property: a property
5356 * Return an System.Reflection.MonoProperty object representing the property @property
5359 MonoReflectionProperty*
5360 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5362 MonoReflectionProperty *res;
5365 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5366 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5367 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5369 res->property = property;
5370 CACHE_OBJECT (property, res, klass);
5375 * mono_event_get_object:
5376 * @domain: an app domain
5380 * Return an System.Reflection.MonoEvent object representing the event @event
5383 MonoReflectionEvent*
5384 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5386 MonoReflectionEvent *res;
5389 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5390 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5391 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5394 CACHE_OBJECT (event, res, klass);
5399 * mono_param_get_objects:
5400 * @domain: an app domain
5403 * Return an System.Reflection.ParameterInfo array object representing the parameters
5404 * in the method @method.
5407 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5409 static MonoClass *System_Reflection_ParameterInfo;
5410 MonoArray *res = NULL;
5411 MonoReflectionMethod *member = NULL;
5412 MonoReflectionParameter *param = NULL;
5413 char **names, **blobs = NULL;
5414 MonoObject *dbnull = mono_get_dbnull_object (domain);
5415 MonoMarshalSpec **mspecs;
5418 if (!System_Reflection_ParameterInfo)
5419 System_Reflection_ParameterInfo = mono_class_from_name (
5420 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5422 if (!method->signature->param_count)
5423 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5425 /* Note: the cache is based on the address of the signature into the method
5426 * since we already cache MethodInfos with the method as keys.
5428 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5430 member = mono_method_get_object (domain, method, NULL);
5431 names = g_new (char *, method->signature->param_count);
5432 mono_method_get_param_names (method, (const char **) names);
5434 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5435 mono_method_get_marshal_info (method, mspecs);
5437 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5438 for (i = 0; i < method->signature->param_count; ++i) {
5439 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5440 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5441 param->MemberImpl = (MonoObject*)member;
5442 param->NameImpl = mono_string_new (domain, names [i]);
5443 param->PositionImpl = i;
5444 param->AttrsImpl = method->signature->params [i]->attrs;
5446 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5447 param->DefaultValueImpl = dbnull;
5449 MonoType *type = param->ClassImpl->type;
5452 blobs = g_new0 (char *, method->signature->param_count);
5453 get_default_param_value_blobs (method, blobs);
5456 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5458 if (!param->DefaultValueImpl) {
5459 param->DefaultValueImpl = dbnull;
5464 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5466 mono_array_set (res, gpointer, i, param);
5471 for (i = method->signature->param_count; i >= 0; i--)
5473 mono_metadata_free_marshal_spec (mspecs [i]);
5476 CACHE_OBJECT (&(method->signature), res, NULL);
5481 * mono_method_body_get_object:
5482 * @domain: an app domain
5485 * Return an System.Reflection.MethodBody object representing the method @method.
5487 MonoReflectionMethodBody*
5488 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5490 static MonoClass *System_Reflection_MethodBody = NULL;
5491 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5492 MonoReflectionMethodBody *ret;
5493 MonoMethodNormal *mn;
5494 MonoMethodHeader *header;
5497 if (!System_Reflection_MethodBody)
5498 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5499 if (!System_Reflection_LocalVariableInfo)
5500 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5502 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5504 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5505 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5507 mn = (MonoMethodNormal *)method;
5508 header = mn->header;
5510 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5511 /* FIXME: Other fields */
5512 ret->init_locals = header->init_locals;
5513 ret->max_stack = header->max_stack;
5514 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5515 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5516 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5517 for (i = 0; i < header->num_locals; ++i) {
5518 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5519 info->local_type = mono_type_get_object (domain, header->locals [i]);
5520 info->is_pinned = header->locals [i]->pinned;
5521 info->local_index = 0;
5524 CACHE_OBJECT (method, ret, NULL);
5529 mono_get_dbnull_object (MonoDomain *domain)
5533 static MonoClassField *dbnull_value_field = NULL;
5535 if (!dbnull_value_field) {
5536 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5537 mono_class_init (klass);
5538 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5539 g_assert (dbnull_value_field);
5541 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5548 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5550 guint32 param_index, i, lastp, crow = 0;
5551 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5554 MonoClass *klass = method->klass;
5555 MonoImage *image = klass->image;
5556 MonoMethodSignature *methodsig = method->signature;
5558 MonoTableInfo *constt;
5559 MonoTableInfo *methodt;
5560 MonoTableInfo *paramt;
5562 if (!methodsig->param_count)
5565 if (klass->generic_inst) {
5566 return; /* FIXME - ??? */
5569 mono_class_init (klass);
5571 if (klass->image->dynamic) {
5572 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5573 if (aux && aux->param_defaults)
5574 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5578 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5579 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5580 constt = &image->tables [MONO_TABLE_CONSTANT];
5582 for (i = 0; i < klass->method.count; ++i) {
5583 if (method == klass->methods [i]) {
5584 idx = klass->method.first + i;
5589 g_assert (idx != -1);
5591 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5592 if (idx + 1 < methodt->rows)
5593 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5595 lastp = paramt->rows + 1;
5597 for (i = param_index; i < lastp; ++i) {
5600 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5601 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5603 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5606 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5611 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5612 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5619 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5628 klass = mono_class_from_mono_type (type);
5629 if (klass->valuetype) {
5630 object = mono_object_new (domain, klass);
5631 retval = ((gchar *) object + sizeof (MonoObject));
5636 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5643 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5647 memset (assembly, 0, sizeof (MonoAssemblyName));
5649 assembly->culture = "";
5650 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5652 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5655 while (*p == ' ' || *p == ',') {
5664 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5666 assembly->major = strtoul (p, &s, 10);
5667 if (s == p || *s != '.')
5670 assembly->minor = strtoul (p, &s, 10);
5671 if (s == p || *s != '.')
5674 assembly->build = strtoul (p, &s, 10);
5675 if (s == p || *s != '.')
5678 assembly->revision = strtoul (p, &s, 10);
5682 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5684 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5685 assembly->culture = "";
5688 assembly->culture = p;
5689 while (*p && *p != ',') {
5693 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5695 if (strncmp (p, "null", 4) == 0) {
5700 while (*p && *p != ',') {
5703 len = (p - start + 1);
5704 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5705 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5706 g_strlcpy (assembly->public_key_token, start, len);
5709 while (*p && *p != ',')
5713 while (*p == ' ' || *p == ',') {
5727 * mono_reflection_parse_type:
5730 * Parse a type name as accepted by the GetType () method and output the info
5731 * extracted in the info structure.
5732 * the name param will be mangled, so, make a copy before passing it to this function.
5733 * The fields in info will be valid until the memory pointed to by name is valid.
5734 * Returns 0 on parse error.
5735 * See also mono_type_get_name () below.
5738 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5740 char *start, *p, *w, *last_point, *startn;
5741 int in_modifiers = 0;
5742 int isbyref = 0, rank;
5744 start = p = w = name;
5746 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5747 info->name = info->name_space = NULL;
5748 info->nested = NULL;
5749 info->modifiers = NULL;
5751 /* last_point separates the namespace from the name */
5757 *p = 0; /* NULL terminate the name */
5759 info->nested = g_list_append (info->nested, startn);
5760 /* we have parsed the nesting namespace + name */
5764 info->name_space = start;
5766 info->name = last_point + 1;
5768 info->name_space = (char *)"";
5794 info->name_space = start;
5796 info->name = last_point + 1;
5798 info->name_space = (char *)"";
5805 if (isbyref) /* only one level allowed by the spec */
5808 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5812 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5823 else if (*p != '*') /* '*' means unknown lower bound */
5829 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5841 return 0; /* missing assembly name */
5842 if (!assembly_name_to_aname (&info->assembly, p))
5849 if (info->assembly.name)
5852 *w = 0; /* terminate class name */
5853 if (!info->name || !*info->name)
5855 /* add other consistency checks */
5860 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5867 image = mono_defaults.corlib;
5870 klass = mono_class_from_name_case (image, info->name_space, info->name);
5872 klass = mono_class_from_name (image, info->name_space, info->name);
5875 for (mod = info->nested; mod; mod = mod->next) {
5878 mono_class_init (klass);
5879 nested = klass->nested_classes;
5882 klass = nested->data;
5884 if (g_strcasecmp (klass->name, mod->data) == 0)
5887 if (strcmp (klass->name, mod->data) == 0)
5891 nested = nested->next;
5898 mono_class_init (klass);
5899 for (mod = info->modifiers; mod; mod = mod->next) {
5900 modval = GPOINTER_TO_UINT (mod->data);
5901 if (!modval) { /* byref: must be last modifier */
5902 return &klass->this_arg;
5903 } else if (modval == -1) {
5904 klass = mono_ptr_class_get (&klass->byval_arg);
5905 } else { /* array rank */
5906 klass = mono_array_class_get (klass, modval);
5908 mono_class_init (klass);
5911 return &klass->byval_arg;
5915 * mono_reflection_get_type:
5916 * @image: a metadata context
5917 * @info: type description structure
5918 * @ignorecase: flag for case-insensitive string compares
5919 * @type_resolve: whenever type resolve was already tried
5921 * Build a MonoType from the type description in @info.
5926 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5929 MonoReflectionAssembly *assembly;
5933 type = mono_reflection_get_type_internal (image, info, ignorecase);
5936 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5943 *type_resolve = TRUE;
5946 /* Reconstruct the type name */
5947 fullName = g_string_new ("");
5948 if (info->name_space && (info->name_space [0] != '\0'))
5949 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5951 g_string_printf (fullName, info->name);
5952 for (mod = info->nested; mod; mod = mod->next)
5953 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5955 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5957 if (assembly->assembly->dynamic) {
5958 /* Enumerate all modules */
5959 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5963 if (abuilder->modules) {
5964 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5965 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5966 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5972 if (!type && abuilder->loaded_modules) {
5973 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5974 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5975 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5982 type = mono_reflection_get_type_internal (assembly->assembly->image,
5985 g_string_free (fullName, TRUE);
5990 * mono_reflection_type_from_name:
5992 * @image: a metadata context (can be NULL).
5994 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5995 * it defaults to get the type from @image or, if @image is NULL or loading
5996 * from it fails, uses corlib.
6000 mono_reflection_type_from_name (char *name, MonoImage *image)
6003 MonoTypeNameParse info;
6004 MonoAssembly *assembly;
6006 gboolean type_resolve = FALSE;
6008 /* Make a copy since parse_type modifies its argument */
6009 tmp = g_strdup (name);
6011 /*g_print ("requested type %s\n", str);*/
6012 if (!mono_reflection_parse_type (tmp, &info)) {
6014 g_list_free (info.modifiers);
6015 g_list_free (info.nested);
6019 if (info.assembly.name) {
6020 assembly = mono_assembly_loaded (&info.assembly);
6022 /* then we must load the assembly ourselve - see #60439 */
6023 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6026 g_list_free (info.modifiers);
6027 g_list_free (info.nested);
6031 image = assembly->image;
6032 } else if (image == NULL) {
6033 image = mono_defaults.corlib;
6036 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6037 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6038 image = mono_defaults.corlib;
6039 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6043 g_list_free (info.modifiers);
6044 g_list_free (info.nested);
6049 * mono_reflection_get_token:
6051 * Return the metadata token of OBJ which should be an object
6052 * representing a metadata element.
6055 mono_reflection_get_token (MonoObject *obj)
6060 klass = obj->vtable->klass;
6062 if (strcmp (klass->name, "MethodBuilder") == 0) {
6063 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6065 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6066 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6067 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6069 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6070 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6071 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6072 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6073 if (tb->generic_params) {
6074 g_assert_not_reached ();
6076 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6078 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6079 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6080 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6081 } else if (strcmp (klass->name, "MonoType") == 0) {
6082 MonoReflectionType *tb = (MonoReflectionType *)obj;
6083 token = mono_class_from_mono_type (tb->type)->type_token;
6084 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6085 strcmp (klass->name, "MonoMethod") == 0) {
6086 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6087 if (m->method->signature->is_inflated) {
6088 g_assert_not_reached ();
6089 } else if (m->method->signature->generic_param_count) {
6090 g_assert_not_reached ();
6091 } else if (m->method->klass->generic_inst) {
6092 g_assert_not_reached ();
6094 token = m->method->token;
6096 } else if (strcmp (klass->name, "MonoField") == 0) {
6097 MonoReflectionField *f = (MonoReflectionField*)obj;
6099 token = mono_class_get_field_token (f->field);
6100 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6101 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6103 token = mono_class_get_property_token (p->property);
6104 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6105 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6107 token = mono_class_get_event_token (p->event);
6108 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6109 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6111 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6112 } else if (strcmp (klass->name, "Module") == 0) {
6113 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6116 } else if (strcmp (klass->name, "Assembly") == 0) {
6117 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6119 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6120 MonoException *ex = mono_get_exception_not_implemented (msg);
6122 mono_raise_exception (ex);
6129 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6131 int slen, type = t->type;
6136 case MONO_TYPE_BOOLEAN: {
6137 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6142 case MONO_TYPE_CHAR:
6144 case MONO_TYPE_I2: {
6145 guint16 *val = g_malloc (sizeof (guint16));
6150 #if SIZEOF_VOID_P == 4
6156 case MONO_TYPE_I4: {
6157 guint32 *val = g_malloc (sizeof (guint32));
6162 #if SIZEOF_VOID_P == 8
6163 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6168 case MONO_TYPE_I8: {
6169 guint64 *val = g_malloc (sizeof (guint64));
6174 case MONO_TYPE_VALUETYPE:
6175 if (t->data.klass->enumtype) {
6176 type = t->data.klass->enum_basetype->type;
6179 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6182 case MONO_TYPE_STRING:
6183 if (*p == (char)0xFF) {
6187 slen = mono_metadata_decode_value (p, &p);
6189 return mono_string_new_len (mono_domain_get (), p, slen);
6190 case MONO_TYPE_CLASS: {
6193 if (*p == (char)0xFF) {
6198 slen = mono_metadata_decode_value (p, &p);
6199 n = g_memdup (p, slen + 1);
6201 t = mono_reflection_type_from_name (n, image);
6203 g_warning ("Cannot load type '%s'", n);
6207 return mono_type_get_object (mono_domain_get (), t);
6211 case MONO_TYPE_OBJECT: {
6214 MonoClass *subc = NULL;
6219 } else if (subt == 0x0E) {
6220 type = MONO_TYPE_STRING;
6222 } else if (subt == 0x55) {
6225 slen = mono_metadata_decode_value (p, &p);
6226 n = g_memdup (p, slen + 1);
6228 t = mono_reflection_type_from_name (n, image);
6230 g_warning ("Cannot load type '%s'", n);
6233 subc = mono_class_from_mono_type (t);
6234 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6235 MonoType simple_type = {{0}};
6236 simple_type.type = subt;
6237 subc = mono_class_from_mono_type (&simple_type);
6239 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6241 val = load_cattr_value (image, &subc->byval_arg, p, end);
6242 obj = mono_object_new (mono_domain_get (), subc);
6243 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6247 case MONO_TYPE_SZARRAY: {
6249 guint32 i, alen, basetype;
6252 if (alen == 0xffffffff) {
6256 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6257 basetype = t->data.klass->byval_arg.type;
6262 case MONO_TYPE_BOOLEAN:
6263 for (i = 0; i < alen; i++) {
6264 MonoBoolean val = *p++;
6265 mono_array_set (arr, MonoBoolean, i, val);
6268 case MONO_TYPE_CHAR:
6271 for (i = 0; i < alen; i++) {
6272 guint16 val = read16 (p);
6273 mono_array_set (arr, guint16, i, val);
6280 for (i = 0; i < alen; i++) {
6281 guint32 val = read32 (p);
6282 mono_array_set (arr, guint32, i, val);
6289 for (i = 0; i < alen; i++) {
6290 guint64 val = read64 (p);
6291 mono_array_set (arr, guint64, i, val);
6295 case MONO_TYPE_CLASS:
6296 case MONO_TYPE_OBJECT:
6297 case MONO_TYPE_STRING:
6298 for (i = 0; i < alen; i++) {
6299 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6300 mono_array_set (arr, gpointer, i, item);
6304 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6310 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6316 type_is_reference (MonoType *type)
6318 switch (type->type) {
6319 case MONO_TYPE_BOOLEAN:
6320 case MONO_TYPE_CHAR:
6333 case MONO_TYPE_VALUETYPE:
6341 free_param_data (MonoMethodSignature *sig, void **params) {
6343 for (i = 0; i < sig->param_count; ++i) {
6344 if (!type_is_reference (sig->params [i]))
6345 g_free (params [i]);
6350 * Find the method index in the metadata methodDef table.
6351 * Later put these three helper methods in metadata and export them.
6354 find_method_index (MonoMethod *method) {
6355 MonoClass *klass = method->klass;
6358 for (i = 0; i < klass->method.count; ++i) {
6359 if (method == klass->methods [i])
6360 return klass->method.first + 1 + i;
6366 * Find the field index in the metadata FieldDef table.
6369 find_field_index (MonoClass *klass, MonoClassField *field) {
6372 for (i = 0; i < klass->field.count; ++i) {
6373 if (field == &klass->fields [i])
6374 return klass->field.first + 1 + i;
6380 * Find the property index in the metadata Property table.
6383 find_property_index (MonoClass *klass, MonoProperty *property) {
6386 for (i = 0; i < klass->property.count; ++i) {
6387 if (property == &klass->properties [i])
6388 return klass->property.first + 1 + i;
6394 * Find the event index in the metadata Event table.
6397 find_event_index (MonoClass *klass, MonoEvent *event) {
6400 for (i = 0; i < klass->event.count; ++i) {
6401 if (event == &klass->events [i])
6402 return klass->event.first + 1 + i;
6408 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6410 const char *p = data;
6412 guint32 i, j, num_named;
6416 mono_class_init (method->klass);
6419 attr = mono_object_new (mono_domain_get (), method->klass);
6420 mono_runtime_invoke (method, attr, NULL, NULL);
6424 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6427 /*g_print ("got attr %s\n", method->klass->name);*/
6429 params = g_new (void*, method->signature->param_count);
6433 for (i = 0; i < method->signature->param_count; ++i) {
6434 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6438 attr = mono_object_new (mono_domain_get (), method->klass);
6439 mono_runtime_invoke (method, attr, params, NULL);
6440 free_param_data (method->signature, params);
6442 num_named = read16 (named);
6444 for (j = 0; j < num_named; j++) {
6446 char *name, named_type, data_type;
6447 named_type = *named++;
6448 data_type = *named++; /* type of data */
6449 if (data_type == 0x55) {
6452 type_len = mono_metadata_decode_blob_size (named, &named);
6453 type_name = g_malloc (type_len + 1);
6454 memcpy (type_name, named, type_len);
6455 type_name [type_len] = 0;
6457 /* FIXME: lookup the type and check type consistency */
6458 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6459 /* this seems to be the type of the element of the array */
6460 /* g_print ("skipping 0x%02x after prop\n", *named); */
6463 name_len = mono_metadata_decode_blob_size (named, &named);
6464 name = g_malloc (name_len + 1);
6465 memcpy (name, named, name_len);
6466 name [name_len] = 0;
6468 if (named_type == 0x53) {
6469 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6470 void *val = load_cattr_value (image, field->type, named, &named);
6471 mono_field_set_value (attr, field, val);
6472 if (!type_is_reference (field->type))
6474 } else if (named_type == 0x54) {
6477 MonoType *prop_type;
6479 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6480 /* can we have more that 1 arg in a custom attr named property? */
6481 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6482 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6483 mono_property_set_value (prop, attr, pparams, NULL);
6484 if (!type_is_reference (prop_type))
6485 g_free (pparams [0]);
6494 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6501 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6502 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6503 for (i = 0; i < cinfo->num_attrs; ++i) {
6504 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6505 mono_array_set (result, gpointer, i, attr);
6511 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6513 guint32 mtoken, i, len;
6514 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6516 MonoCustomAttrInfo *ainfo;
6517 GList *tmp, *list = NULL;
6520 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6522 i = mono_metadata_custom_attrs_from_index (image, idx);
6526 while (i < ca->rows) {
6527 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6529 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6532 len = g_list_length (list);
6535 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6536 ainfo->num_attrs = len;
6537 ainfo->image = image;
6538 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6539 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6540 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6541 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6542 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6543 mtoken |= MONO_TOKEN_METHOD_DEF;
6545 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6546 mtoken |= MONO_TOKEN_MEMBER_REF;
6549 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6552 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6553 if (!ainfo->attrs [i].ctor)
6554 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6555 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6556 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6557 ainfo->attrs [i].data = data;
6565 mono_custom_attrs_from_method (MonoMethod *method)
6567 MonoCustomAttrInfo *cinfo;
6570 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6572 idx = find_method_index (method);
6573 idx <<= MONO_CUSTOM_ATTR_BITS;
6574 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6575 return mono_custom_attrs_from_index (method->klass->image, idx);
6579 mono_custom_attrs_from_class (MonoClass *klass)
6581 MonoCustomAttrInfo *cinfo;
6584 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6586 idx = mono_metadata_token_index (klass->type_token);
6587 idx <<= MONO_CUSTOM_ATTR_BITS;
6588 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6589 return mono_custom_attrs_from_index (klass->image, idx);
6593 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6595 MonoCustomAttrInfo *cinfo;
6598 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6600 idx = 1; /* there is only one assembly */
6601 idx <<= MONO_CUSTOM_ATTR_BITS;
6602 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6603 return mono_custom_attrs_from_index (assembly->image, idx);
6606 static MonoCustomAttrInfo*
6607 mono_custom_attrs_from_module (MonoImage *image)
6609 MonoCustomAttrInfo *cinfo;
6612 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6614 idx = 1; /* there is only one module */
6615 idx <<= MONO_CUSTOM_ATTR_BITS;
6616 idx |= MONO_CUSTOM_ATTR_MODULE;
6617 return mono_custom_attrs_from_index (image, idx);
6621 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6623 MonoCustomAttrInfo *cinfo;
6626 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6628 idx = find_property_index (klass, property);
6629 idx <<= MONO_CUSTOM_ATTR_BITS;
6630 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6631 return mono_custom_attrs_from_index (klass->image, idx);
6635 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6637 MonoCustomAttrInfo *cinfo;
6640 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6642 idx = find_event_index (klass, event);
6643 idx <<= MONO_CUSTOM_ATTR_BITS;
6644 idx |= MONO_CUSTOM_ATTR_EVENT;
6645 return mono_custom_attrs_from_index (klass->image, idx);
6649 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6651 MonoCustomAttrInfo *cinfo;
6654 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6656 idx = find_field_index (klass, field);
6657 idx <<= MONO_CUSTOM_ATTR_BITS;
6658 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6659 return mono_custom_attrs_from_index (klass->image, idx);
6663 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6666 guint32 i, idx, method_index;
6667 guint32 param_list, param_last, param_pos, found;
6669 MonoReflectionMethodAux *aux;
6671 if (method->klass->image->dynamic) {
6672 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6673 if (!aux || !aux->param_cattr)
6675 return aux->param_cattr [param];
6678 image = method->klass->image;
6679 method_index = find_method_index (method);
6680 ca = &image->tables [MONO_TABLE_METHOD];
6682 if (method->klass->generic_inst || method->klass->generic_container ||
6683 method->signature->generic_param_count) {
6684 /* FIXME FIXME FIXME */
6688 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6689 if (method_index == ca->rows) {
6690 ca = &image->tables [MONO_TABLE_PARAM];
6691 param_last = ca->rows + 1;
6693 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6694 ca = &image->tables [MONO_TABLE_PARAM];
6697 for (i = param_list; i < param_last; ++i) {
6698 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6699 if (param_pos == param) {
6707 idx <<= MONO_CUSTOM_ATTR_BITS;
6708 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6709 return mono_custom_attrs_from_index (image, idx);
6713 * mono_reflection_get_custom_attrs:
6714 * @obj: a reflection object handle
6716 * Return an array with all the custom attributes defined of the
6717 * reflection handle @obj. The objects are fully build.
6720 mono_reflection_get_custom_attrs (MonoObject *obj)
6724 MonoCustomAttrInfo *cinfo = NULL;
6726 MONO_ARCH_SAVE_REGS;
6728 klass = obj->vtable->klass;
6729 if (klass == mono_defaults.monotype_class) {
6730 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6731 klass = mono_class_from_mono_type (rtype->type);
6732 cinfo = mono_custom_attrs_from_class (klass);
6733 } else if (strcmp ("Assembly", klass->name) == 0) {
6734 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6735 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6736 } else if (strcmp ("Module", klass->name) == 0) {
6737 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6738 cinfo = mono_custom_attrs_from_module (module->image);
6739 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6740 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6741 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6742 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6743 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6744 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6745 } else if (strcmp ("MonoField", klass->name) == 0) {
6746 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6747 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6748 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6749 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6750 cinfo = mono_custom_attrs_from_method (rmethod->method);
6751 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6752 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6753 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6754 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6755 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6756 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6757 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6758 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6759 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6760 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6761 } else { /* handle other types here... */
6762 g_error ("get custom attrs not yet supported for %s", klass->name);
6766 result = mono_custom_attrs_construct (cinfo);
6768 mono_custom_attrs_free (cinfo);
6770 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6771 result = mono_array_new (mono_domain_get (), klass, 0);
6777 static MonoMethodSignature*
6778 parameters_to_signature (MonoArray *parameters) {
6779 MonoMethodSignature *sig;
6782 count = parameters? mono_array_length (parameters): 0;
6784 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6785 sig->param_count = count;
6786 sig->sentinelpos = -1; /* FIXME */
6787 for (i = 0; i < count; ++i) {
6788 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6789 sig->params [i] = pt->type;
6794 static MonoMethodSignature*
6795 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6796 MonoMethodSignature *sig;
6798 sig = parameters_to_signature (ctor->parameters);
6799 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6800 sig->ret = &mono_defaults.void_class->byval_arg;
6804 static MonoMethodSignature*
6805 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6806 MonoMethodSignature *sig;
6808 sig = parameters_to_signature (method->parameters);
6809 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6810 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6811 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6815 static MonoMethodSignature*
6816 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6817 MonoMethodSignature *sig;
6819 sig = parameters_to_signature (method->parameters);
6820 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6821 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6822 sig->generic_param_count = 0;
6827 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6829 MonoClass *klass = mono_object_class (prop);
6830 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6831 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6832 *name = mono_string_to_utf8 (pb->name);
6833 *type = pb->type->type;
6835 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6836 *name = g_strdup (p->property->name);
6837 if (p->property->get)
6838 *type = p->property->get->signature->ret;
6840 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6845 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6847 MonoClass *klass = mono_object_class (field);
6848 if (strcmp (klass->name, "FieldBuilder") == 0) {
6849 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6850 *name = mono_string_to_utf8 (fb->name);
6851 *type = fb->type->type;
6853 MonoReflectionField *f = (MonoReflectionField *)field;
6854 *name = g_strdup (f->field->name);
6855 *type = f->field->type;
6860 * Encode a value in a custom attribute stream of bytes.
6861 * The value to encode is either supplied as an object in argument val
6862 * (valuetypes are boxed), or as a pointer to the data in the
6864 * @type represents the type of the value
6865 * @buffer is the start of the buffer
6866 * @p the current position in the buffer
6867 * @buflen contains the size of the buffer and is used to return the new buffer size
6868 * if this needs to be realloced.
6869 * @retbuffer and @retp return the start and the position of the buffer
6872 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6874 MonoTypeEnum simple_type;
6876 if ((p-buffer) + 10 >= *buflen) {
6879 newbuf = g_realloc (buffer, *buflen);
6880 p = newbuf + (p-buffer);
6884 argval = ((char*)arg + sizeof (MonoObject));
6885 simple_type = type->type;
6887 switch (simple_type) {
6888 case MONO_TYPE_BOOLEAN:
6893 case MONO_TYPE_CHAR:
6896 swap_with_size (p, argval, 2, 1);
6902 swap_with_size (p, argval, 4, 1);
6908 swap_with_size (p, argval, 8, 1);
6911 case MONO_TYPE_VALUETYPE:
6912 if (type->data.klass->enumtype) {
6913 simple_type = type->data.klass->enum_basetype->type;
6916 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6919 case MONO_TYPE_STRING: {
6926 str = mono_string_to_utf8 ((MonoString*)arg);
6927 slen = strlen (str);
6928 if ((p-buffer) + 10 + slen >= *buflen) {
6932 newbuf = g_realloc (buffer, *buflen);
6933 p = newbuf + (p-buffer);
6936 mono_metadata_encode_value (slen, p, &p);
6937 memcpy (p, str, slen);
6942 case MONO_TYPE_CLASS: {
6950 k = mono_object_class (arg);
6951 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6952 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6953 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6955 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6956 slen = strlen (str);
6957 if ((p-buffer) + 10 + slen >= *buflen) {
6961 newbuf = g_realloc (buffer, *buflen);
6962 p = newbuf + (p-buffer);
6965 mono_metadata_encode_value (slen, p, &p);
6966 memcpy (p, str, slen);
6971 case MONO_TYPE_SZARRAY: {
6973 MonoClass *eclass, *arg_eclass;
6976 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6979 len = mono_array_length ((MonoArray*)arg);
6981 *p++ = (len >> 8) & 0xff;
6982 *p++ = (len >> 16) & 0xff;
6983 *p++ = (len >> 24) & 0xff;
6985 *retbuffer = buffer;
6986 eclass = type->data.klass;
6987 arg_eclass = mono_object_class (arg)->element_class;
6988 if (eclass->valuetype && arg_eclass->valuetype) {
6989 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6990 int elsize = mono_class_array_element_size (eclass);
6991 for (i = 0; i < len; ++i) {
6992 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6996 for (i = 0; i < len; ++i) {
6997 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7002 /* it may be a boxed value or a Type */
7003 case MONO_TYPE_OBJECT: {
7004 MonoClass *klass = mono_object_class (arg);
7008 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7011 } else if (klass->enumtype) {
7013 } else if (klass == mono_defaults.string_class) {
7014 simple_type = MONO_TYPE_STRING;
7017 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7018 *p++ = simple_type = klass->byval_arg.type;
7021 g_error ("unhandled type in custom attr");
7023 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7024 slen = strlen (str);
7025 if ((p-buffer) + 10 + slen >= *buflen) {
7029 newbuf = g_realloc (buffer, *buflen);
7030 p = newbuf + (p-buffer);
7033 mono_metadata_encode_value (slen, p, &p);
7034 memcpy (p, str, slen);
7037 simple_type = klass->enum_basetype->type;
7041 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7044 *retbuffer = buffer;
7048 * mono_reflection_get_custom_attrs_blob:
7049 * @ctor: custom attribute constructor
7050 * @ctorArgs: arguments o the constructor
7056 * Creates the blob of data that needs to be saved in the metadata and that represents
7057 * the custom attributed described by @ctor, @ctorArgs etc.
7058 * Returns: a Byte array representing the blob of data.
7061 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7064 MonoMethodSignature *sig;
7069 MONO_ARCH_SAVE_REGS;
7071 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7072 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7074 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7076 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7078 p = buffer = g_malloc (buflen);
7079 /* write the prolog */
7082 for (i = 0; i < sig->param_count; ++i) {
7083 arg = mono_array_get (ctorArgs, MonoObject*, i);
7084 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7088 i += mono_array_length (properties);
7090 i += mono_array_length (fields);
7092 *p++ = (i >> 8) & 0xff;
7095 for (i = 0; i < mono_array_length (properties); ++i) {
7100 prop = mono_array_get (properties, gpointer, i);
7101 get_prop_name_and_type (prop, &pname, &ptype);
7102 *p++ = 0x54; /* PROPERTY signature */
7104 /* Preallocate a large enough buffer */
7105 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7106 char *str = type_get_qualified_name (ptype, NULL);
7112 len += strlen (pname);
7114 if ((p-buffer) + 20 + len >= buflen) {
7118 newbuf = g_realloc (buffer, buflen);
7119 p = newbuf + (p-buffer);
7123 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7124 char *str = type_get_qualified_name (ptype, NULL);
7125 int slen = strlen (str);
7129 * This seems to be optional...
7132 mono_metadata_encode_value (slen, p, &p);
7133 memcpy (p, str, slen);
7137 mono_metadata_encode_value (ptype->type, p, &p);
7138 if (ptype->type == MONO_TYPE_SZARRAY)
7139 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7141 len = strlen (pname);
7142 mono_metadata_encode_value (len, p, &p);
7143 memcpy (p, pname, len);
7145 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7152 for (i = 0; i < mono_array_length (fields); ++i) {
7157 field = mono_array_get (fields, gpointer, i);
7158 get_field_name_and_type (field, &fname, &ftype);
7159 *p++ = 0x53; /* FIELD signature */
7160 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7161 char *str = type_get_qualified_name (ftype, NULL);
7162 int slen = strlen (str);
7163 if ((p-buffer) + 10 + slen >= buflen) {
7167 newbuf = g_realloc (buffer, buflen);
7168 p = newbuf + (p-buffer);
7173 * This seems to be optional...
7176 mono_metadata_encode_value (slen, p, &p);
7177 memcpy (p, str, slen);
7181 mono_metadata_encode_value (ftype->type, p, &p);
7182 if (ftype->type == MONO_TYPE_SZARRAY)
7183 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7185 len = strlen (fname);
7186 mono_metadata_encode_value (len, p, &p);
7187 memcpy (p, fname, len);
7189 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7194 g_assert (p - buffer <= buflen);
7195 buflen = p - buffer;
7196 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7197 p = mono_array_addr (result, char, 0);
7198 memcpy (p, buffer, buflen);
7200 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7206 * mono_reflection_setup_internal_class:
7207 * @tb: a TypeBuilder object
7209 * Creates a MonoClass that represents the TypeBuilder.
7210 * This is a trick that lets us simplify a lot of reflection code
7211 * (and will allow us to support Build and Run assemblies easier).
7214 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7216 MonoClass *klass, *parent;
7218 MONO_ARCH_SAVE_REGS;
7221 /* check so we can compile corlib correctly */
7222 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7223 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7224 parent = tb->parent->type->data.klass;
7226 parent = my_mono_class_from_mono_type (tb->parent->type);
7232 /* the type has already being created: it means we just have to change the parent */
7233 if (tb->type.type) {
7234 klass = mono_class_from_mono_type (tb->type.type);
7235 klass->parent = NULL;
7236 /* fool mono_class_setup_parent */
7237 g_free (klass->supertypes);
7238 klass->supertypes = NULL;
7239 mono_class_setup_parent (klass, parent);
7240 mono_class_setup_mono_type (klass);
7244 klass = g_new0 (MonoClass, 1);
7246 klass->image = &tb->module->dynamic_image->image;
7248 klass->inited = 1; /* we lie to the runtime */
7249 klass->name = mono_string_to_utf8 (tb->name);
7250 klass->name_space = mono_string_to_utf8 (tb->nspace);
7251 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7252 klass->flags = tb->attrs;
7254 klass->element_class = klass;
7255 klass->reflection_info = tb; /* need to pin. */
7257 /* Put into cache so mono_class_get () will find it */
7258 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7260 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7261 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7263 if (parent != NULL) {
7264 mono_class_setup_parent (klass, parent);
7265 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7266 const char *old_n = klass->name;
7267 /* trick to get relative numbering right when compiling corlib */
7268 klass->name = "BuildingObject";
7269 mono_class_setup_parent (klass, mono_defaults.object_class);
7270 klass->name = old_n;
7273 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7274 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7275 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7276 klass->instance_size = sizeof (MonoObject);
7277 klass->size_inited = 1;
7278 mono_class_setup_vtable (klass, NULL, 0);
7281 mono_class_setup_mono_type (klass);
7283 mono_class_setup_supertypes (klass);
7286 * FIXME: handle interfaces.
7289 tb->type.type = &klass->byval_arg;
7291 if (tb->nesting_type) {
7292 g_assert (tb->nesting_type->type);
7293 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7296 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7300 * mono_reflection_setup_generic_class:
7301 * @tb: a TypeBuilder object
7303 * Setup the generic class before adding the first generic parameter.
7306 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7310 MONO_ARCH_SAVE_REGS;
7312 klass = my_mono_class_from_mono_type (tb->type.type);
7313 if (tb->generic_container)
7316 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7317 tb->generic_container->klass = klass;
7321 * mono_reflection_create_generic_class:
7322 * @tb: a TypeBuilder object
7324 * Creates the generic class after all generic parameters have been added.
7327 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7332 MONO_ARCH_SAVE_REGS;
7334 klass = my_mono_class_from_mono_type (tb->type.type);
7336 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7338 if (klass->generic_container || (count == 0))
7341 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7343 klass->generic_container = tb->generic_container;
7345 klass->generic_container->type_argc = count;
7346 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7348 for (i = 0; i < count; i++) {
7349 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7350 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7351 g_assert (klass->generic_container->type_params [i].owner);
7356 * mono_reflection_create_internal_class:
7357 * @tb: a TypeBuilder object
7359 * Actually create the MonoClass that is associated with the TypeBuilder.
7362 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7366 MONO_ARCH_SAVE_REGS;
7368 klass = my_mono_class_from_mono_type (tb->type.type);
7370 if (klass->enumtype && klass->enum_basetype == NULL) {
7371 MonoReflectionFieldBuilder *fb;
7374 g_assert (tb->fields != NULL);
7375 g_assert (mono_array_length (tb->fields) >= 1);
7377 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7379 klass->enum_basetype = fb->type->type;
7380 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7381 if (!klass->element_class)
7382 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7385 * get the element_class from the current corlib.
7387 ec = default_class_from_mono_type (klass->enum_basetype);
7388 klass->instance_size = ec->instance_size;
7389 klass->size_inited = 1;
7391 * this is almost safe to do with enums and it's needed to be able
7392 * to create objects of the enum type (for use in SetConstant).
7394 /* FIXME: Does this mean enums can't have method overrides ? */
7395 mono_class_setup_vtable (klass, NULL, 0);
7399 static MonoMarshalSpec*
7400 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7401 MonoReflectionMarshal *minfo)
7403 MonoMarshalSpec *res;
7405 res = g_new0 (MonoMarshalSpec, 1);
7406 res->native = minfo->type;
7408 switch (minfo->type) {
7409 case MONO_NATIVE_LPARRAY:
7410 res->data.array_data.elem_type = minfo->eltype;
7411 res->data.array_data.param_num = 0; /* Not yet */
7412 res->data.array_data.num_elem = minfo->count;
7415 case MONO_NATIVE_BYVALTSTR:
7416 case MONO_NATIVE_BYVALARRAY:
7417 res->data.array_data.num_elem = minfo->count;
7420 case MONO_NATIVE_CUSTOM:
7421 if (minfo->marshaltyperef)
7422 res->data.custom_data.custom_name =
7423 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7425 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7435 MonoReflectionMarshal*
7436 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7437 MonoMarshalSpec *spec)
7439 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7440 MonoReflectionMarshal *minfo;
7443 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7444 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7445 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7446 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7449 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7450 minfo->type = spec->native;
7452 switch (minfo->type) {
7453 case MONO_NATIVE_LPARRAY:
7454 minfo->eltype = spec->data.array_data.elem_type;
7455 minfo->count = spec->data.array_data.num_elem;
7458 case MONO_NATIVE_BYVALTSTR:
7459 case MONO_NATIVE_BYVALARRAY:
7460 minfo->count = spec->data.array_data.num_elem;
7463 case MONO_NATIVE_CUSTOM:
7464 if (spec->data.custom_data.custom_name) {
7465 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7467 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7469 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7471 if (spec->data.custom_data.cookie)
7472 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7483 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7484 ReflectionMethodBuilder *rmb,
7485 MonoMethodSignature *sig)
7488 MonoMethodNormal *pm;
7489 MonoMarshalSpec **specs;
7490 MonoReflectionMethodAux *method_aux;
7493 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7494 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7495 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7497 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7499 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7501 pm = (MonoMethodNormal*)m;
7504 m->flags = rmb->attrs;
7505 m->iflags = rmb->iattrs;
7506 m->name = mono_string_to_utf8 (rmb->name);
7510 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7512 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7513 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7516 m->signature->pinvoke = 1;
7517 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7518 m->signature->pinvoke = 1;
7520 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7522 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7523 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7525 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7527 if (klass->image->dynamic)
7528 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7531 } else if (!m->klass->dummy &&
7532 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7533 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7534 MonoMethodHeader *header;
7536 gint32 max_stack, i;
7537 gint32 num_locals = 0;
7538 gint32 num_clauses = 0;
7542 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7543 code_size = rmb->ilgen->code_len;
7544 max_stack = rmb->ilgen->max_stack;
7545 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7546 if (rmb->ilgen->ex_handlers)
7547 num_clauses = method_count_clauses (rmb->ilgen);
7550 code = mono_array_addr (rmb->code, guint8, 0);
7551 code_size = mono_array_length (rmb->code);
7552 /* we probably need to run a verifier on the code... */
7562 header = g_malloc0 (sizeof (MonoMethodHeader) +
7563 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7564 header->code_size = code_size;
7565 header->code = g_malloc (code_size);
7566 memcpy ((char*)header->code, code, code_size);
7567 header->max_stack = max_stack;
7568 header->init_locals = rmb->init_locals;
7569 header->num_locals = num_locals;
7571 for (i = 0; i < num_locals; ++i) {
7572 MonoReflectionLocalBuilder *lb =
7573 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7575 header->locals [i] = g_new0 (MonoType, 1);
7576 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7579 header->num_clauses = num_clauses;
7581 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7582 rmb->ilgen, num_clauses);
7585 pm->header = header;
7588 if (rmb->generic_params) {
7589 int count = mono_array_length (rmb->generic_params);
7590 MonoGenericContainer *container;
7592 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7593 container->type_argc = count;
7594 container->type_params = g_new0 (MonoGenericParam, count);
7596 for (i = 0; i < count; i++) {
7597 MonoReflectionGenericParam *gp =
7598 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7600 container->type_params [i] = *gp->type.type->data.generic_param;
7605 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7608 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7610 for (i = 0; i < rmb->nrefs; ++i)
7611 mw->data = g_list_append (mw->data, rmb->refs [i]);
7616 /* Parameter info */
7619 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7620 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7621 for (i = 0; i <= m->signature->param_count; ++i) {
7622 MonoReflectionParamBuilder *pb;
7623 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7625 m->signature->params [i - 1]->attrs = pb->attrs;
7627 if (pb->def_value) {
7628 MonoDynamicImage *assembly;
7629 guint32 idx, def_type, len;
7633 if (!method_aux->param_defaults)
7634 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7635 assembly = (MonoDynamicImage*)klass->image;
7636 idx = encode_constant (assembly, pb->def_value, &def_type);
7637 /* Copy the data from the blob since it might get realloc-ed */
7638 p = assembly->blob.data + idx;
7639 len = mono_metadata_decode_blob_size (p, &p2);
7641 method_aux->param_defaults [i] = g_malloc (len);
7642 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7646 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7648 if (!method_aux->param_cattr)
7649 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7650 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7656 /* Parameter marshalling */
7659 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7660 MonoReflectionParamBuilder *pb;
7661 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7662 if (pb->marshal_info) {
7664 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7665 specs [pb->position] =
7666 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7670 if (specs != NULL) {
7672 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7673 method_aux->param_marshall = specs;
7676 if (klass->image->dynamic && method_aux)
7677 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7683 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7685 ReflectionMethodBuilder rmb;
7686 MonoMethodSignature *sig;
7688 sig = ctor_builder_to_signature (mb);
7690 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7692 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7693 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7695 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7696 /* ilgen is no longer needed */
7704 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7706 ReflectionMethodBuilder rmb;
7707 MonoMethodSignature *sig;
7709 sig = method_builder_to_signature (mb);
7711 reflection_methodbuilder_from_method_builder (&rmb, mb);
7713 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7714 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7716 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7717 /* ilgen is no longer needed */
7723 static MonoClassField*
7724 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7726 MonoClassField *field;
7733 field = g_new0 (MonoClassField, 1);
7735 field->name = mono_string_to_utf8 (fb->name);
7737 /* FIXME: handle type modifiers */
7738 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7739 field->type->attrs = fb->attrs;
7741 field->type = fb->type->type;
7743 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7744 field->data = mono_array_addr (fb->rva_data, char, 0);
7745 if (fb->offset != -1)
7746 field->offset = fb->offset;
7747 field->parent = klass;
7749 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7751 if (fb->def_value) {
7752 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7753 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7754 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7755 /* Copy the data from the blob since it might get realloc-ed */
7756 p = assembly->blob.data + idx;
7757 len = mono_metadata_decode_blob_size (p, &p2);
7759 field->data = g_malloc (len);
7760 memcpy ((gpointer)field->data, p, len);
7767 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7769 MonoClass *klass, *gklass;
7770 MonoReflectionTypeBuilder *tb = NULL;
7771 MonoGenericInst *ginst, *cached;
7776 klass = mono_class_from_mono_type (type->type);
7777 if (!klass->generic_container && !klass->generic_inst &&
7778 !(klass->nested_in && klass->nested_in->generic_container))
7781 mono_loader_lock ();
7783 domain = mono_object_domain (type);
7785 ginst = g_new0 (MonoGenericInst, 1);
7787 if (!klass->generic_inst) {
7788 ginst->type_argc = type_argc;
7789 ginst->type_argv = types;
7791 for (i = 0; i < ginst->type_argc; ++i) {
7792 if (!ginst->is_open)
7793 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7796 ginst->generic_type = &klass->byval_arg;
7798 MonoGenericInst *kginst = klass->generic_inst;
7800 ginst->type_argc = kginst->type_argc;
7801 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7803 for (i = 0; i < ginst->type_argc; i++) {
7804 MonoType *t = kginst->type_argv [i];
7806 if (t->type == MONO_TYPE_VAR)
7807 t = types [t->data.generic_param->num];
7809 if (!ginst->is_open)
7810 ginst->is_open = mono_class_is_open_constructed_type (t);
7812 ginst->type_argv [i] = t;
7815 ginst->generic_type = kginst->generic_type;
7818 geninst = g_new0 (MonoType, 1);
7819 geninst->type = MONO_TYPE_GENERICINST;
7821 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7824 mono_loader_unlock ();
7825 geninst->data.generic_inst = cached;
7829 gklass = mono_class_from_mono_type (ginst->generic_type);
7830 g_assert ((ginst->container = gklass->generic_container) != NULL);
7832 geninst->data.generic_inst = ginst;
7834 ginst->context = g_new0 (MonoGenericContext, 1);
7835 ginst->context->ginst = ginst;
7837 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7838 tb = (MonoReflectionTypeBuilder *) type;
7840 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7841 ginst->is_dynamic = TRUE;
7842 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7843 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7844 MonoReflectionType *rgt = rgi->generic_type;
7846 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7847 tb = (MonoReflectionTypeBuilder *) rgt;
7849 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7850 ginst->is_dynamic = TRUE;
7852 icount = klass->interface_count;
7855 ginst->ifaces = g_new0 (MonoType *, icount);
7856 ginst->count_ifaces = icount;
7858 for (i = 0; i < icount; i++) {
7859 MonoReflectionType *itype;
7862 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7864 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7865 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7866 if (!ginst->ifaces [i])
7867 ginst->ifaces [i] = itype->type;
7870 mono_class_create_generic (ginst);
7872 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7874 mono_loader_unlock ();
7880 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7882 MonoClass *klass, *pklass = NULL;
7883 MonoReflectionType *parent = NULL;
7885 MonoReflectionTypeBuilder *tb = NULL;
7886 MonoGenericInst *ginst;
7889 domain = mono_object_domain (type);
7890 klass = mono_class_from_mono_type (type->type);
7892 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7893 tb = (MonoReflectionTypeBuilder *) type;
7896 parent = tb->parent;
7897 pklass = mono_class_from_mono_type (parent->type);
7900 pklass = klass->parent;
7902 parent = mono_type_get_object (domain, &pklass->byval_arg);
7903 else if (klass->generic_inst && klass->generic_inst->parent) {
7904 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7905 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7909 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7913 ginst = geninst->data.generic_inst;
7915 if (pklass && pklass->generic_inst)
7916 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7921 MonoReflectionMethod*
7922 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7924 MonoMethod *method, *inflated;
7925 MonoReflectionMethodBuilder *mb = NULL;
7926 MonoGenericMethod *gmethod;
7927 MonoGenericContext *context;
7930 MONO_ARCH_SAVE_REGS;
7931 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7932 MonoReflectionTypeBuilder *tb;
7935 mb = (MonoReflectionMethodBuilder *) rmethod;
7936 tb = (MonoReflectionTypeBuilder *) mb->type;
7937 klass = mono_class_from_mono_type (tb->type.type);
7939 method = methodbuilder_to_mono_method (klass, mb);
7941 method = rmethod->method;
7944 count = method->signature->generic_param_count;
7945 if (count != mono_array_length (types))
7948 gmethod = g_new0 (MonoGenericMethod, 1);
7949 gmethod->mtype_argc = count;
7950 gmethod->mtype_argv = g_new0 (MonoType *, count);
7951 for (i = 0; i < count; i++) {
7952 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7953 gmethod->mtype_argv [i] = garg->type;
7956 gmethod->reflection_info = rmethod;
7958 context = g_new0 (MonoGenericContext, 1);
7959 context->ginst = method->klass->generic_inst;
7960 context->gmethod = gmethod;
7962 inflated = mono_class_inflate_generic_method (method, context, NULL);
7964 return mono_method_get_object (
7965 mono_object_domain (rmethod), inflated, NULL);
7969 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7971 MonoGenericMethod *gmethod;
7972 MonoGenericInst *ginst;
7973 MonoGenericContext *context;
7976 ginst = type->type.type->data.generic_inst;
7978 gmethod = g_new0 (MonoGenericMethod, 1);
7979 gmethod->reflection_info = obj;
7981 gmethod->mtype_argc = method->signature->generic_param_count;
7982 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7984 for (i = 0; i < gmethod->mtype_argc; i++) {
7985 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7986 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7988 g_assert (gparam->pklass);
7989 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7992 context = g_new0 (MonoGenericContext, 1);
7993 context->ginst = ginst;
7994 context->gmethod = gmethod;
7996 return mono_class_inflate_generic_method (method, context, ginst->klass);
8000 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8005 klass = mono_class_from_mono_type (type->type.type);
8007 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8008 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8009 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8010 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8011 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8012 method = ((MonoReflectionMethod *) obj)->method;
8014 method = NULL; /* prevent compiler warning */
8015 g_assert_not_reached ();
8018 return inflate_mono_method (type, method, obj);
8022 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8023 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8025 MonoGenericInst *ginst;
8026 MonoDynamicGenericInst *dginst;
8027 MonoClass *klass, *gklass, *pklass;
8030 MONO_ARCH_SAVE_REGS;
8032 klass = mono_class_from_mono_type (type->type.type);
8033 ginst = type->type.type->data.generic_inst;
8035 if (ginst->initialized)
8038 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8040 gklass = mono_class_from_mono_type (ginst->generic_type);
8041 mono_class_init (gklass);
8044 pklass = mono_class_from_mono_type (ginst->parent);
8046 pklass = gklass->parent;
8048 mono_class_setup_parent (klass, pklass);
8050 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8051 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8052 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8053 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8054 dginst->count_events = events ? mono_array_length (events) : 0;
8056 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8057 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8058 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8059 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8060 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8062 for (i = 0; i < dginst->count_methods; i++) {
8063 MonoObject *obj = mono_array_get (methods, gpointer, i);
8065 dginst->methods [i] = inflate_method (type, obj);
8068 for (i = 0; i < dginst->count_ctors; i++) {
8069 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8071 dginst->ctors [i] = inflate_method (type, obj);
8074 for (i = 0; i < dginst->count_fields; i++) {
8075 MonoObject *obj = mono_array_get (fields, gpointer, i);
8076 MonoClassField *field;
8077 MonoInflatedField *ifield;
8079 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8080 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8081 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8082 field = ((MonoReflectionField *) obj)->field;
8084 field = NULL; /* prevent compiler warning */
8085 g_assert_not_reached ();
8088 ifield = g_new0 (MonoInflatedField, 1);
8089 ifield->generic_type = field->type;
8090 ifield->reflection_info = obj;
8092 dginst->fields [i] = *field;
8093 dginst->fields [i].generic_info = ifield;
8094 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8097 for (i = 0; i < dginst->count_properties; i++) {
8098 MonoObject *obj = mono_array_get (properties, gpointer, i);
8099 MonoProperty *property = &dginst->properties [i];
8101 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8102 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8104 property->parent = klass;
8105 property->attrs = pb->attrs;
8106 property->name = mono_string_to_utf8 (pb->name);
8108 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8110 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8111 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8112 *property = *((MonoReflectionProperty *) obj)->property;
8115 property->get = inflate_mono_method (type, property->get, NULL);
8117 property->set = inflate_mono_method (type, property->set, NULL);
8119 g_assert_not_reached ();
8122 for (i = 0; i < dginst->count_events; i++) {
8123 MonoObject *obj = mono_array_get (events, gpointer, i);
8124 MonoEvent *event = &dginst->events [i];
8126 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8127 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8129 event->parent = klass;
8130 event->attrs = eb->attrs;
8131 event->name = mono_string_to_utf8 (eb->name);
8133 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8134 if (eb->remove_method)
8135 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8136 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8137 *event = *((MonoReflectionEvent *) obj)->event;
8140 event->add = inflate_mono_method (type, event->add, NULL);
8142 event->remove = inflate_mono_method (type, event->remove, NULL);
8144 g_assert_not_reached ();
8147 ginst->initialized = TRUE;
8151 ensure_runtime_vtable (MonoClass *klass)
8153 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8154 int i, num, j, onum;
8155 MonoMethod **overrides;
8157 if (!tb || klass->wastypebuilder)
8160 ensure_runtime_vtable (klass->parent);
8162 num = tb->ctors? mono_array_length (tb->ctors): 0;
8163 num += tb->num_methods;
8164 klass->method.count = num;
8165 klass->methods = g_new (MonoMethod*, num);
8166 num = tb->ctors? mono_array_length (tb->ctors): 0;
8167 for (i = 0; i < num; ++i)
8168 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8169 num = tb->num_methods;
8171 for (i = 0; i < num; ++i)
8172 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8174 if (tb->interfaces) {
8175 klass->interface_count = mono_array_length (tb->interfaces);
8176 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8177 for (i = 0; i < klass->interface_count; ++i) {
8178 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8179 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8183 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8184 for (i = 0; i < klass->method.count; ++i)
8185 klass->methods [i]->slot = i;
8190 for (i = 0; i < tb->num_methods; ++i) {
8191 MonoReflectionMethodBuilder *mb =
8192 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8193 if (mb->override_method)
8198 overrides = g_new0 (MonoMethod*, onum * 2);
8202 for (i = 0; i < tb->num_methods; ++i) {
8203 MonoReflectionMethodBuilder *mb =
8204 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8205 if (mb->override_method) {
8206 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8207 overrides [onum * 2] =
8208 mb->override_method->method;
8209 overrides [onum * 2 + 1] =
8212 g_assert (mb->mhandle);
8219 mono_class_setup_vtable (klass, overrides, onum);
8224 typebuilder_setup_fields (MonoClass *klass)
8226 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8227 MonoReflectionFieldBuilder *fb;
8228 MonoClassField *field;
8233 klass->field.count = tb->num_fields;
8234 klass->field.first = 0;
8235 klass->field.last = klass->field.count;
8237 if (!klass->field.count)
8240 klass->fields = g_new0 (MonoClassField, klass->field.count);
8242 for (i = 0; i < klass->field.count; ++i) {
8243 fb = mono_array_get (tb->fields, gpointer, i);
8244 field = &klass->fields [i];
8245 field->name = mono_string_to_utf8 (fb->name);
8247 /* FIXME: handle type modifiers */
8248 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8249 field->type->attrs = fb->attrs;
8251 field->type = fb->type->type;
8253 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8254 field->data = mono_array_addr (fb->rva_data, char, 0);
8255 if (fb->offset != -1)
8256 field->offset = fb->offset;
8257 field->parent = klass;
8259 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8261 if (fb->def_value) {
8262 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8263 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8264 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8265 /* Copy the data from the blob since it might get realloc-ed */
8266 p = assembly->blob.data + idx;
8267 len = mono_metadata_decode_blob_size (p, &p2);
8269 field->data = g_malloc (len);
8270 memcpy ((gpointer)field->data, p, len);
8273 mono_class_layout_fields (klass);
8277 typebuilder_setup_properties (MonoClass *klass)
8279 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8280 MonoReflectionPropertyBuilder *pb;
8283 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8284 klass->property.first = 0;
8285 klass->property.last = klass->property.count;
8287 klass->properties = g_new0 (MonoProperty, klass->property.count);
8288 for (i = 0; i < klass->property.count; ++i) {
8289 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8290 klass->properties [i].parent = klass;
8291 klass->properties [i].attrs = pb->attrs;
8292 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8294 klass->properties [i].get = pb->get_method->mhandle;
8296 klass->properties [i].set = pb->set_method->mhandle;
8300 MonoReflectionEvent *
8301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8303 MonoEvent *event = g_new0 (MonoEvent, 1);
8307 klass = my_mono_class_from_mono_type (tb->type.type);
8309 event->parent = klass;
8310 event->attrs = eb->attrs;
8311 event->name = mono_string_to_utf8 (eb->name);
8313 event->add = eb->add_method->mhandle;
8314 if (eb->remove_method)
8315 event->remove = eb->remove_method->mhandle;
8316 if (eb->raise_method)
8317 event->raise = eb->raise_method->mhandle;
8319 if (eb->other_methods) {
8320 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8321 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8322 MonoReflectionMethodBuilder *mb =
8323 mono_array_get (eb->other_methods,
8324 MonoReflectionMethodBuilder*, j);
8325 event->other [j] = mb->mhandle;
8329 return mono_event_get_object (mono_object_domain (tb), klass, event);
8333 typebuilder_setup_events (MonoClass *klass)
8335 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8336 MonoReflectionEventBuilder *eb;
8339 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8340 klass->event.first = 0;
8341 klass->event.last = klass->event.count;
8343 klass->events = g_new0 (MonoEvent, klass->event.count);
8344 for (i = 0; i < klass->event.count; ++i) {
8345 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8346 klass->events [i].parent = klass;
8347 klass->events [i].attrs = eb->attrs;
8348 klass->events [i].name = mono_string_to_utf8 (eb->name);
8350 klass->events [i].add = eb->add_method->mhandle;
8351 if (eb->remove_method)
8352 klass->events [i].remove = eb->remove_method->mhandle;
8353 if (eb->raise_method)
8354 klass->events [i].raise = eb->raise_method->mhandle;
8356 if (eb->other_methods) {
8357 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8358 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8359 MonoReflectionMethodBuilder *mb =
8360 mono_array_get (eb->other_methods,
8361 MonoReflectionMethodBuilder*, j);
8362 klass->events [i].other [j] = mb->mhandle;
8369 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8372 MonoReflectionType* res;
8375 MONO_ARCH_SAVE_REGS;
8377 klass = my_mono_class_from_mono_type (tb->type.type);
8379 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8382 * Fields to set in klass:
8383 * the various flags: delegate/unicode/contextbound etc.
8385 klass->flags = tb->attrs;
8387 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8388 /* No need to fully construct the type */
8389 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8391 /* enums are done right away */
8392 if (!klass->enumtype)
8393 ensure_runtime_vtable (klass);
8396 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8397 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8398 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8402 /* fields and object layout */
8403 if (klass->parent) {
8404 if (!klass->parent->size_inited)
8405 mono_class_init (klass->parent);
8406 klass->instance_size += klass->parent->instance_size;
8407 klass->class_size += klass->parent->class_size;
8408 klass->min_align = klass->parent->min_align;
8410 klass->instance_size = sizeof (MonoObject);
8411 klass->min_align = 1;
8414 /* FIXME: handle packing_size and instance_size */
8415 typebuilder_setup_fields (klass);
8417 typebuilder_setup_properties (klass);
8419 typebuilder_setup_events (klass);
8421 klass->wastypebuilder = TRUE;
8423 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8424 g_assert (res != (MonoReflectionType*)tb);
8429 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8431 MonoGenericParam *param;
8434 MONO_ARCH_SAVE_REGS;
8436 param = g_new0 (MonoGenericParam, 1);
8438 if (gparam->mbuilder) {
8439 if (!gparam->mbuilder->generic_container)
8440 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8441 param->owner = gparam->mbuilder->generic_container;
8442 } else if (gparam->tbuilder) {
8443 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8444 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8449 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8450 if (gparam->index >= count)
8453 container = nesting->generic_container;
8454 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8457 g_assert (container);
8458 param->owner = container;
8461 param->method = NULL;
8462 param->name = mono_string_to_utf8 (gparam->name);
8463 param->num = gparam->index;
8465 image = &gparam->tbuilder->module->dynamic_image->image;
8466 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8468 param->pklass->reflection_info = gparam;
8470 gparam->type.type = g_new0 (MonoType, 1);
8471 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8472 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8473 gparam->type.type->data.generic_param = param;
8477 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8479 MonoDynamicImage *assembly = sig->module->dynamic_image;
8480 guint32 na = mono_array_length (sig->arguments);
8485 MONO_ARCH_SAVE_REGS;
8487 p = buf = g_malloc (10 + na * 10);
8489 mono_metadata_encode_value (0x07, p, &p);
8490 mono_metadata_encode_value (na, p, &p);
8491 for (i = 0; i < na; ++i) {
8492 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8493 encode_reflection_type (assembly, type, p, &p);
8497 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8498 p = mono_array_addr (result, char, 0);
8499 memcpy (p, buf, buflen);
8506 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8508 MonoDynamicImage *assembly = sig->module->dynamic_image;
8509 guint32 na = mono_array_length (sig->arguments);
8514 MONO_ARCH_SAVE_REGS;
8516 p = buf = g_malloc (10 + na * 10);
8518 mono_metadata_encode_value (0x06, p, &p);
8519 for (i = 0; i < na; ++i) {
8520 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8521 encode_reflection_type (assembly, type, p, &p);
8525 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8526 p = mono_array_addr (result, char, 0);
8527 memcpy (p, buf, buflen);
8534 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8536 ReflectionMethodBuilder rmb;
8537 MonoMethodSignature *sig;
8540 sig = dynamic_method_to_signature (mb);
8542 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8545 * Resolve references.
8547 rmb.nrefs = mb->nrefs;
8548 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8549 for (i = 0; i < mb->nrefs; ++i) {
8550 gpointer ref = resolve_object (mb->module->image,
8551 mono_array_get (mb->refs, MonoObject*, i));
8554 mono_raise_exception (mono_get_exception_type_load (NULL));
8561 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8565 /* ilgen is no longer needed */
8570 * mono_reflection_lookup_dynamic_token:
8572 * Finish the Builder object pointed to by TOKEN and return the corresponding
8573 * runtime structure.
8576 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8578 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8581 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8584 return resolve_object (image, obj);
8588 resolve_object (MonoImage *image, MonoObject *obj)
8590 gpointer result = NULL;
8592 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8593 result = mono_string_intern ((MonoString*)obj);
8595 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8596 MonoReflectionType *tb = (MonoReflectionType*)obj;
8597 result = mono_class_from_mono_type (tb->type);
8599 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8600 result = ((MonoReflectionMethod*)obj)->method;
8602 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8603 result = ((MonoReflectionMethod*)obj)->method;
8605 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8606 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8607 result = mb->mhandle;
8609 /* Type is not yet created */
8610 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8612 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8615 * Hopefully this has been filled in by calling CreateType() on the
8619 * TODO: This won't work if the application finishes another
8620 * TypeBuilder instance instead of this one.
8622 result = mb->mhandle;
8624 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8625 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8627 result = cb->mhandle;
8629 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8631 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8632 result = cb->mhandle;
8634 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8635 result = ((MonoReflectionField*)obj)->field;
8637 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8638 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8639 result = fb->handle;
8642 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8644 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8645 result = fb->handle;
8647 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8648 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8651 klass = tb->type.type->data.klass;
8652 if (klass->wastypebuilder) {
8653 /* Already created */
8657 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8658 result = tb->type.type->data.klass;
8661 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8662 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8663 MonoMethodSignature *sig;
8666 if (helper->arguments)
8667 nargs = mono_array_length (helper->arguments);
8671 sig = mono_metadata_signature_alloc (image, nargs);
8672 sig->explicit_this = helper->call_conv & 64;
8673 sig->hasthis = helper->call_conv & 32;
8675 if (helper->call_conv == 0) /* unmanaged */
8676 sig->call_convention = helper->unmanaged_call_conv - 1;
8678 if (helper->call_conv & 0x02)
8679 sig->call_convention = MONO_CALL_VARARG;
8681 sig->call_convention = MONO_CALL_DEFAULT;
8683 sig->param_count = nargs;
8684 /* TODO: Copy type ? */
8685 sig->ret = helper->return_type->type;
8686 for (i = 0; i < nargs; ++i) {
8687 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8688 sig->params [i] = rt->type;
8693 g_print (obj->vtable->klass->name);
8694 g_assert_not_reached ();