2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
160 alloc_table (MonoDynamicTable *table, guint nrows)
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows) {
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
169 table->alloc_rows *= 2;
173 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
175 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
180 make_room_in_stream (MonoDynamicStream *stream, int size)
182 while (stream->alloc_size <= size) {
183 if (stream->alloc_size < 4096)
184 stream->alloc_size = 4096;
186 stream->alloc_size *= 2;
189 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
191 stream->data = ALLOC_ATOMIC (stream->alloc_size);
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
199 gpointer oldkey, oldval;
201 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202 return GPOINTER_TO_UINT (oldval);
204 len = strlen (str) + 1;
206 if (idx + len > sh->alloc_size)
207 make_room_in_stream (sh, idx + len);
210 * We strdup the string even if we already copy them in sh->data
211 * so that the string pointers in the hash remain valid even if
212 * we need to realloc sh->data. We may want to avoid that later.
214 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215 memcpy (sh->data + idx, str, len);
221 string_heap_init (MonoDynamicStream *sh)
224 sh->alloc_size = 4096;
225 sh->data = ALLOC_ATOMIC (4096);
226 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227 string_heap_insert (sh, "");
230 #if 0 /* never used */
232 string_heap_free (MonoDynamicStream *sh)
234 FREE_ATOMIC (sh->data);
235 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236 g_hash_table_destroy (sh->hash);
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memcpy (stream->data + stream->index, data, len);
248 stream->index += len;
250 * align index? Not without adding an additional param that controls it since
251 * we may store a blob value in pieces.
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
260 if (stream->alloc_size < stream->index + len)
261 make_room_in_stream (stream, stream->index + len);
262 memset (stream->data + stream->index, 0, len);
264 stream->index += len;
269 stream_data_align (MonoDynamicStream *stream)
272 guint32 count = stream->index % 4;
274 /* we assume the stream data will be aligned */
276 mono_image_add_stream_data (stream, buf, 4 - count);
280 mono_blob_entry_hash (const char* str)
284 len = mono_metadata_decode_blob_size (str, &str);
288 for (str += 1; str < end; str++)
289 h = (h << 5) - h + *str;
297 mono_blob_entry_equal (const char *str1, const char *str2) {
301 len = mono_metadata_decode_blob_size (str1, &end1);
302 len2 = mono_metadata_decode_blob_size (str2, &end2);
305 return memcmp (end1, end2, len) == 0;
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
313 gpointer oldkey, oldval;
315 copy = ALLOC_ATOMIC (s1+s2);
316 memcpy (copy, b1, s1);
317 memcpy (copy + s1, b2, s2);
318 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
320 idx = GPOINTER_TO_UINT (oldval);
322 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323 mono_image_add_stream_data (&assembly->blob, b2, s2);
324 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
330 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331 * dest may be misaligned.
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
338 for (elem = 0; elem < nelem; ++elem) {
364 g_assert_not_reached ();
370 memcpy (dest, val, len * nelem);
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
379 guint32 idx = 0, len;
381 len = str->length * 2;
382 mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
385 char *swapped = g_malloc (2 * mono_string_length (str));
386 const char *p = (const char*)mono_string_chars (str);
388 swap_with_size (swapped, p, 2, mono_string_length (str));
389 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
393 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
398 /* modified version needed to handle building corlib */
400 my_mono_class_from_mono_type (MonoType *type) {
401 switch (type->type) {
402 case MONO_TYPE_ARRAY:
404 case MONO_TYPE_SZARRAY:
405 case MONO_TYPE_GENERICINST:
406 return mono_class_from_mono_type (type);
409 g_assert (type->data.generic_param->pklass);
410 return type->data.generic_param->pklass;
412 /* should be always valid when we reach this case... */
413 return type->data.klass;
418 default_class_from_mono_type (MonoType *type)
420 switch (type->type) {
421 case MONO_TYPE_OBJECT:
422 return mono_defaults.object_class;
424 return mono_defaults.void_class;
425 case MONO_TYPE_BOOLEAN:
426 return mono_defaults.boolean_class;
428 return mono_defaults.char_class;
430 return mono_defaults.sbyte_class;
432 return mono_defaults.byte_class;
434 return mono_defaults.int16_class;
436 return mono_defaults.uint16_class;
438 return mono_defaults.int32_class;
440 return mono_defaults.uint32_class;
442 return mono_defaults.int_class;
444 return mono_defaults.uint_class;
446 return mono_defaults.int64_class;
448 return mono_defaults.uint64_class;
450 return mono_defaults.single_class;
452 return mono_defaults.double_class;
453 case MONO_TYPE_STRING:
454 return mono_defaults.string_class;
456 g_warning ("implement me 0x%02x\n", type->type);
457 g_assert_not_reached ();
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
469 g_assert_not_reached ();
473 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474 encode_type (assembly, ginst->generic_type, p, &p);
475 mono_metadata_encode_value (ginst->type_argc, p, &p);
476 for (i = 0; i < ginst->type_argc; ++i)
477 encode_type (assembly, ginst->type_argv [i], p, &p);
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
486 g_assert_not_reached ();
491 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
495 case MONO_TYPE_BOOLEAN:
509 case MONO_TYPE_STRING:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_TYPEDBYREF:
512 mono_metadata_encode_value (type->type, p, &p);
515 mono_metadata_encode_value (type->type, p, &p);
516 encode_type (assembly, type->data.type, p, &p);
518 case MONO_TYPE_SZARRAY:
519 mono_metadata_encode_value (type->type, p, &p);
520 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
522 case MONO_TYPE_VALUETYPE:
523 case MONO_TYPE_CLASS: {
524 MonoClass *k = mono_class_from_mono_type (type);
525 mono_metadata_encode_value (type->type, p, &p);
527 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528 * otherwise two typerefs could point to the same type, leading to
529 * verification errors.
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
534 case MONO_TYPE_ARRAY:
535 mono_metadata_encode_value (type->type, p, &p);
536 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537 mono_metadata_encode_value (type->data.array->rank, p, &p);
538 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539 mono_metadata_encode_value (0, p, &p);
541 case MONO_TYPE_GENERICINST:
542 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
546 mono_metadata_encode_value (type->type, p, &p);
547 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
550 g_error ("need to encode type %x", type->type);
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
559 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
563 encode_type (assembly, type->type, p, endbuf);
567 g_assert_not_reached ();
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
577 for (i = 0; i < mono_array_length (modreq); ++i) {
578 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_REQD;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
585 for (i = 0; i < mono_array_length (modopt); ++i) {
586 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587 *p = MONO_TYPE_CMOD_OPT;
589 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
602 g_assert_not_reached ();
605 size += 1 + type_get_signature_size (ginst->generic_type);
607 for (i = 0; i < ginst->type_argc; ++i)
608 size += type_get_signature_size (ginst->type_argv [i]);
614 type_get_signature_size (MonoType *type)
619 g_assert_not_reached ();
627 case MONO_TYPE_BOOLEAN:
641 case MONO_TYPE_STRING:
642 case MONO_TYPE_OBJECT:
643 case MONO_TYPE_TYPEDBYREF:
646 return size + 1 + type_get_signature_size (type->data.type);
647 case MONO_TYPE_SZARRAY:
648 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS:
652 case MONO_TYPE_ARRAY:
653 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654 case MONO_TYPE_GENERICINST:
655 return size + generic_inst_get_signature_size (type->data.generic_inst);
660 g_error ("need to encode type %x", type->type);
666 method_get_signature_size (MonoMethodSignature *sig)
671 size = type_get_signature_size (sig->ret);
672 for (i = 0; i < sig->param_count; i++)
673 size += type_get_signature_size (sig->params [i]);
675 if (sig->generic_param_count)
677 if (sig->sentinelpos >= 0)
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
689 guint32 nparams = sig->param_count;
690 guint32 size = 11 + method_get_signature_size (sig);
698 p = buf = g_malloc (size);
700 * FIXME: vararg, explicit_this, differenc call_conv values...
702 *p = sig->call_convention;
704 *p |= 0x20; /* hasthis */
705 if (sig->generic_param_count)
706 *p |= 0x10; /* generic */
708 if (sig->generic_param_count)
709 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710 mono_metadata_encode_value (nparams, p, &p);
711 encode_type (assembly, sig->ret, p, &p);
712 for (i = 0; i < nparams; ++i) {
713 if (i == sig->sentinelpos)
714 *p++ = MONO_TYPE_SENTINEL;
715 encode_type (assembly, sig->params [i], p, &p);
718 g_assert (p - buf < size);
719 mono_metadata_encode_value (p-buf, b, &b);
720 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
729 * FIXME: reuse code from method_encode_signature().
734 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
735 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737 guint32 size = 21 + nparams * 20 + notypes * 20;
742 p = buf = g_malloc (size);
743 /* LAMESPEC: all the call conv spec is foobared */
744 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745 if (mb->call_conv & 2)
746 *p |= 0x5; /* vararg */
747 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748 *p |= 0x20; /* hasthis */
750 *p |= 0x10; /* generic */
753 mono_metadata_encode_value (ngparams, p, &p);
754 mono_metadata_encode_value (nparams + notypes, p, &p);
755 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756 encode_reflection_type (assembly, mb->rtype, p, &p);
757 for (i = 0; i < nparams; ++i) {
758 MonoArray *modreq = NULL;
759 MonoArray *modopt = NULL;
760 MonoReflectionType *pt;
762 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
771 *p++ = MONO_TYPE_SENTINEL;
772 for (i = 0; i < notypes; ++i) {
773 MonoReflectionType *pt;
775 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776 encode_reflection_type (assembly, pt, p, &p);
780 g_assert (p - buf < size);
781 mono_metadata_encode_value (p-buf, b, &b);
782 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
790 MonoDynamicTable *table;
793 guint32 idx, sig_idx, size;
794 guint nl = mono_array_length (ilgen->locals);
801 p = buf = g_malloc (size);
802 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803 idx = table->next_idx ++;
805 alloc_table (table, table->rows);
806 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
808 mono_metadata_encode_value (0x07, p, &p);
809 mono_metadata_encode_value (nl, p, &p);
810 for (i = 0; i < nl; ++i) {
811 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
814 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
816 encode_reflection_type (assembly, lb->type, p, &p);
818 g_assert (p - buf < size);
819 mono_metadata_encode_value (p-buf, b, &b);
820 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
823 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
829 method_count_clauses (MonoReflectionILGen *ilgen)
831 guint32 num_clauses = 0;
834 MonoILExceptionInfo *ex_info;
835 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 if (ex_info->handlers)
838 num_clauses += mono_array_length (ex_info->handlers);
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
849 MonoExceptionClause *clauses;
850 MonoExceptionClause *clause;
851 MonoILExceptionInfo *ex_info;
852 MonoILExceptionBlock *ex_block;
853 guint32 finally_start;
854 int i, j, clause_index;;
856 clauses = g_new0 (MonoExceptionClause, num_clauses);
859 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861 finally_start = ex_info->start + ex_info->len;
862 g_assert (ex_info->handlers);
863 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865 clause = &(clauses [clause_index]);
867 clause->flags = ex_block->type;
868 clause->try_offset = ex_info->start;
870 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871 clause->try_len = finally_start - ex_info->start;
873 clause->try_len = ex_info->len;
874 clause->handler_offset = ex_block->start;
875 clause->handler_len = ex_block->len;
876 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878 if (ex_block->extype) {
879 mono_g_hash_table_insert (assembly->tokens,
880 GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
882 finally_start = ex_block->start + ex_block->len;
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
898 gint32 num_locals = 0;
899 gint32 num_exception = 0;
902 char fat_header [12];
905 guint32 local_sig = 0;
906 guint32 header_size = 12;
909 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
914 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
916 code = mb->ilgen->code;
917 code_size = mb->ilgen->code_len;
918 max_stack = mb->ilgen->max_stack;
919 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920 if (mb->ilgen->ex_handlers)
921 num_exception = method_count_clauses (mb->ilgen);
925 char *name = mono_string_to_utf8 (mb->name);
926 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
930 mono_raise_exception (exception);
933 code_size = mono_array_length (code);
934 max_stack = 8; /* we probably need to run a verifier on the code... */
937 stream_data_align (&assembly->code);
939 /* check for exceptions, maxstack, locals */
940 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
942 if (code_size < 64 && !(code_size & 1)) {
943 flags = (code_size << 2) | 0x2;
944 } else if (code_size < 32 && (code_size & 1)) {
945 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
949 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
953 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
954 return assembly->text_rva + idx;
958 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
960 * FIXME: need to set also the header size in fat_flags.
961 * (and more sects and init locals flags)
965 fat_flags |= METHOD_HEADER_MORE_SECTS;
967 fat_flags |= METHOD_HEADER_INIT_LOCALS;
968 fat_header [0] = fat_flags;
969 fat_header [1] = (header_size / 4 ) << 4;
970 shortp = (guint16*)(fat_header + 2);
971 *shortp = GUINT16_TO_LE (max_stack);
972 intp = (guint32*)(fat_header + 4);
973 *intp = GUINT32_TO_LE (code_size);
974 intp = (guint32*)(fat_header + 8);
975 *intp = GUINT32_TO_LE (local_sig);
976 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
977 /* add to the fixup todo list */
978 if (mb->ilgen && mb->ilgen->num_token_fixups)
979 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
983 unsigned char sheader [4];
984 MonoExceptionClause clause;
985 MonoILExceptionInfo * ex_info;
986 MonoILExceptionBlock * ex_block;
989 stream_data_align (&assembly->code);
990 /* always use fat format for now */
991 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
992 num_exception *= sizeof (MonoExceptionClause);
993 num_exception += 4; /* include the size of the header */
994 sheader [1] = num_exception & 0xff;
995 sheader [2] = (num_exception >> 8) & 0xff;
996 sheader [3] = (num_exception >> 16) & 0xff;
997 mono_image_add_stream_data (&assembly->code, sheader, 4);
998 /* fat header, so we are already aligned */
1000 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1001 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1002 if (ex_info->handlers) {
1003 int finally_start = ex_info->start + ex_info->len;
1004 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1005 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1006 clause.flags = GUINT32_TO_LE (ex_block->type);
1007 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1008 /* need fault, too, probably */
1009 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1010 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1012 clause.try_len = GUINT32_TO_LE (ex_info->len);
1013 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1014 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1015 finally_start = ex_block->start + ex_block->len;
1016 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1017 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1018 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1019 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1020 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1021 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1024 g_error ("No clauses for ex info block %d", i);
1028 return assembly->text_rva + idx;
1032 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1035 MonoDynamicTable *table;
1038 table = &assembly->tables [table_idx];
1040 g_assert (col < table->columns);
1042 values = table->values + table->columns;
1043 for (i = 1; i <= table->rows; ++i) {
1044 if (values [col] == token)
1046 values += table->columns;
1051 static GHashTable *dynamic_custom_attrs = NULL;
1053 static MonoCustomAttrInfo*
1054 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1057 MonoCustomAttrInfo *ainfo;
1058 MonoReflectionCustomAttr *cattr;
1062 /* FIXME: check in assembly the Run flag is set */
1064 count = mono_array_length (cattrs);
1066 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1068 ainfo->image = image;
1069 ainfo->num_attrs = count;
1070 for (i = 0; i < count; ++i) {
1071 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1072 ainfo->attrs [i].ctor = cattr->ctor->method;
1073 /* FIXME: might want to memdup the data here */
1074 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1075 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1082 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1084 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1089 if (!dynamic_custom_attrs)
1090 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1092 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1093 ainfo->cached = TRUE;
1097 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1099 /* they are cached, so we don't free them */
1100 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1106 * idx is the table index of the object
1107 * type is one of MONO_CUSTOM_ATTR_*
1110 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1112 MonoDynamicTable *table;
1113 MonoReflectionCustomAttr *cattr;
1115 guint32 count, i, token;
1117 char *p = blob_size;
1119 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1122 count = mono_array_length (cattrs);
1123 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1124 table->rows += count;
1125 alloc_table (table, table->rows);
1126 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1127 idx <<= MONO_CUSTOM_ATTR_BITS;
1129 for (i = 0; i < count; ++i) {
1130 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1131 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1132 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1133 type = mono_metadata_token_index (token);
1134 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1135 switch (mono_metadata_token_table (token)) {
1136 case MONO_TABLE_METHOD:
1137 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1139 case MONO_TABLE_MEMBERREF:
1140 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1143 g_warning ("got wrong token in custom attr");
1146 values [MONO_CUSTOM_ATTR_TYPE] = type;
1148 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1149 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1150 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1151 values += MONO_CUSTOM_ATTR_SIZE;
1157 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1159 MonoDynamicTable *table;
1161 guint32 count, i, idx;
1162 MonoReflectionPermissionSet *perm;
1167 count = mono_array_length (permissions);
1168 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1169 table->rows += count;
1170 alloc_table (table, table->rows);
1172 for (i = 0; i < mono_array_length (permissions); ++i) {
1173 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1175 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1177 idx = mono_metadata_token_index (parent_token);
1178 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1179 switch (mono_metadata_token_table (parent_token)) {
1180 case MONO_TABLE_TYPEDEF:
1181 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1183 case MONO_TABLE_METHOD:
1184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1186 case MONO_TABLE_ASSEMBLY:
1187 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1190 g_assert_not_reached ();
1193 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1194 values [MONO_DECL_SECURITY_PARENT] = idx;
1195 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1202 * Fill in the MethodDef and ParamDef tables for a method.
1203 * This is used for both normal methods and constructors.
1206 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1208 MonoDynamicTable *table;
1213 /* room in this table is already allocated */
1214 table = &assembly->tables [MONO_TABLE_METHOD];
1215 *mb->table_idx = table->next_idx ++;
1216 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1217 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1218 name = mono_string_to_utf8 (mb->name);
1219 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1221 values [MONO_METHOD_FLAGS] = mb->attrs;
1222 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1223 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1224 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1226 table = &assembly->tables [MONO_TABLE_PARAM];
1227 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1229 mono_image_add_decl_security (assembly,
1230 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1233 MonoDynamicTable *mtable;
1236 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1237 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1240 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1241 if (mono_array_get (mb->pinfo, gpointer, i))
1244 table->rows += count;
1245 alloc_table (table, table->rows);
1246 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1247 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1248 MonoReflectionParamBuilder *pb;
1249 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1250 values [MONO_PARAM_FLAGS] = pb->attrs;
1251 values [MONO_PARAM_SEQUENCE] = i;
1252 if (pb->name != NULL) {
1253 name = mono_string_to_utf8 (pb->name);
1254 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1257 values [MONO_PARAM_NAME] = 0;
1259 values += MONO_PARAM_SIZE;
1260 if (pb->marshal_info) {
1262 alloc_table (mtable, mtable->rows);
1263 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1264 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1265 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1267 pb->table_idx = table->next_idx++;
1268 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1269 guint32 field_type = 0;
1270 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1272 alloc_table (mtable, mtable->rows);
1273 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1274 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1275 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1276 mvalues [MONO_CONSTANT_TYPE] = field_type;
1277 mvalues [MONO_CONSTANT_PADDING] = 0;
1285 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mb->rtype;
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = mb->generic_params;
1291 rmb->opt_types = NULL;
1292 rmb->pinfo = mb->pinfo;
1293 rmb->attrs = mb->attrs;
1294 rmb->iattrs = mb->iattrs;
1295 rmb->call_conv = mb->call_conv;
1296 rmb->code = mb->code;
1297 rmb->type = mb->type;
1298 rmb->name = mb->name;
1299 rmb->table_idx = &mb->table_idx;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = mb->return_modreq;
1302 rmb->return_modopt = mb->return_modopt;
1303 rmb->param_modreq = mb->param_modreq;
1304 rmb->param_modopt = mb->param_modopt;
1305 rmb->permissions = mb->permissions;
1306 rmb->mhandle = mb->mhandle;
1311 rmb->charset = rmb->charset & 0xf;
1312 rmb->lasterr = rmb->charset & 0x40;
1313 rmb->native_cc = rmb->native_cc;
1314 rmb->dllentry = mb->dllentry;
1320 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1322 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1324 rmb->ilgen = mb->ilgen;
1325 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1326 rmb->parameters = mb->parameters;
1327 rmb->generic_params = NULL;
1328 rmb->opt_types = NULL;
1329 rmb->pinfo = mb->pinfo;
1330 rmb->attrs = mb->attrs;
1331 rmb->iattrs = mb->iattrs;
1332 rmb->call_conv = mb->call_conv;
1334 rmb->type = mb->type;
1335 rmb->name = mono_string_new (mono_domain_get (), name);
1336 rmb->table_idx = &mb->table_idx;
1337 rmb->init_locals = mb->init_locals;
1338 rmb->return_modreq = NULL;
1339 rmb->return_modopt = NULL;
1340 rmb->param_modreq = mb->param_modreq;
1341 rmb->param_modopt = mb->param_modopt;
1342 rmb->permissions = mb->permissions;
1343 rmb->mhandle = mb->mhandle;
1349 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = NULL;
1355 rmb->opt_types = NULL;
1357 rmb->attrs = mb->attrs;
1359 rmb->call_conv = mb->call_conv;
1362 rmb->name = mb->name;
1363 rmb->table_idx = NULL;
1364 rmb->init_locals = mb->init_locals;
1365 rmb->return_modreq = NULL;
1366 rmb->return_modopt = NULL;
1367 rmb->param_modreq = NULL;
1368 rmb->param_modopt = NULL;
1369 rmb->permissions = NULL;
1370 rmb->mhandle = mb->mhandle;
1376 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1378 MonoDynamicTable *table;
1381 ReflectionMethodBuilder rmb;
1384 reflection_methodbuilder_from_method_builder (&rmb, mb);
1386 mono_image_basic_method (&rmb, assembly);
1388 if (mb->dll) { /* It's a P/Invoke method */
1390 int charset = mb->charset & 0xf;
1391 int lasterr = mb->charset & 0x40;
1392 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1394 alloc_table (table, table->rows);
1395 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1396 /* map CharSet values to on-disk values */
1398 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1399 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1400 name = mono_string_to_utf8 (mb->dllentry);
1401 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1403 name = mono_string_to_utf8 (mb->dll);
1404 moduleref = string_heap_insert (&assembly->sheap, name);
1406 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1407 table = &assembly->tables [MONO_TABLE_MODULEREF];
1409 alloc_table (table, table->rows);
1410 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1411 values [MONO_IMPLMAP_SCOPE] = table->rows;
1415 if (mb->override_method) {
1416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1418 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1420 alloc_table (table, table->rows);
1421 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1422 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1423 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1425 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1426 switch (mono_metadata_token_table (tok)) {
1427 case MONO_TABLE_MEMBERREF:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1430 case MONO_TABLE_METHOD:
1431 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1434 g_assert_not_reached ();
1436 values [MONO_METHODIMPL_DECLARATION] = tok;
1439 if (mb->generic_params) {
1440 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1441 table->rows += mono_array_length (mb->generic_params);
1442 alloc_table (table, table->rows);
1443 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1444 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1446 mono_image_get_generic_param_info (
1447 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1454 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1456 ReflectionMethodBuilder rmb;
1458 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1460 mono_image_basic_method (&rmb, assembly);
1464 type_get_fully_qualified_name (MonoType *type) {
1465 char *name, *result;
1469 name = mono_type_get_name (type);
1470 klass = my_mono_class_from_mono_type (type);
1471 ta = klass->image->assembly;
1473 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1474 name, ta->aname.name,
1475 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1476 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1477 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1483 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1487 klass = my_mono_class_from_mono_type (type);
1489 return mono_type_get_name (type);
1490 ta = klass->image->assembly;
1491 if (ta == ass || klass->image == mono_defaults.corlib)
1492 return mono_type_get_name (type);
1494 return type_get_fully_qualified_name (type);
1498 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1500 char blob_size [64];
1501 char *b = blob_size;
1506 if (!assembly->save)
1509 p = buf = g_malloc (64);
1511 mono_metadata_encode_value (0x06, p, &p);
1512 /* encode custom attributes before the type */
1513 encode_type (assembly, type, p, &p);
1514 g_assert (p-buf < 64);
1515 mono_metadata_encode_value (p-buf, b, &b);
1516 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1522 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1524 char blob_size [64];
1525 char *b = blob_size;
1530 p = buf = g_malloc (64);
1532 mono_metadata_encode_value (0x06, p, &p);
1533 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1534 /* encode custom attributes before the type */
1535 encode_reflection_type (assembly, fb->type, p, &p);
1536 g_assert (p-buf < 64);
1537 mono_metadata_encode_value (p-buf, b, &b);
1538 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1544 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1545 char blob_size [64];
1546 char *b = blob_size;
1549 guint32 idx = 0, len = 0, dummy = 0;
1551 p = buf = g_malloc (64);
1553 *ret_type = MONO_TYPE_CLASS;
1555 box_val = (char*)&dummy;
1557 box_val = ((char*)val) + sizeof (MonoObject);
1558 *ret_type = val->vtable->klass->byval_arg.type;
1561 switch (*ret_type) {
1562 case MONO_TYPE_BOOLEAN:
1567 case MONO_TYPE_CHAR:
1582 case MONO_TYPE_VALUETYPE:
1583 if (val->vtable->klass->enumtype) {
1584 *ret_type = val->vtable->klass->enum_basetype->type;
1587 g_error ("we can't encode valuetypes");
1588 case MONO_TYPE_CLASS:
1590 case MONO_TYPE_STRING: {
1591 MonoString *str = (MonoString*)val;
1592 /* there is no signature */
1593 len = str->length * 2;
1594 mono_metadata_encode_value (len, b, &b);
1595 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1597 char *swapped = g_malloc (2 * mono_string_length (str));
1598 const char *p = (const char*)mono_string_chars (str);
1600 swap_with_size (swapped, p, 2, mono_string_length (str));
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1605 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1612 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1615 /* there is no signature */
1616 mono_metadata_encode_value (len, b, &b);
1617 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1618 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1619 swap_with_size (blob_size, box_val, len, 1);
1620 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1630 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1631 char blob_size [64];
1632 char *b = blob_size;
1633 char *p, *buf, *str;
1634 guint32 idx, len, bufsize = 256;
1636 p = buf = g_malloc (bufsize);
1638 switch (minfo->type) {
1639 case MONO_NATIVE_BYVALTSTR:
1640 case MONO_NATIVE_BYVALARRAY:
1641 mono_metadata_encode_value (minfo->type, p, &p);
1642 mono_metadata_encode_value (minfo->count, p, &p);
1644 case MONO_NATIVE_LPARRAY:
1645 mono_metadata_encode_value (minfo->type, p, &p);
1646 if (minfo->eltype || (minfo->count > 0)) {
1647 mono_metadata_encode_value (minfo->eltype, p, &p);
1648 if (minfo->count > 0) {
1649 mono_metadata_encode_value (0, p, &p);
1650 mono_metadata_encode_value (minfo->count, p, &p);
1654 case MONO_NATIVE_CUSTOM:
1655 mono_metadata_encode_value (minfo->type, p, &p);
1657 str = mono_string_to_utf8 (minfo->guid);
1659 mono_metadata_encode_value (len, p, &p);
1660 memcpy (p, str, len);
1664 mono_metadata_encode_value (0, p, &p);
1666 if (minfo->marshaltype) {
1667 str = mono_string_to_utf8 (minfo->marshaltype);
1669 mono_metadata_encode_value (len, p, &p);
1670 if (p + len >= buf + bufsize) {
1673 buf = g_realloc (buf, bufsize);
1676 memcpy (p, str, len);
1680 mono_metadata_encode_value (0, p, &p);
1682 if (minfo->marshaltyperef) {
1683 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1685 mono_metadata_encode_value (len, p, &p);
1686 if (p + len >= buf + bufsize) {
1689 buf = g_realloc (buf, bufsize);
1692 memcpy (p, str, len);
1696 mono_metadata_encode_value (0, p, &p);
1698 if (minfo->mcookie) {
1699 str = mono_string_to_utf8 (minfo->mcookie);
1701 mono_metadata_encode_value (len, p, &p);
1702 if (p + len >= buf + bufsize) {
1705 buf = g_realloc (buf, bufsize);
1708 memcpy (p, str, len);
1712 mono_metadata_encode_value (0, p, &p);
1716 mono_metadata_encode_value (minfo->type, p, &p);
1720 mono_metadata_encode_value (len, b, &b);
1721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1727 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1729 MonoDynamicTable *table;
1733 /* maybe this fixup should be done in the C# code */
1734 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1735 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1736 table = &assembly->tables [MONO_TABLE_FIELD];
1737 fb->table_idx = table->next_idx ++;
1738 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1739 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1740 name = mono_string_to_utf8 (fb->name);
1741 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1743 values [MONO_FIELD_FLAGS] = fb->attrs;
1744 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1746 if (fb->offset != -1) {
1747 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1751 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1752 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1754 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1755 guint32 field_type = 0;
1756 table = &assembly->tables [MONO_TABLE_CONSTANT];
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1760 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1761 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1762 values [MONO_CONSTANT_TYPE] = field_type;
1763 values [MONO_CONSTANT_PADDING] = 0;
1765 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1767 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1769 alloc_table (table, table->rows);
1770 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1771 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1773 * We store it in the code section because it's simpler for now.
1776 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1778 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1779 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1781 if (fb->marshal_info) {
1782 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1784 alloc_table (table, table->rows);
1785 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1786 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1787 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1792 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1796 char *b = blob_size;
1797 guint32 nparams = 0;
1798 MonoReflectionMethodBuilder *mb = fb->get_method;
1799 MonoReflectionMethodBuilder *smb = fb->set_method;
1800 guint32 idx, i, size;
1802 if (mb && mb->parameters)
1803 nparams = mono_array_length (mb->parameters);
1804 if (!mb && smb && smb->parameters)
1805 nparams = mono_array_length (smb->parameters) - 1;
1806 size = 24 + nparams * 10;
1807 buf = p = g_malloc (size);
1810 mono_metadata_encode_value (nparams, p, &p);
1812 encode_reflection_type (assembly, mb->rtype, p, &p);
1813 for (i = 0; i < nparams; ++i) {
1814 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1815 encode_reflection_type (assembly, pt, p, &p);
1818 /* the property type is the last param */
1819 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1820 for (i = 0; i < nparams; ++i) {
1821 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1822 encode_reflection_type (assembly, pt, p, &p);
1826 g_assert (p - buf < size);
1827 mono_metadata_encode_value (p-buf, b, &b);
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1834 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1836 MonoDynamicTable *table;
1839 guint num_methods = 0;
1843 * we need to set things in the following tables:
1844 * PROPERTYMAP (info already filled in _get_type_info ())
1845 * PROPERTY (rows already preallocated in _get_type_info ())
1846 * METHOD (method info already done with the generic method code)
1849 table = &assembly->tables [MONO_TABLE_PROPERTY];
1850 pb->table_idx = table->next_idx ++;
1851 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1852 name = mono_string_to_utf8 (pb->name);
1853 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1855 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1856 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1858 /* FIXME: we still don't handle 'other' methods */
1859 if (pb->get_method) num_methods ++;
1860 if (pb->set_method) num_methods ++;
1862 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1863 table->rows += num_methods;
1864 alloc_table (table, table->rows);
1866 if (pb->get_method) {
1867 semaidx = table->next_idx ++;
1868 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1869 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1870 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1871 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1873 if (pb->set_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1883 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1885 MonoDynamicTable *table;
1888 guint num_methods = 0;
1892 * we need to set things in the following tables:
1893 * EVENTMAP (info already filled in _get_type_info ())
1894 * EVENT (rows already preallocated in _get_type_info ())
1895 * METHOD (method info already done with the generic method code)
1898 table = &assembly->tables [MONO_TABLE_EVENT];
1899 eb->table_idx = table->next_idx ++;
1900 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1901 name = mono_string_to_utf8 (eb->name);
1902 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1904 values [MONO_EVENT_FLAGS] = eb->attrs;
1905 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1908 * FIXME: we still don't handle 'other' methods
1910 if (eb->add_method) num_methods ++;
1911 if (eb->remove_method) num_methods ++;
1912 if (eb->raise_method) num_methods ++;
1914 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1915 table->rows += num_methods;
1916 alloc_table (table, table->rows);
1918 if (eb->add_method) {
1919 semaidx = table->next_idx ++;
1920 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1921 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1922 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1923 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1925 if (eb->remove_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->raise_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1942 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1944 static MonoClass *NewConstraintAttr;
1945 static MonoMethod *NewConstraintAttr_ctor;
1946 MonoDynamicTable *table;
1948 guint32 token, type;
1949 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1952 if (!NewConstraintAttr)
1953 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1954 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1955 g_assert (NewConstraintAttr);
1957 if (!NewConstraintAttr_ctor) {
1960 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1961 MonoMethod *m = NewConstraintAttr->methods [i];
1963 if (strcmp (m->name, ".ctor"))
1966 NewConstraintAttr_ctor = m;
1970 g_assert (NewConstraintAttr_ctor);
1973 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1975 alloc_table (table, table->rows);
1977 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1978 owner <<= MONO_CUSTOM_ATTR_BITS;
1979 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1980 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1982 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1984 type = mono_metadata_token_index (token);
1985 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1986 switch (mono_metadata_token_table (token)) {
1987 case MONO_TABLE_METHOD:
1988 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1990 case MONO_TABLE_MEMBERREF:
1991 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1994 g_warning ("got wrong token in custom attr");
1997 values [MONO_CUSTOM_ATTR_TYPE] = type;
1999 buf = p = g_malloc (1);
2000 mono_metadata_encode_value (4, p, &p);
2001 g_assert (p-buf == 1);
2003 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2005 values += MONO_CUSTOM_ATTR_SIZE;
2010 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2013 guint32 num_constraints, i;
2017 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2018 num_constraints = gparam->iface_constraints ?
2019 mono_array_length (gparam->iface_constraints) : 0;
2020 table->rows += num_constraints;
2021 if (gparam->base_type)
2023 alloc_table (table, table->rows);
2025 if (gparam->base_type) {
2026 table_idx = table->next_idx ++;
2027 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2029 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2030 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2031 assembly, gparam->base_type->type);
2034 for (i = 0; i < num_constraints; i++) {
2035 MonoReflectionType *constraint = mono_array_get (
2036 gparam->iface_constraints, gpointer, i);
2038 table_idx = table->next_idx ++;
2039 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2041 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2042 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2043 assembly, constraint->type);
2046 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2047 encode_new_constraint (assembly, owner);
2051 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2053 GenericParamTableEntry *entry;
2056 * The GenericParam table must be sorted according to the `owner' field.
2057 * We need to do this sorting prior to writing the GenericParamConstraint
2058 * table, since we have to use the final GenericParam table indices there
2059 * and they must also be sorted.
2062 entry = g_new0 (GenericParamTableEntry, 1);
2063 entry->owner = owner;
2064 entry->gparam = gparam;
2066 g_ptr_array_add (assembly->gen_params, entry);
2070 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2072 MonoDynamicTable *table;
2073 MonoGenericParam *param;
2077 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2078 table_idx = table->next_idx ++;
2079 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2081 param = entry->gparam->type.type->data.generic_param;
2083 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2084 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2085 values [MONO_GENERICPARAM_NUMBER] = param->num;
2086 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2087 values [MONO_GENERICPARAM_KIND] = 0;
2089 encode_constraints (entry->gparam, table_idx, assembly);
2093 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2095 MonoDynamicTable *table;
2098 guint32 cols [MONO_ASSEMBLY_SIZE];
2102 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2105 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2106 table = &assembly->tables [MONO_TABLE_MODULEREF];
2107 token = table->next_idx ++;
2109 alloc_table (table, table->rows);
2110 values = table->values + token * MONO_MODULEREF_SIZE;
2111 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2113 token <<= MONO_RESOLTION_SCOPE_BITS;
2114 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2115 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2120 if (image->assembly->dynamic)
2122 memset (cols, 0, sizeof (cols));
2124 /* image->assembly->image is the manifest module */
2125 image = image->assembly->image;
2126 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2129 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2130 token = table->next_idx ++;
2132 alloc_table (table, table->rows);
2133 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2134 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2135 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2136 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2137 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2138 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2139 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2140 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2141 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2143 if (strcmp ("", image->assembly->aname.culture)) {
2144 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2145 image->assembly->aname.culture);
2148 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2149 guchar pubtoken [9];
2151 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2152 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2154 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2156 token <<= MONO_RESOLTION_SCOPE_BITS;
2157 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2158 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2163 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2165 MonoDynamicTable *table;
2171 char *b = blob_size;
2173 switch (type->type) {
2174 case MONO_TYPE_FNPTR:
2176 case MONO_TYPE_SZARRAY:
2177 case MONO_TYPE_ARRAY:
2179 case MONO_TYPE_MVAR:
2180 case MONO_TYPE_GENERICINST:
2181 encode_type (assembly, type, p, &p);
2183 case MONO_TYPE_CLASS:
2184 case MONO_TYPE_VALUETYPE: {
2185 MonoClass *k = mono_class_from_mono_type (type);
2186 if (!k || !k->generic_inst)
2188 encode_generic_inst (assembly, k->generic_inst, p, &p);
2195 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2196 if (assembly->save) {
2197 g_assert (p-sig < 128);
2198 mono_metadata_encode_value (p-sig, b, &b);
2199 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2200 alloc_table (table, table->rows + 1);
2201 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2202 values [MONO_TYPESPEC_SIGNATURE] = token;
2205 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2206 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2212 * Despite the name, we handle also TypeSpec (with the above helper).
2215 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2217 MonoDynamicTable *table;
2219 guint32 token, scope, enclosing;
2222 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2225 token = create_typespec (assembly, type);
2228 klass = my_mono_class_from_mono_type (type);
2230 klass = mono_class_from_mono_type (type);
2233 * If it's in the same module and not a generic type parameter:
2235 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2236 (type->type != MONO_TYPE_MVAR)) {
2237 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2238 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2239 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2243 if (klass->nested_in) {
2244 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2245 /* get the typeref idx of the enclosing type */
2246 enclosing >>= MONO_TYPEDEFORREF_BITS;
2247 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2249 scope = resolution_scope_from_image (assembly, klass->image);
2251 table = &assembly->tables [MONO_TABLE_TYPEREF];
2252 if (assembly->save) {
2253 alloc_table (table, table->rows + 1);
2254 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2255 values [MONO_TYPEREF_SCOPE] = scope;
2256 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2257 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2259 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2260 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2262 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2267 * Insert a memberef row into the metadata: the token that point to the memberref
2268 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2269 * mono_image_get_fieldref_token()).
2270 * The sig param is an index to an already built signature.
2273 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2275 MonoDynamicTable *table;
2277 guint32 token, pclass;
2280 parent = mono_image_typedef_or_ref (assembly, type);
2281 switch (parent & MONO_TYPEDEFORREF_MASK) {
2282 case MONO_TYPEDEFORREF_TYPEREF:
2283 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2285 case MONO_TYPEDEFORREF_TYPESPEC:
2286 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2288 case MONO_TYPEDEFORREF_TYPEDEF:
2289 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2292 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2295 /* extract the index */
2296 parent >>= MONO_TYPEDEFORREF_BITS;
2298 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2300 if (assembly->save) {
2301 alloc_table (table, table->rows + 1);
2302 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2303 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2304 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2305 values [MONO_MEMBERREF_SIGNATURE] = sig;
2308 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2315 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2318 MonoMethodSignature *sig;
2320 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2325 * A methodref signature can't contain an unmanaged calling convention.
2327 sig = mono_metadata_signature_dup (method->signature);
2328 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2329 sig->call_convention = MONO_CALL_DEFAULT;
2330 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2331 method->name, method_encode_signature (assembly, sig));
2333 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2338 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2339 const gchar *name, guint32 sig)
2341 MonoDynamicTable *table;
2345 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2347 if (assembly->save) {
2348 alloc_table (table, table->rows + 1);
2349 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2350 values [MONO_MEMBERREF_CLASS] = original;
2351 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2352 values [MONO_MEMBERREF_SIGNATURE] = sig;
2355 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2362 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2365 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2371 reflection_methodbuilder_from_method_builder (&rmb, mb);
2373 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2374 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2375 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2380 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2383 ReflectionMethodBuilder rmb;
2385 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2389 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2391 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2392 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2393 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2398 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2403 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2406 g_assert (f->field->parent);
2407 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2408 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2409 f->field->name, fieldref_encode_signature (assembly, type));
2410 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2420 guint32 nparams = gmethod->mtype_argc;
2421 guint32 size = 10 + nparams * 10;
2424 char *b = blob_size;
2426 if (!assembly->save)
2429 p = buf = g_malloc (size);
2431 * FIXME: vararg, explicit_this, differenc call_conv values...
2433 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2434 mono_metadata_encode_value (nparams, p, &p);
2436 for (i = 0; i < nparams; i++)
2437 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2440 g_assert (p - buf < size);
2441 mono_metadata_encode_value (p-buf, b, &b);
2442 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2450 MonoDynamicTable *table;
2452 guint32 token, mtoken = 0, sig;
2453 MonoMethodInflated *imethod;
2454 MonoMethod *declaring;
2456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2458 g_assert (method->signature->is_inflated);
2459 imethod = (MonoMethodInflated *) method;
2460 declaring = imethod->declaring;
2462 sig = method_encode_signature (assembly, declaring->signature);
2463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2465 if (!declaring->signature->generic_param_count)
2468 switch (mono_metadata_token_table (mtoken)) {
2469 case MONO_TABLE_MEMBERREF:
2470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2472 case MONO_TABLE_METHOD:
2473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2476 g_assert_not_reached ();
2479 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2481 if (assembly->save) {
2482 alloc_table (table, table->rows + 1);
2483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2484 values [MONO_METHODSPEC_METHOD] = mtoken;
2485 values [MONO_METHODSPEC_SIGNATURE] = sig;
2488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2497 MonoMethodInflated *imethod;
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2504 g_assert (m->signature->is_inflated);
2505 imethod = (MonoMethodInflated *) m;
2507 if (imethod->declaring->signature->generic_param_count) {
2508 token = method_encode_methodspec (assembly, m);
2510 guint32 sig = method_encode_signature (
2511 assembly, imethod->declaring->signature);
2512 token = mono_image_get_memberref_token (
2513 assembly, &m->klass->byval_arg, m->name, sig);
2516 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2526 sig = method_encode_signature (assembly, imethod->declaring->signature);
2527 token = mono_image_get_memberref_token (
2528 assembly, &m->klass->byval_arg, m->name, sig);
2534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2536 MonoDynamicTable *table;
2543 char *b = blob_size;
2547 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2548 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2549 * Because of this, we must not insert it into the `typeref' hash table.
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2556 g_assert (tb->generic_params);
2557 klass = mono_class_from_mono_type (tb->type.type);
2559 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2560 encode_type (assembly, &klass->byval_arg, p, &p);
2562 count = mono_array_length (tb->generic_params);
2563 mono_metadata_encode_value (count, p, &p);
2564 for (i = 0; i < count; i++) {
2565 MonoReflectionGenericParam *gparam;
2567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2569 encode_type (assembly, gparam->type.type, p, &p);
2572 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2573 if (assembly->save) {
2574 g_assert (p-sig < 128);
2575 mono_metadata_encode_value (p-sig, b, &b);
2576 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2579 values [MONO_TYPESPEC_SIGNATURE] = token;
2582 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2591 MonoDynamicTable *table;
2594 guint32 token, pclass, parent, sig;
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2601 klass = mono_class_from_mono_type (fb->typeb->type);
2602 name = mono_string_to_utf8 (fb->name);
2604 sig = fieldref_encode_signature (assembly, fb->type->type);
2606 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2609 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610 parent >>= MONO_TYPEDEFORREF_BITS;
2612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2614 if (assembly->save) {
2615 alloc_table (table, table->rows + 1);
2616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619 values [MONO_MEMBERREF_SIGNATURE] = sig;
2622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2624 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2637 char *b = blob_size;
2639 if (!assembly->save)
2643 g_assert (helper->type == 2);
2645 if (helper->arguments)
2646 nargs = mono_array_length (helper->arguments);
2650 size = 10 + (nargs * 10);
2652 p = buf = g_malloc (size);
2654 /* Encode calling convention */
2655 /* Change Any to Standard */
2656 if ((helper->call_conv & 0x03) == 0x03)
2657 helper->call_conv = 0x01;
2658 /* explicit_this implies has_this */
2659 if (helper->call_conv & 0x40)
2660 helper->call_conv &= 0x20;
2662 if (helper->call_conv == 0) { /* Unmanaged */
2663 *p = helper->unmanaged_call_conv - 1;
2666 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2667 if (helper->call_conv & 0x02) /* varargs */
2672 mono_metadata_encode_value (nargs, p, &p);
2673 encode_reflection_type (assembly, helper->return_type, p, &p);
2674 for (i = 0; i < nargs; ++i) {
2675 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2676 encode_reflection_type (assembly, pt, p, &p);
2679 g_assert (p - buf < size);
2680 mono_metadata_encode_value (p-buf, b, &b);
2681 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2688 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2691 MonoDynamicTable *table;
2694 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2695 idx = table->next_idx ++;
2697 alloc_table (table, table->rows);
2698 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2700 values [MONO_STAND_ALONE_SIGNATURE] =
2701 mono_reflection_encode_sighelper (assembly, helper);
2707 reflection_cc_to_file (int call_conv) {
2708 switch (call_conv & 0x3) {
2710 case 1: return MONO_CALL_DEFAULT;
2711 case 2: return MONO_CALL_VARARG;
2713 g_assert_not_reached ();
2720 MonoMethodSignature *sig;
2726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2731 MonoMethodSignature *sig;
2734 name = mono_string_to_utf8 (m->name);
2735 nparams = mono_array_length (m->parameters);
2736 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2738 sig->sentinelpos = -1;
2739 sig->call_convention = reflection_cc_to_file (m->call_conv);
2740 sig->param_count = nparams;
2741 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2742 for (i = 0; i < nparams; ++i) {
2743 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2744 sig->params [i] = t->type;
2747 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2749 if (strcmp (name, am->name) == 0 &&
2750 mono_metadata_type_equal (am->parent, m->parent->type) &&
2751 mono_metadata_signature_equal (am->sig, sig)) {
2754 m->table_idx = am->token & 0xffffff;
2758 am = g_new0 (ArrayMethod, 1);
2761 am->parent = m->parent->type;
2762 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2763 method_encode_signature (assembly, sig));
2764 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2765 m->table_idx = am->token & 0xffffff;
2770 * Insert into the metadata tables all the info about the TypeBuilder tb.
2771 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2774 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2776 MonoDynamicTable *table;
2778 int i, is_object = 0, is_system = 0;
2781 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2782 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2783 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2784 n = mono_string_to_utf8 (tb->name);
2785 if (strcmp (n, "Object") == 0)
2787 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2789 n = mono_string_to_utf8 (tb->nspace);
2790 if (strcmp (n, "System") == 0)
2792 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2794 if (tb->parent && !(is_system && is_object) &&
2795 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2796 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2798 values [MONO_TYPEDEF_EXTENDS] = 0;
2800 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2801 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2804 * if we have explicitlayout or sequentiallayouts, output data in the
2805 * ClassLayout table.
2807 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2808 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2809 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2811 alloc_table (table, table->rows);
2812 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2813 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2814 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2815 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2818 /* handle interfaces */
2819 if (tb->interfaces) {
2820 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2822 table->rows += mono_array_length (tb->interfaces);
2823 alloc_table (table, table->rows);
2824 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2825 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2826 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2827 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2828 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2829 values += MONO_INTERFACEIMPL_SIZE;
2835 table = &assembly->tables [MONO_TABLE_FIELD];
2836 table->rows += tb->num_fields;
2837 alloc_table (table, table->rows);
2838 for (i = 0; i < tb->num_fields; ++i)
2839 mono_image_get_field_info (
2840 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2843 /* handle constructors */
2845 table = &assembly->tables [MONO_TABLE_METHOD];
2846 table->rows += mono_array_length (tb->ctors);
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2849 mono_image_get_ctor_info (domain,
2850 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2853 /* handle methods */
2855 table = &assembly->tables [MONO_TABLE_METHOD];
2856 table->rows += tb->num_methods;
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < tb->num_methods; ++i)
2859 mono_image_get_method_info (
2860 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2863 /* Do the same with properties etc.. */
2864 if (tb->events && mono_array_length (tb->events)) {
2865 table = &assembly->tables [MONO_TABLE_EVENT];
2866 table->rows += mono_array_length (tb->events);
2867 alloc_table (table, table->rows);
2868 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2870 alloc_table (table, table->rows);
2871 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2872 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2873 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2874 for (i = 0; i < mono_array_length (tb->events); ++i)
2875 mono_image_get_event_info (
2876 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2878 if (tb->properties && mono_array_length (tb->properties)) {
2879 table = &assembly->tables [MONO_TABLE_PROPERTY];
2880 table->rows += mono_array_length (tb->properties);
2881 alloc_table (table, table->rows);
2882 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2884 alloc_table (table, table->rows);
2885 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2886 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2887 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2888 for (i = 0; i < mono_array_length (tb->properties); ++i)
2889 mono_image_get_property_info (
2890 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2893 /* handle generic parameters */
2894 if (tb->generic_params) {
2895 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2896 table->rows += mono_array_length (tb->generic_params);
2897 alloc_table (table, table->rows);
2898 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2899 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2901 mono_image_get_generic_param_info (
2902 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2906 mono_image_add_decl_security (assembly,
2907 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2910 MonoDynamicTable *ntable;
2912 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2913 ntable->rows += mono_array_length (tb->subtypes);
2914 alloc_table (ntable, ntable->rows);
2915 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2917 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2918 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2920 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2921 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2922 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2923 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2924 mono_string_to_utf8 (tb->name), tb->table_idx,
2925 ntable->next_idx, ntable->rows);*/
2926 values += MONO_NESTED_CLASS_SIZE;
2933 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2937 g_ptr_array_add (types, type);
2939 if (!type->subtypes)
2942 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2943 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2944 collect_types (types, subtype);
2949 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2951 if ((*type1)->table_idx < (*type2)->table_idx)
2954 if ((*type1)->table_idx > (*type2)->table_idx)
2961 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2966 for (i = 0; i < mono_array_length (pinfo); ++i) {
2967 MonoReflectionParamBuilder *pb;
2968 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2971 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2976 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2979 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2981 for (i = 0; i < tb->num_fields; ++i) {
2982 MonoReflectionFieldBuilder* fb;
2983 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2984 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2988 for (i = 0; i < mono_array_length (tb->events); ++i) {
2989 MonoReflectionEventBuilder* eb;
2990 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2991 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2994 if (tb->properties) {
2995 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2996 MonoReflectionPropertyBuilder* pb;
2997 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2998 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3002 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3003 MonoReflectionCtorBuilder* cb;
3004 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3005 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3006 params_add_cattrs (assembly, cb->pinfo);
3011 for (i = 0; i < tb->num_methods; ++i) {
3012 MonoReflectionMethodBuilder* mb;
3013 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3014 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3015 params_add_cattrs (assembly, mb->pinfo);
3020 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3021 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3026 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3031 /* no types in the module */
3035 for (i = 0; i < mb->num_types; ++i)
3036 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3040 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3042 MonoDynamicTable *table;
3046 char *b = blob_size;
3049 table = &assembly->tables [MONO_TABLE_FILE];
3051 alloc_table (table, table->rows);
3052 values = table->values + table->next_idx * MONO_FILE_SIZE;
3053 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3054 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3055 if (module->image->dynamic) {
3056 /* This depends on the fact that the main module is emitted last */
3057 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3058 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3061 path = g_strdup (module->image->name);
3063 mono_sha1_get_digest_from_file (path, hash);
3066 mono_metadata_encode_value (20, b, &b);
3067 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3068 mono_image_add_stream_data (&assembly->blob, hash, 20);
3073 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3079 table = &assembly->tables [MONO_TABLE_MODULE];
3080 mb->table_idx = table->next_idx ++;
3081 name = mono_string_to_utf8 (mb->module.name);
3082 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3084 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3088 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3093 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3094 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3096 MonoDynamicTable *table;
3100 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3101 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3104 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3106 alloc_table (table, table->rows);
3107 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3109 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3110 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3111 if (klass->nested_in)
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3114 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3115 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3116 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3118 res = table->next_idx;
3122 /* Emit nested types */
3123 if (klass->nested_classes) {
3126 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3127 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3134 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3135 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3140 klass = mono_class_from_mono_type (tb->type.type);
3142 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3144 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3145 parent_index, assembly);
3149 * We need to do this ourselves since klass->nested_classes is not set up.
3152 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3153 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3158 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3159 guint32 module_index, MonoDynamicImage *assembly)
3161 MonoImage *image = module->image;
3165 t = &image->tables [MONO_TABLE_TYPEDEF];
3167 for (i = 0; i < t->rows; ++i) {
3168 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3170 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3171 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3175 #define align_pointer(base,p)\
3177 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3179 (p) += 4 - (__diff & 3);\
3183 compare_semantics (const void *a, const void *b)
3185 const guint32 *a_values = a;
3186 const guint32 *b_values = b;
3187 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3190 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3194 compare_custom_attrs (const void *a, const void *b)
3196 const guint32 *a_values = a;
3197 const guint32 *b_values = b;
3199 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3203 compare_field_marshal (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3208 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3212 compare_nested (const void *a, const void *b)
3214 const guint32 *a_values = a;
3215 const guint32 *b_values = b;
3217 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3221 compare_genericparam (const void *a, const void *b)
3223 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3224 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3226 return (*a_entry)->owner - (*b_entry)->owner;
3230 compare_declsecurity_attrs (const void *a, const void *b)
3232 const guint32 *a_values = a;
3233 const guint32 *b_values = b;
3235 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3239 pad_heap (MonoDynamicStream *sh)
3241 if (sh->index & 3) {
3242 int sz = 4 - (sh->index & 3);
3243 memset (sh->data + sh->index, 0, sz);
3250 MonoDynamicStream *stream;
3254 * build_compressed_metadata() fills in the blob of data that represents the
3255 * raw metadata as it will be saved in the PE file. The five streams are output
3256 * and the metadata tables are comnpressed from the guint32 array representation,
3257 * to the compressed on-disk format.
3260 build_compressed_metadata (MonoDynamicImage *assembly)
3262 MonoDynamicTable *table;
3264 guint64 valid_mask = 0;
3265 guint64 sorted_mask;
3266 guint32 heapt_size = 0;
3267 guint32 meta_size = 256; /* allow for header and other stuff */
3268 guint32 table_offset;
3269 guint32 ntables = 0;
3275 struct StreamDesc stream_desc [5];
3277 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3278 for (i = 0; i < assembly->gen_params->len; i++){
3279 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3280 write_generic_param_entry (assembly, entry);
3283 stream_desc [0].name = "#~";
3284 stream_desc [0].stream = &assembly->tstream;
3285 stream_desc [1].name = "#Strings";
3286 stream_desc [1].stream = &assembly->sheap;
3287 stream_desc [2].name = "#US";
3288 stream_desc [2].stream = &assembly->us;
3289 stream_desc [3].name = "#Blob";
3290 stream_desc [3].stream = &assembly->blob;
3291 stream_desc [4].name = "#GUID";
3292 stream_desc [4].stream = &assembly->guid;
3294 /* tables that are sorted */
3295 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3296 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3297 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3298 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3299 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3300 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3302 /* Compute table sizes */
3303 /* the MonoImage has already been created in mono_image_basic_init() */
3304 meta = &assembly->image;
3306 /* sizes should be multiple of 4 */
3307 pad_heap (&assembly->blob);
3308 pad_heap (&assembly->guid);
3309 pad_heap (&assembly->sheap);
3310 pad_heap (&assembly->us);
3312 /* Setup the info used by compute_sizes () */
3313 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3314 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3315 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3317 meta_size += assembly->blob.index;
3318 meta_size += assembly->guid.index;
3319 meta_size += assembly->sheap.index;
3320 meta_size += assembly->us.index;
3322 for (i=0; i < 64; ++i)
3323 meta->tables [i].rows = assembly->tables [i].rows;
3325 for (i = 0; i < 64; i++){
3326 if (meta->tables [i].rows == 0)
3328 valid_mask |= (guint64)1 << i;
3330 meta->tables [i].row_size = mono_metadata_compute_size (
3331 meta, i, &meta->tables [i].size_bitfield);
3332 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3334 heapt_size += 24; /* #~ header size */
3335 heapt_size += ntables * 4;
3336 /* make multiple of 4 */
3339 meta_size += heapt_size;
3340 meta->raw_metadata = g_malloc0 (meta_size);
3341 p = meta->raw_metadata;
3342 /* the metadata signature */
3343 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3344 /* version numbers and 4 bytes reserved */
3345 int16val = (guint16*)p;
3346 *int16val++ = GUINT16_TO_LE (1);
3347 *int16val = GUINT16_TO_LE (1);
3349 /* version string */
3350 int32val = (guint32*)p;
3351 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3353 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3354 p += GUINT32_FROM_LE (*int32val);
3355 align_pointer (meta->raw_metadata, p);
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3358 *int16val = GUINT16_TO_LE (5); /* number of streams */
3362 * write the stream info.
3364 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3365 table_offset += 3; table_offset &= ~3;
3367 assembly->tstream.index = heapt_size;
3368 for (i = 0; i < 5; ++i) {
3369 int32val = (guint32*)p;
3370 stream_desc [i].stream->offset = table_offset;
3371 *int32val++ = GUINT32_TO_LE (table_offset);
3372 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3373 table_offset += GUINT32_FROM_LE (*int32val);
3374 table_offset += 3; table_offset &= ~3;
3376 strcpy (p, stream_desc [i].name);
3377 p += strlen (stream_desc [i].name) + 1;
3378 align_pointer (meta->raw_metadata, p);
3381 * now copy the data, the table stream header and contents goes first.
3383 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3384 p = meta->raw_metadata + assembly->tstream.offset;
3385 int32val = (guint32*)p;
3386 *int32val = GUINT32_TO_LE (0); /* reserved */
3389 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3390 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3391 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3392 *p++ = 1; /* version */
3395 *p++ = 1; /* version */
3399 if (meta->idx_string_wide)
3401 if (meta->idx_guid_wide)
3403 if (meta->idx_blob_wide)
3406 *p++ = 0; /* reserved */
3407 int64val = (guint64*)p;
3408 *int64val++ = GUINT64_TO_LE (valid_mask);
3409 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3411 int32val = (guint32*)p;
3412 for (i = 0; i < 64; i++){
3413 if (meta->tables [i].rows == 0)
3415 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3417 p = (unsigned char*)int32val;
3419 /* sort the tables that still need sorting */
3420 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3422 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3423 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3425 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3426 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3428 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3429 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3431 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3432 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3433 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3435 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3437 /* compress the tables */
3438 for (i = 0; i < 64; i++){
3441 guint32 bitfield = meta->tables [i].size_bitfield;
3442 if (!meta->tables [i].rows)
3444 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3445 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3446 meta->tables [i].base = p;
3447 for (row = 1; row <= meta->tables [i].rows; ++row) {
3448 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3449 for (col = 0; col < assembly->tables [i].columns; ++col) {
3450 switch (mono_metadata_table_size (bitfield, col)) {
3452 *p++ = values [col];
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3459 *p++ = values [col] & 0xff;
3460 *p++ = (values [col] >> 8) & 0xff;
3461 *p++ = (values [col] >> 16) & 0xff;
3462 *p++ = (values [col] >> 24) & 0xff;
3465 g_assert_not_reached ();
3469 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3472 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3473 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3474 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3475 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3476 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3478 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 * Some tables in metadata need to be sorted according to some criteria, but
3483 * when methods and fields are first created with reflection, they may be assigned a token
3484 * that doesn't correspond to the final token they will get assigned after the sorting.
3485 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3486 * with the reflection objects that represent them. Once all the tables are set up, the
3487 * reflection objects will contains the correct table index. fixup_method() will fixup the
3488 * tokens for the method with ILGenerator @ilgen.
3491 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3492 guint32 code_idx = GPOINTER_TO_UINT (value);
3493 MonoReflectionILTokenInfo *iltoken;
3494 MonoReflectionFieldBuilder *field;
3495 MonoReflectionCtorBuilder *ctor;
3496 MonoReflectionMethodBuilder *method;
3497 MonoReflectionTypeBuilder *tb;
3498 MonoReflectionArrayMethod *am;
3500 unsigned char *target;
3502 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3503 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3504 target = assembly->code.data + code_idx + iltoken->code_pos;
3505 switch (target [3]) {
3506 case MONO_TABLE_FIELD:
3507 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3508 field = (MonoReflectionFieldBuilder *)iltoken->member;
3509 idx = field->table_idx;
3510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3511 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3512 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3514 g_assert_not_reached ();
3517 case MONO_TABLE_METHOD:
3518 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3519 method = (MonoReflectionMethodBuilder *)iltoken->member;
3520 idx = method->table_idx;
3521 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3522 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3523 idx = ctor->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3525 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3526 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3527 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3529 g_assert_not_reached ();
3532 case MONO_TABLE_TYPEDEF:
3533 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3534 g_assert_not_reached ();
3535 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3536 idx = tb->table_idx;
3538 case MONO_TABLE_MEMBERREF:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3540 am = (MonoReflectionArrayMethod*)iltoken->member;
3541 idx = am->table_idx;
3542 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3543 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3544 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3545 g_assert (m->klass->generic_inst);
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3550 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3551 g_assert (f->generic_info);
3553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3556 g_assert_not_reached ();
3559 case MONO_TABLE_METHODSPEC:
3560 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3561 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3562 g_assert (m->signature->generic_param_count);
3565 g_assert_not_reached ();
3569 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3571 target [0] = idx & 0xff;
3572 target [1] = (idx >> 8) & 0xff;
3573 target [2] = (idx >> 16) & 0xff;
3580 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3581 * value is not known when the table is emitted.
3584 fixup_cattrs (MonoDynamicImage *assembly)
3586 MonoDynamicTable *table;
3588 guint32 type, i, idx, token;
3591 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3593 for (i = 0; i < table->rows; ++i) {
3594 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3596 type = values [MONO_CUSTOM_ATTR_TYPE];
3597 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3598 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3599 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3600 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3603 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3604 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3605 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3606 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3613 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3615 MonoDynamicTable *table;
3619 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3621 alloc_table (table, table->rows);
3622 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3623 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3624 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3625 name = mono_string_to_utf8 (rsrc->name);
3626 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3628 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3633 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3635 MonoDynamicTable *table;
3639 char *b = blob_size;
3641 guint32 idx, offset;
3643 if (rsrc->filename) {
3644 name = mono_string_to_utf8 (rsrc->filename);
3645 sname = g_path_get_basename (name);
3647 table = &assembly->tables [MONO_TABLE_FILE];
3649 alloc_table (table, table->rows);
3650 values = table->values + table->next_idx * MONO_FILE_SIZE;
3651 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3652 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3655 mono_sha1_get_digest_from_file (name, hash);
3656 mono_metadata_encode_value (20, b, &b);
3657 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3658 mono_image_add_stream_data (&assembly->blob, hash, 20);
3660 idx = table->next_idx++;
3662 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3665 offset = mono_array_length (rsrc->data);
3666 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3667 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3668 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3669 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3673 * The entry should be emitted into the MANIFESTRESOURCE table of
3674 * the main module, but that needs to reference the FILE table
3675 * which isn't emitted yet.
3682 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3686 set_version_from_string (MonoString *version, guint32 *values)
3688 gchar *ver, *p, *str;
3691 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3692 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3693 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3694 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3697 ver = str = mono_string_to_utf8 (version);
3698 for (i = 0; i < 4; ++i) {
3699 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3705 /* handle Revision and Build */
3715 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3719 char *b = blob_size;
3724 len = mono_array_length (pkey);
3725 mono_metadata_encode_value (len, b, &b);
3726 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3727 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3729 /* need to get the actual value from the key type... */
3730 assembly->strong_name_size = 128;
3731 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3737 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3739 MonoDynamicTable *table;
3740 MonoDynamicImage *assembly;
3741 MonoReflectionAssemblyBuilder *assemblyb;
3746 guint32 module_index;
3748 assemblyb = moduleb->assemblyb;
3749 assembly = moduleb->dynamic_image;
3750 domain = mono_object_domain (assemblyb);
3752 /* Emit ASSEMBLY table */
3753 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3754 alloc_table (table, 1);
3755 values = table->values + MONO_ASSEMBLY_SIZE;
3756 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3757 name = mono_string_to_utf8 (assemblyb->name);
3758 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3760 if (assemblyb->culture) {
3761 name = mono_string_to_utf8 (assemblyb->culture);
3762 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3765 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3767 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3768 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3769 set_version_from_string (assemblyb->version, values);
3771 /* Emit FILE + EXPORTED_TYPE table */
3773 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3775 MonoReflectionModuleBuilder *file_module =
3776 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3777 if (file_module != moduleb) {
3778 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3780 if (file_module->types) {
3781 for (j = 0; j < file_module->num_types; ++j) {
3782 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3783 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3788 if (assemblyb->loaded_modules) {
3789 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3790 MonoReflectionModule *file_module =
3791 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3792 mono_image_fill_file_table (domain, file_module, assembly);
3794 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3798 /* Emit MANIFESTRESOURCE table */
3800 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3802 MonoReflectionModuleBuilder *file_module =
3803 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3804 /* The table for the main module is emitted later */
3805 if (file_module != moduleb) {
3807 if (file_module->resources) {
3808 int len = mono_array_length (file_module->resources);
3809 for (j = 0; j < len; ++j) {
3810 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3811 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3819 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3820 * for the modulebuilder @moduleb.
3821 * At the end of the process, method and field tokens are fixed up and the
3822 * on-disk compressed metadata representation is created.
3825 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3827 MonoDynamicTable *table;
3828 MonoDynamicImage *assembly;
3829 MonoReflectionAssemblyBuilder *assemblyb;
3834 assemblyb = moduleb->assemblyb;
3835 assembly = moduleb->dynamic_image;
3836 domain = mono_object_domain (assemblyb);
3838 if (assembly->text_rva)
3841 assembly->text_rva = START_TEXT_RVA;
3843 if (moduleb->is_main) {
3844 mono_image_emit_manifest (moduleb);
3847 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3848 table->rows = 1; /* .<Module> */
3850 alloc_table (table, table->rows);
3852 * Set the first entry.
3854 values = table->values + table->columns;
3855 values [MONO_TYPEDEF_FLAGS] = 0;
3856 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3857 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3858 values [MONO_TYPEDEF_EXTENDS] = 0;
3859 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3860 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3863 * handle global methods
3864 * FIXME: test what to do when global methods are defined in multiple modules.
3866 if (moduleb->global_methods) {
3867 table = &assembly->tables [MONO_TABLE_METHOD];
3868 table->rows += mono_array_length (moduleb->global_methods);
3869 alloc_table (table, table->rows);
3870 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3871 mono_image_get_method_info (
3872 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3874 if (moduleb->global_fields) {
3875 table = &assembly->tables [MONO_TABLE_FIELD];
3876 table->rows += mono_array_length (moduleb->global_fields);
3877 alloc_table (table, table->rows);
3878 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3879 mono_image_get_field_info (
3880 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3883 table = &assembly->tables [MONO_TABLE_MODULE];
3884 alloc_table (table, 1);
3885 mono_image_fill_module_table (domain, moduleb, assembly);
3889 /* Collect all types into a list sorted by their table_idx */
3890 GPtrArray *types = g_ptr_array_new ();
3893 for (i = 0; i < moduleb->num_types; ++i) {
3894 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3895 collect_types (types, type);
3898 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows += types->len;
3901 alloc_table (table, table->rows);
3903 for (i = 0; i < types->len; ++i) {
3904 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3905 mono_image_get_type_info (domain, type, assembly);
3907 g_ptr_array_free (types, TRUE);
3911 * table->rows is already set above and in mono_image_fill_module_table.
3913 /* add all the custom attributes at the end, once all the indexes are stable */
3914 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3916 /* CAS assembly permissions */
3917 if (assemblyb->permissions_minimum)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3919 if (assemblyb->permissions_optional)
3920 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3921 if (assemblyb->permissions_refused)
3922 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3924 module_add_cattrs (assembly, moduleb);
3927 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3928 fixup_cattrs (assembly);
3932 * mono_image_insert_string:
3933 * @module: module builder object
3936 * Insert @str into the user string stream of @module.
3939 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3941 MonoDynamicImage *assembly;
3946 MONO_ARCH_SAVE_REGS;
3948 if (!module->dynamic_image)
3949 mono_image_module_basic_init (module);
3951 assembly = module->dynamic_image;
3953 if (assembly->save) {
3954 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3955 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3956 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3958 char *swapped = g_malloc (2 * mono_string_length (str));
3959 const char *p = (const char*)mono_string_chars (str);
3961 swap_with_size (swapped, p, 2, mono_string_length (str));
3962 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3966 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3968 mono_image_add_stream_data (&assembly->us, "", 1);
3970 idx = assembly->us.index ++;
3973 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3975 return MONO_TOKEN_STRING | idx;
3979 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3984 klass = obj->vtable->klass;
3985 if (strcmp (klass->name, "MonoMethod") == 0) {
3986 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3987 MonoMethodSignature *sig, *old;
3988 guint32 sig_token, parent;
3991 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3993 nargs = mono_array_length (opt_param_types);
3994 old = method->signature;
3995 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3997 sig->hasthis = old->hasthis;
3998 sig->explicit_this = old->explicit_this;
3999 sig->call_convention = old->call_convention;
4000 sig->generic_param_count = old->generic_param_count;
4001 sig->param_count = old->param_count + nargs;
4002 sig->sentinelpos = old->param_count;
4003 sig->ret = old->ret;
4005 for (i = 0; i < old->param_count; i++)
4006 sig->params [i] = old->params [i];
4008 for (i = 0; i < nargs; i++) {
4009 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4010 sig->params [old->param_count + i] = rt->type;
4013 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4014 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4015 parent >>= MONO_TYPEDEFORREF_BITS;
4017 parent <<= MONO_MEMBERREF_PARENT_BITS;
4018 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4020 sig_token = method_encode_signature (assembly, sig);
4021 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4022 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4024 ReflectionMethodBuilder rmb;
4025 guint32 parent, sig;
4027 reflection_methodbuilder_from_method_builder (&rmb, mb);
4028 rmb.opt_types = opt_param_types;
4030 sig = method_builder_encode_signature (assembly, &rmb);
4032 parent = mono_image_create_token (assembly, obj, TRUE);
4033 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4035 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4036 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4038 token = mono_image_get_varargs_method_token (
4039 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4041 g_error ("requested method token for %s\n", klass->name);
4048 * mono_image_create_token:
4049 * @assembly: a dynamic assembly
4052 * Get a token to insert in the IL code stream for the given MemberInfo.
4053 * @obj can be one of:
4054 * ConstructorBuilder
4064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4069 klass = obj->vtable->klass;
4070 if (strcmp (klass->name, "MethodBuilder") == 0) {
4071 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4073 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4074 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4076 token = mono_image_get_methodbuilder_token (assembly, mb);
4077 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4078 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4079 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4081 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4082 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4084 token = mono_image_get_ctorbuilder_token (assembly, mb);
4085 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4086 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4087 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4088 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4089 if (tb->generic_params) {
4090 token = mono_image_get_generic_field_token (assembly, fb);
4092 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4094 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4095 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4096 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4097 } else if (strcmp (klass->name, "MonoType") == 0 ||
4098 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4099 MonoReflectionType *tb = (MonoReflectionType *)obj;
4100 token = mono_metadata_token_from_dor (
4101 mono_image_typedef_or_ref (assembly, tb->type));
4102 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4103 MonoReflectionType *tb = (MonoReflectionType *)obj;
4104 token = mono_metadata_token_from_dor (
4105 mono_image_typedef_or_ref (assembly, tb->type));
4106 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4107 strcmp (klass->name, "MonoMethod") == 0) {
4108 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4109 if (m->method->signature->is_inflated) {
4110 if (create_methodspec)
4111 token = mono_image_get_methodspec_token (assembly, m->method);
4113 token = mono_image_get_inflated_method_token (assembly, m->method);
4114 } else if (m->method->signature->generic_param_count) {
4115 g_assert_not_reached ();
4116 } else if ((m->method->klass->image == &assembly->image) &&
4117 !m->method->klass->generic_inst) {
4118 static guint32 method_table_idx = 0xffffff;
4119 if (m->method->klass->wastypebuilder) {
4120 /* we use the same token as the one that was assigned
4121 * to the Methodbuilder.
4122 * FIXME: do the equivalent for Fields.
4124 token = m->method->token;
4127 * Each token should have a unique index, but the indexes are
4128 * assigned by managed code, so we don't know about them. An
4129 * easy solution is to count backwards...
4131 method_table_idx --;
4132 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4135 token = mono_image_get_methodref_token (assembly, m->method);
4137 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4138 } else if (strcmp (klass->name, "MonoField") == 0) {
4139 MonoReflectionField *f = (MonoReflectionField *)obj;
4140 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4141 static guint32 field_table_idx = 0xffffff;
4143 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4145 token = mono_image_get_fieldref_token (assembly, f);
4147 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4148 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4149 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4150 token = mono_image_get_array_token (assembly, m);
4151 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4152 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4153 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4155 g_error ("requested token for %s\n", klass->name);
4158 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4164 guint32 import_lookup_table;
4168 guint32 import_address_table_rva;
4176 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4178 static MonoDynamicImage*
4179 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4181 static const guchar entrycode [16] = {0xff, 0x25, 0};
4182 MonoDynamicImage *image;
4185 const char *version = mono_get_runtime_version ();
4188 image = GC_MALLOC (sizeof (MonoDynamicImage));
4190 image = g_new0 (MonoDynamicImage, 1);
4193 /* keep in sync with image.c */
4194 image->image.name = assembly_name;
4195 image->image.assembly_name = image->image.name; /* they may be different */
4196 image->image.module_name = module_name;
4197 image->image.version = g_strdup (version);
4198 image->image.dynamic = TRUE;
4200 image->image.references = g_new0 (MonoAssembly*, 1);
4201 image->image.references [0] = NULL;
4203 mono_image_init (&image->image);
4205 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4206 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4207 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4208 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4209 image->handleref = g_hash_table_new (NULL, NULL);
4210 image->tokens = mono_g_hash_table_new (NULL, NULL);
4211 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4212 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4213 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4214 image->gen_params = g_ptr_array_new ();
4216 string_heap_init (&image->sheap);
4217 mono_image_add_stream_data (&image->us, "", 1);
4218 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4219 /* import tables... */
4220 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4221 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4222 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4223 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4225 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4226 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4227 stream_data_align (&image->code);
4229 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4231 for (i=0; i < 64; ++i) {
4232 image->tables [i].next_idx = 1;
4233 image->tables [i].columns = table_sizes [i];
4236 image->image.assembly = (MonoAssembly*)assembly;
4237 image->run = assembly->run;
4238 image->save = assembly->save;
4239 image->pe_kind = 0x1; /* ILOnly */
4240 image->machine = 0x14c; /* I386 */
4246 * mono_image_basic_init:
4247 * @assembly: an assembly builder object
4249 * Create the MonoImage that represents the assembly builder and setup some
4250 * of the helper hash table and the basic metadata streams.
4253 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4255 MonoDynamicAssembly *assembly;
4256 MonoDynamicImage *image;
4258 MONO_ARCH_SAVE_REGS;
4260 if (assemblyb->dynamic_assembly)
4264 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4266 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4269 assembly->assembly.dynamic = TRUE;
4270 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4271 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4272 if (assemblyb->culture)
4273 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4275 assembly->assembly.aname.culture = g_strdup ("");
4277 assembly->run = assemblyb->access != 2;
4278 assembly->save = assemblyb->access != 1;
4280 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4281 image->initial_image = TRUE;
4282 assembly->assembly.aname.name = image->image.name;
4283 assembly->assembly.image = &image->image;
4285 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4286 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4290 calc_section_size (MonoDynamicImage *assembly)
4294 /* alignment constraints */
4295 assembly->code.index += 3;
4296 assembly->code.index &= ~3;
4297 assembly->meta_size += 3;
4298 assembly->meta_size &= ~3;
4299 assembly->resources.index += 3;
4300 assembly->resources.index &= ~3;
4302 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4303 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4306 if (assembly->win32_res) {
4307 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4309 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4310 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4314 assembly->sections [MONO_SECTION_RELOC].size = 12;
4315 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4325 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4329 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4331 ResTreeNode *t1 = (ResTreeNode*)a;
4332 ResTreeNode *t2 = (ResTreeNode*)b;
4334 return t1->id - t2->id;
4338 * resource_tree_create:
4340 * Organize the resources into a resource tree.
4342 static ResTreeNode *
4343 resource_tree_create (MonoArray *win32_resources)
4345 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4349 tree = g_new0 (ResTreeNode, 1);
4351 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4352 MonoReflectionWin32Resource *win32_res =
4353 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4357 lang_node = g_new0 (ResTreeNode, 1);
4358 lang_node->id = win32_res->lang_id;
4359 lang_node->win32_res = win32_res;
4361 /* Create type node if neccesary */
4363 for (l = tree->children; l; l = l->next)
4364 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4365 type_node = (ResTreeNode*)l->data;
4370 type_node = g_new0 (ResTreeNode, 1);
4371 type_node->id = win32_res->res_type;
4374 * The resource types have to be sorted otherwise
4375 * Windows Explorer can't display the version information.
4377 tree->children = g_slist_insert_sorted (tree->children,
4378 type_node, resource_tree_compare_by_id);
4381 /* Create res node if neccesary */
4383 for (l = type_node->children; l; l = l->next)
4384 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4385 res_node = (ResTreeNode*)l->data;
4390 res_node = g_new0 (ResTreeNode, 1);
4391 res_node->id = win32_res->res_id;
4392 type_node->children = g_slist_append (type_node->children, res_node);
4395 res_node->children = g_slist_append (res_node->children, lang_node);
4402 * resource_tree_encode:
4404 * Encode the resource tree into the format used in the PE file.
4407 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4410 MonoPEResourceDir dir;
4411 MonoPEResourceDirEntry dir_entry;
4412 MonoPEResourceDataEntry data_entry;
4416 * For the format of the resource directory, see the article
4417 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4421 memset (&dir, 0, sizeof (dir));
4422 memset (&dir_entry, 0, sizeof (dir_entry));
4423 memset (&data_entry, 0, sizeof (data_entry));
4425 g_assert (sizeof (dir) == 16);
4426 g_assert (sizeof (dir_entry) == 8);
4427 g_assert (sizeof (data_entry) == 16);
4429 node->offset = p - begin;
4431 /* IMAGE_RESOURCE_DIRECTORY */
4432 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4434 memcpy (p, &dir, sizeof (dir));
4437 /* Reserve space for entries */
4439 p += sizeof (dir_entry) * dir.res_id_entries;
4441 /* Write children */
4442 for (l = node->children; l; l = l->next) {
4443 ResTreeNode *child = (ResTreeNode*)l->data;
4445 if (child->win32_res) {
4447 child->offset = p - begin;
4449 /* IMAGE_RESOURCE_DATA_ENTRY */
4450 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4451 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4453 memcpy (p, &data_entry, sizeof (data_entry));
4454 p += sizeof (data_entry);
4456 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4457 p += data_entry.rde_size;
4459 resource_tree_encode (child, begin, p, &p);
4463 /* IMAGE_RESOURCE_ENTRY */
4464 for (l = node->children; l; l = l->next) {
4465 ResTreeNode *child = (ResTreeNode*)l->data;
4466 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4468 dir_entry.is_dir = child->win32_res ? 0 : 1;
4469 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4471 memcpy (entries, &dir_entry, sizeof (dir_entry));
4472 entries += sizeof (dir_entry);
4479 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4484 MonoReflectionWin32Resource *win32_res;
4487 if (!assemblyb->win32_resources)
4491 * Resources are stored in a three level tree inside the PE file.
4492 * - level one contains a node for each type of resource
4493 * - level two contains a node for each resource
4494 * - level three contains a node for each instance of a resource for a
4495 * specific language.
4498 tree = resource_tree_create (assemblyb->win32_resources);
4500 /* Estimate the size of the encoded tree */
4502 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4503 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4504 size += mono_array_length (win32_res->res_data);
4506 /* Directory structure */
4507 size += mono_array_length (assemblyb->win32_resources) * 256;
4508 p = buf = g_malloc (size);
4510 resource_tree_encode (tree, p, p, &p);
4512 g_assert (p - buf < size);
4514 assembly->win32_res = g_malloc (p - buf);
4515 assembly->win32_res_size = p - buf;
4516 memcpy (assembly->win32_res, buf, p - buf);
4522 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4524 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4527 p += sizeof (MonoPEResourceDir);
4528 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4529 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4530 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4531 if (dir_entry->is_dir) {
4532 fixup_resource_directory (res_section, child, rva);
4534 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4535 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4538 p += sizeof (MonoPEResourceDirEntry);
4543 * mono_image_create_pefile:
4544 * @mb: a module builder object
4546 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4547 * assembly->pefile where it can be easily retrieved later in chunks.
4550 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4551 MonoMSDOSHeader *msdos;
4552 MonoDotNetHeader *header;
4553 MonoSectionTable *section;
4554 MonoCLIHeader *cli_header;
4555 guint32 size, image_size, virtual_base, text_offset;
4556 guint32 header_start, section_start, file_offset, virtual_offset;
4557 MonoDynamicImage *assembly;
4558 MonoReflectionAssemblyBuilder *assemblyb;
4559 MonoDynamicStream *pefile;
4561 guint32 *rva, value;
4564 static const unsigned char msheader[] = {
4565 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4566 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4569 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4570 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4571 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4572 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4575 assemblyb = mb->assemblyb;
4577 mono_image_basic_init (assemblyb);
4578 assembly = mb->dynamic_image;
4580 assembly->pe_kind = assemblyb->pe_kind;
4581 assembly->machine = assemblyb->machine;
4582 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4583 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4585 /* already created */
4586 if (assembly->pefile.index)
4589 mono_image_build_metadata (mb);
4591 if (mb->is_main && assemblyb->resources) {
4592 int len = mono_array_length (assemblyb->resources);
4593 for (i = 0; i < len; ++i)
4594 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4597 if (mb->resources) {
4598 int len = mono_array_length (mb->resources);
4599 for (i = 0; i < len; ++i)
4600 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4603 build_compressed_metadata (assembly);
4606 assembly_add_win32_resources (assembly, assemblyb);
4608 nsections = calc_section_size (assembly);
4610 pefile = &assembly->pefile;
4612 /* The DOS header and stub */
4613 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4614 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4616 /* the dotnet header */
4617 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4619 /* the section tables */
4620 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4622 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4623 virtual_offset = VIRT_ALIGN;
4626 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4627 if (!assembly->sections [i].size)
4630 file_offset += FILE_ALIGN - 1;
4631 file_offset &= ~(FILE_ALIGN - 1);
4632 virtual_offset += VIRT_ALIGN - 1;
4633 virtual_offset &= ~(VIRT_ALIGN - 1);
4635 assembly->sections [i].offset = file_offset;
4636 assembly->sections [i].rva = virtual_offset;
4638 file_offset += assembly->sections [i].size;
4639 virtual_offset += assembly->sections [i].size;
4640 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4643 file_offset += FILE_ALIGN - 1;
4644 file_offset &= ~(FILE_ALIGN - 1);
4645 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4647 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4649 /* back-patch info */
4650 msdos = (MonoMSDOSHeader*)pefile->data;
4651 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4652 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4653 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4655 header = (MonoDotNetHeader*)(pefile->data + header_start);
4656 header->pesig [0] = 'P';
4657 header->pesig [1] = 'E';
4659 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4660 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4661 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4662 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4663 if (assemblyb->pekind == 1) {
4665 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4668 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4671 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4673 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4674 header->pe.pe_major = 6;
4675 header->pe.pe_minor = 0;
4676 size = assembly->sections [MONO_SECTION_TEXT].size;
4677 size += FILE_ALIGN - 1;
4678 size &= ~(FILE_ALIGN - 1);
4679 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4680 size = assembly->sections [MONO_SECTION_RSRC].size;
4681 size += FILE_ALIGN - 1;
4682 size &= ~(FILE_ALIGN - 1);
4683 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4684 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4685 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4686 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4687 /* pe_rva_entry_point always at the beginning of the text section */
4688 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4690 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4691 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4692 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4693 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4694 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4695 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4696 size = section_start;
4697 size += FILE_ALIGN - 1;
4698 size &= ~(FILE_ALIGN - 1);
4699 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4701 size += VIRT_ALIGN - 1;
4702 size &= ~(VIRT_ALIGN - 1);
4703 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4706 // Translate the PEFileKind value to the value expected by the Windows loader
4712 // PEFileKinds.Dll == 1
4713 // PEFileKinds.ConsoleApplication == 2
4714 // PEFileKinds.WindowApplication == 3
4717 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4718 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4720 if (assemblyb->pekind == 3)
4725 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4727 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4728 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4729 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4730 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4731 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4732 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4734 /* fill data directory entries */
4736 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4737 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4739 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4740 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4742 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4743 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4744 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4745 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4746 /* patch imported function RVA name */
4747 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4748 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4750 /* the import table */
4751 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4752 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4753 /* patch imported dll RVA name and other entries in the dir */
4754 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4755 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4756 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4757 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4758 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4759 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4761 p = (assembly->code.data + assembly->ilt_offset);
4762 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4763 *p++ = (value) & 0xff;
4764 *p++ = (value >> 8) & (0xff);
4765 *p++ = (value >> 16) & (0xff);
4766 *p++ = (value >> 24) & (0xff);
4768 /* the CLI header info */
4769 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4770 cli_header->ch_size = GUINT32_FROM_LE (72);
4771 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4772 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4773 if (assemblyb->entry_point) {
4774 guint32 table_idx = 0;
4775 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4776 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4777 table_idx = methodb->table_idx;
4779 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4781 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4783 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4785 /* The embedded managed resources */
4786 text_offset = assembly->text_rva + assembly->code.index;
4787 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4788 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4789 text_offset += assembly->resources.index;
4790 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4791 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4792 text_offset += assembly->meta_size;
4793 if (assembly->strong_name_size) {
4794 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4795 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4796 text_offset += assembly->strong_name_size;
4799 /* write the section tables and section content */
4800 section = (MonoSectionTable*)(pefile->data + section_start);
4801 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4802 static const char *section_names [] = {
4803 ".text", ".rsrc", ".reloc"
4805 if (!assembly->sections [i].size)
4807 strcpy (section->st_name, section_names [i]);
4808 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4809 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4810 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4811 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4812 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4813 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4814 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4816 case MONO_SECTION_TEXT:
4817 /* patch entry point */
4818 p = (assembly->code.data + 2);
4819 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4820 *p++ = (value) & 0xff;
4821 *p++ = (value >> 8) & 0xff;
4822 *p++ = (value >> 16) & 0xff;
4823 *p++ = (value >> 24) & 0xff;
4825 text_offset = assembly->sections [i].offset;
4826 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4827 text_offset += assembly->code.index;
4828 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4829 text_offset += assembly->resources.index;
4830 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4831 text_offset += assembly->meta_size;
4832 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4834 g_free (assembly->image.raw_metadata);
4836 case MONO_SECTION_RELOC:
4837 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4838 *rva = GUINT32_FROM_LE (assembly->text_rva);
4840 *rva = GUINT32_FROM_LE (12);
4842 data16 = (guint16*)rva;
4844 * the entrypoint is always at the start of the text section
4845 * 3 is IMAGE_REL_BASED_HIGHLOW
4846 * 2 is patch_size_rva - text_rva
4848 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4850 *data16 = 0; /* terminate */
4852 case MONO_SECTION_RSRC:
4853 if (assembly->win32_res) {
4854 text_offset = assembly->sections [i].offset;
4856 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4857 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4859 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4863 g_assert_not_reached ();
4868 /* check that the file is properly padded */
4871 FILE *f = fopen ("mypetest.exe", "w");
4872 fwrite (pefile->data, pefile->index, 1, f);
4878 MonoReflectionModule *
4879 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4883 MonoImageOpenStatus status;
4884 MonoDynamicAssembly *assembly;
4885 guint32 module_count;
4886 MonoImage **new_modules;
4888 name = mono_string_to_utf8 (fileName);
4890 image = mono_image_open (name, &status);
4893 if (status == MONO_IMAGE_ERROR_ERRNO)
4894 exc = mono_get_exception_file_not_found (fileName);
4896 exc = mono_get_exception_bad_image_format (name);
4898 mono_raise_exception (exc);
4903 assembly = ab->dynamic_assembly;
4904 image->assembly = (MonoAssembly*)assembly;
4906 module_count = image->assembly->image->module_count;
4907 new_modules = g_new0 (MonoImage *, module_count + 1);
4909 if (image->assembly->image->modules)
4910 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4911 new_modules [module_count] = image;
4913 g_free (image->assembly->image->modules);
4914 image->assembly->image->modules = new_modules;
4915 image->assembly->image->module_count ++;
4917 mono_assembly_load_references (image, &status);
4919 mono_image_close (image);
4920 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4923 return mono_module_get_object (mono_domain_get (), image);
4927 * We need to return always the same object for MethodInfo, FieldInfo etc..
4928 * but we need to consider the reflected type.
4929 * type uses a different hash, since it uses custom hash/equal functions.
4934 MonoClass *refclass;
4938 reflected_equal (gconstpointer a, gconstpointer b) {
4939 const ReflectedEntry *ea = a;
4940 const ReflectedEntry *eb = b;
4942 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4946 reflected_hash (gconstpointer a) {
4947 const ReflectedEntry *ea = a;
4948 return GPOINTER_TO_UINT (ea->item);
4951 #define CHECK_OBJECT(t,p,k) \
4957 mono_domain_lock (domain); \
4958 if (!domain->refobject_hash) \
4959 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4960 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4961 mono_domain_unlock (domain); \
4967 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4969 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4972 #define CACHE_OBJECT(p,o,k) \
4974 ReflectedEntry *e = ALLOC_REFENTRY; \
4976 e->refclass = (k); \
4977 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4978 mono_domain_unlock (domain); \
4982 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4984 /* this is done only once */
4985 mono_domain_lock (domain);
4986 CACHE_OBJECT (assembly, res, NULL);
4990 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4992 /* this is done only once */
4993 mono_domain_lock (domain);
4994 CACHE_OBJECT (module, res, NULL);
4998 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5000 MonoDynamicImage *image = moduleb->dynamic_image;
5001 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5004 * FIXME: we already created an image in mono_image_basic_init (), but
5005 * we don't know which module it belongs to, since that is only
5006 * determined at assembly save time.
5008 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5009 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5011 moduleb->module.image = &image->image;
5012 moduleb->dynamic_image = image;
5013 register_module (mono_object_domain (moduleb), moduleb, image);
5018 * mono_assembly_get_object:
5019 * @domain: an app domain
5020 * @assembly: an assembly
5022 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5024 MonoReflectionAssembly*
5025 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5027 static MonoClass *System_Reflection_Assembly;
5028 MonoReflectionAssembly *res;
5030 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5031 if (!System_Reflection_Assembly)
5032 System_Reflection_Assembly = mono_class_from_name (
5033 mono_defaults.corlib, "System.Reflection", "Assembly");
5034 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5035 res->assembly = assembly;
5036 CACHE_OBJECT (assembly, res, NULL);
5042 MonoReflectionModule*
5043 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5045 static MonoClass *System_Reflection_Module;
5046 MonoReflectionModule *res;
5048 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5049 if (!System_Reflection_Module)
5050 System_Reflection_Module = mono_class_from_name (
5051 mono_defaults.corlib, "System.Reflection", "Module");
5052 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5055 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5057 res->fqname = mono_string_new (domain, image->name);
5058 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5059 res->scopename = mono_string_new (domain, image->module_name);
5061 if (image->assembly->image == image) {
5062 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5065 g_assert (image->assembly->image->modules);
5067 for (i = 0; i < image->assembly->image->module_count; i++) {
5068 if (image->assembly->image->modules [i] == image)
5069 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5071 g_assert (res->token);
5074 mono_image_addref (image);
5076 CACHE_OBJECT (image, res, NULL);
5080 MonoReflectionModule*
5081 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5083 static MonoClass *System_Reflection_Module;
5084 MonoReflectionModule *res;
5085 MonoTableInfo *table;
5086 guint32 cols [MONO_FILE_SIZE];
5088 guint32 i, name_idx;
5091 if (!System_Reflection_Module)
5092 System_Reflection_Module = mono_class_from_name (
5093 mono_defaults.corlib, "System.Reflection", "Module");
5094 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5096 table = &image->tables [MONO_TABLE_FILE];
5097 g_assert (table_index < table->rows);
5098 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5101 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5102 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5104 /* Check whenever the row has a corresponding row in the moduleref table */
5105 table = &image->tables [MONO_TABLE_MODULEREF];
5106 for (i = 0; i < table->rows; ++i) {
5107 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5108 val = mono_metadata_string_heap (image, name_idx);
5109 if (strcmp (val, name) == 0)
5110 res->image = image->modules [i];
5113 res->fqname = mono_string_new (domain, name);
5114 res->name = mono_string_new (domain, name);
5115 res->scopename = mono_string_new (domain, name);
5116 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5117 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5123 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5125 if ((t1->type != t2->type) ||
5126 (t1->byref != t2->byref))
5130 case MONO_TYPE_VOID:
5131 case MONO_TYPE_BOOLEAN:
5132 case MONO_TYPE_CHAR:
5143 case MONO_TYPE_STRING:
5146 case MONO_TYPE_OBJECT:
5147 case MONO_TYPE_TYPEDBYREF:
5149 case MONO_TYPE_VALUETYPE:
5150 case MONO_TYPE_CLASS:
5151 case MONO_TYPE_SZARRAY:
5152 return t1->data.klass == t2->data.klass;
5154 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5155 case MONO_TYPE_ARRAY:
5156 if (t1->data.array->rank != t2->data.array->rank)
5158 return t1->data.array->eklass == t2->data.array->eklass;
5159 case MONO_TYPE_GENERICINST: {
5161 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5163 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5165 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5166 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5172 case MONO_TYPE_MVAR:
5173 return t1->data.generic_param == t2->data.generic_param;
5175 g_error ("implement type compare for %0x!", t1->type);
5183 mymono_metadata_type_hash (MonoType *t1)
5189 hash |= t1->byref << 6; /* do not collide with t1->type values */
5191 case MONO_TYPE_VALUETYPE:
5192 case MONO_TYPE_CLASS:
5193 case MONO_TYPE_SZARRAY:
5194 /* check if the distribution is good enough */
5195 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5197 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5202 static MonoReflectionGenericInst*
5203 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5205 static MonoClass *System_Reflection_MonoGenericInst;
5206 MonoReflectionGenericInst *res;
5207 MonoGenericInst *ginst;
5210 if (!System_Reflection_MonoGenericInst) {
5211 System_Reflection_MonoGenericInst = mono_class_from_name (
5212 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5213 g_assert (System_Reflection_MonoGenericInst);
5216 ginst = geninst->data.generic_inst;
5217 gklass = mono_class_from_mono_type (ginst->generic_type);
5219 mono_class_init (ginst->klass);
5221 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5223 res->type.type = geninst;
5224 if (gklass->wastypebuilder && gklass->reflection_info)
5225 res->generic_type = gklass->reflection_info;
5227 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5233 * mono_type_get_object:
5234 * @domain: an app domain
5237 * Return an System.MonoType object representing the type @type.
5240 mono_type_get_object (MonoDomain *domain, MonoType *type)
5242 MonoReflectionType *res;
5243 MonoClass *klass = mono_class_from_mono_type (type);
5245 mono_domain_lock (domain);
5246 if (!domain->type_hash)
5247 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5248 (GCompareFunc)mymono_metadata_type_equal);
5249 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5250 mono_domain_unlock (domain);
5253 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5254 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5255 mono_g_hash_table_insert (domain->type_hash, type, res);
5256 mono_domain_unlock (domain);
5259 if (klass->reflection_info && !klass->wastypebuilder) {
5260 /* g_assert_not_reached (); */
5261 /* should this be considered an error condition? */
5263 mono_domain_unlock (domain);
5264 return klass->reflection_info;
5267 mono_class_init (klass);
5268 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5270 mono_g_hash_table_insert (domain->type_hash, type, res);
5271 mono_domain_unlock (domain);
5276 * mono_method_get_object:
5277 * @domain: an app domain
5279 * @refclass: the reflected type (can be NULL)
5281 * Return an System.Reflection.MonoMethod object representing the method @method.
5283 MonoReflectionMethod*
5284 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5287 * We use the same C representation for methods and constructors, but the type
5288 * name in C# is different.
5292 MonoReflectionMethod *ret;
5295 refclass = method->klass;
5297 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5298 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5299 cname = "MonoCMethod";
5301 cname = "MonoMethod";
5302 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5304 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5305 ret->method = method;
5306 ret->name = mono_string_new (domain, method->name);
5307 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5308 CACHE_OBJECT (method, ret, refclass);
5313 * mono_field_get_object:
5314 * @domain: an app domain
5318 * Return an System.Reflection.MonoField object representing the field @field
5321 MonoReflectionField*
5322 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5324 MonoReflectionField *res;
5327 CHECK_OBJECT (MonoReflectionField *, field, klass);
5328 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5329 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5332 res->name = mono_string_new (domain, field->name);
5333 if (field->generic_info)
5334 res->attrs = field->generic_info->generic_type->attrs;
5336 res->attrs = field->type->attrs;
5337 res->type = mono_type_get_object (domain, field->type);
5338 CACHE_OBJECT (field, res, klass);
5343 * mono_property_get_object:
5344 * @domain: an app domain
5346 * @property: a property
5348 * Return an System.Reflection.MonoProperty object representing the property @property
5351 MonoReflectionProperty*
5352 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5354 MonoReflectionProperty *res;
5357 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5358 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5359 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5361 res->property = property;
5362 CACHE_OBJECT (property, res, klass);
5367 * mono_event_get_object:
5368 * @domain: an app domain
5372 * Return an System.Reflection.MonoEvent object representing the event @event
5375 MonoReflectionEvent*
5376 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5378 MonoReflectionEvent *res;
5381 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5382 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5383 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5386 CACHE_OBJECT (event, res, klass);
5391 * mono_param_get_objects:
5392 * @domain: an app domain
5395 * Return an System.Reflection.ParameterInfo array object representing the parameters
5396 * in the method @method.
5399 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5401 static MonoClass *System_Reflection_ParameterInfo;
5402 MonoArray *res = NULL;
5403 MonoReflectionMethod *member = NULL;
5404 MonoReflectionParameter *param = NULL;
5405 char **names, **blobs = NULL;
5406 MonoObject *dbnull = mono_get_dbnull_object (domain);
5407 MonoMarshalSpec **mspecs;
5410 if (!System_Reflection_ParameterInfo)
5411 System_Reflection_ParameterInfo = mono_class_from_name (
5412 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5414 if (!method->signature->param_count)
5415 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5417 /* Note: the cache is based on the address of the signature into the method
5418 * since we already cache MethodInfos with the method as keys.
5420 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5422 member = mono_method_get_object (domain, method, NULL);
5423 names = g_new (char *, method->signature->param_count);
5424 mono_method_get_param_names (method, (const char **) names);
5426 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5427 mono_method_get_marshal_info (method, mspecs);
5429 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5430 for (i = 0; i < method->signature->param_count; ++i) {
5431 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5432 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5433 param->MemberImpl = (MonoObject*)member;
5434 param->NameImpl = mono_string_new (domain, names [i]);
5435 param->PositionImpl = i;
5436 param->AttrsImpl = method->signature->params [i]->attrs;
5438 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5439 param->DefaultValueImpl = dbnull;
5441 MonoType *type = param->ClassImpl->type;
5444 blobs = g_new0 (char *, method->signature->param_count);
5445 get_default_param_value_blobs (method, blobs);
5448 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5450 if (!param->DefaultValueImpl) {
5451 param->DefaultValueImpl = dbnull;
5456 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5458 mono_array_set (res, gpointer, i, param);
5463 for (i = method->signature->param_count; i >= 0; i--)
5465 mono_metadata_free_marshal_spec (mspecs [i]);
5468 CACHE_OBJECT (&(method->signature), res, NULL);
5473 mono_get_dbnull_object (MonoDomain *domain)
5477 static MonoClassField *dbnull_value_field = NULL;
5479 if (!dbnull_value_field) {
5480 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5481 mono_class_init (klass);
5482 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5483 g_assert (dbnull_value_field);
5485 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5492 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5494 guint32 param_index, i, lastp, crow = 0;
5495 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5498 MonoClass *klass = method->klass;
5499 MonoImage *image = klass->image;
5500 MonoMethodSignature *methodsig = method->signature;
5502 MonoTableInfo *constt;
5503 MonoTableInfo *methodt;
5504 MonoTableInfo *paramt;
5506 if (!methodsig->param_count)
5509 if (klass->generic_inst) {
5510 return; /* FIXME - ??? */
5513 mono_class_init (klass);
5515 if (klass->image->dynamic) {
5516 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5517 if (aux && aux->param_defaults)
5518 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5522 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5523 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5524 constt = &image->tables [MONO_TABLE_CONSTANT];
5526 for (i = 0; i < klass->method.count; ++i) {
5527 if (method == klass->methods [i]) {
5528 idx = klass->method.first + i;
5533 g_assert (idx != -1);
5535 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5536 if (idx + 1 < methodt->rows)
5537 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5539 lastp = paramt->rows + 1;
5541 for (i = param_index; i < lastp; ++i) {
5544 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5545 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5547 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5550 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5555 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5556 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5563 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5572 klass = mono_class_from_mono_type (type);
5573 if (klass->valuetype) {
5574 object = mono_object_new (domain, klass);
5575 retval = ((gchar *) object + sizeof (MonoObject));
5580 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5587 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5591 memset (assembly, 0, sizeof (MonoAssemblyName));
5593 assembly->culture = "";
5594 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5596 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5599 while (*p == ' ' || *p == ',') {
5608 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5610 assembly->major = strtoul (p, &s, 10);
5611 if (s == p || *s != '.')
5614 assembly->minor = strtoul (p, &s, 10);
5615 if (s == p || *s != '.')
5618 assembly->build = strtoul (p, &s, 10);
5619 if (s == p || *s != '.')
5622 assembly->revision = strtoul (p, &s, 10);
5626 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5628 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5629 assembly->culture = "";
5632 assembly->culture = p;
5633 while (*p && *p != ',') {
5637 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5639 if (strncmp (p, "null", 4) == 0) {
5644 while (*p && *p != ',') {
5647 len = (p - start + 1);
5648 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5649 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5650 g_strlcpy (assembly->public_key_token, start, len);
5653 while (*p && *p != ',')
5657 while (*p == ' ' || *p == ',') {
5671 * mono_reflection_parse_type:
5674 * Parse a type name as accepted by the GetType () method and output the info
5675 * extracted in the info structure.
5676 * the name param will be mangled, so, make a copy before passing it to this function.
5677 * The fields in info will be valid until the memory pointed to by name is valid.
5678 * Returns 0 on parse error.
5679 * See also mono_type_get_name () below.
5682 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5684 char *start, *p, *w, *last_point, *startn;
5685 int in_modifiers = 0;
5686 int isbyref = 0, rank;
5688 start = p = w = name;
5690 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5691 info->name = info->name_space = NULL;
5692 info->nested = NULL;
5693 info->modifiers = NULL;
5695 /* last_point separates the namespace from the name */
5701 *p = 0; /* NULL terminate the name */
5703 info->nested = g_list_append (info->nested, startn);
5704 /* we have parsed the nesting namespace + name */
5708 info->name_space = start;
5710 info->name = last_point + 1;
5712 info->name_space = (char *)"";
5738 info->name_space = start;
5740 info->name = last_point + 1;
5742 info->name_space = (char *)"";
5749 if (isbyref) /* only one level allowed by the spec */
5752 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5756 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5767 else if (*p != '*') /* '*' means unknown lower bound */
5773 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5785 return 0; /* missing assembly name */
5786 if (!assembly_name_to_aname (&info->assembly, p))
5793 if (info->assembly.name)
5796 *w = 0; /* terminate class name */
5797 if (!info->name || !*info->name)
5799 /* add other consistency checks */
5804 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5811 image = mono_defaults.corlib;
5814 klass = mono_class_from_name_case (image, info->name_space, info->name);
5816 klass = mono_class_from_name (image, info->name_space, info->name);
5819 for (mod = info->nested; mod; mod = mod->next) {
5822 mono_class_init (klass);
5823 nested = klass->nested_classes;
5826 klass = nested->data;
5828 if (g_strcasecmp (klass->name, mod->data) == 0)
5831 if (strcmp (klass->name, mod->data) == 0)
5835 nested = nested->next;
5842 mono_class_init (klass);
5843 for (mod = info->modifiers; mod; mod = mod->next) {
5844 modval = GPOINTER_TO_UINT (mod->data);
5845 if (!modval) { /* byref: must be last modifier */
5846 return &klass->this_arg;
5847 } else if (modval == -1) {
5848 klass = mono_ptr_class_get (&klass->byval_arg);
5849 } else { /* array rank */
5850 klass = mono_array_class_get (klass, modval);
5852 mono_class_init (klass);
5855 return &klass->byval_arg;
5859 * mono_reflection_get_type:
5860 * @image: a metadata context
5861 * @info: type description structure
5862 * @ignorecase: flag for case-insensitive string compares
5863 * @type_resolve: whenever type resolve was already tried
5865 * Build a MonoType from the type description in @info.
5870 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5873 MonoReflectionAssembly *assembly;
5877 type = mono_reflection_get_type_internal (image, info, ignorecase);
5880 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5883 /* FIXME: Enabling this causes regressions (#65577) */
5889 *type_resolve = TRUE;
5893 /* Reconstruct the type name */
5894 fullName = g_string_new ("");
5895 if (info->name_space && (info->name_space [0] != '\0'))
5896 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5898 g_string_printf (fullName, info->name);
5899 for (mod = info->nested; mod; mod = mod->next)
5900 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5902 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5903 if (assembly && (!image || (assembly->assembly->image == image))) {
5905 if (assembly->assembly->dynamic) {
5906 /* Enumerate all modules */
5907 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5911 if (abuilder->modules) {
5912 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5913 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5914 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5920 if (!type && abuilder->loaded_modules) {
5921 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5922 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5923 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5930 type = mono_reflection_get_type_internal (assembly->assembly->image,
5933 g_string_free (fullName, TRUE);
5938 * mono_reflection_type_from_name:
5940 * @image: a metadata context (can be NULL).
5942 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5943 * it defaults to get the type from @image or, if @image is NULL or loading
5944 * from it fails, uses corlib.
5948 mono_reflection_type_from_name (char *name, MonoImage *image)
5951 MonoTypeNameParse info;
5952 MonoAssembly *assembly;
5954 gboolean type_resolve = FALSE;
5956 /* Make a copy since parse_type modifies its argument */
5957 tmp = g_strdup (name);
5959 /*g_print ("requested type %s\n", str);*/
5960 if (!mono_reflection_parse_type (tmp, &info)) {
5962 g_list_free (info.modifiers);
5963 g_list_free (info.nested);
5967 if (info.assembly.name) {
5968 assembly = mono_assembly_loaded (&info.assembly);
5970 /* then we must load the assembly ourselve - see #60439 */
5971 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5974 g_list_free (info.modifiers);
5975 g_list_free (info.nested);
5979 image = assembly->image;
5980 } else if (image == NULL) {
5981 image = mono_defaults.corlib;
5984 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5985 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5986 image = mono_defaults.corlib;
5987 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5991 g_list_free (info.modifiers);
5992 g_list_free (info.nested);
5997 * mono_reflection_get_token:
5999 * Return the metadata token of OBJ which should be an object
6000 * representing a metadata element.
6003 mono_reflection_get_token (MonoObject *obj)
6008 klass = obj->vtable->klass;
6010 if (strcmp (klass->name, "MethodBuilder") == 0) {
6011 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6013 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6014 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6015 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6017 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6018 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6019 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6020 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6021 if (tb->generic_params) {
6022 g_assert_not_reached ();
6024 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6026 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6027 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6028 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6029 } else if (strcmp (klass->name, "MonoType") == 0) {
6030 MonoReflectionType *tb = (MonoReflectionType *)obj;
6031 token = mono_class_from_mono_type (tb->type)->type_token;
6032 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6033 strcmp (klass->name, "MonoMethod") == 0) {
6034 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6035 if (m->method->signature->is_inflated) {
6036 g_assert_not_reached ();
6037 } else if (m->method->signature->generic_param_count) {
6038 g_assert_not_reached ();
6039 } else if (m->method->klass->generic_inst) {
6040 g_assert_not_reached ();
6042 token = m->method->token;
6044 } else if (strcmp (klass->name, "MonoField") == 0) {
6045 MonoReflectionField *f = (MonoReflectionField*)obj;
6047 token = mono_class_get_field_token (f->field);
6048 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6049 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6051 token = mono_class_get_property_token (p->property);
6052 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6053 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6055 token = mono_class_get_event_token (p->event);
6056 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6057 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6059 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6060 } else if (strcmp (klass->name, "Module") == 0) {
6061 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6064 } else if (strcmp (klass->name, "Assembly") == 0) {
6065 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6067 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6068 MonoException *ex = mono_get_exception_not_implemented (msg);
6070 mono_raise_exception (ex);
6077 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6079 int slen, type = t->type;
6084 case MONO_TYPE_BOOLEAN: {
6085 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6090 case MONO_TYPE_CHAR:
6092 case MONO_TYPE_I2: {
6093 guint16 *val = g_malloc (sizeof (guint16));
6098 #if SIZEOF_VOID_P == 4
6104 case MONO_TYPE_I4: {
6105 guint32 *val = g_malloc (sizeof (guint32));
6110 #if SIZEOF_VOID_P == 8
6111 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6116 case MONO_TYPE_I8: {
6117 guint64 *val = g_malloc (sizeof (guint64));
6122 case MONO_TYPE_VALUETYPE:
6123 if (t->data.klass->enumtype) {
6124 type = t->data.klass->enum_basetype->type;
6127 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6130 case MONO_TYPE_STRING:
6131 if (*p == (char)0xFF) {
6135 slen = mono_metadata_decode_value (p, &p);
6137 return mono_string_new_len (mono_domain_get (), p, slen);
6138 case MONO_TYPE_CLASS: {
6141 if (*p == (char)0xFF) {
6146 slen = mono_metadata_decode_value (p, &p);
6147 n = g_memdup (p, slen + 1);
6149 t = mono_reflection_type_from_name (n, image);
6151 g_warning ("Cannot load type '%s'", n);
6155 return mono_type_get_object (mono_domain_get (), t);
6159 case MONO_TYPE_OBJECT: {
6162 MonoClass *subc = NULL;
6167 } else if (subt == 0x0E) {
6168 type = MONO_TYPE_STRING;
6170 } else if (subt == 0x55) {
6173 slen = mono_metadata_decode_value (p, &p);
6174 n = g_memdup (p, slen + 1);
6176 t = mono_reflection_type_from_name (n, image);
6178 g_warning ("Cannot load type '%s'", n);
6181 subc = mono_class_from_mono_type (t);
6182 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6183 MonoType simple_type = {{0}};
6184 simple_type.type = subt;
6185 subc = mono_class_from_mono_type (&simple_type);
6187 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6189 val = load_cattr_value (image, &subc->byval_arg, p, end);
6190 obj = mono_object_new (mono_domain_get (), subc);
6191 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6195 case MONO_TYPE_SZARRAY: {
6197 guint32 i, alen, basetype;
6200 if (alen == 0xffffffff) {
6204 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6205 basetype = t->data.klass->byval_arg.type;
6210 case MONO_TYPE_BOOLEAN:
6211 for (i = 0; i < alen; i++) {
6212 MonoBoolean val = *p++;
6213 mono_array_set (arr, MonoBoolean, i, val);
6216 case MONO_TYPE_CHAR:
6219 for (i = 0; i < alen; i++) {
6220 guint16 val = read16 (p);
6221 mono_array_set (arr, guint16, i, val);
6228 for (i = 0; i < alen; i++) {
6229 guint32 val = read32 (p);
6230 mono_array_set (arr, guint32, i, val);
6237 for (i = 0; i < alen; i++) {
6238 guint64 val = read64 (p);
6239 mono_array_set (arr, guint64, i, val);
6243 case MONO_TYPE_CLASS:
6244 case MONO_TYPE_OBJECT:
6245 case MONO_TYPE_STRING:
6246 for (i = 0; i < alen; i++) {
6247 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6248 mono_array_set (arr, gpointer, i, item);
6252 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6258 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6264 type_is_reference (MonoType *type)
6266 switch (type->type) {
6267 case MONO_TYPE_BOOLEAN:
6268 case MONO_TYPE_CHAR:
6281 case MONO_TYPE_VALUETYPE:
6289 free_param_data (MonoMethodSignature *sig, void **params) {
6291 for (i = 0; i < sig->param_count; ++i) {
6292 if (!type_is_reference (sig->params [i]))
6293 g_free (params [i]);
6298 * Find the method index in the metadata methodDef table.
6299 * Later put these three helper methods in metadata and export them.
6302 find_method_index (MonoMethod *method) {
6303 MonoClass *klass = method->klass;
6306 for (i = 0; i < klass->method.count; ++i) {
6307 if (method == klass->methods [i])
6308 return klass->method.first + 1 + i;
6314 * Find the field index in the metadata FieldDef table.
6317 find_field_index (MonoClass *klass, MonoClassField *field) {
6320 for (i = 0; i < klass->field.count; ++i) {
6321 if (field == &klass->fields [i])
6322 return klass->field.first + 1 + i;
6328 * Find the property index in the metadata Property table.
6331 find_property_index (MonoClass *klass, MonoProperty *property) {
6334 for (i = 0; i < klass->property.count; ++i) {
6335 if (property == &klass->properties [i])
6336 return klass->property.first + 1 + i;
6342 * Find the event index in the metadata Event table.
6345 find_event_index (MonoClass *klass, MonoEvent *event) {
6348 for (i = 0; i < klass->event.count; ++i) {
6349 if (event == &klass->events [i])
6350 return klass->event.first + 1 + i;
6356 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6358 const char *p = data;
6360 guint32 i, j, num_named;
6364 mono_class_init (method->klass);
6367 attr = mono_object_new (mono_domain_get (), method->klass);
6368 mono_runtime_invoke (method, attr, NULL, NULL);
6372 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6375 /*g_print ("got attr %s\n", method->klass->name);*/
6377 params = g_new (void*, method->signature->param_count);
6381 for (i = 0; i < method->signature->param_count; ++i) {
6382 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6386 attr = mono_object_new (mono_domain_get (), method->klass);
6387 mono_runtime_invoke (method, attr, params, NULL);
6388 free_param_data (method->signature, params);
6390 num_named = read16 (named);
6392 for (j = 0; j < num_named; j++) {
6394 char *name, named_type, data_type;
6395 named_type = *named++;
6396 data_type = *named++; /* type of data */
6397 if (data_type == 0x55) {
6400 type_len = mono_metadata_decode_blob_size (named, &named);
6401 type_name = g_malloc (type_len + 1);
6402 memcpy (type_name, named, type_len);
6403 type_name [type_len] = 0;
6405 /* FIXME: lookup the type and check type consistency */
6406 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6407 /* this seems to be the type of the element of the array */
6408 /* g_print ("skipping 0x%02x after prop\n", *named); */
6411 name_len = mono_metadata_decode_blob_size (named, &named);
6412 name = g_malloc (name_len + 1);
6413 memcpy (name, named, name_len);
6414 name [name_len] = 0;
6416 if (named_type == 0x53) {
6417 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6418 void *val = load_cattr_value (image, field->type, named, &named);
6419 mono_field_set_value (attr, field, val);
6420 if (!type_is_reference (field->type))
6422 } else if (named_type == 0x54) {
6425 MonoType *prop_type;
6427 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6428 /* can we have more that 1 arg in a custom attr named property? */
6429 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6430 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6431 mono_property_set_value (prop, attr, pparams, NULL);
6432 if (!type_is_reference (prop_type))
6433 g_free (pparams [0]);
6442 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6449 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6450 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6451 for (i = 0; i < cinfo->num_attrs; ++i) {
6452 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6453 mono_array_set (result, gpointer, i, attr);
6459 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6461 guint32 mtoken, i, len;
6462 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6464 MonoCustomAttrInfo *ainfo;
6465 GList *tmp, *list = NULL;
6468 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6470 i = mono_metadata_custom_attrs_from_index (image, idx);
6474 while (i < ca->rows) {
6475 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6477 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6480 len = g_list_length (list);
6483 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6484 ainfo->num_attrs = len;
6485 ainfo->image = image;
6486 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6487 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6488 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6489 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6490 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6491 mtoken |= MONO_TOKEN_METHOD_DEF;
6493 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6494 mtoken |= MONO_TOKEN_MEMBER_REF;
6497 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6500 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6501 if (!ainfo->attrs [i].ctor)
6502 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6503 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6504 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6505 ainfo->attrs [i].data = data;
6513 mono_custom_attrs_from_method (MonoMethod *method)
6515 MonoCustomAttrInfo *cinfo;
6518 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6520 idx = find_method_index (method);
6521 idx <<= MONO_CUSTOM_ATTR_BITS;
6522 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6523 return mono_custom_attrs_from_index (method->klass->image, idx);
6527 mono_custom_attrs_from_class (MonoClass *klass)
6529 MonoCustomAttrInfo *cinfo;
6532 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6534 idx = mono_metadata_token_index (klass->type_token);
6535 idx <<= MONO_CUSTOM_ATTR_BITS;
6536 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6537 return mono_custom_attrs_from_index (klass->image, idx);
6541 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6543 MonoCustomAttrInfo *cinfo;
6546 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6548 idx = 1; /* there is only one assembly */
6549 idx <<= MONO_CUSTOM_ATTR_BITS;
6550 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6551 return mono_custom_attrs_from_index (assembly->image, idx);
6554 static MonoCustomAttrInfo*
6555 mono_custom_attrs_from_module (MonoImage *image)
6557 MonoCustomAttrInfo *cinfo;
6560 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6562 idx = 1; /* there is only one module */
6563 idx <<= MONO_CUSTOM_ATTR_BITS;
6564 idx |= MONO_CUSTOM_ATTR_MODULE;
6565 return mono_custom_attrs_from_index (image, idx);
6569 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6571 MonoCustomAttrInfo *cinfo;
6574 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6576 idx = find_property_index (klass, property);
6577 idx <<= MONO_CUSTOM_ATTR_BITS;
6578 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6579 return mono_custom_attrs_from_index (klass->image, idx);
6583 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6585 MonoCustomAttrInfo *cinfo;
6588 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6590 idx = find_event_index (klass, event);
6591 idx <<= MONO_CUSTOM_ATTR_BITS;
6592 idx |= MONO_CUSTOM_ATTR_EVENT;
6593 return mono_custom_attrs_from_index (klass->image, idx);
6597 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6599 MonoCustomAttrInfo *cinfo;
6602 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6604 idx = find_field_index (klass, field);
6605 idx <<= MONO_CUSTOM_ATTR_BITS;
6606 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6607 return mono_custom_attrs_from_index (klass->image, idx);
6611 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6614 guint32 i, idx, method_index;
6615 guint32 param_list, param_last, param_pos, found;
6617 MonoReflectionMethodAux *aux;
6619 if (method->klass->image->dynamic) {
6620 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6621 if (!aux || !aux->param_cattr)
6623 return aux->param_cattr [param];
6626 image = method->klass->image;
6627 method_index = find_method_index (method);
6628 ca = &image->tables [MONO_TABLE_METHOD];
6630 if (method->klass->generic_inst || method->klass->generic_container ||
6631 method->signature->generic_param_count) {
6632 /* FIXME FIXME FIXME */
6636 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6637 if (method_index == ca->rows) {
6638 ca = &image->tables [MONO_TABLE_PARAM];
6639 param_last = ca->rows + 1;
6641 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6642 ca = &image->tables [MONO_TABLE_PARAM];
6645 for (i = param_list; i < param_last; ++i) {
6646 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6647 if (param_pos == param) {
6655 idx <<= MONO_CUSTOM_ATTR_BITS;
6656 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6657 return mono_custom_attrs_from_index (image, idx);
6661 * mono_reflection_get_custom_attrs:
6662 * @obj: a reflection object handle
6664 * Return an array with all the custom attributes defined of the
6665 * reflection handle @obj. The objects are fully build.
6668 mono_reflection_get_custom_attrs (MonoObject *obj)
6672 MonoCustomAttrInfo *cinfo = NULL;
6674 MONO_ARCH_SAVE_REGS;
6676 klass = obj->vtable->klass;
6677 if (klass == mono_defaults.monotype_class) {
6678 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6679 klass = mono_class_from_mono_type (rtype->type);
6680 cinfo = mono_custom_attrs_from_class (klass);
6681 } else if (strcmp ("Assembly", klass->name) == 0) {
6682 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6683 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6684 } else if (strcmp ("Module", klass->name) == 0) {
6685 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6686 cinfo = mono_custom_attrs_from_module (module->image);
6687 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6688 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6689 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6690 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6691 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6692 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6693 } else if (strcmp ("MonoField", klass->name) == 0) {
6694 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6695 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6696 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6697 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6698 cinfo = mono_custom_attrs_from_method (rmethod->method);
6699 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6700 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6701 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6702 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6703 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6704 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6705 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6706 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6707 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6708 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6709 } else { /* handle other types here... */
6710 g_error ("get custom attrs not yet supported for %s", klass->name);
6714 result = mono_custom_attrs_construct (cinfo);
6716 mono_custom_attrs_free (cinfo);
6718 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6719 result = mono_array_new (mono_domain_get (), klass, 0);
6725 static MonoMethodSignature*
6726 parameters_to_signature (MonoArray *parameters) {
6727 MonoMethodSignature *sig;
6730 count = parameters? mono_array_length (parameters): 0;
6732 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6733 sig->param_count = count;
6734 sig->sentinelpos = -1; /* FIXME */
6735 for (i = 0; i < count; ++i) {
6736 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6737 sig->params [i] = pt->type;
6742 static MonoMethodSignature*
6743 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6744 MonoMethodSignature *sig;
6746 sig = parameters_to_signature (ctor->parameters);
6747 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6748 sig->ret = &mono_defaults.void_class->byval_arg;
6752 static MonoMethodSignature*
6753 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6754 MonoMethodSignature *sig;
6756 sig = parameters_to_signature (method->parameters);
6757 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6758 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6759 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6763 static MonoMethodSignature*
6764 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6765 MonoMethodSignature *sig;
6767 sig = parameters_to_signature (method->parameters);
6768 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6769 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6770 sig->generic_param_count = 0;
6775 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6777 MonoClass *klass = mono_object_class (prop);
6778 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6779 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6780 *name = mono_string_to_utf8 (pb->name);
6781 *type = pb->type->type;
6783 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6784 *name = g_strdup (p->property->name);
6785 if (p->property->get)
6786 *type = p->property->get->signature->ret;
6788 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6793 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6795 MonoClass *klass = mono_object_class (field);
6796 if (strcmp (klass->name, "FieldBuilder") == 0) {
6797 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6798 *name = mono_string_to_utf8 (fb->name);
6799 *type = fb->type->type;
6801 MonoReflectionField *f = (MonoReflectionField *)field;
6802 *name = g_strdup (f->field->name);
6803 *type = f->field->type;
6808 * Encode a value in a custom attribute stream of bytes.
6809 * The value to encode is either supplied as an object in argument val
6810 * (valuetypes are boxed), or as a pointer to the data in the
6812 * @type represents the type of the value
6813 * @buffer is the start of the buffer
6814 * @p the current position in the buffer
6815 * @buflen contains the size of the buffer and is used to return the new buffer size
6816 * if this needs to be realloced.
6817 * @retbuffer and @retp return the start and the position of the buffer
6820 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6822 MonoTypeEnum simple_type;
6824 if ((p-buffer) + 10 >= *buflen) {
6827 newbuf = g_realloc (buffer, *buflen);
6828 p = newbuf + (p-buffer);
6832 argval = ((char*)arg + sizeof (MonoObject));
6833 simple_type = type->type;
6835 switch (simple_type) {
6836 case MONO_TYPE_BOOLEAN:
6841 case MONO_TYPE_CHAR:
6844 swap_with_size (p, argval, 2, 1);
6850 swap_with_size (p, argval, 4, 1);
6856 swap_with_size (p, argval, 8, 1);
6859 case MONO_TYPE_VALUETYPE:
6860 if (type->data.klass->enumtype) {
6861 simple_type = type->data.klass->enum_basetype->type;
6864 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6867 case MONO_TYPE_STRING: {
6874 str = mono_string_to_utf8 ((MonoString*)arg);
6875 slen = strlen (str);
6876 if ((p-buffer) + 10 + slen >= *buflen) {
6880 newbuf = g_realloc (buffer, *buflen);
6881 p = newbuf + (p-buffer);
6884 mono_metadata_encode_value (slen, p, &p);
6885 memcpy (p, str, slen);
6890 case MONO_TYPE_CLASS: {
6898 k = mono_object_class (arg);
6899 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6900 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6901 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6903 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6904 slen = strlen (str);
6905 if ((p-buffer) + 10 + slen >= *buflen) {
6909 newbuf = g_realloc (buffer, *buflen);
6910 p = newbuf + (p-buffer);
6913 mono_metadata_encode_value (slen, p, &p);
6914 memcpy (p, str, slen);
6919 case MONO_TYPE_SZARRAY: {
6921 MonoClass *eclass, *arg_eclass;
6924 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6927 len = mono_array_length ((MonoArray*)arg);
6929 *p++ = (len >> 8) & 0xff;
6930 *p++ = (len >> 16) & 0xff;
6931 *p++ = (len >> 24) & 0xff;
6933 *retbuffer = buffer;
6934 eclass = type->data.klass;
6935 arg_eclass = mono_object_class (arg)->element_class;
6936 if (eclass->valuetype && arg_eclass->valuetype) {
6937 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6938 int elsize = mono_class_array_element_size (eclass);
6939 for (i = 0; i < len; ++i) {
6940 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6944 for (i = 0; i < len; ++i) {
6945 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6950 /* it may be a boxed value or a Type */
6951 case MONO_TYPE_OBJECT: {
6952 MonoClass *klass = mono_object_class (arg);
6956 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6959 } else if (klass->enumtype) {
6961 } else if (klass == mono_defaults.string_class) {
6962 simple_type = MONO_TYPE_STRING;
6965 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6966 *p++ = simple_type = klass->byval_arg.type;
6969 g_error ("unhandled type in custom attr");
6971 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6972 slen = strlen (str);
6973 if ((p-buffer) + 10 + slen >= *buflen) {
6977 newbuf = g_realloc (buffer, *buflen);
6978 p = newbuf + (p-buffer);
6981 mono_metadata_encode_value (slen, p, &p);
6982 memcpy (p, str, slen);
6985 simple_type = klass->enum_basetype->type;
6989 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6992 *retbuffer = buffer;
6996 * mono_reflection_get_custom_attrs_blob:
6997 * @ctor: custom attribute constructor
6998 * @ctorArgs: arguments o the constructor
7004 * Creates the blob of data that needs to be saved in the metadata and that represents
7005 * the custom attributed described by @ctor, @ctorArgs etc.
7006 * Returns: a Byte array representing the blob of data.
7009 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7012 MonoMethodSignature *sig;
7017 MONO_ARCH_SAVE_REGS;
7019 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7020 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7022 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7024 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7026 p = buffer = g_malloc (buflen);
7027 /* write the prolog */
7030 for (i = 0; i < sig->param_count; ++i) {
7031 arg = mono_array_get (ctorArgs, MonoObject*, i);
7032 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7036 i += mono_array_length (properties);
7038 i += mono_array_length (fields);
7040 *p++ = (i >> 8) & 0xff;
7043 for (i = 0; i < mono_array_length (properties); ++i) {
7048 prop = mono_array_get (properties, gpointer, i);
7049 get_prop_name_and_type (prop, &pname, &ptype);
7050 *p++ = 0x54; /* PROPERTY signature */
7052 /* Preallocate a large enough buffer */
7053 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7054 char *str = type_get_qualified_name (ptype, NULL);
7060 len += strlen (pname);
7062 if ((p-buffer) + 20 + len >= buflen) {
7066 newbuf = g_realloc (buffer, buflen);
7067 p = newbuf + (p-buffer);
7071 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7072 char *str = type_get_qualified_name (ptype, NULL);
7073 int slen = strlen (str);
7077 * This seems to be optional...
7080 mono_metadata_encode_value (slen, p, &p);
7081 memcpy (p, str, slen);
7085 mono_metadata_encode_value (ptype->type, p, &p);
7086 if (ptype->type == MONO_TYPE_SZARRAY)
7087 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7089 len = strlen (pname);
7090 mono_metadata_encode_value (len, p, &p);
7091 memcpy (p, pname, len);
7093 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7100 for (i = 0; i < mono_array_length (fields); ++i) {
7105 field = mono_array_get (fields, gpointer, i);
7106 get_field_name_and_type (field, &fname, &ftype);
7107 *p++ = 0x53; /* FIELD signature */
7108 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7109 char *str = type_get_qualified_name (ftype, NULL);
7110 int slen = strlen (str);
7111 if ((p-buffer) + 10 + slen >= buflen) {
7115 newbuf = g_realloc (buffer, buflen);
7116 p = newbuf + (p-buffer);
7121 * This seems to be optional...
7124 mono_metadata_encode_value (slen, p, &p);
7125 memcpy (p, str, slen);
7129 mono_metadata_encode_value (ftype->type, p, &p);
7130 if (ftype->type == MONO_TYPE_SZARRAY)
7131 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7133 len = strlen (fname);
7134 mono_metadata_encode_value (len, p, &p);
7135 memcpy (p, fname, len);
7137 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7142 g_assert (p - buffer <= buflen);
7143 buflen = p - buffer;
7144 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7145 p = mono_array_addr (result, char, 0);
7146 memcpy (p, buffer, buflen);
7148 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7154 * mono_reflection_setup_internal_class:
7155 * @tb: a TypeBuilder object
7157 * Creates a MonoClass that represents the TypeBuilder.
7158 * This is a trick that lets us simplify a lot of reflection code
7159 * (and will allow us to support Build and Run assemblies easier).
7162 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7164 MonoClass *klass, *parent;
7166 MONO_ARCH_SAVE_REGS;
7169 /* check so we can compile corlib correctly */
7170 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7171 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7172 parent = tb->parent->type->data.klass;
7174 parent = my_mono_class_from_mono_type (tb->parent->type);
7180 /* the type has already being created: it means we just have to change the parent */
7181 if (tb->type.type) {
7182 klass = mono_class_from_mono_type (tb->type.type);
7183 klass->parent = NULL;
7184 /* fool mono_class_setup_parent */
7185 g_free (klass->supertypes);
7186 klass->supertypes = NULL;
7187 mono_class_setup_parent (klass, parent);
7188 mono_class_setup_mono_type (klass);
7192 klass = g_new0 (MonoClass, 1);
7194 klass->image = &tb->module->dynamic_image->image;
7196 klass->inited = 1; /* we lie to the runtime */
7197 klass->name = mono_string_to_utf8 (tb->name);
7198 klass->name_space = mono_string_to_utf8 (tb->nspace);
7199 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7200 klass->flags = tb->attrs;
7202 klass->element_class = klass;
7203 klass->reflection_info = tb; /* need to pin. */
7205 /* Put into cache so mono_class_get () will find it */
7206 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7208 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7209 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7211 if (parent != NULL) {
7212 mono_class_setup_parent (klass, parent);
7213 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7214 const char *old_n = klass->name;
7215 /* trick to get relative numbering right when compiling corlib */
7216 klass->name = "BuildingObject";
7217 mono_class_setup_parent (klass, mono_defaults.object_class);
7218 klass->name = old_n;
7221 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7222 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7223 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7224 klass->instance_size = sizeof (MonoObject);
7225 klass->size_inited = 1;
7226 mono_class_setup_vtable (klass, NULL, 0);
7229 mono_class_setup_mono_type (klass);
7231 mono_class_setup_supertypes (klass);
7234 * FIXME: handle interfaces.
7237 tb->type.type = &klass->byval_arg;
7239 if (tb->nesting_type) {
7240 g_assert (tb->nesting_type->type);
7241 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7244 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7248 * mono_reflection_setup_generic_class:
7249 * @tb: a TypeBuilder object
7251 * Setup the generic class after all generic parameters have been added.
7254 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7257 MonoGenericContainer *container;
7260 MONO_ARCH_SAVE_REGS;
7262 klass = my_mono_class_from_mono_type (tb->type.type);
7264 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7266 if (klass->generic_container || (count == 0))
7269 klass->generic_container = container = g_new0 (MonoGenericContainer, 1);
7271 container->klass = klass;
7272 container->type_argc = count;
7273 container->type_params = g_new0 (MonoGenericParam, count);
7275 for (i = 0; i < count; i++) {
7276 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7277 container->type_params [i] = *gparam->type.type->data.generic_param;
7278 gparam->type.type->data.generic_param->owner = container;
7279 container->type_params [i].owner = container;
7284 * mono_reflection_create_internal_class:
7285 * @tb: a TypeBuilder object
7287 * Actually create the MonoClass that is associated with the TypeBuilder.
7290 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7294 MONO_ARCH_SAVE_REGS;
7296 klass = my_mono_class_from_mono_type (tb->type.type);
7298 if (klass->enumtype && klass->enum_basetype == NULL) {
7299 MonoReflectionFieldBuilder *fb;
7302 g_assert (tb->fields != NULL);
7303 g_assert (mono_array_length (tb->fields) >= 1);
7305 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7307 klass->enum_basetype = fb->type->type;
7308 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7309 if (!klass->element_class)
7310 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7313 * get the element_class from the current corlib.
7315 ec = default_class_from_mono_type (klass->enum_basetype);
7316 klass->instance_size = ec->instance_size;
7317 klass->size_inited = 1;
7319 * this is almost safe to do with enums and it's needed to be able
7320 * to create objects of the enum type (for use in SetConstant).
7322 /* FIXME: Does this mean enums can't have method overrides ? */
7323 mono_class_setup_vtable (klass, NULL, 0);
7327 static MonoMarshalSpec*
7328 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7329 MonoReflectionMarshal *minfo)
7331 MonoMarshalSpec *res;
7333 res = g_new0 (MonoMarshalSpec, 1);
7334 res->native = minfo->type;
7336 switch (minfo->type) {
7337 case MONO_NATIVE_LPARRAY:
7338 res->data.array_data.elem_type = minfo->eltype;
7339 res->data.array_data.param_num = 0; /* Not yet */
7340 res->data.array_data.num_elem = minfo->count;
7343 case MONO_NATIVE_BYVALTSTR:
7344 case MONO_NATIVE_BYVALARRAY:
7345 res->data.array_data.num_elem = minfo->count;
7348 case MONO_NATIVE_CUSTOM:
7349 if (minfo->marshaltyperef)
7350 res->data.custom_data.custom_name =
7351 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7353 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7363 MonoReflectionMarshal*
7364 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7365 MonoMarshalSpec *spec)
7367 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7368 MonoReflectionMarshal *minfo;
7371 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7372 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7373 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7374 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7377 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7378 minfo->type = spec->native;
7380 switch (minfo->type) {
7381 case MONO_NATIVE_LPARRAY:
7382 minfo->eltype = spec->data.array_data.elem_type;
7383 minfo->count = spec->data.array_data.num_elem;
7386 case MONO_NATIVE_BYVALTSTR:
7387 case MONO_NATIVE_BYVALARRAY:
7388 minfo->count = spec->data.array_data.num_elem;
7391 case MONO_NATIVE_CUSTOM:
7392 if (spec->data.custom_data.custom_name) {
7393 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7395 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7397 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7399 if (spec->data.custom_data.cookie)
7400 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7411 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7412 ReflectionMethodBuilder *rmb,
7413 MonoMethodSignature *sig)
7416 MonoMethodNormal *pm;
7417 MonoMarshalSpec **specs;
7418 MonoReflectionMethodAux *method_aux;
7421 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7422 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7423 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7425 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7427 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7429 pm = (MonoMethodNormal*)m;
7432 m->flags = rmb->attrs;
7433 m->iflags = rmb->iattrs;
7434 m->name = mono_string_to_utf8 (rmb->name);
7438 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7440 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7441 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7444 m->signature->pinvoke = 1;
7445 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7446 m->signature->pinvoke = 1;
7448 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7450 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7451 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7453 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7455 if (klass->image->dynamic)
7456 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7459 } else if (!m->klass->dummy &&
7460 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7461 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7462 MonoMethodHeader *header;
7464 gint32 max_stack, i;
7465 gint32 num_locals = 0;
7466 gint32 num_clauses = 0;
7470 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7471 code_size = rmb->ilgen->code_len;
7472 max_stack = rmb->ilgen->max_stack;
7473 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7474 if (rmb->ilgen->ex_handlers)
7475 num_clauses = method_count_clauses (rmb->ilgen);
7478 code = mono_array_addr (rmb->code, guint8, 0);
7479 code_size = mono_array_length (rmb->code);
7480 /* we probably need to run a verifier on the code... */
7490 header = g_malloc0 (sizeof (MonoMethodHeader) +
7491 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7492 header->code_size = code_size;
7493 header->code = g_malloc (code_size);
7494 memcpy ((char*)header->code, code, code_size);
7495 header->max_stack = max_stack;
7496 header->init_locals = rmb->init_locals;
7497 header->num_locals = num_locals;
7499 for (i = 0; i < num_locals; ++i) {
7500 MonoReflectionLocalBuilder *lb =
7501 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7503 header->locals [i] = g_new0 (MonoType, 1);
7504 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7507 header->num_clauses = num_clauses;
7509 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7510 rmb->ilgen, num_clauses);
7513 pm->header = header;
7516 if (rmb->generic_params) {
7517 int count = mono_array_length (rmb->generic_params);
7518 MonoGenericContainer *container;
7520 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7521 container->type_argc = count;
7522 container->type_params = g_new0 (MonoGenericParam, count);
7524 for (i = 0; i < count; i++) {
7525 MonoReflectionGenericParam *gp =
7526 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7528 container->type_params [i] = *gp->type.type->data.generic_param;
7533 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7536 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7538 for (i = 0; i < rmb->nrefs; ++i)
7539 mw->data = g_list_append (mw->data, rmb->refs [i]);
7544 /* Parameter info */
7547 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7548 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7549 for (i = 0; i <= m->signature->param_count; ++i) {
7550 MonoReflectionParamBuilder *pb;
7551 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7553 m->signature->params [i - 1]->attrs = pb->attrs;
7555 if (pb->def_value) {
7556 MonoDynamicImage *assembly;
7557 guint32 idx, def_type, len;
7561 if (!method_aux->param_defaults)
7562 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7563 assembly = (MonoDynamicImage*)klass->image;
7564 idx = encode_constant (assembly, pb->def_value, &def_type);
7565 /* Copy the data from the blob since it might get realloc-ed */
7566 p = assembly->blob.data + idx;
7567 len = mono_metadata_decode_blob_size (p, &p2);
7569 method_aux->param_defaults [i] = g_malloc (len);
7570 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7574 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7576 if (!method_aux->param_cattr)
7577 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7578 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7584 /* Parameter marshalling */
7587 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7588 MonoReflectionParamBuilder *pb;
7589 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7590 if (pb->marshal_info) {
7592 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7593 specs [pb->position] =
7594 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7598 if (specs != NULL) {
7600 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7601 method_aux->param_marshall = specs;
7604 if (klass->image->dynamic && method_aux)
7605 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7611 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7613 ReflectionMethodBuilder rmb;
7614 MonoMethodSignature *sig;
7616 sig = ctor_builder_to_signature (mb);
7618 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7620 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7621 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7623 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7624 /* ilgen is no longer needed */
7632 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7634 ReflectionMethodBuilder rmb;
7635 MonoMethodSignature *sig;
7637 sig = method_builder_to_signature (mb);
7639 reflection_methodbuilder_from_method_builder (&rmb, mb);
7641 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7642 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7644 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7645 /* ilgen is no longer needed */
7651 static MonoClassField*
7652 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7654 MonoClassField *field;
7661 field = g_new0 (MonoClassField, 1);
7663 field->name = mono_string_to_utf8 (fb->name);
7665 /* FIXME: handle type modifiers */
7666 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7667 field->type->attrs = fb->attrs;
7669 field->type = fb->type->type;
7671 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7672 field->data = mono_array_addr (fb->rva_data, char, 0);
7673 if (fb->offset != -1)
7674 field->offset = fb->offset;
7675 field->parent = klass;
7677 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7679 if (fb->def_value) {
7680 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7681 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7682 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7683 /* Copy the data from the blob since it might get realloc-ed */
7684 p = assembly->blob.data + idx;
7685 len = mono_metadata_decode_blob_size (p, &p2);
7687 field->data = g_malloc (len);
7688 memcpy ((gpointer)field->data, p, len);
7695 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7697 MonoClass *klass, *gklass;
7698 MonoReflectionTypeBuilder *tb = NULL;
7699 MonoGenericInst *ginst, *cached;
7704 klass = mono_class_from_mono_type (type->type);
7705 if (!klass->generic_container && !klass->generic_inst &&
7706 !(klass->nested_in && klass->nested_in->generic_container))
7709 mono_loader_lock ();
7711 domain = mono_object_domain (type);
7713 ginst = g_new0 (MonoGenericInst, 1);
7715 if (!klass->generic_inst) {
7716 ginst->type_argc = type_argc;
7717 ginst->type_argv = types;
7719 for (i = 0; i < ginst->type_argc; ++i) {
7720 if (!ginst->is_open)
7721 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7724 ginst->generic_type = &klass->byval_arg;
7726 MonoGenericInst *kginst = klass->generic_inst;
7728 ginst->type_argc = kginst->type_argc;
7729 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7731 for (i = 0; i < ginst->type_argc; i++) {
7732 MonoType *t = kginst->type_argv [i];
7734 if (t->type == MONO_TYPE_VAR)
7735 t = types [t->data.generic_param->num];
7737 if (!ginst->is_open)
7738 ginst->is_open = mono_class_is_open_constructed_type (t);
7740 ginst->type_argv [i] = t;
7743 ginst->generic_type = kginst->generic_type;
7746 geninst = g_new0 (MonoType, 1);
7747 geninst->type = MONO_TYPE_GENERICINST;
7749 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7752 mono_loader_unlock ();
7753 geninst->data.generic_inst = cached;
7757 gklass = mono_class_from_mono_type (ginst->generic_type);
7758 g_assert ((ginst->container = gklass->generic_container) != NULL);
7760 geninst->data.generic_inst = ginst;
7762 ginst->context = g_new0 (MonoGenericContext, 1);
7763 ginst->context->ginst = ginst;
7765 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7766 tb = (MonoReflectionTypeBuilder *) type;
7768 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7769 ginst->is_dynamic = TRUE;
7770 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7771 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7772 MonoReflectionType *rgt = rgi->generic_type;
7774 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7775 tb = (MonoReflectionTypeBuilder *) rgt;
7777 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7778 ginst->is_dynamic = TRUE;
7780 icount = klass->interface_count;
7783 ginst->ifaces = g_new0 (MonoType *, icount);
7784 ginst->count_ifaces = icount;
7786 for (i = 0; i < icount; i++) {
7787 MonoReflectionType *itype;
7790 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7792 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7793 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7794 if (!ginst->ifaces [i])
7795 ginst->ifaces [i] = itype->type;
7798 mono_class_create_generic (ginst);
7800 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7802 mono_loader_unlock ();
7808 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7810 MonoClass *klass, *pklass = NULL;
7811 MonoReflectionType *parent = NULL;
7813 MonoReflectionTypeBuilder *tb = NULL;
7814 MonoGenericInst *ginst;
7817 domain = mono_object_domain (type);
7818 klass = mono_class_from_mono_type (type->type);
7820 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7821 tb = (MonoReflectionTypeBuilder *) type;
7824 parent = tb->parent;
7825 pklass = mono_class_from_mono_type (parent->type);
7828 pklass = klass->parent;
7830 parent = mono_type_get_object (domain, &pklass->byval_arg);
7833 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7837 ginst = geninst->data.generic_inst;
7839 if (pklass && pklass->generic_inst)
7840 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7845 MonoReflectionMethod*
7846 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7848 MonoMethod *method, *inflated;
7849 MonoReflectionMethodBuilder *mb = NULL;
7850 MonoGenericMethod *gmethod;
7851 MonoGenericContext *context;
7854 MONO_ARCH_SAVE_REGS;
7855 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7856 MonoReflectionTypeBuilder *tb;
7859 mb = (MonoReflectionMethodBuilder *) rmethod;
7860 tb = (MonoReflectionTypeBuilder *) mb->type;
7861 klass = mono_class_from_mono_type (tb->type.type);
7863 method = methodbuilder_to_mono_method (klass, mb);
7865 method = rmethod->method;
7868 count = method->signature->generic_param_count;
7869 if (count != mono_array_length (types))
7872 gmethod = g_new0 (MonoGenericMethod, 1);
7873 gmethod->mtype_argc = count;
7874 gmethod->mtype_argv = g_new0 (MonoType *, count);
7875 for (i = 0; i < count; i++) {
7876 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7877 gmethod->mtype_argv [i] = garg->type;
7880 gmethod->reflection_info = rmethod;
7882 context = g_new0 (MonoGenericContext, 1);
7883 context->ginst = method->klass->generic_inst;
7884 context->gmethod = gmethod;
7886 inflated = mono_class_inflate_generic_method (method, context, NULL);
7888 return mono_method_get_object (
7889 mono_object_domain (rmethod), inflated, NULL);
7893 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7895 MonoGenericMethod *gmethod;
7896 MonoGenericInst *ginst;
7897 MonoGenericContext *context;
7900 ginst = type->type.type->data.generic_inst;
7902 gmethod = g_new0 (MonoGenericMethod, 1);
7903 gmethod->reflection_info = obj;
7905 gmethod->mtype_argc = method->signature->generic_param_count;
7906 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7908 for (i = 0; i < gmethod->mtype_argc; i++) {
7909 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7910 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7912 g_assert (gparam->pklass);
7913 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7916 context = g_new0 (MonoGenericContext, 1);
7917 context->ginst = ginst;
7918 context->gmethod = gmethod;
7920 return mono_class_inflate_generic_method (method, context, ginst->klass);
7924 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7929 klass = mono_class_from_mono_type (type->type.type);
7931 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7932 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7933 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7934 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7935 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7936 method = ((MonoReflectionMethod *) obj)->method;
7938 method = NULL; /* prevent compiler warning */
7939 g_assert_not_reached ();
7942 return inflate_mono_method (type, method, obj);
7946 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
7947 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7949 MonoGenericInst *ginst;
7950 MonoDynamicGenericInst *dginst;
7951 MonoClass *klass, *gklass, *pklass;
7954 MONO_ARCH_SAVE_REGS;
7956 klass = mono_class_from_mono_type (type->type.type);
7957 ginst = type->type.type->data.generic_inst;
7959 if (ginst->initialized)
7962 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7964 gklass = mono_class_from_mono_type (ginst->generic_type);
7965 mono_class_init (gklass);
7968 pklass = mono_class_from_mono_type (ginst->parent);
7970 pklass = gklass->parent;
7972 mono_class_setup_parent (klass, pklass);
7974 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7975 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7976 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7977 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7978 dginst->count_events = events ? mono_array_length (events) : 0;
7980 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7981 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7982 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7983 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7984 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7986 for (i = 0; i < dginst->count_methods; i++) {
7987 MonoObject *obj = mono_array_get (methods, gpointer, i);
7989 dginst->methods [i] = inflate_method (type, obj);
7992 for (i = 0; i < dginst->count_ctors; i++) {
7993 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7995 dginst->ctors [i] = inflate_method (type, obj);
7998 for (i = 0; i < dginst->count_fields; i++) {
7999 MonoObject *obj = mono_array_get (fields, gpointer, i);
8000 MonoClassField *field;
8001 MonoInflatedField *ifield;
8003 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8004 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8005 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8006 field = ((MonoReflectionField *) obj)->field;
8008 field = NULL; /* prevent compiler warning */
8009 g_assert_not_reached ();
8012 ifield = g_new0 (MonoInflatedField, 1);
8013 ifield->generic_type = field->type;
8014 ifield->reflection_info = obj;
8016 dginst->fields [i] = *field;
8017 dginst->fields [i].generic_info = ifield;
8018 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8021 for (i = 0; i < dginst->count_properties; i++) {
8022 MonoObject *obj = mono_array_get (properties, gpointer, i);
8023 MonoProperty *property = &dginst->properties [i];
8025 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8026 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8028 property->parent = klass;
8029 property->attrs = pb->attrs;
8030 property->name = mono_string_to_utf8 (pb->name);
8032 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8034 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8035 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8036 *property = *((MonoReflectionProperty *) obj)->property;
8039 property->get = inflate_mono_method (type, property->get, NULL);
8041 property->set = inflate_mono_method (type, property->set, NULL);
8043 g_assert_not_reached ();
8046 for (i = 0; i < dginst->count_events; i++) {
8047 MonoObject *obj = mono_array_get (events, gpointer, i);
8048 MonoEvent *event = &dginst->events [i];
8050 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8051 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8053 event->parent = klass;
8054 event->attrs = eb->attrs;
8055 event->name = mono_string_to_utf8 (eb->name);
8057 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8058 if (eb->remove_method)
8059 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8060 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8061 *event = *((MonoReflectionEvent *) obj)->event;
8064 event->add = inflate_mono_method (type, event->add, NULL);
8066 event->remove = inflate_mono_method (type, event->remove, NULL);
8068 g_assert_not_reached ();
8071 ginst->initialized = TRUE;
8075 ensure_runtime_vtable (MonoClass *klass)
8077 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8078 int i, num, j, onum;
8079 MonoMethod **overrides;
8081 if (!tb || klass->wastypebuilder)
8084 ensure_runtime_vtable (klass->parent);
8086 num = tb->ctors? mono_array_length (tb->ctors): 0;
8087 num += tb->num_methods;
8088 klass->method.count = num;
8089 klass->methods = g_new (MonoMethod*, num);
8090 num = tb->ctors? mono_array_length (tb->ctors): 0;
8091 for (i = 0; i < num; ++i)
8092 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8093 num = tb->num_methods;
8095 for (i = 0; i < num; ++i)
8096 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8098 klass->wastypebuilder = TRUE;
8099 if (tb->interfaces) {
8100 klass->interface_count = mono_array_length (tb->interfaces);
8101 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8102 for (i = 0; i < klass->interface_count; ++i) {
8103 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8104 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8108 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8109 for (i = 0; i < klass->method.count; ++i)
8110 klass->methods [i]->slot = i;
8115 for (i = 0; i < tb->num_methods; ++i) {
8116 MonoReflectionMethodBuilder *mb =
8117 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8118 if (mb->override_method)
8123 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8127 for (i = 0; i < tb->num_methods; ++i) {
8128 MonoReflectionMethodBuilder *mb =
8129 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8130 if (mb->override_method) {
8131 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8132 overrides [onum * 2] =
8133 mb->override_method->method;
8134 overrides [onum * 2 + 1] =
8137 g_assert (mb->mhandle);
8144 mono_class_setup_vtable (klass, overrides, onum);
8148 typebuilder_setup_fields (MonoClass *klass)
8150 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8151 MonoReflectionFieldBuilder *fb;
8152 MonoClassField *field;
8157 klass->field.count = tb->num_fields;
8158 klass->field.first = 0;
8159 klass->field.last = klass->field.count;
8161 if (!klass->field.count)
8164 klass->fields = g_new0 (MonoClassField, klass->field.count);
8166 for (i = 0; i < klass->field.count; ++i) {
8167 fb = mono_array_get (tb->fields, gpointer, i);
8168 field = &klass->fields [i];
8169 field->name = mono_string_to_utf8 (fb->name);
8171 /* FIXME: handle type modifiers */
8172 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8173 field->type->attrs = fb->attrs;
8175 field->type = fb->type->type;
8177 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8178 field->data = mono_array_addr (fb->rva_data, char, 0);
8179 if (fb->offset != -1)
8180 field->offset = fb->offset;
8181 field->parent = klass;
8183 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8185 if (fb->def_value) {
8186 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8187 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8188 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8189 /* Copy the data from the blob since it might get realloc-ed */
8190 p = assembly->blob.data + idx;
8191 len = mono_metadata_decode_blob_size (p, &p2);
8193 field->data = g_malloc (len);
8194 memcpy ((gpointer)field->data, p, len);
8197 mono_class_layout_fields (klass);
8201 typebuilder_setup_properties (MonoClass *klass)
8203 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8204 MonoReflectionPropertyBuilder *pb;
8207 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8208 klass->property.first = 0;
8209 klass->property.last = klass->property.count;
8211 klass->properties = g_new0 (MonoProperty, klass->property.count);
8212 for (i = 0; i < klass->property.count; ++i) {
8213 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8214 klass->properties [i].parent = klass;
8215 klass->properties [i].attrs = pb->attrs;
8216 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8218 klass->properties [i].get = pb->get_method->mhandle;
8220 klass->properties [i].set = pb->set_method->mhandle;
8224 MonoReflectionEvent *
8225 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8227 MonoEvent *event = g_new0 (MonoEvent, 1);
8231 klass = my_mono_class_from_mono_type (tb->type.type);
8233 event->parent = klass;
8234 event->attrs = eb->attrs;
8235 event->name = mono_string_to_utf8 (eb->name);
8237 event->add = eb->add_method->mhandle;
8238 if (eb->remove_method)
8239 event->remove = eb->remove_method->mhandle;
8240 if (eb->raise_method)
8241 event->raise = eb->raise_method->mhandle;
8243 if (eb->other_methods) {
8244 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8245 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8246 MonoReflectionMethodBuilder *mb =
8247 mono_array_get (eb->other_methods,
8248 MonoReflectionMethodBuilder*, j);
8249 event->other [j] = mb->mhandle;
8253 return mono_event_get_object (mono_object_domain (tb), klass, event);
8257 typebuilder_setup_events (MonoClass *klass)
8259 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8260 MonoReflectionEventBuilder *eb;
8263 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8264 klass->event.first = 0;
8265 klass->event.last = klass->event.count;
8267 klass->events = g_new0 (MonoEvent, klass->event.count);
8268 for (i = 0; i < klass->event.count; ++i) {
8269 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8270 klass->events [i].parent = klass;
8271 klass->events [i].attrs = eb->attrs;
8272 klass->events [i].name = mono_string_to_utf8 (eb->name);
8274 klass->events [i].add = eb->add_method->mhandle;
8275 if (eb->remove_method)
8276 klass->events [i].remove = eb->remove_method->mhandle;
8277 if (eb->raise_method)
8278 klass->events [i].raise = eb->raise_method->mhandle;
8280 if (eb->other_methods) {
8281 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8282 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8283 MonoReflectionMethodBuilder *mb =
8284 mono_array_get (eb->other_methods,
8285 MonoReflectionMethodBuilder*, j);
8286 klass->events [i].other [j] = mb->mhandle;
8293 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8296 MonoReflectionType* res;
8299 MONO_ARCH_SAVE_REGS;
8301 klass = my_mono_class_from_mono_type (tb->type.type);
8303 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8306 * Fields to set in klass:
8307 * the various flags: delegate/unicode/contextbound etc.
8309 klass->flags = tb->attrs;
8311 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8312 /* No need to fully construct the type */
8313 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8315 /* enums are done right away */
8316 if (!klass->enumtype)
8317 ensure_runtime_vtable (klass);
8320 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8321 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8322 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8326 /* fields and object layout */
8327 if (klass->parent) {
8328 if (!klass->parent->size_inited)
8329 mono_class_init (klass->parent);
8330 klass->instance_size += klass->parent->instance_size;
8331 klass->class_size += klass->parent->class_size;
8332 klass->min_align = klass->parent->min_align;
8334 klass->instance_size = sizeof (MonoObject);
8335 klass->min_align = 1;
8338 /* FIXME: handle packing_size and instance_size */
8339 typebuilder_setup_fields (klass);
8341 typebuilder_setup_properties (klass);
8343 typebuilder_setup_events (klass);
8345 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8346 /* with enums res == tb: need to fix that. */
8347 if (!klass->enumtype)
8348 g_assert (res != (MonoReflectionType*)tb);
8353 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8355 MonoGenericParam *param;
8358 MONO_ARCH_SAVE_REGS;
8360 param = g_new0 (MonoGenericParam, 1);
8362 if (gparam->mbuilder) {
8363 if (!gparam->mbuilder->generic_container)
8364 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8365 param->owner = gparam->mbuilder->generic_container;
8366 } else if (gparam->tbuilder) {
8367 if (!gparam->tbuilder->generic_container) {
8368 MonoClass *klass = my_mono_class_from_mono_type (gparam->tbuilder->type.type);
8369 gparam->tbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8370 gparam->tbuilder->generic_container->klass = klass;
8372 param->owner = gparam->tbuilder->generic_container;
8375 param->method = NULL;
8376 param->name = mono_string_to_utf8 (gparam->name);
8377 param->num = gparam->index;
8379 image = &gparam->tbuilder->module->dynamic_image->image;
8380 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8382 param->pklass->reflection_info = gparam;
8384 gparam->type.type = g_new0 (MonoType, 1);
8385 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8386 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8387 gparam->type.type->data.generic_param = param;
8391 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8393 MonoDynamicImage *assembly = sig->module->dynamic_image;
8394 guint32 na = mono_array_length (sig->arguments);
8399 MONO_ARCH_SAVE_REGS;
8401 p = buf = g_malloc (10 + na * 10);
8403 mono_metadata_encode_value (0x07, p, &p);
8404 mono_metadata_encode_value (na, p, &p);
8405 for (i = 0; i < na; ++i) {
8406 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8407 encode_reflection_type (assembly, type, p, &p);
8411 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8412 p = mono_array_addr (result, char, 0);
8413 memcpy (p, buf, buflen);
8420 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8422 MonoDynamicImage *assembly = sig->module->dynamic_image;
8423 guint32 na = mono_array_length (sig->arguments);
8428 MONO_ARCH_SAVE_REGS;
8430 p = buf = g_malloc (10 + na * 10);
8432 mono_metadata_encode_value (0x06, p, &p);
8433 for (i = 0; i < na; ++i) {
8434 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8435 encode_reflection_type (assembly, type, p, &p);
8439 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8440 p = mono_array_addr (result, char, 0);
8441 memcpy (p, buf, buflen);
8448 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8450 ReflectionMethodBuilder rmb;
8451 MonoMethodSignature *sig;
8454 sig = dynamic_method_to_signature (mb);
8456 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8459 * Resolve references.
8461 rmb.nrefs = mb->nrefs;
8462 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8463 for (i = 0; i < mb->nrefs; ++i) {
8464 gpointer ref = resolve_object (mb->module->image,
8465 mono_array_get (mb->refs, MonoObject*, i));
8468 mono_raise_exception (mono_get_exception_type_load (NULL));
8475 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8479 /* ilgen is no longer needed */
8484 * mono_reflection_lookup_dynamic_token:
8486 * Finish the Builder object pointed to by TOKEN and return the corresponding
8487 * runtime structure.
8490 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8492 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8495 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8498 return resolve_object (image, obj);
8502 resolve_object (MonoImage *image, MonoObject *obj)
8504 gpointer result = NULL;
8506 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8507 result = mono_string_intern ((MonoString*)obj);
8509 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8510 MonoReflectionType *tb = (MonoReflectionType*)obj;
8511 result = mono_class_from_mono_type (tb->type);
8513 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8514 result = ((MonoReflectionMethod*)obj)->method;
8516 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8517 result = ((MonoReflectionMethod*)obj)->method;
8519 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8520 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8521 result = mb->mhandle;
8523 /* Type is not yet created */
8524 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8526 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8529 * Hopefully this has been filled in by calling CreateType() on the
8533 * TODO: This won't work if the application finishes another
8534 * TypeBuilder instance instead of this one.
8536 result = mb->mhandle;
8538 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8539 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8541 result = cb->mhandle;
8543 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8545 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8546 result = cb->mhandle;
8548 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8549 result = ((MonoReflectionField*)obj)->field;
8551 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8552 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8553 result = fb->handle;
8556 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8558 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8559 result = fb->handle;
8561 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8562 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8565 klass = tb->type.type->data.klass;
8566 if (klass->wastypebuilder) {
8567 /* Already created */
8571 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8572 result = tb->type.type->data.klass;
8575 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8576 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8577 MonoMethodSignature *sig;
8580 if (helper->arguments)
8581 nargs = mono_array_length (helper->arguments);
8585 sig = mono_metadata_signature_alloc (image, nargs);
8586 sig->explicit_this = helper->call_conv & 64;
8587 sig->hasthis = helper->call_conv & 32;
8589 if (helper->call_conv == 0) /* unmanaged */
8590 sig->call_convention = helper->unmanaged_call_conv - 1;
8592 if (helper->call_conv & 0x02)
8593 sig->call_convention = MONO_CALL_VARARG;
8595 sig->call_convention = MONO_CALL_DEFAULT;
8597 sig->param_count = nargs;
8598 /* TODO: Copy type ? */
8599 sig->ret = helper->return_type->type;
8600 for (i = 0; i < nargs; ++i) {
8601 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8602 sig->params [i] = rt->type;
8607 g_print (obj->vtable->klass->name);
8608 g_assert_not_reached ();