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,
125 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
126 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
127 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
128 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
129 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
130 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
131 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
132 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
133 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
134 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
135 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
136 static void ensure_runtime_vtable (MonoClass *klass);
137 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
138 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
139 static guint32 type_get_signature_size (MonoType *type);
140 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
141 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows) {
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
162 make_room_in_stream (MonoDynamicStream *stream, int size)
164 if (size <= stream->alloc_size)
167 while (stream->alloc_size <= size) {
168 if (stream->alloc_size < 4096)
169 stream->alloc_size = 4096;
171 stream->alloc_size *= 2;
174 stream->data = g_realloc (stream->data, stream->alloc_size);
178 string_heap_insert (MonoDynamicStream *sh, const char *str)
182 gpointer oldkey, oldval;
184 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
185 return GPOINTER_TO_UINT (oldval);
187 len = strlen (str) + 1;
190 make_room_in_stream (sh, idx + len);
193 * We strdup the string even if we already copy them in sh->data
194 * so that the string pointers in the hash remain valid even if
195 * we need to realloc sh->data. We may want to avoid that later.
197 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
198 memcpy (sh->data + idx, str, len);
204 string_heap_init (MonoDynamicStream *sh)
207 sh->alloc_size = 4096;
208 sh->data = g_malloc (4096);
209 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
210 string_heap_insert (sh, "");
213 #if 0 /* never used */
215 string_heap_free (MonoDynamicStream *sh)
218 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
219 g_hash_table_destroy (sh->hash);
224 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
228 make_room_in_stream (stream, stream->index + len);
229 memcpy (stream->data + stream->index, data, len);
231 stream->index += len;
233 * align index? Not without adding an additional param that controls it since
234 * we may store a blob value in pieces.
240 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
244 make_room_in_stream (stream, stream->index + len);
245 memset (stream->data + stream->index, 0, len);
247 stream->index += len;
252 stream_data_align (MonoDynamicStream *stream)
255 guint32 count = stream->index % 4;
257 /* we assume the stream data will be aligned */
259 mono_image_add_stream_data (stream, buf, 4 - count);
263 mono_blob_entry_hash (const char* str)
267 len = mono_metadata_decode_blob_size (str, &str);
271 for (str += 1; str < end; str++)
272 h = (h << 5) - h + *str;
280 mono_blob_entry_equal (const char *str1, const char *str2) {
284 len = mono_metadata_decode_blob_size (str1, &end1);
285 len2 = mono_metadata_decode_blob_size (str2, &end2);
288 return memcmp (end1, end2, len) == 0;
292 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
296 gpointer oldkey, oldval;
298 copy = g_malloc (s1+s2);
299 memcpy (copy, b1, s1);
300 memcpy (copy + s1, b2, s2);
301 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
303 idx = GPOINTER_TO_UINT (oldval);
305 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
306 mono_image_add_stream_data (&assembly->blob, b2, s2);
307 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
313 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
314 * dest may be misaligned.
317 swap_with_size (char *dest, const char* val, int len, int nelem) {
318 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
321 for (elem = 0; elem < nelem; ++elem) {
347 g_assert_not_reached ();
353 memcpy (dest, val, len * nelem);
358 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
362 guint32 idx = 0, len;
364 len = str->length * 2;
365 mono_metadata_encode_value (len, b, &b);
366 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
368 char *swapped = g_malloc (2 * mono_string_length (str));
369 const char *p = (const char*)mono_string_chars (str);
371 swap_with_size (swapped, p, 2, mono_string_length (str));
372 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
376 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
381 /* modified version needed to handle building corlib */
383 my_mono_class_from_mono_type (MonoType *type) {
384 switch (type->type) {
385 case MONO_TYPE_ARRAY:
387 case MONO_TYPE_SZARRAY:
388 case MONO_TYPE_GENERICINST:
389 return mono_class_from_mono_type (type);
392 g_assert (type->data.generic_param->pklass);
393 return type->data.generic_param->pklass;
395 /* should be always valid when we reach this case... */
396 return type->data.klass;
401 default_class_from_mono_type (MonoType *type)
403 switch (type->type) {
404 case MONO_TYPE_OBJECT:
405 return mono_defaults.object_class;
407 return mono_defaults.void_class;
408 case MONO_TYPE_BOOLEAN:
409 return mono_defaults.boolean_class;
411 return mono_defaults.char_class;
413 return mono_defaults.sbyte_class;
415 return mono_defaults.byte_class;
417 return mono_defaults.int16_class;
419 return mono_defaults.uint16_class;
421 return mono_defaults.int32_class;
423 return mono_defaults.uint32_class;
425 return mono_defaults.int_class;
427 return mono_defaults.uint_class;
429 return mono_defaults.int64_class;
431 return mono_defaults.uint64_class;
433 return mono_defaults.single_class;
435 return mono_defaults.double_class;
436 case MONO_TYPE_STRING:
437 return mono_defaults.string_class;
439 g_warning ("implement me 0x%02x\n", type->type);
440 g_assert_not_reached ();
447 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
452 g_assert_not_reached ();
456 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
457 encode_type (assembly, ginst->generic_type, p, &p);
458 mono_metadata_encode_value (ginst->type_argc, p, &p);
459 for (i = 0; i < ginst->type_argc; ++i)
460 encode_type (assembly, ginst->type_argv [i], p, &p);
466 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
469 g_assert_not_reached ();
474 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
478 case MONO_TYPE_BOOLEAN:
492 case MONO_TYPE_STRING:
493 case MONO_TYPE_OBJECT:
494 case MONO_TYPE_TYPEDBYREF:
495 mono_metadata_encode_value (type->type, p, &p);
498 mono_metadata_encode_value (type->type, p, &p);
499 encode_type (assembly, type->data.type, p, &p);
501 case MONO_TYPE_SZARRAY:
502 mono_metadata_encode_value (type->type, p, &p);
503 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
505 case MONO_TYPE_VALUETYPE:
506 case MONO_TYPE_CLASS: {
507 MonoClass *k = mono_class_from_mono_type (type);
508 mono_metadata_encode_value (type->type, p, &p);
510 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
511 * otherwise two typerefs could point to the same type, leading to
512 * verification errors.
514 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
517 case MONO_TYPE_ARRAY:
518 mono_metadata_encode_value (type->type, p, &p);
519 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
520 mono_metadata_encode_value (type->data.array->rank, p, &p);
521 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
522 mono_metadata_encode_value (0, p, &p);
524 case MONO_TYPE_GENERICINST:
525 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
529 mono_metadata_encode_value (type->type, p, &p);
530 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
533 g_error ("need to encode type %x", type->type);
539 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
542 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
546 encode_type (assembly, type->type, p, endbuf);
550 g_assert_not_reached ();
555 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
560 for (i = 0; i < mono_array_length (modreq); ++i) {
561 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
562 *p = MONO_TYPE_CMOD_REQD;
564 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
568 for (i = 0; i < mono_array_length (modopt); ++i) {
569 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
570 *p = MONO_TYPE_CMOD_OPT;
572 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
579 generic_inst_get_signature_size (MonoGenericInst *ginst)
585 g_assert_not_reached ();
588 size += 1 + type_get_signature_size (ginst->generic_type);
590 for (i = 0; i < ginst->type_argc; ++i)
591 size += type_get_signature_size (ginst->type_argv [i]);
597 type_get_signature_size (MonoType *type)
602 g_assert_not_reached ();
610 case MONO_TYPE_BOOLEAN:
624 case MONO_TYPE_STRING:
625 case MONO_TYPE_OBJECT:
626 case MONO_TYPE_TYPEDBYREF:
629 return size + 1 + type_get_signature_size (type->data.type);
630 case MONO_TYPE_SZARRAY:
631 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
632 case MONO_TYPE_VALUETYPE:
633 case MONO_TYPE_CLASS:
635 case MONO_TYPE_ARRAY:
636 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
637 case MONO_TYPE_GENERICINST:
638 return size + generic_inst_get_signature_size (type->data.generic_inst);
643 g_error ("need to encode type %x", type->type);
649 method_get_signature_size (MonoMethodSignature *sig)
654 size = type_get_signature_size (sig->ret);
655 for (i = 0; i < sig->param_count; i++)
656 size += type_get_signature_size (sig->params [i]);
658 if (sig->generic_param_count)
660 if (sig->sentinelpos >= 0)
667 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
672 guint32 nparams = sig->param_count;
673 guint32 size = 11 + method_get_signature_size (sig);
681 p = buf = g_malloc (size);
683 * FIXME: vararg, explicit_this, differenc call_conv values...
685 *p = sig->call_convention;
687 *p |= 0x20; /* hasthis */
688 if (sig->generic_param_count)
689 *p |= 0x10; /* generic */
691 if (sig->generic_param_count)
692 mono_metadata_encode_value (sig->generic_param_count, p, &p);
693 mono_metadata_encode_value (nparams, p, &p);
694 encode_type (assembly, sig->ret, p, &p);
695 for (i = 0; i < nparams; ++i) {
696 if (i == sig->sentinelpos)
697 *p++ = MONO_TYPE_SENTINEL;
698 encode_type (assembly, sig->params [i], p, &p);
701 g_assert (p - buf < size);
702 mono_metadata_encode_value (p-buf, b, &b);
703 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
709 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
712 * FIXME: reuse code from method_encode_signature().
717 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
718 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
719 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
720 guint32 size = 21 + nparams * 20 + notypes * 20;
725 p = buf = g_malloc (size);
726 /* LAMESPEC: all the call conv spec is foobared */
727 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
728 if (mb->call_conv & 2)
729 *p |= 0x5; /* vararg */
730 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
731 *p |= 0x20; /* hasthis */
733 *p |= 0x10; /* generic */
736 mono_metadata_encode_value (ngparams, p, &p);
737 mono_metadata_encode_value (nparams + notypes, p, &p);
738 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
739 encode_reflection_type (assembly, mb->rtype, p, &p);
740 for (i = 0; i < nparams; ++i) {
741 MonoArray *modreq = NULL;
742 MonoArray *modopt = NULL;
743 MonoReflectionType *pt;
745 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
746 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
747 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
748 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
749 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
750 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
751 encode_reflection_type (assembly, pt, p, &p);
754 *p++ = MONO_TYPE_SENTINEL;
755 for (i = 0; i < notypes; ++i) {
756 MonoReflectionType *pt;
758 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
759 encode_reflection_type (assembly, pt, p, &p);
763 g_assert (p - buf < size);
764 mono_metadata_encode_value (p-buf, b, &b);
765 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
771 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
773 MonoDynamicTable *table;
776 guint32 idx, sig_idx, size;
777 guint nl = mono_array_length (ilgen->locals);
784 p = buf = g_malloc (size);
785 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
786 idx = table->next_idx ++;
788 alloc_table (table, table->rows);
789 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
791 mono_metadata_encode_value (0x07, p, &p);
792 mono_metadata_encode_value (nl, p, &p);
793 for (i = 0; i < nl; ++i) {
794 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
797 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
799 encode_reflection_type (assembly, lb->type, p, &p);
801 g_assert (p - buf < size);
802 mono_metadata_encode_value (p-buf, b, &b);
803 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
806 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
812 method_count_clauses (MonoReflectionILGen *ilgen)
814 guint32 num_clauses = 0;
817 MonoILExceptionInfo *ex_info;
818 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
819 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
820 if (ex_info->handlers)
821 num_clauses += mono_array_length (ex_info->handlers);
829 static MonoExceptionClause*
830 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
832 MonoExceptionClause *clauses;
833 MonoExceptionClause *clause;
834 MonoILExceptionInfo *ex_info;
835 MonoILExceptionBlock *ex_block;
836 guint32 finally_start;
837 int i, j, clause_index;;
839 clauses = g_new0 (MonoExceptionClause, num_clauses);
842 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
843 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
844 finally_start = ex_info->start + ex_info->len;
845 g_assert (ex_info->handlers);
846 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
847 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
848 clause = &(clauses [clause_index]);
850 clause->flags = ex_block->type;
851 clause->try_offset = ex_info->start;
853 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
854 clause->try_len = finally_start - ex_info->start;
856 clause->try_len = ex_info->len;
857 clause->handler_offset = ex_block->start;
858 clause->handler_len = ex_block->len;
859 if (ex_block->extype) {
860 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
862 /* FIXME: handle filters */
863 clause->data.filter_offset = 0;
865 finally_start = ex_block->start + ex_block->len;
875 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
881 gint32 num_locals = 0;
882 gint32 num_exception = 0;
885 char fat_header [12];
888 guint32 local_sig = 0;
889 guint32 header_size = 12;
892 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
893 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
897 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
899 code = mb->ilgen->code;
900 code_size = mb->ilgen->code_len;
901 max_stack = mb->ilgen->max_stack;
902 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
903 if (mb->ilgen->ex_handlers)
904 num_exception = method_count_clauses (mb->ilgen);
908 char *name = mono_string_to_utf8 (mb->name);
909 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
910 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
913 mono_raise_exception (exception);
916 code_size = mono_array_length (code);
917 max_stack = 8; /* we probably need to run a verifier on the code... */
920 stream_data_align (&assembly->code);
922 /* check for exceptions, maxstack, locals */
923 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
925 if (code_size < 64 && !(code_size & 1)) {
926 flags = (code_size << 2) | 0x2;
927 } else if (code_size < 32 && (code_size & 1)) {
928 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
932 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
933 /* add to the fixup todo list */
934 if (mb->ilgen && mb->ilgen->num_token_fixups)
935 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
936 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
937 return assembly->text_rva + idx;
941 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
943 * FIXME: need to set also the header size in fat_flags.
944 * (and more sects and init locals flags)
948 fat_flags |= METHOD_HEADER_MORE_SECTS;
950 fat_flags |= METHOD_HEADER_INIT_LOCALS;
951 fat_header [0] = fat_flags;
952 fat_header [1] = (header_size / 4 ) << 4;
953 shortp = (guint16*)(fat_header + 2);
954 *shortp = GUINT16_TO_LE (max_stack);
955 intp = (guint32*)(fat_header + 4);
956 *intp = GUINT32_TO_LE (code_size);
957 intp = (guint32*)(fat_header + 8);
958 *intp = GUINT32_TO_LE (local_sig);
959 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
960 /* add to the fixup todo list */
961 if (mb->ilgen && mb->ilgen->num_token_fixups)
962 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
964 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
966 unsigned char sheader [4];
967 MonoILExceptionInfo * ex_info;
968 MonoILExceptionBlock * ex_block;
971 stream_data_align (&assembly->code);
972 /* always use fat format for now */
973 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
974 num_exception *= 6 * sizeof (guint32);
975 num_exception += 4; /* include the size of the header */
976 sheader [1] = num_exception & 0xff;
977 sheader [2] = (num_exception >> 8) & 0xff;
978 sheader [3] = (num_exception >> 16) & 0xff;
979 mono_image_add_stream_data (&assembly->code, sheader, 4);
980 /* fat header, so we are already aligned */
982 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
983 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
984 if (ex_info->handlers) {
985 int finally_start = ex_info->start + ex_info->len;
986 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
988 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
990 val = GUINT32_TO_LE (ex_block->type);
991 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
993 val = GUINT32_TO_LE (ex_info->start);
994 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
995 /* need fault, too, probably */
996 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
997 val = GUINT32_TO_LE (finally_start - ex_info->start);
999 val = GUINT32_TO_LE (ex_info->len);
1000 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1001 /* handler offset */
1002 val = GUINT32_TO_LE (ex_block->start);
1003 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1005 val = GUINT32_TO_LE (ex_block->len);
1006 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1007 finally_start = ex_block->start + ex_block->len;
1008 if (ex_block->extype) {
1009 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1011 /* FIXME: handle filters */
1014 val = GUINT32_TO_LE (val);
1015 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1016 /*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",
1017 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);*/
1020 g_error ("No clauses for ex info block %d", i);
1024 return assembly->text_rva + idx;
1028 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1031 MonoDynamicTable *table;
1034 table = &assembly->tables [table_idx];
1036 g_assert (col < table->columns);
1038 values = table->values + table->columns;
1039 for (i = 1; i <= table->rows; ++i) {
1040 if (values [col] == token)
1042 values += table->columns;
1047 static GHashTable *dynamic_custom_attrs = NULL;
1049 static MonoCustomAttrInfo*
1050 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1053 MonoCustomAttrInfo *ainfo;
1054 MonoReflectionCustomAttr *cattr;
1058 /* FIXME: check in assembly the Run flag is set */
1060 count = mono_array_length (cattrs);
1062 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1064 ainfo->image = image;
1065 ainfo->num_attrs = count;
1066 for (i = 0; i < count; ++i) {
1067 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1068 ainfo->attrs [i].ctor = cattr->ctor->method;
1069 /* FIXME: might want to memdup the data here */
1070 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1071 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1078 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1080 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1085 if (!dynamic_custom_attrs)
1086 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1088 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1089 ainfo->cached = TRUE;
1093 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1095 /* they are cached, so we don't free them */
1096 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1102 * idx is the table index of the object
1103 * type is one of MONO_CUSTOM_ATTR_*
1106 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1108 MonoDynamicTable *table;
1109 MonoReflectionCustomAttr *cattr;
1111 guint32 count, i, token;
1113 char *p = blob_size;
1115 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1118 count = mono_array_length (cattrs);
1119 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1120 table->rows += count;
1121 alloc_table (table, table->rows);
1122 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1123 idx <<= MONO_CUSTOM_ATTR_BITS;
1125 for (i = 0; i < count; ++i) {
1126 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1127 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1128 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1129 type = mono_metadata_token_index (token);
1130 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1131 switch (mono_metadata_token_table (token)) {
1132 case MONO_TABLE_METHOD:
1133 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1135 case MONO_TABLE_MEMBERREF:
1136 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1139 g_warning ("got wrong token in custom attr");
1142 values [MONO_CUSTOM_ATTR_TYPE] = type;
1144 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1145 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1146 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1147 values += MONO_CUSTOM_ATTR_SIZE;
1153 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1155 MonoDynamicTable *table;
1157 guint32 count, i, idx;
1158 MonoReflectionPermissionSet *perm;
1163 count = mono_array_length (permissions);
1164 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1165 table->rows += count;
1166 alloc_table (table, table->rows);
1168 for (i = 0; i < mono_array_length (permissions); ++i) {
1169 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1171 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1173 idx = mono_metadata_token_index (parent_token);
1174 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1175 switch (mono_metadata_token_table (parent_token)) {
1176 case MONO_TABLE_TYPEDEF:
1177 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1179 case MONO_TABLE_METHOD:
1180 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1182 case MONO_TABLE_ASSEMBLY:
1183 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1186 g_assert_not_reached ();
1189 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1190 values [MONO_DECL_SECURITY_PARENT] = idx;
1191 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1198 * Fill in the MethodDef and ParamDef tables for a method.
1199 * This is used for both normal methods and constructors.
1202 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1204 MonoDynamicTable *table;
1209 /* room in this table is already allocated */
1210 table = &assembly->tables [MONO_TABLE_METHOD];
1211 *mb->table_idx = table->next_idx ++;
1212 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1213 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1214 name = mono_string_to_utf8 (mb->name);
1215 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1217 values [MONO_METHOD_FLAGS] = mb->attrs;
1218 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1219 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1220 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1222 table = &assembly->tables [MONO_TABLE_PARAM];
1223 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1225 mono_image_add_decl_security (assembly,
1226 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1229 MonoDynamicTable *mtable;
1232 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1233 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1236 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1237 if (mono_array_get (mb->pinfo, gpointer, i))
1240 table->rows += count;
1241 alloc_table (table, table->rows);
1242 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1243 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1244 MonoReflectionParamBuilder *pb;
1245 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1246 values [MONO_PARAM_FLAGS] = pb->attrs;
1247 values [MONO_PARAM_SEQUENCE] = i;
1248 if (pb->name != NULL) {
1249 name = mono_string_to_utf8 (pb->name);
1250 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1253 values [MONO_PARAM_NAME] = 0;
1255 values += MONO_PARAM_SIZE;
1256 if (pb->marshal_info) {
1258 alloc_table (mtable, mtable->rows);
1259 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1260 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1261 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1263 pb->table_idx = table->next_idx++;
1264 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1265 guint32 field_type = 0;
1266 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1268 alloc_table (mtable, mtable->rows);
1269 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1270 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1271 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1272 mvalues [MONO_CONSTANT_TYPE] = field_type;
1273 mvalues [MONO_CONSTANT_PADDING] = 0;
1281 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1283 rmb->ilgen = mb->ilgen;
1284 rmb->rtype = mb->rtype;
1285 rmb->parameters = mb->parameters;
1286 rmb->generic_params = mb->generic_params;
1287 rmb->opt_types = NULL;
1288 rmb->pinfo = mb->pinfo;
1289 rmb->attrs = mb->attrs;
1290 rmb->iattrs = mb->iattrs;
1291 rmb->call_conv = mb->call_conv;
1292 rmb->code = mb->code;
1293 rmb->type = mb->type;
1294 rmb->name = mb->name;
1295 rmb->table_idx = &mb->table_idx;
1296 rmb->init_locals = mb->init_locals;
1297 rmb->return_modreq = mb->return_modreq;
1298 rmb->return_modopt = mb->return_modopt;
1299 rmb->param_modreq = mb->param_modreq;
1300 rmb->param_modopt = mb->param_modopt;
1301 rmb->permissions = mb->permissions;
1302 rmb->mhandle = mb->mhandle;
1307 rmb->charset = rmb->charset & 0xf;
1308 rmb->lasterr = rmb->charset & 0x40;
1309 rmb->native_cc = rmb->native_cc;
1310 rmb->dllentry = mb->dllentry;
1316 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1318 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1320 rmb->ilgen = mb->ilgen;
1321 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1322 rmb->parameters = mb->parameters;
1323 rmb->generic_params = NULL;
1324 rmb->opt_types = NULL;
1325 rmb->pinfo = mb->pinfo;
1326 rmb->attrs = mb->attrs;
1327 rmb->iattrs = mb->iattrs;
1328 rmb->call_conv = mb->call_conv;
1330 rmb->type = mb->type;
1331 rmb->name = mono_string_new (mono_domain_get (), name);
1332 rmb->table_idx = &mb->table_idx;
1333 rmb->init_locals = mb->init_locals;
1334 rmb->return_modreq = NULL;
1335 rmb->return_modopt = NULL;
1336 rmb->param_modreq = mb->param_modreq;
1337 rmb->param_modopt = mb->param_modopt;
1338 rmb->permissions = mb->permissions;
1339 rmb->mhandle = mb->mhandle;
1345 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1347 rmb->ilgen = mb->ilgen;
1348 rmb->rtype = mb->rtype;
1349 rmb->parameters = mb->parameters;
1350 rmb->generic_params = NULL;
1351 rmb->opt_types = NULL;
1353 rmb->attrs = mb->attrs;
1355 rmb->call_conv = mb->call_conv;
1358 rmb->name = mb->name;
1359 rmb->table_idx = NULL;
1360 rmb->init_locals = mb->init_locals;
1361 rmb->return_modreq = NULL;
1362 rmb->return_modopt = NULL;
1363 rmb->param_modreq = NULL;
1364 rmb->param_modopt = NULL;
1365 rmb->permissions = NULL;
1366 rmb->mhandle = mb->mhandle;
1372 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1374 MonoDynamicTable *table;
1377 ReflectionMethodBuilder rmb;
1380 reflection_methodbuilder_from_method_builder (&rmb, mb);
1382 mono_image_basic_method (&rmb, assembly);
1384 if (mb->dll) { /* It's a P/Invoke method */
1386 int charset = mb->charset & 0xf;
1387 int lasterr = mb->charset & 0x40;
1388 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1390 alloc_table (table, table->rows);
1391 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1392 /* map CharSet values to on-disk values */
1394 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1395 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1396 name = mono_string_to_utf8 (mb->dllentry);
1397 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1399 name = mono_string_to_utf8 (mb->dll);
1400 moduleref = string_heap_insert (&assembly->sheap, name);
1402 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1403 table = &assembly->tables [MONO_TABLE_MODULEREF];
1405 alloc_table (table, table->rows);
1406 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1407 values [MONO_IMPLMAP_SCOPE] = table->rows;
1411 if (mb->override_method) {
1412 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1414 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1416 alloc_table (table, table->rows);
1417 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1418 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1419 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1421 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1422 switch (mono_metadata_token_table (tok)) {
1423 case MONO_TABLE_MEMBERREF:
1424 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1426 case MONO_TABLE_METHOD:
1427 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1430 g_assert_not_reached ();
1432 values [MONO_METHODIMPL_DECLARATION] = tok;
1435 if (mb->generic_params) {
1436 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1437 table->rows += mono_array_length (mb->generic_params);
1438 alloc_table (table, table->rows);
1439 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1440 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1442 mono_image_get_generic_param_info (
1443 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1450 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1452 ReflectionMethodBuilder rmb;
1454 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1456 mono_image_basic_method (&rmb, assembly);
1460 type_get_fully_qualified_name (MonoType *type) {
1461 char *name, *result;
1465 name = mono_type_get_name (type);
1466 klass = my_mono_class_from_mono_type (type);
1467 ta = klass->image->assembly;
1469 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1470 name, ta->aname.name,
1471 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1472 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1473 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1479 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1483 klass = my_mono_class_from_mono_type (type);
1485 return mono_type_get_name (type);
1486 ta = klass->image->assembly;
1487 if (ta == ass || klass->image == mono_defaults.corlib)
1488 return mono_type_get_name (type);
1490 return type_get_fully_qualified_name (type);
1494 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1496 char blob_size [64];
1497 char *b = blob_size;
1502 if (!assembly->save)
1505 p = buf = g_malloc (64);
1507 mono_metadata_encode_value (0x06, p, &p);
1508 /* encode custom attributes before the type */
1509 encode_type (assembly, type, p, &p);
1510 g_assert (p-buf < 64);
1511 mono_metadata_encode_value (p-buf, b, &b);
1512 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1518 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1520 char blob_size [64];
1521 char *b = blob_size;
1526 p = buf = g_malloc (64);
1528 mono_metadata_encode_value (0x06, p, &p);
1529 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1530 /* encode custom attributes before the type */
1531 encode_reflection_type (assembly, fb->type, p, &p);
1532 g_assert (p-buf < 64);
1533 mono_metadata_encode_value (p-buf, b, &b);
1534 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1540 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1541 char blob_size [64];
1542 char *b = blob_size;
1545 guint32 idx = 0, len = 0, dummy = 0;
1547 p = buf = g_malloc (64);
1549 *ret_type = MONO_TYPE_CLASS;
1551 box_val = (char*)&dummy;
1553 box_val = ((char*)val) + sizeof (MonoObject);
1554 *ret_type = val->vtable->klass->byval_arg.type;
1557 switch (*ret_type) {
1558 case MONO_TYPE_BOOLEAN:
1563 case MONO_TYPE_CHAR:
1578 case MONO_TYPE_VALUETYPE:
1579 if (val->vtable->klass->enumtype) {
1580 *ret_type = val->vtable->klass->enum_basetype->type;
1583 g_error ("we can't encode valuetypes");
1584 case MONO_TYPE_CLASS:
1586 case MONO_TYPE_STRING: {
1587 MonoString *str = (MonoString*)val;
1588 /* there is no signature */
1589 len = str->length * 2;
1590 mono_metadata_encode_value (len, b, &b);
1591 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1593 char *swapped = g_malloc (2 * mono_string_length (str));
1594 const char *p = (const char*)mono_string_chars (str);
1596 swap_with_size (swapped, p, 2, mono_string_length (str));
1597 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1608 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1611 /* there is no signature */
1612 mono_metadata_encode_value (len, b, &b);
1613 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1614 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1615 swap_with_size (blob_size, box_val, len, 1);
1616 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1618 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1626 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1627 char blob_size [64];
1628 char *b = blob_size;
1629 char *p, *buf, *str;
1630 guint32 idx, len, bufsize = 256;
1632 p = buf = g_malloc (bufsize);
1634 switch (minfo->type) {
1635 case MONO_NATIVE_BYVALTSTR:
1636 case MONO_NATIVE_BYVALARRAY:
1637 mono_metadata_encode_value (minfo->type, p, &p);
1638 mono_metadata_encode_value (minfo->count, p, &p);
1640 case MONO_NATIVE_LPARRAY:
1641 mono_metadata_encode_value (minfo->type, p, &p);
1642 if (minfo->eltype || (minfo->count > 0)) {
1643 mono_metadata_encode_value (minfo->eltype, p, &p);
1644 if (minfo->count > 0) {
1645 mono_metadata_encode_value (0, p, &p);
1646 mono_metadata_encode_value (minfo->count, p, &p);
1650 case MONO_NATIVE_CUSTOM:
1651 mono_metadata_encode_value (minfo->type, p, &p);
1653 str = mono_string_to_utf8 (minfo->guid);
1655 mono_metadata_encode_value (len, p, &p);
1656 memcpy (p, str, len);
1660 mono_metadata_encode_value (0, p, &p);
1662 if (minfo->marshaltype) {
1663 str = mono_string_to_utf8 (minfo->marshaltype);
1665 mono_metadata_encode_value (len, p, &p);
1666 if (p + len >= buf + bufsize) {
1669 buf = g_realloc (buf, bufsize);
1672 memcpy (p, str, len);
1676 mono_metadata_encode_value (0, p, &p);
1678 if (minfo->marshaltyperef) {
1679 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1681 mono_metadata_encode_value (len, p, &p);
1682 if (p + len >= buf + bufsize) {
1685 buf = g_realloc (buf, bufsize);
1688 memcpy (p, str, len);
1692 mono_metadata_encode_value (0, p, &p);
1694 if (minfo->mcookie) {
1695 str = mono_string_to_utf8 (minfo->mcookie);
1697 mono_metadata_encode_value (len, p, &p);
1698 if (p + len >= buf + bufsize) {
1701 buf = g_realloc (buf, bufsize);
1704 memcpy (p, str, len);
1708 mono_metadata_encode_value (0, p, &p);
1712 mono_metadata_encode_value (minfo->type, p, &p);
1716 mono_metadata_encode_value (len, b, &b);
1717 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1723 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1725 MonoDynamicTable *table;
1729 /* maybe this fixup should be done in the C# code */
1730 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1731 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1732 table = &assembly->tables [MONO_TABLE_FIELD];
1733 fb->table_idx = table->next_idx ++;
1734 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1735 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1736 name = mono_string_to_utf8 (fb->name);
1737 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1739 values [MONO_FIELD_FLAGS] = fb->attrs;
1740 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1742 if (fb->offset != -1) {
1743 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1745 alloc_table (table, table->rows);
1746 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1747 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1748 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1750 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1751 guint32 field_type = 0;
1752 table = &assembly->tables [MONO_TABLE_CONSTANT];
1754 alloc_table (table, table->rows);
1755 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1756 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1757 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1758 values [MONO_CONSTANT_TYPE] = field_type;
1759 values [MONO_CONSTANT_PADDING] = 0;
1761 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1763 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1765 alloc_table (table, table->rows);
1766 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1767 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1769 * We store it in the code section because it's simpler for now.
1772 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1774 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1775 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1777 if (fb->marshal_info) {
1778 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1780 alloc_table (table, table->rows);
1781 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1782 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1783 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1788 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1792 char *b = blob_size;
1793 guint32 nparams = 0;
1794 MonoReflectionMethodBuilder *mb = fb->get_method;
1795 MonoReflectionMethodBuilder *smb = fb->set_method;
1796 guint32 idx, i, size;
1798 if (mb && mb->parameters)
1799 nparams = mono_array_length (mb->parameters);
1800 if (!mb && smb && smb->parameters)
1801 nparams = mono_array_length (smb->parameters) - 1;
1802 size = 24 + nparams * 10;
1803 buf = p = g_malloc (size);
1806 mono_metadata_encode_value (nparams, p, &p);
1808 encode_reflection_type (assembly, mb->rtype, p, &p);
1809 for (i = 0; i < nparams; ++i) {
1810 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1811 encode_reflection_type (assembly, pt, p, &p);
1814 /* the property type is the last param */
1815 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1816 for (i = 0; i < nparams; ++i) {
1817 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1818 encode_reflection_type (assembly, pt, p, &p);
1822 g_assert (p - buf < size);
1823 mono_metadata_encode_value (p-buf, b, &b);
1824 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1830 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1832 MonoDynamicTable *table;
1835 guint num_methods = 0;
1839 * we need to set things in the following tables:
1840 * PROPERTYMAP (info already filled in _get_type_info ())
1841 * PROPERTY (rows already preallocated in _get_type_info ())
1842 * METHOD (method info already done with the generic method code)
1845 table = &assembly->tables [MONO_TABLE_PROPERTY];
1846 pb->table_idx = table->next_idx ++;
1847 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1848 name = mono_string_to_utf8 (pb->name);
1849 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1851 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1852 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1854 /* FIXME: we still don't handle 'other' methods */
1855 if (pb->get_method) num_methods ++;
1856 if (pb->set_method) num_methods ++;
1858 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1859 table->rows += num_methods;
1860 alloc_table (table, table->rows);
1862 if (pb->get_method) {
1863 semaidx = table->next_idx ++;
1864 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1865 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1866 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1867 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1869 if (pb->set_method) {
1870 semaidx = table->next_idx ++;
1871 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1872 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1873 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1874 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1879 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1881 MonoDynamicTable *table;
1884 guint num_methods = 0;
1888 * we need to set things in the following tables:
1889 * EVENTMAP (info already filled in _get_type_info ())
1890 * EVENT (rows already preallocated in _get_type_info ())
1891 * METHOD (method info already done with the generic method code)
1894 table = &assembly->tables [MONO_TABLE_EVENT];
1895 eb->table_idx = table->next_idx ++;
1896 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1897 name = mono_string_to_utf8 (eb->name);
1898 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1900 values [MONO_EVENT_FLAGS] = eb->attrs;
1901 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1904 * FIXME: we still don't handle 'other' methods
1906 if (eb->add_method) num_methods ++;
1907 if (eb->remove_method) num_methods ++;
1908 if (eb->raise_method) num_methods ++;
1910 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1911 table->rows += num_methods;
1912 alloc_table (table, table->rows);
1914 if (eb->add_method) {
1915 semaidx = table->next_idx ++;
1916 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1917 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1918 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1919 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1921 if (eb->remove_method) {
1922 semaidx = table->next_idx ++;
1923 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1924 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1925 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1926 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1928 if (eb->raise_method) {
1929 semaidx = table->next_idx ++;
1930 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1931 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1932 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1933 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1938 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1940 static MonoClass *NewConstraintAttr;
1941 static MonoMethod *NewConstraintAttr_ctor;
1942 MonoDynamicTable *table;
1944 guint32 token, type;
1945 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1948 if (!NewConstraintAttr)
1949 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1950 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1951 g_assert (NewConstraintAttr);
1953 if (!NewConstraintAttr_ctor) {
1956 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1957 MonoMethod *m = NewConstraintAttr->methods [i];
1959 if (strcmp (m->name, ".ctor"))
1962 NewConstraintAttr_ctor = m;
1966 g_assert (NewConstraintAttr_ctor);
1969 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1971 alloc_table (table, table->rows);
1973 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1974 owner <<= MONO_CUSTOM_ATTR_BITS;
1975 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1976 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1978 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1980 type = mono_metadata_token_index (token);
1981 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1982 switch (mono_metadata_token_table (token)) {
1983 case MONO_TABLE_METHOD:
1984 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1986 case MONO_TABLE_MEMBERREF:
1987 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1990 g_warning ("got wrong token in custom attr");
1993 values [MONO_CUSTOM_ATTR_TYPE] = type;
1995 buf = p = g_malloc (1);
1996 mono_metadata_encode_value (4, p, &p);
1997 g_assert (p-buf == 1);
1999 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2001 values += MONO_CUSTOM_ATTR_SIZE;
2006 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2008 MonoDynamicTable *table;
2009 guint32 num_constraints, i;
2013 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2014 num_constraints = gparam->iface_constraints ?
2015 mono_array_length (gparam->iface_constraints) : 0;
2016 table->rows += num_constraints;
2017 if (gparam->base_type)
2019 alloc_table (table, table->rows);
2021 if (gparam->base_type) {
2022 table_idx = table->next_idx ++;
2023 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2025 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2026 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2027 assembly, gparam->base_type->type);
2030 for (i = 0; i < num_constraints; i++) {
2031 MonoReflectionType *constraint = mono_array_get (
2032 gparam->iface_constraints, gpointer, i);
2034 table_idx = table->next_idx ++;
2035 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2037 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2038 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2039 assembly, constraint->type);
2042 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2043 encode_new_constraint (assembly, owner);
2047 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2049 GenericParamTableEntry *entry;
2052 * The GenericParam table must be sorted according to the `owner' field.
2053 * We need to do this sorting prior to writing the GenericParamConstraint
2054 * table, since we have to use the final GenericParam table indices there
2055 * and they must also be sorted.
2058 entry = g_new0 (GenericParamTableEntry, 1);
2059 entry->owner = owner;
2060 entry->gparam = gparam;
2062 g_ptr_array_add (assembly->gen_params, entry);
2066 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2068 MonoDynamicTable *table;
2069 MonoGenericParam *param;
2073 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2074 table_idx = table->next_idx ++;
2075 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2077 param = entry->gparam->type.type->data.generic_param;
2079 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2080 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2081 values [MONO_GENERICPARAM_NUMBER] = param->num;
2082 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2083 values [MONO_GENERICPARAM_KIND] = 0;
2085 encode_constraints (entry->gparam, table_idx, assembly);
2089 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2091 MonoDynamicTable *table;
2094 guint32 cols [MONO_ASSEMBLY_SIZE];
2098 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2101 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2102 table = &assembly->tables [MONO_TABLE_MODULEREF];
2103 token = table->next_idx ++;
2105 alloc_table (table, table->rows);
2106 values = table->values + token * MONO_MODULEREF_SIZE;
2107 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2109 token <<= MONO_RESOLTION_SCOPE_BITS;
2110 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2111 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2116 if (image->assembly->dynamic)
2118 memset (cols, 0, sizeof (cols));
2120 /* image->assembly->image is the manifest module */
2121 image = image->assembly->image;
2122 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2125 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2126 token = table->next_idx ++;
2128 alloc_table (table, table->rows);
2129 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2130 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2131 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2132 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2133 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2134 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2135 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2136 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2137 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2139 if (strcmp ("", image->assembly->aname.culture)) {
2140 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2141 image->assembly->aname.culture);
2144 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2145 guchar pubtoken [9];
2147 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2148 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2150 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2152 token <<= MONO_RESOLTION_SCOPE_BITS;
2153 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2154 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2159 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2161 MonoDynamicTable *table;
2167 char *b = blob_size;
2169 switch (type->type) {
2170 case MONO_TYPE_FNPTR:
2172 case MONO_TYPE_SZARRAY:
2173 case MONO_TYPE_ARRAY:
2175 case MONO_TYPE_MVAR:
2176 case MONO_TYPE_GENERICINST:
2177 encode_type (assembly, type, p, &p);
2179 case MONO_TYPE_CLASS:
2180 case MONO_TYPE_VALUETYPE: {
2181 MonoClass *k = mono_class_from_mono_type (type);
2182 if (!k || !k->generic_inst)
2184 encode_generic_inst (assembly, k->generic_inst, p, &p);
2191 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2192 if (assembly->save) {
2193 g_assert (p-sig < 128);
2194 mono_metadata_encode_value (p-sig, b, &b);
2195 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2196 alloc_table (table, table->rows + 1);
2197 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2198 values [MONO_TYPESPEC_SIGNATURE] = token;
2201 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2202 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2208 * Despite the name, we handle also TypeSpec (with the above helper).
2211 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2213 MonoDynamicTable *table;
2215 guint32 token, scope, enclosing;
2218 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2221 token = create_typespec (assembly, type);
2224 klass = my_mono_class_from_mono_type (type);
2226 klass = mono_class_from_mono_type (type);
2229 * If it's in the same module and not a generic type parameter:
2231 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2232 (type->type != MONO_TYPE_MVAR)) {
2233 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2234 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2235 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2239 if (klass->nested_in) {
2240 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2241 /* get the typeref idx of the enclosing type */
2242 enclosing >>= MONO_TYPEDEFORREF_BITS;
2243 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2245 scope = resolution_scope_from_image (assembly, klass->image);
2247 table = &assembly->tables [MONO_TABLE_TYPEREF];
2248 if (assembly->save) {
2249 alloc_table (table, table->rows + 1);
2250 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2251 values [MONO_TYPEREF_SCOPE] = scope;
2252 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2253 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2255 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2256 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2258 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2263 * Insert a memberef row into the metadata: the token that point to the memberref
2264 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2265 * mono_image_get_fieldref_token()).
2266 * The sig param is an index to an already built signature.
2269 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2271 MonoDynamicTable *table;
2273 guint32 token, pclass;
2276 parent = mono_image_typedef_or_ref (assembly, type);
2277 switch (parent & MONO_TYPEDEFORREF_MASK) {
2278 case MONO_TYPEDEFORREF_TYPEREF:
2279 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2281 case MONO_TYPEDEFORREF_TYPESPEC:
2282 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2284 case MONO_TYPEDEFORREF_TYPEDEF:
2285 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2288 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2291 /* extract the index */
2292 parent >>= MONO_TYPEDEFORREF_BITS;
2294 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2296 if (assembly->save) {
2297 alloc_table (table, table->rows + 1);
2298 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2299 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2300 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2301 values [MONO_MEMBERREF_SIGNATURE] = sig;
2304 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2311 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2314 MonoMethodSignature *sig;
2316 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2321 * A methodref signature can't contain an unmanaged calling convention.
2323 sig = mono_metadata_signature_dup (method->signature);
2324 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2325 sig->call_convention = MONO_CALL_DEFAULT;
2326 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2327 method->name, method_encode_signature (assembly, sig));
2329 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2334 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2335 const gchar *name, guint32 sig)
2337 MonoDynamicTable *table;
2341 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2343 if (assembly->save) {
2344 alloc_table (table, table->rows + 1);
2345 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2346 values [MONO_MEMBERREF_CLASS] = original;
2347 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2348 values [MONO_MEMBERREF_SIGNATURE] = sig;
2351 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2358 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2361 ReflectionMethodBuilder rmb;
2363 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2367 reflection_methodbuilder_from_method_builder (&rmb, mb);
2369 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2370 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2371 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2376 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2379 ReflectionMethodBuilder rmb;
2381 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2385 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2387 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2388 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2389 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2394 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2399 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2402 g_assert (f->field->parent);
2403 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2404 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2405 f->field->name, fieldref_encode_signature (assembly, type));
2406 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2411 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2416 guint32 nparams = gmethod->mtype_argc;
2417 guint32 size = 10 + nparams * 10;
2420 char *b = blob_size;
2422 if (!assembly->save)
2425 p = buf = g_malloc (size);
2427 * FIXME: vararg, explicit_this, differenc call_conv values...
2429 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2430 mono_metadata_encode_value (nparams, p, &p);
2432 for (i = 0; i < nparams; i++)
2433 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2436 g_assert (p - buf < size);
2437 mono_metadata_encode_value (p-buf, b, &b);
2438 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2444 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2446 MonoDynamicTable *table;
2448 guint32 token, mtoken = 0, sig;
2449 MonoMethodInflated *imethod;
2450 MonoMethod *declaring;
2452 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2454 g_assert (method->signature->is_inflated);
2455 imethod = (MonoMethodInflated *) method;
2456 declaring = imethod->declaring;
2458 sig = method_encode_signature (assembly, declaring->signature);
2459 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2461 if (!declaring->signature->generic_param_count)
2464 switch (mono_metadata_token_table (mtoken)) {
2465 case MONO_TABLE_MEMBERREF:
2466 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2468 case MONO_TABLE_METHOD:
2469 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2472 g_assert_not_reached ();
2475 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2477 if (assembly->save) {
2478 alloc_table (table, table->rows + 1);
2479 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2480 values [MONO_METHODSPEC_METHOD] = mtoken;
2481 values [MONO_METHODSPEC_SIGNATURE] = sig;
2484 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2491 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2493 MonoMethodInflated *imethod;
2496 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2500 g_assert (m->signature->is_inflated);
2501 imethod = (MonoMethodInflated *) m;
2503 if (imethod->declaring->signature->generic_param_count) {
2504 token = method_encode_methodspec (assembly, m);
2506 guint32 sig = method_encode_signature (
2507 assembly, imethod->declaring->signature);
2508 token = mono_image_get_memberref_token (
2509 assembly, &m->klass->byval_arg, m->name, sig);
2512 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2517 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2519 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2522 sig = method_encode_signature (assembly, imethod->declaring->signature);
2523 token = mono_image_get_memberref_token (
2524 assembly, &m->klass->byval_arg, m->name, sig);
2530 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2532 MonoDynamicTable *table;
2539 char *b = blob_size;
2543 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2544 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2545 * Because of this, we must not insert it into the `typeref' hash table.
2548 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2552 g_assert (tb->generic_params);
2553 klass = mono_class_from_mono_type (tb->type.type);
2555 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2556 encode_type (assembly, &klass->byval_arg, p, &p);
2558 count = mono_array_length (tb->generic_params);
2559 mono_metadata_encode_value (count, p, &p);
2560 for (i = 0; i < count; i++) {
2561 MonoReflectionGenericParam *gparam;
2563 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2565 encode_type (assembly, gparam->type.type, p, &p);
2568 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2569 if (assembly->save) {
2570 g_assert (p-sig < 128);
2571 mono_metadata_encode_value (p-sig, b, &b);
2572 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2573 alloc_table (table, table->rows + 1);
2574 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2575 values [MONO_TYPESPEC_SIGNATURE] = token;
2578 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2579 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2585 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2587 MonoDynamicTable *table;
2590 guint32 token, pclass, parent, sig;
2593 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2597 klass = mono_class_from_mono_type (fb->typeb->type);
2598 name = mono_string_to_utf8 (fb->name);
2600 sig = fieldref_encode_signature (assembly, fb->type->type);
2602 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2603 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2605 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2606 parent >>= MONO_TYPEDEFORREF_BITS;
2608 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2610 if (assembly->save) {
2611 alloc_table (table, table->rows + 1);
2612 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2613 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2614 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2615 values [MONO_MEMBERREF_SIGNATURE] = sig;
2618 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2620 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2625 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2633 char *b = blob_size;
2635 if (!assembly->save)
2639 g_assert (helper->type == 2);
2641 if (helper->arguments)
2642 nargs = mono_array_length (helper->arguments);
2646 size = 10 + (nargs * 10);
2648 p = buf = g_malloc (size);
2650 /* Encode calling convention */
2651 /* Change Any to Standard */
2652 if ((helper->call_conv & 0x03) == 0x03)
2653 helper->call_conv = 0x01;
2654 /* explicit_this implies has_this */
2655 if (helper->call_conv & 0x40)
2656 helper->call_conv &= 0x20;
2658 if (helper->call_conv == 0) { /* Unmanaged */
2659 *p = helper->unmanaged_call_conv - 1;
2662 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2663 if (helper->call_conv & 0x02) /* varargs */
2668 mono_metadata_encode_value (nargs, p, &p);
2669 encode_reflection_type (assembly, helper->return_type, p, &p);
2670 for (i = 0; i < nargs; ++i) {
2671 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2672 encode_reflection_type (assembly, pt, p, &p);
2675 g_assert (p - buf < size);
2676 mono_metadata_encode_value (p-buf, b, &b);
2677 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2684 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2687 MonoDynamicTable *table;
2690 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2691 idx = table->next_idx ++;
2693 alloc_table (table, table->rows);
2694 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2696 values [MONO_STAND_ALONE_SIGNATURE] =
2697 mono_reflection_encode_sighelper (assembly, helper);
2703 reflection_cc_to_file (int call_conv) {
2704 switch (call_conv & 0x3) {
2706 case 1: return MONO_CALL_DEFAULT;
2707 case 2: return MONO_CALL_VARARG;
2709 g_assert_not_reached ();
2716 MonoMethodSignature *sig;
2722 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2727 MonoMethodSignature *sig;
2730 name = mono_string_to_utf8 (m->name);
2731 nparams = mono_array_length (m->parameters);
2732 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2734 sig->sentinelpos = -1;
2735 sig->call_convention = reflection_cc_to_file (m->call_conv);
2736 sig->param_count = nparams;
2737 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2738 for (i = 0; i < nparams; ++i) {
2739 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2740 sig->params [i] = t->type;
2743 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2745 if (strcmp (name, am->name) == 0 &&
2746 mono_metadata_type_equal (am->parent, m->parent->type) &&
2747 mono_metadata_signature_equal (am->sig, sig)) {
2750 m->table_idx = am->token & 0xffffff;
2754 am = g_new0 (ArrayMethod, 1);
2757 am->parent = m->parent->type;
2758 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2759 method_encode_signature (assembly, sig));
2760 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2761 m->table_idx = am->token & 0xffffff;
2766 * Insert into the metadata tables all the info about the TypeBuilder tb.
2767 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2770 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2772 MonoDynamicTable *table;
2774 int i, is_object = 0, is_system = 0;
2777 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2778 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2779 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2780 n = mono_string_to_utf8 (tb->name);
2781 if (strcmp (n, "Object") == 0)
2783 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2785 n = mono_string_to_utf8 (tb->nspace);
2786 if (strcmp (n, "System") == 0)
2788 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2790 if (tb->parent && !(is_system && is_object) &&
2791 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2792 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2794 values [MONO_TYPEDEF_EXTENDS] = 0;
2796 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2797 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2800 * if we have explicitlayout or sequentiallayouts, output data in the
2801 * ClassLayout table.
2803 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2804 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2805 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2807 alloc_table (table, table->rows);
2808 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2809 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2810 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2811 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2814 /* handle interfaces */
2815 if (tb->interfaces) {
2816 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2818 table->rows += mono_array_length (tb->interfaces);
2819 alloc_table (table, table->rows);
2820 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2821 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2822 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2823 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2824 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2825 values += MONO_INTERFACEIMPL_SIZE;
2831 table = &assembly->tables [MONO_TABLE_FIELD];
2832 table->rows += tb->num_fields;
2833 alloc_table (table, table->rows);
2834 for (i = 0; i < tb->num_fields; ++i)
2835 mono_image_get_field_info (
2836 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2839 /* handle constructors */
2841 table = &assembly->tables [MONO_TABLE_METHOD];
2842 table->rows += mono_array_length (tb->ctors);
2843 alloc_table (table, table->rows);
2844 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2845 mono_image_get_ctor_info (domain,
2846 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2849 /* handle methods */
2851 table = &assembly->tables [MONO_TABLE_METHOD];
2852 table->rows += tb->num_methods;
2853 alloc_table (table, table->rows);
2854 for (i = 0; i < tb->num_methods; ++i)
2855 mono_image_get_method_info (
2856 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2859 /* Do the same with properties etc.. */
2860 if (tb->events && mono_array_length (tb->events)) {
2861 table = &assembly->tables [MONO_TABLE_EVENT];
2862 table->rows += mono_array_length (tb->events);
2863 alloc_table (table, table->rows);
2864 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2866 alloc_table (table, table->rows);
2867 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2868 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2869 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2870 for (i = 0; i < mono_array_length (tb->events); ++i)
2871 mono_image_get_event_info (
2872 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2874 if (tb->properties && mono_array_length (tb->properties)) {
2875 table = &assembly->tables [MONO_TABLE_PROPERTY];
2876 table->rows += mono_array_length (tb->properties);
2877 alloc_table (table, table->rows);
2878 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2880 alloc_table (table, table->rows);
2881 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2882 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2883 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2884 for (i = 0; i < mono_array_length (tb->properties); ++i)
2885 mono_image_get_property_info (
2886 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2889 /* handle generic parameters */
2890 if (tb->generic_params) {
2891 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2892 table->rows += mono_array_length (tb->generic_params);
2893 alloc_table (table, table->rows);
2894 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2895 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2897 mono_image_get_generic_param_info (
2898 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2902 mono_image_add_decl_security (assembly,
2903 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2906 MonoDynamicTable *ntable;
2908 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2909 ntable->rows += mono_array_length (tb->subtypes);
2910 alloc_table (ntable, ntable->rows);
2911 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2913 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2914 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2916 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2917 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2918 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2919 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2920 mono_string_to_utf8 (tb->name), tb->table_idx,
2921 ntable->next_idx, ntable->rows);*/
2922 values += MONO_NESTED_CLASS_SIZE;
2929 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2933 g_ptr_array_add (types, type);
2935 if (!type->subtypes)
2938 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2939 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2940 collect_types (types, subtype);
2945 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2947 if ((*type1)->table_idx < (*type2)->table_idx)
2950 if ((*type1)->table_idx > (*type2)->table_idx)
2957 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2962 for (i = 0; i < mono_array_length (pinfo); ++i) {
2963 MonoReflectionParamBuilder *pb;
2964 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2967 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2972 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2975 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2977 for (i = 0; i < tb->num_fields; ++i) {
2978 MonoReflectionFieldBuilder* fb;
2979 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2980 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2984 for (i = 0; i < mono_array_length (tb->events); ++i) {
2985 MonoReflectionEventBuilder* eb;
2986 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2987 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2990 if (tb->properties) {
2991 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2992 MonoReflectionPropertyBuilder* pb;
2993 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2994 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2998 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2999 MonoReflectionCtorBuilder* cb;
3000 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3001 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3002 params_add_cattrs (assembly, cb->pinfo);
3007 for (i = 0; i < tb->num_methods; ++i) {
3008 MonoReflectionMethodBuilder* mb;
3009 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3010 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3011 params_add_cattrs (assembly, mb->pinfo);
3016 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3017 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3022 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3025 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3027 /* no types in the module */
3031 for (i = 0; i < mb->num_types; ++i)
3032 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3036 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3038 MonoDynamicTable *table;
3042 char *b = blob_size;
3045 table = &assembly->tables [MONO_TABLE_FILE];
3047 alloc_table (table, table->rows);
3048 values = table->values + table->next_idx * MONO_FILE_SIZE;
3049 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3050 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3051 if (module->image->dynamic) {
3052 /* This depends on the fact that the main module is emitted last */
3053 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3054 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3057 path = g_strdup (module->image->name);
3059 mono_sha1_get_digest_from_file (path, hash);
3062 mono_metadata_encode_value (20, b, &b);
3063 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3064 mono_image_add_stream_data (&assembly->blob, hash, 20);
3069 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3071 MonoDynamicTable *table;
3075 table = &assembly->tables [MONO_TABLE_MODULE];
3076 mb->table_idx = table->next_idx ++;
3077 name = mono_string_to_utf8 (mb->module.name);
3078 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3080 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3083 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3084 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3085 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3089 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3090 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3092 MonoDynamicTable *table;
3096 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3097 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3100 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3102 alloc_table (table, table->rows);
3103 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3105 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3106 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3107 if (klass->nested_in)
3108 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3110 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3111 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3112 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3114 res = table->next_idx;
3118 /* Emit nested types */
3119 if (klass->nested_classes) {
3122 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3123 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3130 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3131 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3136 klass = mono_class_from_mono_type (tb->type.type);
3138 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3140 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3141 parent_index, assembly);
3145 * We need to do this ourselves since klass->nested_classes is not set up.
3148 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3149 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3154 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3155 guint32 module_index, MonoDynamicImage *assembly)
3157 MonoImage *image = module->image;
3161 t = &image->tables [MONO_TABLE_TYPEDEF];
3163 for (i = 0; i < t->rows; ++i) {
3164 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3166 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3167 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3171 #define align_pointer(base,p)\
3173 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3175 (p) += 4 - (__diff & 3);\
3179 compare_semantics (const void *a, const void *b)
3181 const guint32 *a_values = a;
3182 const guint32 *b_values = b;
3183 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3186 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3190 compare_custom_attrs (const void *a, const void *b)
3192 const guint32 *a_values = a;
3193 const guint32 *b_values = b;
3195 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3199 compare_field_marshal (const void *a, const void *b)
3201 const guint32 *a_values = a;
3202 const guint32 *b_values = b;
3204 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3208 compare_nested (const void *a, const void *b)
3210 const guint32 *a_values = a;
3211 const guint32 *b_values = b;
3213 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3217 compare_genericparam (const void *a, const void *b)
3219 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3220 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3222 return (*a_entry)->owner - (*b_entry)->owner;
3226 compare_declsecurity_attrs (const void *a, const void *b)
3228 const guint32 *a_values = a;
3229 const guint32 *b_values = b;
3231 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3235 pad_heap (MonoDynamicStream *sh)
3237 if (sh->index & 3) {
3238 int sz = 4 - (sh->index & 3);
3239 memset (sh->data + sh->index, 0, sz);
3246 MonoDynamicStream *stream;
3250 * build_compressed_metadata() fills in the blob of data that represents the
3251 * raw metadata as it will be saved in the PE file. The five streams are output
3252 * and the metadata tables are comnpressed from the guint32 array representation,
3253 * to the compressed on-disk format.
3256 build_compressed_metadata (MonoDynamicImage *assembly)
3258 MonoDynamicTable *table;
3260 guint64 valid_mask = 0;
3261 guint64 sorted_mask;
3262 guint32 heapt_size = 0;
3263 guint32 meta_size = 256; /* allow for header and other stuff */
3264 guint32 table_offset;
3265 guint32 ntables = 0;
3271 struct StreamDesc stream_desc [5];
3273 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3274 for (i = 0; i < assembly->gen_params->len; i++){
3275 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3276 write_generic_param_entry (assembly, entry);
3279 stream_desc [0].name = "#~";
3280 stream_desc [0].stream = &assembly->tstream;
3281 stream_desc [1].name = "#Strings";
3282 stream_desc [1].stream = &assembly->sheap;
3283 stream_desc [2].name = "#US";
3284 stream_desc [2].stream = &assembly->us;
3285 stream_desc [3].name = "#Blob";
3286 stream_desc [3].stream = &assembly->blob;
3287 stream_desc [4].name = "#GUID";
3288 stream_desc [4].stream = &assembly->guid;
3290 /* tables that are sorted */
3291 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3292 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3293 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3294 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3295 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3296 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3298 /* Compute table sizes */
3299 /* the MonoImage has already been created in mono_image_basic_init() */
3300 meta = &assembly->image;
3302 /* sizes should be multiple of 4 */
3303 pad_heap (&assembly->blob);
3304 pad_heap (&assembly->guid);
3305 pad_heap (&assembly->sheap);
3306 pad_heap (&assembly->us);
3308 /* Setup the info used by compute_sizes () */
3309 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3310 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3311 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3313 meta_size += assembly->blob.index;
3314 meta_size += assembly->guid.index;
3315 meta_size += assembly->sheap.index;
3316 meta_size += assembly->us.index;
3318 for (i=0; i < 64; ++i)
3319 meta->tables [i].rows = assembly->tables [i].rows;
3321 for (i = 0; i < 64; i++){
3322 if (meta->tables [i].rows == 0)
3324 valid_mask |= (guint64)1 << i;
3326 meta->tables [i].row_size = mono_metadata_compute_size (
3327 meta, i, &meta->tables [i].size_bitfield);
3328 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3330 heapt_size += 24; /* #~ header size */
3331 heapt_size += ntables * 4;
3332 /* make multiple of 4 */
3335 meta_size += heapt_size;
3336 meta->raw_metadata = g_malloc0 (meta_size);
3337 p = meta->raw_metadata;
3338 /* the metadata signature */
3339 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3340 /* version numbers and 4 bytes reserved */
3341 int16val = (guint16*)p;
3342 *int16val++ = GUINT16_TO_LE (1);
3343 *int16val = GUINT16_TO_LE (1);
3345 /* version string */
3346 int32val = (guint32*)p;
3347 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3349 memcpy (p, meta->version, strlen (meta->version));
3350 p += GUINT32_FROM_LE (*int32val);
3351 align_pointer (meta->raw_metadata, p);
3352 int16val = (guint16*)p;
3353 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3354 *int16val = GUINT16_TO_LE (5); /* number of streams */
3358 * write the stream info.
3360 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3361 table_offset += 3; table_offset &= ~3;
3363 assembly->tstream.index = heapt_size;
3364 for (i = 0; i < 5; ++i) {
3365 int32val = (guint32*)p;
3366 stream_desc [i].stream->offset = table_offset;
3367 *int32val++ = GUINT32_TO_LE (table_offset);
3368 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3369 table_offset += GUINT32_FROM_LE (*int32val);
3370 table_offset += 3; table_offset &= ~3;
3372 strcpy (p, stream_desc [i].name);
3373 p += strlen (stream_desc [i].name) + 1;
3374 align_pointer (meta->raw_metadata, p);
3377 * now copy the data, the table stream header and contents goes first.
3379 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3380 p = meta->raw_metadata + assembly->tstream.offset;
3381 int32val = (guint32*)p;
3382 *int32val = GUINT32_TO_LE (0); /* reserved */
3385 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3386 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3387 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3388 *p++ = 1; /* version */
3391 *p++ = 1; /* version */
3395 if (meta->idx_string_wide)
3397 if (meta->idx_guid_wide)
3399 if (meta->idx_blob_wide)
3402 *p++ = 1; /* reserved */
3403 int64val = (guint64*)p;
3404 *int64val++ = GUINT64_TO_LE (valid_mask);
3405 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3407 int32val = (guint32*)p;
3408 for (i = 0; i < 64; i++){
3409 if (meta->tables [i].rows == 0)
3411 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3413 p = (unsigned char*)int32val;
3415 /* sort the tables that still need sorting */
3416 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3418 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3419 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3421 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3422 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3424 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3425 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3427 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3428 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3429 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3431 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3433 /* compress the tables */
3434 for (i = 0; i < 64; i++){
3437 guint32 bitfield = meta->tables [i].size_bitfield;
3438 if (!meta->tables [i].rows)
3440 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3441 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3442 meta->tables [i].base = p;
3443 for (row = 1; row <= meta->tables [i].rows; ++row) {
3444 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3445 for (col = 0; col < assembly->tables [i].columns; ++col) {
3446 switch (mono_metadata_table_size (bitfield, col)) {
3448 *p++ = values [col];
3451 *p++ = values [col] & 0xff;
3452 *p++ = (values [col] >> 8) & 0xff;
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3457 *p++ = (values [col] >> 16) & 0xff;
3458 *p++ = (values [col] >> 24) & 0xff;
3461 g_assert_not_reached ();
3465 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3468 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3469 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3470 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3471 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3472 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3474 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3478 * Some tables in metadata need to be sorted according to some criteria, but
3479 * when methods and fields are first created with reflection, they may be assigned a token
3480 * that doesn't correspond to the final token they will get assigned after the sorting.
3481 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3482 * with the reflection objects that represent them. Once all the tables are set up, the
3483 * reflection objects will contains the correct table index. fixup_method() will fixup the
3484 * tokens for the method with ILGenerator @ilgen.
3487 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3488 guint32 code_idx = GPOINTER_TO_UINT (value);
3489 MonoReflectionILTokenInfo *iltoken;
3490 MonoReflectionFieldBuilder *field;
3491 MonoReflectionCtorBuilder *ctor;
3492 MonoReflectionMethodBuilder *method;
3493 MonoReflectionTypeBuilder *tb;
3494 MonoReflectionArrayMethod *am;
3496 unsigned char *target;
3498 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3499 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3500 target = assembly->code.data + code_idx + iltoken->code_pos;
3501 switch (target [3]) {
3502 case MONO_TABLE_FIELD:
3503 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3504 field = (MonoReflectionFieldBuilder *)iltoken->member;
3505 idx = field->table_idx;
3506 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3507 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3508 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3510 g_assert_not_reached ();
3513 case MONO_TABLE_METHOD:
3514 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3515 method = (MonoReflectionMethodBuilder *)iltoken->member;
3516 idx = method->table_idx;
3517 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3518 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3519 idx = ctor->table_idx;
3520 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3521 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3522 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3523 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3525 g_assert_not_reached ();
3528 case MONO_TABLE_TYPEDEF:
3529 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3530 g_assert_not_reached ();
3531 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3532 idx = tb->table_idx;
3534 case MONO_TABLE_MEMBERREF:
3535 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3536 am = (MonoReflectionArrayMethod*)iltoken->member;
3537 idx = am->table_idx;
3538 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3539 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3540 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3541 g_assert (m->klass->generic_inst);
3543 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3545 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3546 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3547 g_assert (f->generic_info);
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3552 g_assert_not_reached ();
3555 case MONO_TABLE_METHODSPEC:
3556 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3557 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3558 g_assert (m->signature->generic_param_count);
3561 g_assert_not_reached ();
3565 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3567 target [0] = idx & 0xff;
3568 target [1] = (idx >> 8) & 0xff;
3569 target [2] = (idx >> 16) & 0xff;
3576 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3577 * value is not known when the table is emitted.
3580 fixup_cattrs (MonoDynamicImage *assembly)
3582 MonoDynamicTable *table;
3584 guint32 type, i, idx, token;
3587 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3589 for (i = 0; i < table->rows; ++i) {
3590 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3592 type = values [MONO_CUSTOM_ATTR_TYPE];
3593 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3594 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3595 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3596 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3599 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3600 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3601 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3602 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3609 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3611 MonoDynamicTable *table;
3615 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3617 alloc_table (table, table->rows);
3618 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3619 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3620 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3621 name = mono_string_to_utf8 (rsrc->name);
3622 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3624 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3629 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3631 MonoDynamicTable *table;
3635 char *b = blob_size;
3637 guint32 idx, offset;
3639 if (rsrc->filename) {
3640 name = mono_string_to_utf8 (rsrc->filename);
3641 sname = g_path_get_basename (name);
3643 table = &assembly->tables [MONO_TABLE_FILE];
3645 alloc_table (table, table->rows);
3646 values = table->values + table->next_idx * MONO_FILE_SIZE;
3647 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3648 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3651 mono_sha1_get_digest_from_file (name, hash);
3652 mono_metadata_encode_value (20, b, &b);
3653 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3654 mono_image_add_stream_data (&assembly->blob, hash, 20);
3656 idx = table->next_idx++;
3658 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3661 offset = mono_array_length (rsrc->data);
3662 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3663 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3664 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3665 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3669 * The entry should be emitted into the MANIFESTRESOURCE table of
3670 * the main module, but that needs to reference the FILE table
3671 * which isn't emitted yet.
3678 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3682 set_version_from_string (MonoString *version, guint32 *values)
3684 gchar *ver, *p, *str;
3687 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3688 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3689 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3690 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3693 ver = str = mono_string_to_utf8 (version);
3694 for (i = 0; i < 4; ++i) {
3695 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3701 /* handle Revision and Build */
3711 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3715 char *b = blob_size;
3720 len = mono_array_length (pkey);
3721 mono_metadata_encode_value (len, b, &b);
3722 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3723 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3725 /* need to get the actual value from the key type... */
3726 assembly->strong_name_size = 128;
3727 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3733 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3735 MonoDynamicTable *table;
3736 MonoDynamicImage *assembly;
3737 MonoReflectionAssemblyBuilder *assemblyb;
3742 guint32 module_index;
3744 assemblyb = moduleb->assemblyb;
3745 assembly = moduleb->dynamic_image;
3746 domain = mono_object_domain (assemblyb);
3748 /* Emit ASSEMBLY table */
3749 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3750 alloc_table (table, 1);
3751 values = table->values + MONO_ASSEMBLY_SIZE;
3752 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3753 name = mono_string_to_utf8 (assemblyb->name);
3754 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3756 if (assemblyb->culture) {
3757 name = mono_string_to_utf8 (assemblyb->culture);
3758 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3761 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3763 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3764 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3765 set_version_from_string (assemblyb->version, values);
3767 /* Emit FILE + EXPORTED_TYPE table */
3769 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3771 MonoReflectionModuleBuilder *file_module =
3772 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3773 if (file_module != moduleb) {
3774 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3776 if (file_module->types) {
3777 for (j = 0; j < file_module->num_types; ++j) {
3778 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3779 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3784 if (assemblyb->loaded_modules) {
3785 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3786 MonoReflectionModule *file_module =
3787 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3788 mono_image_fill_file_table (domain, file_module, assembly);
3790 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3794 /* Emit MANIFESTRESOURCE table */
3796 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3798 MonoReflectionModuleBuilder *file_module =
3799 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3800 /* The table for the main module is emitted later */
3801 if (file_module != moduleb) {
3803 if (file_module->resources) {
3804 int len = mono_array_length (file_module->resources);
3805 for (j = 0; j < len; ++j) {
3806 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3807 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3815 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3816 * for the modulebuilder @moduleb.
3817 * At the end of the process, method and field tokens are fixed up and the
3818 * on-disk compressed metadata representation is created.
3821 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3823 MonoDynamicTable *table;
3824 MonoDynamicImage *assembly;
3825 MonoReflectionAssemblyBuilder *assemblyb;
3830 assemblyb = moduleb->assemblyb;
3831 assembly = moduleb->dynamic_image;
3832 domain = mono_object_domain (assemblyb);
3834 if (assembly->text_rva)
3837 assembly->text_rva = START_TEXT_RVA;
3839 if (moduleb->is_main) {
3840 mono_image_emit_manifest (moduleb);
3843 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3844 table->rows = 1; /* .<Module> */
3846 alloc_table (table, table->rows);
3848 * Set the first entry.
3850 values = table->values + table->columns;
3851 values [MONO_TYPEDEF_FLAGS] = 0;
3852 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3853 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3854 values [MONO_TYPEDEF_EXTENDS] = 0;
3855 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3856 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3859 * handle global methods
3860 * FIXME: test what to do when global methods are defined in multiple modules.
3862 if (moduleb->global_methods) {
3863 table = &assembly->tables [MONO_TABLE_METHOD];
3864 table->rows += mono_array_length (moduleb->global_methods);
3865 alloc_table (table, table->rows);
3866 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3867 mono_image_get_method_info (
3868 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3870 if (moduleb->global_fields) {
3871 table = &assembly->tables [MONO_TABLE_FIELD];
3872 table->rows += mono_array_length (moduleb->global_fields);
3873 alloc_table (table, table->rows);
3874 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3875 mono_image_get_field_info (
3876 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3879 table = &assembly->tables [MONO_TABLE_MODULE];
3880 alloc_table (table, 1);
3881 mono_image_fill_module_table (domain, moduleb, assembly);
3885 /* Collect all types into a list sorted by their table_idx */
3886 GPtrArray *types = g_ptr_array_new ();
3889 for (i = 0; i < moduleb->num_types; ++i) {
3890 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3891 collect_types (types, type);
3894 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3895 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3896 table->rows += types->len;
3897 alloc_table (table, table->rows);
3899 for (i = 0; i < types->len; ++i) {
3900 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3901 mono_image_get_type_info (domain, type, assembly);
3903 g_ptr_array_free (types, TRUE);
3907 * table->rows is already set above and in mono_image_fill_module_table.
3909 /* add all the custom attributes at the end, once all the indexes are stable */
3910 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3912 /* CAS assembly permissions */
3913 if (assemblyb->permissions_minimum)
3914 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3915 if (assemblyb->permissions_optional)
3916 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3917 if (assemblyb->permissions_refused)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3920 module_add_cattrs (assembly, moduleb);
3923 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3924 fixup_cattrs (assembly);
3928 * mono_image_insert_string:
3929 * @module: module builder object
3932 * Insert @str into the user string stream of @module.
3935 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3937 MonoDynamicImage *assembly;
3942 MONO_ARCH_SAVE_REGS;
3944 if (!module->dynamic_image)
3945 mono_image_module_basic_init (module);
3947 assembly = module->dynamic_image;
3949 if (assembly->save) {
3950 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3951 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3952 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3954 char *swapped = g_malloc (2 * mono_string_length (str));
3955 const char *p = (const char*)mono_string_chars (str);
3957 swap_with_size (swapped, p, 2, mono_string_length (str));
3958 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3962 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3964 mono_image_add_stream_data (&assembly->us, "", 1);
3966 idx = assembly->us.index ++;
3969 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3971 return MONO_TOKEN_STRING | idx;
3975 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3980 klass = obj->vtable->klass;
3981 if (strcmp (klass->name, "MonoMethod") == 0) {
3982 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3983 MonoMethodSignature *sig, *old;
3984 guint32 sig_token, parent;
3987 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3989 nargs = mono_array_length (opt_param_types);
3990 old = method->signature;
3991 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3993 sig->hasthis = old->hasthis;
3994 sig->explicit_this = old->explicit_this;
3995 sig->call_convention = old->call_convention;
3996 sig->generic_param_count = old->generic_param_count;
3997 sig->param_count = old->param_count + nargs;
3998 sig->sentinelpos = old->param_count;
3999 sig->ret = old->ret;
4001 for (i = 0; i < old->param_count; i++)
4002 sig->params [i] = old->params [i];
4004 for (i = 0; i < nargs; i++) {
4005 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4006 sig->params [old->param_count + i] = rt->type;
4009 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4010 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4011 parent >>= MONO_TYPEDEFORREF_BITS;
4013 parent <<= MONO_MEMBERREF_PARENT_BITS;
4014 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4016 sig_token = method_encode_signature (assembly, sig);
4017 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4018 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4019 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4020 ReflectionMethodBuilder rmb;
4021 guint32 parent, sig;
4023 reflection_methodbuilder_from_method_builder (&rmb, mb);
4024 rmb.opt_types = opt_param_types;
4026 sig = method_builder_encode_signature (assembly, &rmb);
4028 parent = mono_image_create_token (assembly, obj, TRUE);
4029 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4031 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4032 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4034 token = mono_image_get_varargs_method_token (
4035 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4037 g_error ("requested method token for %s\n", klass->name);
4044 * mono_image_create_token:
4045 * @assembly: a dynamic assembly
4048 * Get a token to insert in the IL code stream for the given MemberInfo.
4049 * @obj can be one of:
4050 * ConstructorBuilder
4060 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4065 klass = obj->vtable->klass;
4066 if (strcmp (klass->name, "MethodBuilder") == 0) {
4067 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4069 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4070 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4072 token = mono_image_get_methodbuilder_token (assembly, mb);
4073 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4074 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4075 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4077 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4078 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4080 token = mono_image_get_ctorbuilder_token (assembly, mb);
4081 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4082 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4083 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4084 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4085 if (tb->generic_params) {
4086 token = mono_image_get_generic_field_token (assembly, fb);
4088 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4090 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4091 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4092 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4093 } else if (strcmp (klass->name, "MonoType") == 0 ||
4094 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4095 MonoReflectionType *tb = (MonoReflectionType *)obj;
4096 token = mono_metadata_token_from_dor (
4097 mono_image_typedef_or_ref (assembly, tb->type));
4098 } else if (strcmp (klass->name, "MonoGenericInst") == 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, "MonoCMethod") == 0 ||
4103 strcmp (klass->name, "MonoMethod") == 0) {
4104 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4105 if (m->method->signature->is_inflated) {
4106 if (create_methodspec)
4107 token = mono_image_get_methodspec_token (assembly, m->method);
4109 token = mono_image_get_inflated_method_token (assembly, m->method);
4110 } else if ((m->method->klass->image == &assembly->image) &&
4111 !m->method->klass->generic_inst) {
4112 static guint32 method_table_idx = 0xffffff;
4113 if (m->method->klass->wastypebuilder) {
4114 /* we use the same token as the one that was assigned
4115 * to the Methodbuilder.
4116 * FIXME: do the equivalent for Fields.
4118 token = m->method->token;
4121 * Each token should have a unique index, but the indexes are
4122 * assigned by managed code, so we don't know about them. An
4123 * easy solution is to count backwards...
4125 method_table_idx --;
4126 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4129 token = mono_image_get_methodref_token (assembly, m->method);
4131 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4132 } else if (strcmp (klass->name, "MonoField") == 0) {
4133 MonoReflectionField *f = (MonoReflectionField *)obj;
4134 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4135 static guint32 field_table_idx = 0xffffff;
4137 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4139 token = mono_image_get_fieldref_token (assembly, f);
4141 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4142 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4143 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4144 token = mono_image_get_array_token (assembly, m);
4145 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4146 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4147 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4149 g_error ("requested token for %s\n", klass->name);
4152 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4158 guint32 import_lookup_table;
4162 guint32 import_address_table_rva;
4170 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4172 static MonoDynamicImage*
4173 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4175 static const guchar entrycode [16] = {0xff, 0x25, 0};
4176 MonoDynamicImage *image;
4179 const char *version = mono_get_runtime_version ();
4182 image = GC_MALLOC (sizeof (MonoDynamicImage));
4184 image = g_new0 (MonoDynamicImage, 1);
4187 /* keep in sync with image.c */
4188 image->image.name = assembly_name;
4189 image->image.assembly_name = image->image.name; /* they may be different */
4190 image->image.module_name = module_name;
4191 image->image.version = g_strdup (version);
4192 image->image.dynamic = TRUE;
4194 image->image.references = g_new0 (MonoAssembly*, 1);
4195 image->image.references [0] = NULL;
4197 mono_image_init (&image->image);
4199 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4200 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4201 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4202 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4203 image->handleref = g_hash_table_new (NULL, NULL);
4204 image->tokens = mono_g_hash_table_new (NULL, NULL);
4205 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4206 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4207 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4208 image->gen_params = g_ptr_array_new ();
4210 string_heap_init (&image->sheap);
4211 mono_image_add_stream_data (&image->us, "", 1);
4212 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4213 /* import tables... */
4214 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4215 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4216 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4217 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4218 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4219 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4220 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4221 stream_data_align (&image->code);
4223 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4225 for (i=0; i < 64; ++i) {
4226 image->tables [i].next_idx = 1;
4227 image->tables [i].columns = table_sizes [i];
4230 image->image.assembly = (MonoAssembly*)assembly;
4231 image->run = assembly->run;
4232 image->save = assembly->save;
4233 image->pe_kind = 0x1; /* ILOnly */
4234 image->machine = 0x14c; /* I386 */
4240 * mono_image_basic_init:
4241 * @assembly: an assembly builder object
4243 * Create the MonoImage that represents the assembly builder and setup some
4244 * of the helper hash table and the basic metadata streams.
4247 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4249 MonoDynamicAssembly *assembly;
4250 MonoDynamicImage *image;
4252 MONO_ARCH_SAVE_REGS;
4254 if (assemblyb->dynamic_assembly)
4258 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4260 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4263 assembly->assembly.dynamic = TRUE;
4264 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4265 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4266 if (assemblyb->culture)
4267 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4269 assembly->assembly.aname.culture = g_strdup ("");
4271 assembly->run = assemblyb->access != 2;
4272 assembly->save = assemblyb->access != 1;
4274 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4275 image->initial_image = TRUE;
4276 assembly->assembly.aname.name = image->image.name;
4277 assembly->assembly.image = &image->image;
4279 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4280 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4284 calc_section_size (MonoDynamicImage *assembly)
4288 /* alignment constraints */
4289 assembly->code.index += 3;
4290 assembly->code.index &= ~3;
4291 assembly->meta_size += 3;
4292 assembly->meta_size &= ~3;
4293 assembly->resources.index += 3;
4294 assembly->resources.index &= ~3;
4296 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4297 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4300 if (assembly->win32_res) {
4301 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4303 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4304 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4308 assembly->sections [MONO_SECTION_RELOC].size = 12;
4309 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4319 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4323 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4325 ResTreeNode *t1 = (ResTreeNode*)a;
4326 ResTreeNode *t2 = (ResTreeNode*)b;
4328 return t1->id - t2->id;
4332 * resource_tree_create:
4334 * Organize the resources into a resource tree.
4336 static ResTreeNode *
4337 resource_tree_create (MonoArray *win32_resources)
4339 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4343 tree = g_new0 (ResTreeNode, 1);
4345 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4346 MonoReflectionWin32Resource *win32_res =
4347 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4351 lang_node = g_new0 (ResTreeNode, 1);
4352 lang_node->id = win32_res->lang_id;
4353 lang_node->win32_res = win32_res;
4355 /* Create type node if neccesary */
4357 for (l = tree->children; l; l = l->next)
4358 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4359 type_node = (ResTreeNode*)l->data;
4364 type_node = g_new0 (ResTreeNode, 1);
4365 type_node->id = win32_res->res_type;
4368 * The resource types have to be sorted otherwise
4369 * Windows Explorer can't display the version information.
4371 tree->children = g_slist_insert_sorted (tree->children,
4372 type_node, resource_tree_compare_by_id);
4375 /* Create res node if neccesary */
4377 for (l = type_node->children; l; l = l->next)
4378 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4379 res_node = (ResTreeNode*)l->data;
4384 res_node = g_new0 (ResTreeNode, 1);
4385 res_node->id = win32_res->res_id;
4386 type_node->children = g_slist_append (type_node->children, res_node);
4389 res_node->children = g_slist_append (res_node->children, lang_node);
4396 * resource_tree_encode:
4398 * Encode the resource tree into the format used in the PE file.
4401 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4404 MonoPEResourceDir dir;
4405 MonoPEResourceDirEntry dir_entry;
4406 MonoPEResourceDataEntry data_entry;
4410 * For the format of the resource directory, see the article
4411 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4415 memset (&dir, 0, sizeof (dir));
4416 memset (&dir_entry, 0, sizeof (dir_entry));
4417 memset (&data_entry, 0, sizeof (data_entry));
4419 g_assert (sizeof (dir) == 16);
4420 g_assert (sizeof (dir_entry) == 8);
4421 g_assert (sizeof (data_entry) == 16);
4423 node->offset = p - begin;
4425 /* IMAGE_RESOURCE_DIRECTORY */
4426 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4428 memcpy (p, &dir, sizeof (dir));
4431 /* Reserve space for entries */
4433 p += sizeof (dir_entry) * dir.res_id_entries;
4435 /* Write children */
4436 for (l = node->children; l; l = l->next) {
4437 ResTreeNode *child = (ResTreeNode*)l->data;
4439 if (child->win32_res) {
4441 child->offset = p - begin;
4443 /* IMAGE_RESOURCE_DATA_ENTRY */
4444 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4445 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4447 memcpy (p, &data_entry, sizeof (data_entry));
4448 p += sizeof (data_entry);
4450 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4451 p += data_entry.rde_size;
4453 resource_tree_encode (child, begin, p, &p);
4457 /* IMAGE_RESOURCE_ENTRY */
4458 for (l = node->children; l; l = l->next) {
4459 ResTreeNode *child = (ResTreeNode*)l->data;
4460 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4462 dir_entry.is_dir = child->win32_res ? 0 : 1;
4463 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4465 memcpy (entries, &dir_entry, sizeof (dir_entry));
4466 entries += sizeof (dir_entry);
4473 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4478 MonoReflectionWin32Resource *win32_res;
4481 if (!assemblyb->win32_resources)
4485 * Resources are stored in a three level tree inside the PE file.
4486 * - level one contains a node for each type of resource
4487 * - level two contains a node for each resource
4488 * - level three contains a node for each instance of a resource for a
4489 * specific language.
4492 tree = resource_tree_create (assemblyb->win32_resources);
4494 /* Estimate the size of the encoded tree */
4496 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4497 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4498 size += mono_array_length (win32_res->res_data);
4500 /* Directory structure */
4501 size += mono_array_length (assemblyb->win32_resources) * 256;
4502 p = buf = g_malloc (size);
4504 resource_tree_encode (tree, p, p, &p);
4506 g_assert (p - buf < size);
4508 assembly->win32_res = g_malloc (p - buf);
4509 assembly->win32_res_size = p - buf;
4510 memcpy (assembly->win32_res, buf, p - buf);
4516 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4518 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4521 p += sizeof (MonoPEResourceDir);
4522 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4523 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4524 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4525 if (dir_entry->is_dir) {
4526 fixup_resource_directory (res_section, child, rva);
4528 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4529 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4532 p += sizeof (MonoPEResourceDirEntry);
4537 * mono_image_create_pefile:
4538 * @mb: a module builder object
4540 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4541 * assembly->pefile where it can be easily retrieved later in chunks.
4544 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4545 MonoMSDOSHeader *msdos;
4546 MonoDotNetHeader *header;
4547 MonoSectionTable *section;
4548 MonoCLIHeader *cli_header;
4549 guint32 size, image_size, virtual_base, text_offset;
4550 guint32 header_start, section_start, file_offset, virtual_offset;
4551 MonoDynamicImage *assembly;
4552 MonoReflectionAssemblyBuilder *assemblyb;
4553 MonoDynamicStream *pefile;
4555 guint32 *rva, value;
4558 static const unsigned char msheader[] = {
4559 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4560 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4561 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4563 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4564 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4565 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4566 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4569 assemblyb = mb->assemblyb;
4571 mono_image_basic_init (assemblyb);
4572 assembly = mb->dynamic_image;
4574 assembly->pe_kind = assemblyb->pe_kind;
4575 assembly->machine = assemblyb->machine;
4576 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4577 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4579 /* already created */
4580 if (assembly->pefile.index)
4583 mono_image_build_metadata (mb);
4585 if (mb->is_main && assemblyb->resources) {
4586 int len = mono_array_length (assemblyb->resources);
4587 for (i = 0; i < len; ++i)
4588 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4591 if (mb->resources) {
4592 int len = mono_array_length (mb->resources);
4593 for (i = 0; i < len; ++i)
4594 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4597 build_compressed_metadata (assembly);
4600 assembly_add_win32_resources (assembly, assemblyb);
4602 nsections = calc_section_size (assembly);
4604 pefile = &assembly->pefile;
4606 /* The DOS header and stub */
4607 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4608 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4610 /* the dotnet header */
4611 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4613 /* the section tables */
4614 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4616 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4617 virtual_offset = VIRT_ALIGN;
4620 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4621 if (!assembly->sections [i].size)
4624 file_offset += FILE_ALIGN - 1;
4625 file_offset &= ~(FILE_ALIGN - 1);
4626 virtual_offset += VIRT_ALIGN - 1;
4627 virtual_offset &= ~(VIRT_ALIGN - 1);
4629 assembly->sections [i].offset = file_offset;
4630 assembly->sections [i].rva = virtual_offset;
4632 file_offset += assembly->sections [i].size;
4633 virtual_offset += assembly->sections [i].size;
4634 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4637 file_offset += FILE_ALIGN - 1;
4638 file_offset &= ~(FILE_ALIGN - 1);
4639 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4641 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4643 /* back-patch info */
4644 msdos = (MonoMSDOSHeader*)pefile->data;
4645 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4646 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4647 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4649 header = (MonoDotNetHeader*)(pefile->data + header_start);
4650 header->pesig [0] = 'P';
4651 header->pesig [1] = 'E';
4653 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4654 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4655 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4656 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4657 if (assemblyb->pekind == 1) {
4659 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4662 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4665 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4667 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4668 header->pe.pe_major = 6;
4669 header->pe.pe_minor = 0;
4670 size = assembly->sections [MONO_SECTION_TEXT].size;
4671 size += FILE_ALIGN - 1;
4672 size &= ~(FILE_ALIGN - 1);
4673 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4674 size = assembly->sections [MONO_SECTION_RSRC].size;
4675 size += FILE_ALIGN - 1;
4676 size &= ~(FILE_ALIGN - 1);
4677 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4678 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4679 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4680 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4681 /* pe_rva_entry_point always at the beginning of the text section */
4682 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4684 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4685 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4686 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4687 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4688 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4689 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4690 size = section_start;
4691 size += FILE_ALIGN - 1;
4692 size &= ~(FILE_ALIGN - 1);
4693 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4695 size += VIRT_ALIGN - 1;
4696 size &= ~(VIRT_ALIGN - 1);
4697 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4700 // Translate the PEFileKind value to the value expected by the Windows loader
4706 // PEFileKinds.Dll == 1
4707 // PEFileKinds.ConsoleApplication == 2
4708 // PEFileKinds.WindowApplication == 3
4711 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4712 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4714 if (assemblyb->pekind == 3)
4719 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4721 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4722 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4723 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4724 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4725 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4726 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4728 /* fill data directory entries */
4730 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4731 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4733 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4734 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4736 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4737 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4738 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4739 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4740 /* patch entrypoint name */
4741 if (assemblyb->pekind == 1)
4742 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4744 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4745 /* patch imported function RVA name */
4746 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4747 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4749 /* the import table */
4750 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4751 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4752 /* patch imported dll RVA name and other entries in the dir */
4753 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4754 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4755 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4756 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4757 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4758 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4760 p = (assembly->code.data + assembly->ilt_offset);
4761 value = (assembly->text_rva + assembly->imp_names_offset);
4762 *p++ = (value) & 0xff;
4763 *p++ = (value >> 8) & (0xff);
4764 *p++ = (value >> 16) & (0xff);
4765 *p++ = (value >> 24) & (0xff);
4767 /* the CLI header info */
4768 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4769 cli_header->ch_size = GUINT32_FROM_LE (72);
4770 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4771 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4772 if (assemblyb->entry_point) {
4773 guint32 table_idx = 0;
4774 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4775 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4776 table_idx = methodb->table_idx;
4778 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4780 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4782 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4784 /* The embedded managed resources */
4785 text_offset = assembly->text_rva + assembly->code.index;
4786 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4787 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4788 text_offset += assembly->resources.index;
4789 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4790 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4791 text_offset += assembly->meta_size;
4792 if (assembly->strong_name_size) {
4793 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4794 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4795 text_offset += assembly->strong_name_size;
4798 /* write the section tables and section content */
4799 section = (MonoSectionTable*)(pefile->data + section_start);
4800 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4801 static const char *section_names [] = {
4802 ".text", ".rsrc", ".reloc"
4804 if (!assembly->sections [i].size)
4806 strcpy (section->st_name, section_names [i]);
4807 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4808 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4809 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4810 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4811 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4812 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4813 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4815 case MONO_SECTION_TEXT:
4816 /* patch entry point */
4817 p = (assembly->code.data + 2);
4818 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4819 *p++ = (value) & 0xff;
4820 *p++ = (value >> 8) & 0xff;
4821 *p++ = (value >> 16) & 0xff;
4822 *p++ = (value >> 24) & 0xff;
4824 text_offset = assembly->sections [i].offset;
4825 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4826 text_offset += assembly->code.index;
4827 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4828 text_offset += assembly->resources.index;
4829 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4830 text_offset += assembly->meta_size;
4831 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4833 g_free (assembly->image.raw_metadata);
4835 case MONO_SECTION_RELOC:
4836 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4837 *rva = GUINT32_FROM_LE (assembly->text_rva);
4839 *rva = GUINT32_FROM_LE (12);
4841 data16 = (guint16*)rva;
4843 * the entrypoint is always at the start of the text section
4844 * 3 is IMAGE_REL_BASED_HIGHLOW
4845 * 2 is patch_size_rva - text_rva
4847 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4849 *data16 = 0; /* terminate */
4851 case MONO_SECTION_RSRC:
4852 if (assembly->win32_res) {
4853 text_offset = assembly->sections [i].offset;
4855 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4856 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4858 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4862 g_assert_not_reached ();
4867 /* check that the file is properly padded */
4870 FILE *f = fopen ("mypetest.exe", "w");
4871 fwrite (pefile->data, pefile->index, 1, f);
4877 MonoReflectionModule *
4878 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4882 MonoImageOpenStatus status;
4883 MonoDynamicAssembly *assembly;
4884 guint32 module_count;
4885 MonoImage **new_modules;
4887 name = mono_string_to_utf8 (fileName);
4889 image = mono_image_open (name, &status);
4892 if (status == MONO_IMAGE_ERROR_ERRNO)
4893 exc = mono_get_exception_file_not_found (fileName);
4895 exc = mono_get_exception_bad_image_format (name);
4897 mono_raise_exception (exc);
4902 assembly = ab->dynamic_assembly;
4903 image->assembly = (MonoAssembly*)assembly;
4905 module_count = image->assembly->image->module_count;
4906 new_modules = g_new0 (MonoImage *, module_count + 1);
4908 if (image->assembly->image->modules)
4909 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4910 new_modules [module_count] = image;
4912 g_free (image->assembly->image->modules);
4913 image->assembly->image->modules = new_modules;
4914 image->assembly->image->module_count ++;
4916 mono_assembly_load_references (image, &status);
4918 mono_image_close (image);
4919 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4922 return mono_module_get_object (mono_domain_get (), image);
4926 * We need to return always the same object for MethodInfo, FieldInfo etc..
4927 * but we need to consider the reflected type.
4928 * type uses a different hash, since it uses custom hash/equal functions.
4933 MonoClass *refclass;
4937 reflected_equal (gconstpointer a, gconstpointer b) {
4938 const ReflectedEntry *ea = a;
4939 const ReflectedEntry *eb = b;
4941 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4945 reflected_hash (gconstpointer a) {
4946 const ReflectedEntry *ea = a;
4947 return GPOINTER_TO_UINT (ea->item);
4950 #define CHECK_OBJECT(t,p,k) \
4956 mono_domain_lock (domain); \
4957 if (!domain->refobject_hash) \
4958 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4959 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4960 mono_domain_unlock (domain); \
4966 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4968 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4971 #define CACHE_OBJECT(p,o,k) \
4973 ReflectedEntry *e = ALLOC_REFENTRY; \
4975 e->refclass = (k); \
4976 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4977 mono_domain_unlock (domain); \
4981 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4983 /* this is done only once */
4984 mono_domain_lock (domain);
4985 CACHE_OBJECT (assembly, res, NULL);
4989 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4991 /* this is done only once */
4992 mono_domain_lock (domain);
4993 CACHE_OBJECT (module, res, NULL);
4997 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4999 MonoDynamicImage *image = moduleb->dynamic_image;
5000 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5003 * FIXME: we already created an image in mono_image_basic_init (), but
5004 * we don't know which module it belongs to, since that is only
5005 * determined at assembly save time.
5007 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5008 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5010 moduleb->module.image = &image->image;
5011 moduleb->dynamic_image = image;
5012 register_module (mono_object_domain (moduleb), moduleb, image);
5017 * mono_assembly_get_object:
5018 * @domain: an app domain
5019 * @assembly: an assembly
5021 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5023 MonoReflectionAssembly*
5024 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5026 static MonoClass *System_Reflection_Assembly;
5027 MonoReflectionAssembly *res;
5029 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5030 if (!System_Reflection_Assembly)
5031 System_Reflection_Assembly = mono_class_from_name (
5032 mono_defaults.corlib, "System.Reflection", "Assembly");
5033 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5034 res->assembly = assembly;
5035 CACHE_OBJECT (assembly, res, NULL);
5041 MonoReflectionModule*
5042 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5044 static MonoClass *System_Reflection_Module;
5045 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, basename = g_path_get_basename (image->name));
5059 res->scopename = mono_string_new (domain, image->module_name);
5063 if (image->assembly->image == image) {
5064 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5067 g_assert (image->assembly->image->modules);
5069 for (i = 0; i < image->assembly->image->module_count; i++) {
5070 if (image->assembly->image->modules [i] == image)
5071 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5073 g_assert (res->token);
5076 mono_image_addref (image);
5078 CACHE_OBJECT (image, res, NULL);
5082 MonoReflectionModule*
5083 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5085 static MonoClass *System_Reflection_Module;
5086 MonoReflectionModule *res;
5087 MonoTableInfo *table;
5088 guint32 cols [MONO_FILE_SIZE];
5090 guint32 i, name_idx;
5093 if (!System_Reflection_Module)
5094 System_Reflection_Module = mono_class_from_name (
5095 mono_defaults.corlib, "System.Reflection", "Module");
5096 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5098 table = &image->tables [MONO_TABLE_FILE];
5099 g_assert (table_index < table->rows);
5100 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5103 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5104 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5106 /* Check whenever the row has a corresponding row in the moduleref table */
5107 table = &image->tables [MONO_TABLE_MODULEREF];
5108 for (i = 0; i < table->rows; ++i) {
5109 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5110 val = mono_metadata_string_heap (image, name_idx);
5111 if (strcmp (val, name) == 0)
5112 res->image = image->modules [i];
5115 res->fqname = mono_string_new (domain, name);
5116 res->name = mono_string_new (domain, name);
5117 res->scopename = mono_string_new (domain, name);
5118 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5119 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5125 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5127 if ((t1->type != t2->type) ||
5128 (t1->byref != t2->byref))
5132 case MONO_TYPE_VOID:
5133 case MONO_TYPE_BOOLEAN:
5134 case MONO_TYPE_CHAR:
5145 case MONO_TYPE_STRING:
5148 case MONO_TYPE_OBJECT:
5149 case MONO_TYPE_TYPEDBYREF:
5151 case MONO_TYPE_VALUETYPE:
5152 case MONO_TYPE_CLASS:
5153 case MONO_TYPE_SZARRAY:
5154 return t1->data.klass == t2->data.klass;
5156 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5157 case MONO_TYPE_ARRAY:
5158 if (t1->data.array->rank != t2->data.array->rank)
5160 return t1->data.array->eklass == t2->data.array->eklass;
5161 case MONO_TYPE_GENERICINST: {
5163 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5165 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5167 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5168 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5174 case MONO_TYPE_MVAR:
5175 return t1->data.generic_param == t2->data.generic_param;
5177 g_error ("implement type compare for %0x!", t1->type);
5185 mymono_metadata_type_hash (MonoType *t1)
5191 hash |= t1->byref << 6; /* do not collide with t1->type values */
5193 case MONO_TYPE_VALUETYPE:
5194 case MONO_TYPE_CLASS:
5195 case MONO_TYPE_SZARRAY:
5196 /* check if the distribution is good enough */
5197 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5199 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5204 static MonoReflectionGenericInst*
5205 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5207 static MonoClass *System_Reflection_MonoGenericInst;
5208 MonoReflectionGenericInst *res;
5209 MonoGenericInst *ginst;
5212 if (!System_Reflection_MonoGenericInst) {
5213 System_Reflection_MonoGenericInst = mono_class_from_name (
5214 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5215 g_assert (System_Reflection_MonoGenericInst);
5218 ginst = geninst->data.generic_inst;
5219 gklass = mono_class_from_mono_type (ginst->generic_type);
5221 mono_class_init (ginst->klass);
5223 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5225 res->type.type = geninst;
5226 if (gklass->wastypebuilder && gklass->reflection_info)
5227 res->generic_type = gklass->reflection_info;
5229 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5235 * mono_type_get_object:
5236 * @domain: an app domain
5239 * Return an System.MonoType object representing the type @type.
5242 mono_type_get_object (MonoDomain *domain, MonoType *type)
5244 MonoReflectionType *res;
5245 MonoClass *klass = mono_class_from_mono_type (type);
5247 mono_domain_lock (domain);
5248 if (!domain->type_hash)
5249 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5250 (GCompareFunc)mymono_metadata_type_equal);
5251 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5252 mono_domain_unlock (domain);
5255 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5256 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5257 mono_g_hash_table_insert (domain->type_hash, type, res);
5258 mono_domain_unlock (domain);
5261 if (klass->reflection_info && !klass->wastypebuilder) {
5262 /* g_assert_not_reached (); */
5263 /* should this be considered an error condition? */
5265 mono_domain_unlock (domain);
5266 return klass->reflection_info;
5269 mono_class_init (klass);
5270 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5272 mono_g_hash_table_insert (domain->type_hash, type, res);
5273 mono_domain_unlock (domain);
5278 * mono_method_get_object:
5279 * @domain: an app domain
5281 * @refclass: the reflected type (can be NULL)
5283 * Return an System.Reflection.MonoMethod object representing the method @method.
5285 MonoReflectionMethod*
5286 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5289 * We use the same C representation for methods and constructors, but the type
5290 * name in C# is different.
5294 MonoReflectionMethod *ret;
5297 refclass = method->klass;
5299 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5300 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5301 cname = "MonoCMethod";
5303 cname = "MonoMethod";
5304 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5306 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5307 ret->method = method;
5308 ret->name = mono_string_new (domain, method->name);
5309 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5310 CACHE_OBJECT (method, ret, refclass);
5315 * mono_field_get_object:
5316 * @domain: an app domain
5320 * Return an System.Reflection.MonoField object representing the field @field
5323 MonoReflectionField*
5324 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5326 MonoReflectionField *res;
5329 CHECK_OBJECT (MonoReflectionField *, field, klass);
5330 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5331 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5334 res->name = mono_string_new (domain, field->name);
5335 if (field->generic_info)
5336 res->attrs = field->generic_info->generic_type->attrs;
5338 res->attrs = field->type->attrs;
5339 res->type = mono_type_get_object (domain, field->type);
5340 CACHE_OBJECT (field, res, klass);
5345 * mono_property_get_object:
5346 * @domain: an app domain
5348 * @property: a property
5350 * Return an System.Reflection.MonoProperty object representing the property @property
5353 MonoReflectionProperty*
5354 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5356 MonoReflectionProperty *res;
5359 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5360 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5361 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5363 res->property = property;
5364 CACHE_OBJECT (property, res, klass);
5369 * mono_event_get_object:
5370 * @domain: an app domain
5374 * Return an System.Reflection.MonoEvent object representing the event @event
5377 MonoReflectionEvent*
5378 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5380 MonoReflectionEvent *res;
5383 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5384 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5385 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5388 CACHE_OBJECT (event, res, klass);
5393 * mono_param_get_objects:
5394 * @domain: an app domain
5397 * Return an System.Reflection.ParameterInfo array object representing the parameters
5398 * in the method @method.
5401 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5403 static MonoClass *System_Reflection_ParameterInfo;
5404 MonoArray *res = NULL;
5405 MonoReflectionMethod *member = NULL;
5406 MonoReflectionParameter *param = NULL;
5407 char **names, **blobs = NULL;
5408 MonoObject *dbnull = mono_get_dbnull_object (domain);
5409 MonoMarshalSpec **mspecs;
5412 if (!System_Reflection_ParameterInfo)
5413 System_Reflection_ParameterInfo = mono_class_from_name (
5414 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5416 if (!method->signature->param_count)
5417 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5419 /* Note: the cache is based on the address of the signature into the method
5420 * since we already cache MethodInfos with the method as keys.
5422 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5424 member = mono_method_get_object (domain, method, NULL);
5425 names = g_new (char *, method->signature->param_count);
5426 mono_method_get_param_names (method, (const char **) names);
5428 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5429 mono_method_get_marshal_info (method, mspecs);
5431 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5432 for (i = 0; i < method->signature->param_count; ++i) {
5433 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5434 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5435 param->MemberImpl = (MonoObject*)member;
5436 param->NameImpl = mono_string_new (domain, names [i]);
5437 param->PositionImpl = i;
5438 param->AttrsImpl = method->signature->params [i]->attrs;
5440 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5441 param->DefaultValueImpl = dbnull;
5443 MonoType *type = param->ClassImpl->type;
5446 blobs = g_new0 (char *, method->signature->param_count);
5447 get_default_param_value_blobs (method, blobs);
5450 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5452 if (!param->DefaultValueImpl) {
5453 param->DefaultValueImpl = dbnull;
5458 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5460 mono_array_set (res, gpointer, i, param);
5465 for (i = method->signature->param_count; i >= 0; i--)
5467 mono_metadata_free_marshal_spec (mspecs [i]);
5470 CACHE_OBJECT (&(method->signature), res, NULL);
5475 * mono_method_body_get_object:
5476 * @domain: an app domain
5479 * Return an System.Reflection.MethodBody object representing the method @method.
5481 MonoReflectionMethodBody*
5482 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5484 static MonoClass *System_Reflection_MethodBody = NULL;
5485 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5486 MonoReflectionMethodBody *ret;
5487 MonoMethodNormal *mn;
5488 MonoMethodHeader *header;
5491 if (!System_Reflection_MethodBody)
5492 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5493 if (!System_Reflection_LocalVariableInfo)
5494 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5496 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5498 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5499 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5501 mn = (MonoMethodNormal *)method;
5502 header = mono_method_get_header (method);
5504 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5505 /* FIXME: Other fields */
5506 ret->init_locals = header->init_locals;
5507 ret->max_stack = header->max_stack;
5508 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5509 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5510 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5511 for (i = 0; i < header->num_locals; ++i) {
5512 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5513 info->local_type = mono_type_get_object (domain, header->locals [i]);
5514 info->is_pinned = header->locals [i]->pinned;
5515 info->local_index = 0;
5518 CACHE_OBJECT (method, ret, NULL);
5523 mono_get_dbnull_object (MonoDomain *domain)
5527 static MonoClassField *dbnull_value_field = NULL;
5529 if (!dbnull_value_field) {
5530 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5531 mono_class_init (klass);
5532 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5533 g_assert (dbnull_value_field);
5535 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5542 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5544 guint32 param_index, i, lastp, crow = 0;
5545 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5548 MonoClass *klass = method->klass;
5549 MonoImage *image = klass->image;
5550 MonoMethodSignature *methodsig = method->signature;
5552 MonoTableInfo *constt;
5553 MonoTableInfo *methodt;
5554 MonoTableInfo *paramt;
5556 if (!methodsig->param_count)
5559 if (klass->generic_inst) {
5560 return; /* FIXME - ??? */
5563 mono_class_init (klass);
5565 if (klass->image->dynamic) {
5566 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5567 if (aux && aux->param_defaults)
5568 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5572 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5573 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5574 constt = &image->tables [MONO_TABLE_CONSTANT];
5576 for (i = 0; i < klass->method.count; ++i) {
5577 if (method == klass->methods [i]) {
5578 idx = klass->method.first + i;
5583 g_assert (idx != -1);
5585 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5586 if (idx + 1 < methodt->rows)
5587 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5589 lastp = paramt->rows + 1;
5591 for (i = param_index; i < lastp; ++i) {
5594 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5595 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5597 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5600 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5605 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5606 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5613 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5622 klass = mono_class_from_mono_type (type);
5623 if (klass->valuetype) {
5624 object = mono_object_new (domain, klass);
5625 retval = ((gchar *) object + sizeof (MonoObject));
5630 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5637 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5641 memset (assembly, 0, sizeof (MonoAssemblyName));
5643 assembly->culture = "";
5644 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5646 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5649 while (*p == ' ' || *p == ',') {
5658 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5660 assembly->major = strtoul (p, &s, 10);
5661 if (s == p || *s != '.')
5664 assembly->minor = strtoul (p, &s, 10);
5665 if (s == p || *s != '.')
5668 assembly->build = strtoul (p, &s, 10);
5669 if (s == p || *s != '.')
5672 assembly->revision = strtoul (p, &s, 10);
5676 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5678 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5679 assembly->culture = "";
5682 assembly->culture = p;
5683 while (*p && *p != ',') {
5687 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5689 if (strncmp (p, "null", 4) == 0) {
5694 while (*p && *p != ',') {
5697 len = (p - start + 1);
5698 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5699 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5700 g_strlcpy (assembly->public_key_token, start, len);
5703 while (*p && *p != ',')
5707 while (*p == ' ' || *p == ',') {
5721 * mono_reflection_parse_type:
5724 * Parse a type name as accepted by the GetType () method and output the info
5725 * extracted in the info structure.
5726 * the name param will be mangled, so, make a copy before passing it to this function.
5727 * The fields in info will be valid until the memory pointed to by name is valid.
5728 * Returns 0 on parse error.
5729 * See also mono_type_get_name () below.
5732 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5734 char *start, *p, *w, *last_point, *startn;
5735 int in_modifiers = 0;
5736 int isbyref = 0, rank;
5738 start = p = w = name;
5740 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5741 info->name = info->name_space = NULL;
5742 info->nested = NULL;
5743 info->modifiers = NULL;
5745 /* last_point separates the namespace from the name */
5751 *p = 0; /* NULL terminate the name */
5753 info->nested = g_list_append (info->nested, startn);
5754 /* we have parsed the nesting namespace + name */
5758 info->name_space = start;
5760 info->name = last_point + 1;
5762 info->name_space = (char *)"";
5788 info->name_space = start;
5790 info->name = last_point + 1;
5792 info->name_space = (char *)"";
5799 if (isbyref) /* only one level allowed by the spec */
5802 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5806 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5817 else if (*p != '*') /* '*' means unknown lower bound */
5823 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5835 return 0; /* missing assembly name */
5836 if (!assembly_name_to_aname (&info->assembly, p))
5843 if (info->assembly.name)
5846 *w = 0; /* terminate class name */
5847 if (!info->name || !*info->name)
5849 /* add other consistency checks */
5854 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5861 image = mono_defaults.corlib;
5864 klass = mono_class_from_name_case (image, info->name_space, info->name);
5866 klass = mono_class_from_name (image, info->name_space, info->name);
5869 for (mod = info->nested; mod; mod = mod->next) {
5872 mono_class_init (klass);
5873 nested = klass->nested_classes;
5876 klass = nested->data;
5878 if (g_strcasecmp (klass->name, mod->data) == 0)
5881 if (strcmp (klass->name, mod->data) == 0)
5885 nested = nested->next;
5892 mono_class_init (klass);
5893 for (mod = info->modifiers; mod; mod = mod->next) {
5894 modval = GPOINTER_TO_UINT (mod->data);
5895 if (!modval) { /* byref: must be last modifier */
5896 return &klass->this_arg;
5897 } else if (modval == -1) {
5898 klass = mono_ptr_class_get (&klass->byval_arg);
5899 } else { /* array rank */
5900 klass = mono_array_class_get (klass, modval);
5902 mono_class_init (klass);
5905 return &klass->byval_arg;
5909 * mono_reflection_get_type:
5910 * @image: a metadata context
5911 * @info: type description structure
5912 * @ignorecase: flag for case-insensitive string compares
5913 * @type_resolve: whenever type resolve was already tried
5915 * Build a MonoType from the type description in @info.
5920 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5923 MonoReflectionAssembly *assembly;
5927 type = mono_reflection_get_type_internal (image, info, ignorecase);
5930 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5937 *type_resolve = TRUE;
5940 /* Reconstruct the type name */
5941 fullName = g_string_new ("");
5942 if (info->name_space && (info->name_space [0] != '\0'))
5943 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5945 g_string_printf (fullName, info->name);
5946 for (mod = info->nested; mod; mod = mod->next)
5947 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5949 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5951 if (assembly->assembly->dynamic) {
5952 /* Enumerate all modules */
5953 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5957 if (abuilder->modules) {
5958 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5959 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5960 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5966 if (!type && abuilder->loaded_modules) {
5967 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5968 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5969 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5976 type = mono_reflection_get_type_internal (assembly->assembly->image,
5979 g_string_free (fullName, TRUE);
5984 * mono_reflection_type_from_name:
5986 * @image: a metadata context (can be NULL).
5988 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5989 * it defaults to get the type from @image or, if @image is NULL or loading
5990 * from it fails, uses corlib.
5994 mono_reflection_type_from_name (char *name, MonoImage *image)
5997 MonoTypeNameParse info;
5998 MonoAssembly *assembly;
6000 gboolean type_resolve = FALSE;
6002 /* Make a copy since parse_type modifies its argument */
6003 tmp = g_strdup (name);
6005 /*g_print ("requested type %s\n", str);*/
6006 if (!mono_reflection_parse_type (tmp, &info)) {
6008 g_list_free (info.modifiers);
6009 g_list_free (info.nested);
6013 if (info.assembly.name) {
6014 assembly = mono_assembly_loaded (&info.assembly);
6016 /* then we must load the assembly ourselve - see #60439 */
6017 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6020 g_list_free (info.modifiers);
6021 g_list_free (info.nested);
6025 image = assembly->image;
6026 } else if (image == NULL) {
6027 image = mono_defaults.corlib;
6030 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6031 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6032 image = mono_defaults.corlib;
6033 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6037 g_list_free (info.modifiers);
6038 g_list_free (info.nested);
6043 * mono_reflection_get_token:
6045 * Return the metadata token of OBJ which should be an object
6046 * representing a metadata element.
6049 mono_reflection_get_token (MonoObject *obj)
6054 klass = obj->vtable->klass;
6056 if (strcmp (klass->name, "MethodBuilder") == 0) {
6057 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6059 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6060 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6061 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6063 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6064 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6065 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6066 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6067 if (tb->generic_params) {
6068 g_assert_not_reached ();
6070 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6072 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6073 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6074 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6075 } else if (strcmp (klass->name, "MonoType") == 0) {
6076 MonoReflectionType *tb = (MonoReflectionType *)obj;
6077 token = mono_class_from_mono_type (tb->type)->type_token;
6078 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6079 strcmp (klass->name, "MonoMethod") == 0) {
6080 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6081 if (m->method->signature->is_inflated) {
6082 g_assert_not_reached ();
6083 } else if (m->method->signature->generic_param_count) {
6084 g_assert_not_reached ();
6085 } else if (m->method->klass->generic_inst) {
6086 g_assert_not_reached ();
6088 token = m->method->token;
6090 } else if (strcmp (klass->name, "MonoField") == 0) {
6091 MonoReflectionField *f = (MonoReflectionField*)obj;
6093 token = mono_class_get_field_token (f->field);
6094 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6095 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6097 token = mono_class_get_property_token (p->property);
6098 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6099 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6101 token = mono_class_get_event_token (p->event);
6102 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6103 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6105 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6106 } else if (strcmp (klass->name, "Module") == 0) {
6107 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6110 } else if (strcmp (klass->name, "Assembly") == 0) {
6111 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6113 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6114 MonoException *ex = mono_get_exception_not_implemented (msg);
6116 mono_raise_exception (ex);
6123 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6125 int slen, type = t->type;
6130 case MONO_TYPE_BOOLEAN: {
6131 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6136 case MONO_TYPE_CHAR:
6138 case MONO_TYPE_I2: {
6139 guint16 *val = g_malloc (sizeof (guint16));
6144 #if SIZEOF_VOID_P == 4
6150 case MONO_TYPE_I4: {
6151 guint32 *val = g_malloc (sizeof (guint32));
6156 #if SIZEOF_VOID_P == 8
6157 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6162 case MONO_TYPE_I8: {
6163 guint64 *val = g_malloc (sizeof (guint64));
6168 case MONO_TYPE_VALUETYPE:
6169 if (t->data.klass->enumtype) {
6170 type = t->data.klass->enum_basetype->type;
6173 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6176 case MONO_TYPE_STRING:
6177 if (*p == (char)0xFF) {
6181 slen = mono_metadata_decode_value (p, &p);
6183 return mono_string_new_len (mono_domain_get (), p, slen);
6184 case MONO_TYPE_CLASS: {
6187 if (*p == (char)0xFF) {
6192 slen = mono_metadata_decode_value (p, &p);
6193 n = g_memdup (p, slen + 1);
6195 t = mono_reflection_type_from_name (n, image);
6197 g_warning ("Cannot load type '%s'", n);
6201 return mono_type_get_object (mono_domain_get (), t);
6205 case MONO_TYPE_OBJECT: {
6208 MonoClass *subc = NULL;
6213 } else if (subt == 0x0E) {
6214 type = MONO_TYPE_STRING;
6216 } else if (subt == 0x55) {
6219 slen = mono_metadata_decode_value (p, &p);
6220 n = g_memdup (p, slen + 1);
6222 t = mono_reflection_type_from_name (n, image);
6224 g_warning ("Cannot load type '%s'", n);
6227 subc = mono_class_from_mono_type (t);
6228 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6229 MonoType simple_type = {{0}};
6230 simple_type.type = subt;
6231 subc = mono_class_from_mono_type (&simple_type);
6233 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6235 val = load_cattr_value (image, &subc->byval_arg, p, end);
6236 obj = mono_object_new (mono_domain_get (), subc);
6237 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6241 case MONO_TYPE_SZARRAY: {
6243 guint32 i, alen, basetype;
6246 if (alen == 0xffffffff) {
6250 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6251 basetype = t->data.klass->byval_arg.type;
6256 case MONO_TYPE_BOOLEAN:
6257 for (i = 0; i < alen; i++) {
6258 MonoBoolean val = *p++;
6259 mono_array_set (arr, MonoBoolean, i, val);
6262 case MONO_TYPE_CHAR:
6265 for (i = 0; i < alen; i++) {
6266 guint16 val = read16 (p);
6267 mono_array_set (arr, guint16, i, val);
6274 for (i = 0; i < alen; i++) {
6275 guint32 val = read32 (p);
6276 mono_array_set (arr, guint32, i, val);
6283 for (i = 0; i < alen; i++) {
6284 guint64 val = read64 (p);
6285 mono_array_set (arr, guint64, i, val);
6289 case MONO_TYPE_CLASS:
6290 case MONO_TYPE_OBJECT:
6291 case MONO_TYPE_STRING:
6292 for (i = 0; i < alen; i++) {
6293 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6294 mono_array_set (arr, gpointer, i, item);
6298 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6304 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6310 type_is_reference (MonoType *type)
6312 switch (type->type) {
6313 case MONO_TYPE_BOOLEAN:
6314 case MONO_TYPE_CHAR:
6327 case MONO_TYPE_VALUETYPE:
6335 free_param_data (MonoMethodSignature *sig, void **params) {
6337 for (i = 0; i < sig->param_count; ++i) {
6338 if (!type_is_reference (sig->params [i]))
6339 g_free (params [i]);
6344 * Find the method index in the metadata methodDef table.
6345 * Later put these three helper methods in metadata and export them.
6348 find_method_index (MonoMethod *method) {
6349 MonoClass *klass = method->klass;
6352 for (i = 0; i < klass->method.count; ++i) {
6353 if (method == klass->methods [i])
6354 return klass->method.first + 1 + i;
6360 * Find the field index in the metadata FieldDef table.
6363 find_field_index (MonoClass *klass, MonoClassField *field) {
6366 for (i = 0; i < klass->field.count; ++i) {
6367 if (field == &klass->fields [i])
6368 return klass->field.first + 1 + i;
6374 * Find the property index in the metadata Property table.
6377 find_property_index (MonoClass *klass, MonoProperty *property) {
6380 for (i = 0; i < klass->property.count; ++i) {
6381 if (property == &klass->properties [i])
6382 return klass->property.first + 1 + i;
6388 * Find the event index in the metadata Event table.
6391 find_event_index (MonoClass *klass, MonoEvent *event) {
6394 for (i = 0; i < klass->event.count; ++i) {
6395 if (event == &klass->events [i])
6396 return klass->event.first + 1 + i;
6402 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6404 const char *p = data;
6406 guint32 i, j, num_named;
6410 mono_class_init (method->klass);
6413 attr = mono_object_new (mono_domain_get (), method->klass);
6414 mono_runtime_invoke (method, attr, NULL, NULL);
6418 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6421 /*g_print ("got attr %s\n", method->klass->name);*/
6423 params = g_new (void*, method->signature->param_count);
6427 for (i = 0; i < method->signature->param_count; ++i) {
6428 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6432 attr = mono_object_new (mono_domain_get (), method->klass);
6433 mono_runtime_invoke (method, attr, params, NULL);
6434 free_param_data (method->signature, params);
6436 num_named = read16 (named);
6438 for (j = 0; j < num_named; j++) {
6440 char *name, named_type, data_type;
6441 named_type = *named++;
6442 data_type = *named++; /* type of data */
6443 if (data_type == 0x55) {
6446 type_len = mono_metadata_decode_blob_size (named, &named);
6447 type_name = g_malloc (type_len + 1);
6448 memcpy (type_name, named, type_len);
6449 type_name [type_len] = 0;
6451 /* FIXME: lookup the type and check type consistency */
6452 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6453 /* this seems to be the type of the element of the array */
6454 /* g_print ("skipping 0x%02x after prop\n", *named); */
6457 name_len = mono_metadata_decode_blob_size (named, &named);
6458 name = g_malloc (name_len + 1);
6459 memcpy (name, named, name_len);
6460 name [name_len] = 0;
6462 if (named_type == 0x53) {
6463 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6464 void *val = load_cattr_value (image, field->type, named, &named);
6465 mono_field_set_value (attr, field, val);
6466 if (!type_is_reference (field->type))
6468 } else if (named_type == 0x54) {
6471 MonoType *prop_type;
6473 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6474 /* can we have more that 1 arg in a custom attr named property? */
6475 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6476 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6477 mono_property_set_value (prop, attr, pparams, NULL);
6478 if (!type_is_reference (prop_type))
6479 g_free (pparams [0]);
6488 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6495 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6496 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6497 for (i = 0; i < cinfo->num_attrs; ++i) {
6498 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6499 mono_array_set (result, gpointer, i, attr);
6505 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6507 guint32 mtoken, i, len;
6508 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6510 MonoCustomAttrInfo *ainfo;
6511 GList *tmp, *list = NULL;
6514 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6516 i = mono_metadata_custom_attrs_from_index (image, idx);
6520 while (i < ca->rows) {
6521 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6523 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6526 len = g_list_length (list);
6529 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6530 ainfo->num_attrs = len;
6531 ainfo->image = image;
6532 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6533 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6534 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6535 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6536 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6537 mtoken |= MONO_TOKEN_METHOD_DEF;
6539 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6540 mtoken |= MONO_TOKEN_MEMBER_REF;
6543 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6546 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6547 if (!ainfo->attrs [i].ctor)
6548 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6549 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6550 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6551 ainfo->attrs [i].data = data;
6559 mono_custom_attrs_from_method (MonoMethod *method)
6561 MonoCustomAttrInfo *cinfo;
6564 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6566 idx = find_method_index (method);
6567 idx <<= MONO_CUSTOM_ATTR_BITS;
6568 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6569 return mono_custom_attrs_from_index (method->klass->image, idx);
6573 mono_custom_attrs_from_class (MonoClass *klass)
6575 MonoCustomAttrInfo *cinfo;
6578 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6580 idx = mono_metadata_token_index (klass->type_token);
6581 idx <<= MONO_CUSTOM_ATTR_BITS;
6582 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6583 return mono_custom_attrs_from_index (klass->image, idx);
6587 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6589 MonoCustomAttrInfo *cinfo;
6592 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6594 idx = 1; /* there is only one assembly */
6595 idx <<= MONO_CUSTOM_ATTR_BITS;
6596 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6597 return mono_custom_attrs_from_index (assembly->image, idx);
6600 static MonoCustomAttrInfo*
6601 mono_custom_attrs_from_module (MonoImage *image)
6603 MonoCustomAttrInfo *cinfo;
6606 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6608 idx = 1; /* there is only one module */
6609 idx <<= MONO_CUSTOM_ATTR_BITS;
6610 idx |= MONO_CUSTOM_ATTR_MODULE;
6611 return mono_custom_attrs_from_index (image, idx);
6615 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6617 MonoCustomAttrInfo *cinfo;
6620 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6622 idx = find_property_index (klass, property);
6623 idx <<= MONO_CUSTOM_ATTR_BITS;
6624 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6625 return mono_custom_attrs_from_index (klass->image, idx);
6629 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6631 MonoCustomAttrInfo *cinfo;
6634 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6636 idx = find_event_index (klass, event);
6637 idx <<= MONO_CUSTOM_ATTR_BITS;
6638 idx |= MONO_CUSTOM_ATTR_EVENT;
6639 return mono_custom_attrs_from_index (klass->image, idx);
6643 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6645 MonoCustomAttrInfo *cinfo;
6648 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6650 idx = find_field_index (klass, field);
6651 idx <<= MONO_CUSTOM_ATTR_BITS;
6652 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6653 return mono_custom_attrs_from_index (klass->image, idx);
6657 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6660 guint32 i, idx, method_index;
6661 guint32 param_list, param_last, param_pos, found;
6663 MonoReflectionMethodAux *aux;
6665 if (method->klass->image->dynamic) {
6666 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6667 if (!aux || !aux->param_cattr)
6669 return aux->param_cattr [param];
6672 image = method->klass->image;
6673 method_index = find_method_index (method);
6674 ca = &image->tables [MONO_TABLE_METHOD];
6676 if (method->klass->generic_inst || method->klass->generic_container ||
6677 method->signature->generic_param_count) {
6678 /* FIXME FIXME FIXME */
6682 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6683 if (method_index == ca->rows) {
6684 ca = &image->tables [MONO_TABLE_PARAM];
6685 param_last = ca->rows + 1;
6687 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6688 ca = &image->tables [MONO_TABLE_PARAM];
6691 for (i = param_list; i < param_last; ++i) {
6692 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6693 if (param_pos == param) {
6701 idx <<= MONO_CUSTOM_ATTR_BITS;
6702 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6703 return mono_custom_attrs_from_index (image, idx);
6707 * mono_reflection_get_custom_attrs:
6708 * @obj: a reflection object handle
6710 * Return an array with all the custom attributes defined of the
6711 * reflection handle @obj. The objects are fully build.
6714 mono_reflection_get_custom_attrs (MonoObject *obj)
6718 MonoCustomAttrInfo *cinfo = NULL;
6720 MONO_ARCH_SAVE_REGS;
6722 klass = obj->vtable->klass;
6723 if (klass == mono_defaults.monotype_class) {
6724 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6725 klass = mono_class_from_mono_type (rtype->type);
6726 cinfo = mono_custom_attrs_from_class (klass);
6727 } else if (strcmp ("Assembly", klass->name) == 0) {
6728 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6729 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6730 } else if (strcmp ("Module", klass->name) == 0) {
6731 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6732 cinfo = mono_custom_attrs_from_module (module->image);
6733 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6734 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6735 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6736 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6737 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6738 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6739 } else if (strcmp ("MonoField", klass->name) == 0) {
6740 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6741 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6742 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6743 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6744 cinfo = mono_custom_attrs_from_method (rmethod->method);
6745 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6746 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6747 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6748 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6749 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6750 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6751 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6752 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6753 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6754 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6755 } else { /* handle other types here... */
6756 g_error ("get custom attrs not yet supported for %s", klass->name);
6760 result = mono_custom_attrs_construct (cinfo);
6762 mono_custom_attrs_free (cinfo);
6764 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6765 result = mono_array_new (mono_domain_get (), klass, 0);
6771 static MonoMethodSignature*
6772 parameters_to_signature (MonoArray *parameters) {
6773 MonoMethodSignature *sig;
6776 count = parameters? mono_array_length (parameters): 0;
6778 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6779 sig->param_count = count;
6780 sig->sentinelpos = -1; /* FIXME */
6781 for (i = 0; i < count; ++i) {
6782 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6783 sig->params [i] = pt->type;
6788 static MonoMethodSignature*
6789 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6790 MonoMethodSignature *sig;
6792 sig = parameters_to_signature (ctor->parameters);
6793 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6794 sig->ret = &mono_defaults.void_class->byval_arg;
6798 static MonoMethodSignature*
6799 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6800 MonoMethodSignature *sig;
6802 sig = parameters_to_signature (method->parameters);
6803 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6804 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6805 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6809 static MonoMethodSignature*
6810 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6811 MonoMethodSignature *sig;
6813 sig = parameters_to_signature (method->parameters);
6814 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6815 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6816 sig->generic_param_count = 0;
6821 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6823 MonoClass *klass = mono_object_class (prop);
6824 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6825 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6826 *name = mono_string_to_utf8 (pb->name);
6827 *type = pb->type->type;
6829 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6830 *name = g_strdup (p->property->name);
6831 if (p->property->get)
6832 *type = p->property->get->signature->ret;
6834 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6839 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6841 MonoClass *klass = mono_object_class (field);
6842 if (strcmp (klass->name, "FieldBuilder") == 0) {
6843 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6844 *name = mono_string_to_utf8 (fb->name);
6845 *type = fb->type->type;
6847 MonoReflectionField *f = (MonoReflectionField *)field;
6848 *name = g_strdup (f->field->name);
6849 *type = f->field->type;
6854 * Encode a value in a custom attribute stream of bytes.
6855 * The value to encode is either supplied as an object in argument val
6856 * (valuetypes are boxed), or as a pointer to the data in the
6858 * @type represents the type of the value
6859 * @buffer is the start of the buffer
6860 * @p the current position in the buffer
6861 * @buflen contains the size of the buffer and is used to return the new buffer size
6862 * if this needs to be realloced.
6863 * @retbuffer and @retp return the start and the position of the buffer
6866 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6868 MonoTypeEnum simple_type;
6870 if ((p-buffer) + 10 >= *buflen) {
6873 newbuf = g_realloc (buffer, *buflen);
6874 p = newbuf + (p-buffer);
6878 argval = ((char*)arg + sizeof (MonoObject));
6879 simple_type = type->type;
6881 switch (simple_type) {
6882 case MONO_TYPE_BOOLEAN:
6887 case MONO_TYPE_CHAR:
6890 swap_with_size (p, argval, 2, 1);
6896 swap_with_size (p, argval, 4, 1);
6902 swap_with_size (p, argval, 8, 1);
6905 case MONO_TYPE_VALUETYPE:
6906 if (type->data.klass->enumtype) {
6907 simple_type = type->data.klass->enum_basetype->type;
6910 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6913 case MONO_TYPE_STRING: {
6920 str = mono_string_to_utf8 ((MonoString*)arg);
6921 slen = strlen (str);
6922 if ((p-buffer) + 10 + slen >= *buflen) {
6926 newbuf = g_realloc (buffer, *buflen);
6927 p = newbuf + (p-buffer);
6930 mono_metadata_encode_value (slen, p, &p);
6931 memcpy (p, str, slen);
6936 case MONO_TYPE_CLASS: {
6944 k = mono_object_class (arg);
6945 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6946 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6947 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6949 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6950 slen = strlen (str);
6951 if ((p-buffer) + 10 + slen >= *buflen) {
6955 newbuf = g_realloc (buffer, *buflen);
6956 p = newbuf + (p-buffer);
6959 mono_metadata_encode_value (slen, p, &p);
6960 memcpy (p, str, slen);
6965 case MONO_TYPE_SZARRAY: {
6967 MonoClass *eclass, *arg_eclass;
6970 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6973 len = mono_array_length ((MonoArray*)arg);
6975 *p++ = (len >> 8) & 0xff;
6976 *p++ = (len >> 16) & 0xff;
6977 *p++ = (len >> 24) & 0xff;
6979 *retbuffer = buffer;
6980 eclass = type->data.klass;
6981 arg_eclass = mono_object_class (arg)->element_class;
6982 if (eclass->valuetype && arg_eclass->valuetype) {
6983 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6984 int elsize = mono_class_array_element_size (eclass);
6985 for (i = 0; i < len; ++i) {
6986 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6990 for (i = 0; i < len; ++i) {
6991 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6996 /* it may be a boxed value or a Type */
6997 case MONO_TYPE_OBJECT: {
6998 MonoClass *klass = mono_object_class (arg);
7002 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7005 } else if (klass->enumtype) {
7007 } else if (klass == mono_defaults.string_class) {
7008 simple_type = MONO_TYPE_STRING;
7011 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7012 *p++ = simple_type = klass->byval_arg.type;
7015 g_error ("unhandled type in custom attr");
7017 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7018 slen = strlen (str);
7019 if ((p-buffer) + 10 + slen >= *buflen) {
7023 newbuf = g_realloc (buffer, *buflen);
7024 p = newbuf + (p-buffer);
7027 mono_metadata_encode_value (slen, p, &p);
7028 memcpy (p, str, slen);
7031 simple_type = klass->enum_basetype->type;
7035 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7038 *retbuffer = buffer;
7042 * mono_reflection_get_custom_attrs_blob:
7043 * @ctor: custom attribute constructor
7044 * @ctorArgs: arguments o the constructor
7050 * Creates the blob of data that needs to be saved in the metadata and that represents
7051 * the custom attributed described by @ctor, @ctorArgs etc.
7052 * Returns: a Byte array representing the blob of data.
7055 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7058 MonoMethodSignature *sig;
7063 MONO_ARCH_SAVE_REGS;
7065 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7066 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7068 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7070 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7072 p = buffer = g_malloc (buflen);
7073 /* write the prolog */
7076 for (i = 0; i < sig->param_count; ++i) {
7077 arg = mono_array_get (ctorArgs, MonoObject*, i);
7078 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7082 i += mono_array_length (properties);
7084 i += mono_array_length (fields);
7086 *p++ = (i >> 8) & 0xff;
7089 for (i = 0; i < mono_array_length (properties); ++i) {
7094 prop = mono_array_get (properties, gpointer, i);
7095 get_prop_name_and_type (prop, &pname, &ptype);
7096 *p++ = 0x54; /* PROPERTY signature */
7098 /* Preallocate a large enough buffer */
7099 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7100 char *str = type_get_qualified_name (ptype, NULL);
7106 len += strlen (pname);
7108 if ((p-buffer) + 20 + len >= buflen) {
7112 newbuf = g_realloc (buffer, buflen);
7113 p = newbuf + (p-buffer);
7117 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7118 char *str = type_get_qualified_name (ptype, NULL);
7119 int slen = strlen (str);
7123 * This seems to be optional...
7126 mono_metadata_encode_value (slen, p, &p);
7127 memcpy (p, str, slen);
7131 mono_metadata_encode_value (ptype->type, p, &p);
7132 if (ptype->type == MONO_TYPE_SZARRAY)
7133 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7135 len = strlen (pname);
7136 mono_metadata_encode_value (len, p, &p);
7137 memcpy (p, pname, len);
7139 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7146 for (i = 0; i < mono_array_length (fields); ++i) {
7151 field = mono_array_get (fields, gpointer, i);
7152 get_field_name_and_type (field, &fname, &ftype);
7153 *p++ = 0x53; /* FIELD signature */
7154 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7155 char *str = type_get_qualified_name (ftype, NULL);
7156 int slen = strlen (str);
7157 if ((p-buffer) + 10 + slen >= buflen) {
7161 newbuf = g_realloc (buffer, buflen);
7162 p = newbuf + (p-buffer);
7167 * This seems to be optional...
7170 mono_metadata_encode_value (slen, p, &p);
7171 memcpy (p, str, slen);
7175 mono_metadata_encode_value (ftype->type, p, &p);
7176 if (ftype->type == MONO_TYPE_SZARRAY)
7177 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7179 len = strlen (fname);
7180 mono_metadata_encode_value (len, p, &p);
7181 memcpy (p, fname, len);
7183 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7188 g_assert (p - buffer <= buflen);
7189 buflen = p - buffer;
7190 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7191 p = mono_array_addr (result, char, 0);
7192 memcpy (p, buffer, buflen);
7194 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7200 * mono_reflection_setup_internal_class:
7201 * @tb: a TypeBuilder object
7203 * Creates a MonoClass that represents the TypeBuilder.
7204 * This is a trick that lets us simplify a lot of reflection code
7205 * (and will allow us to support Build and Run assemblies easier).
7208 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7210 MonoClass *klass, *parent;
7212 MONO_ARCH_SAVE_REGS;
7215 /* check so we can compile corlib correctly */
7216 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7217 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7218 parent = tb->parent->type->data.klass;
7220 parent = my_mono_class_from_mono_type (tb->parent->type);
7226 /* the type has already being created: it means we just have to change the parent */
7227 if (tb->type.type) {
7228 klass = mono_class_from_mono_type (tb->type.type);
7229 klass->parent = NULL;
7230 /* fool mono_class_setup_parent */
7231 g_free (klass->supertypes);
7232 klass->supertypes = NULL;
7233 mono_class_setup_parent (klass, parent);
7234 mono_class_setup_mono_type (klass);
7238 klass = g_new0 (MonoClass, 1);
7240 klass->image = &tb->module->dynamic_image->image;
7242 klass->inited = 1; /* we lie to the runtime */
7243 klass->name = mono_string_to_utf8 (tb->name);
7244 klass->name_space = mono_string_to_utf8 (tb->nspace);
7245 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7246 klass->flags = tb->attrs;
7248 klass->element_class = klass;
7249 klass->reflection_info = tb; /* need to pin. */
7251 /* Put into cache so mono_class_get () will find it */
7252 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7254 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7255 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7257 if (parent != NULL) {
7258 mono_class_setup_parent (klass, parent);
7259 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7260 const char *old_n = klass->name;
7261 /* trick to get relative numbering right when compiling corlib */
7262 klass->name = "BuildingObject";
7263 mono_class_setup_parent (klass, mono_defaults.object_class);
7264 klass->name = old_n;
7267 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7268 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7269 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7270 klass->instance_size = sizeof (MonoObject);
7271 klass->size_inited = 1;
7272 mono_class_setup_vtable (klass, NULL, 0);
7275 mono_class_setup_mono_type (klass);
7277 mono_class_setup_supertypes (klass);
7280 * FIXME: handle interfaces.
7283 tb->type.type = &klass->byval_arg;
7285 if (tb->nesting_type) {
7286 g_assert (tb->nesting_type->type);
7287 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7290 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7294 * mono_reflection_setup_generic_class:
7295 * @tb: a TypeBuilder object
7297 * Setup the generic class before adding the first generic parameter.
7300 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7304 MONO_ARCH_SAVE_REGS;
7306 klass = my_mono_class_from_mono_type (tb->type.type);
7307 if (tb->generic_container)
7310 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7311 tb->generic_container->klass = klass;
7313 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7314 tb->generic_container->context->container = tb->generic_container;
7318 * mono_reflection_create_generic_class:
7319 * @tb: a TypeBuilder object
7321 * Creates the generic class after all generic parameters have been added.
7324 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7329 MONO_ARCH_SAVE_REGS;
7331 klass = my_mono_class_from_mono_type (tb->type.type);
7333 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7335 if (klass->generic_container || (count == 0))
7338 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7340 klass->generic_container = tb->generic_container;
7342 klass->generic_container->type_argc = count;
7343 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7345 for (i = 0; i < count; i++) {
7346 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7347 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7348 g_assert (klass->generic_container->type_params [i].owner);
7353 * mono_reflection_create_internal_class:
7354 * @tb: a TypeBuilder object
7356 * Actually create the MonoClass that is associated with the TypeBuilder.
7359 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7363 MONO_ARCH_SAVE_REGS;
7365 klass = my_mono_class_from_mono_type (tb->type.type);
7367 if (klass->enumtype && klass->enum_basetype == NULL) {
7368 MonoReflectionFieldBuilder *fb;
7371 g_assert (tb->fields != NULL);
7372 g_assert (mono_array_length (tb->fields) >= 1);
7374 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7376 klass->enum_basetype = fb->type->type;
7377 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7378 if (!klass->element_class)
7379 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7382 * get the element_class from the current corlib.
7384 ec = default_class_from_mono_type (klass->enum_basetype);
7385 klass->instance_size = ec->instance_size;
7386 klass->size_inited = 1;
7388 * this is almost safe to do with enums and it's needed to be able
7389 * to create objects of the enum type (for use in SetConstant).
7391 /* FIXME: Does this mean enums can't have method overrides ? */
7392 mono_class_setup_vtable (klass, NULL, 0);
7396 static MonoMarshalSpec*
7397 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7398 MonoReflectionMarshal *minfo)
7400 MonoMarshalSpec *res;
7402 res = g_new0 (MonoMarshalSpec, 1);
7403 res->native = minfo->type;
7405 switch (minfo->type) {
7406 case MONO_NATIVE_LPARRAY:
7407 res->data.array_data.elem_type = minfo->eltype;
7408 res->data.array_data.param_num = 0; /* Not yet */
7409 res->data.array_data.num_elem = minfo->count;
7412 case MONO_NATIVE_BYVALTSTR:
7413 case MONO_NATIVE_BYVALARRAY:
7414 res->data.array_data.num_elem = minfo->count;
7417 case MONO_NATIVE_CUSTOM:
7418 if (minfo->marshaltyperef)
7419 res->data.custom_data.custom_name =
7420 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7422 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7432 MonoReflectionMarshal*
7433 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7434 MonoMarshalSpec *spec)
7436 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7437 MonoReflectionMarshal *minfo;
7440 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7441 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7442 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7443 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7446 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7447 minfo->type = spec->native;
7449 switch (minfo->type) {
7450 case MONO_NATIVE_LPARRAY:
7451 minfo->eltype = spec->data.array_data.elem_type;
7452 minfo->count = spec->data.array_data.num_elem;
7455 case MONO_NATIVE_BYVALTSTR:
7456 case MONO_NATIVE_BYVALARRAY:
7457 minfo->count = spec->data.array_data.num_elem;
7460 case MONO_NATIVE_CUSTOM:
7461 if (spec->data.custom_data.custom_name) {
7462 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7464 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7466 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7468 if (spec->data.custom_data.cookie)
7469 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7480 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7481 ReflectionMethodBuilder *rmb,
7482 MonoMethodSignature *sig)
7485 MonoMethodNormal *pm;
7486 MonoMarshalSpec **specs;
7487 MonoReflectionMethodAux *method_aux;
7490 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7491 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7492 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7494 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7496 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7498 pm = (MonoMethodNormal*)m;
7501 m->flags = rmb->attrs;
7502 m->iflags = rmb->iattrs;
7503 m->name = mono_string_to_utf8 (rmb->name);
7507 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7509 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7510 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7513 m->signature->pinvoke = 1;
7514 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7515 m->signature->pinvoke = 1;
7517 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7519 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7520 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7522 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7524 if (klass->image->dynamic)
7525 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7528 } else if (!m->klass->dummy &&
7529 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7530 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7531 MonoMethodHeader *header;
7533 gint32 max_stack, i;
7534 gint32 num_locals = 0;
7535 gint32 num_clauses = 0;
7539 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7540 code_size = rmb->ilgen->code_len;
7541 max_stack = rmb->ilgen->max_stack;
7542 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7543 if (rmb->ilgen->ex_handlers)
7544 num_clauses = method_count_clauses (rmb->ilgen);
7547 code = mono_array_addr (rmb->code, guint8, 0);
7548 code_size = mono_array_length (rmb->code);
7549 /* we probably need to run a verifier on the code... */
7559 header = g_malloc0 (sizeof (MonoMethodHeader) +
7560 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7561 header->code_size = code_size;
7562 header->code = g_malloc (code_size);
7563 memcpy ((char*)header->code, code, code_size);
7564 header->max_stack = max_stack;
7565 header->init_locals = rmb->init_locals;
7566 header->num_locals = num_locals;
7568 for (i = 0; i < num_locals; ++i) {
7569 MonoReflectionLocalBuilder *lb =
7570 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7572 header->locals [i] = g_new0 (MonoType, 1);
7573 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7576 header->num_clauses = num_clauses;
7578 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7579 rmb->ilgen, num_clauses);
7582 pm->header = header;
7585 if (rmb->generic_params) {
7586 int count = mono_array_length (rmb->generic_params);
7587 MonoGenericContainer *container;
7589 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7590 container->type_argc = count;
7591 container->type_params = g_new0 (MonoGenericParam, count);
7593 for (i = 0; i < count; i++) {
7594 MonoReflectionGenericParam *gp =
7595 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7597 container->type_params [i] = *gp->type.type->data.generic_param;
7602 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7605 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7607 for (i = 0; i < rmb->nrefs; ++i)
7608 mw->data = g_list_append (mw->data, rmb->refs [i]);
7613 /* Parameter info */
7616 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7617 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7618 for (i = 0; i <= m->signature->param_count; ++i) {
7619 MonoReflectionParamBuilder *pb;
7620 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7622 m->signature->params [i - 1]->attrs = pb->attrs;
7624 if (pb->def_value) {
7625 MonoDynamicImage *assembly;
7626 guint32 idx, def_type, len;
7630 if (!method_aux->param_defaults)
7631 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7632 assembly = (MonoDynamicImage*)klass->image;
7633 idx = encode_constant (assembly, pb->def_value, &def_type);
7634 /* Copy the data from the blob since it might get realloc-ed */
7635 p = assembly->blob.data + idx;
7636 len = mono_metadata_decode_blob_size (p, &p2);
7638 method_aux->param_defaults [i] = g_malloc (len);
7639 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7643 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7645 if (!method_aux->param_cattr)
7646 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7647 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7653 /* Parameter marshalling */
7656 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7657 MonoReflectionParamBuilder *pb;
7658 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7659 if (pb->marshal_info) {
7661 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7662 specs [pb->position] =
7663 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7667 if (specs != NULL) {
7669 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7670 method_aux->param_marshall = specs;
7673 if (klass->image->dynamic && method_aux)
7674 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7680 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7682 ReflectionMethodBuilder rmb;
7683 MonoMethodSignature *sig;
7685 sig = ctor_builder_to_signature (mb);
7687 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7689 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7690 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7692 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7693 /* ilgen is no longer needed */
7701 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7703 ReflectionMethodBuilder rmb;
7704 MonoMethodSignature *sig;
7706 sig = method_builder_to_signature (mb);
7708 reflection_methodbuilder_from_method_builder (&rmb, mb);
7710 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7711 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7713 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7714 /* ilgen is no longer needed */
7720 static MonoClassField*
7721 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7723 MonoClassField *field;
7730 field = g_new0 (MonoClassField, 1);
7732 field->name = mono_string_to_utf8 (fb->name);
7734 /* FIXME: handle type modifiers */
7735 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7736 field->type->attrs = fb->attrs;
7738 field->type = fb->type->type;
7740 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7741 field->data = mono_array_addr (fb->rva_data, char, 0);
7742 if (fb->offset != -1)
7743 field->offset = fb->offset;
7744 field->parent = klass;
7746 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7748 if (fb->def_value) {
7749 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7750 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7751 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7752 /* Copy the data from the blob since it might get realloc-ed */
7753 p = assembly->blob.data + idx;
7754 len = mono_metadata_decode_blob_size (p, &p2);
7756 field->data = g_malloc (len);
7757 memcpy ((gpointer)field->data, p, len);
7764 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7766 MonoClass *klass, *gklass;
7767 MonoReflectionTypeBuilder *tb = NULL;
7768 MonoGenericInst *ginst, *cached;
7773 klass = mono_class_from_mono_type (type->type);
7774 if (!klass->generic_container && !klass->generic_inst &&
7775 !(klass->nested_in && klass->nested_in->generic_container))
7778 mono_loader_lock ();
7780 domain = mono_object_domain (type);
7782 ginst = g_new0 (MonoGenericInst, 1);
7784 ginst->type_argc = type_argc;
7785 ginst->type_argv = types;
7787 for (i = 0; i < ginst->type_argc; ++i) {
7788 if (!ginst->is_open)
7789 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7792 ginst->generic_type = &klass->byval_arg;
7794 if (klass->generic_inst) {
7795 MonoGenericInst *kginst = klass->generic_inst;
7796 MonoGenericInst *oginst = ginst;
7798 oginst->context = g_new0 (MonoGenericContext, 1);
7799 oginst->context->ginst = oginst;
7801 ginst = g_new0 (MonoGenericInst, 1);
7803 ginst->type_argc = kginst->type_argc;
7804 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7806 for (i = 0; i < ginst->type_argc; i++) {
7807 MonoType *t = kginst->type_argv [i];
7809 t = mono_class_inflate_generic_type (t, oginst->context);
7811 if (!ginst->is_open)
7812 ginst->is_open = mono_class_is_open_constructed_type (t);
7814 ginst->type_argv [i] = t;
7817 ginst->generic_type = kginst->generic_type;
7820 geninst = g_new0 (MonoType, 1);
7821 geninst->type = MONO_TYPE_GENERICINST;
7823 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7826 mono_loader_unlock ();
7827 geninst->data.generic_inst = cached;
7831 gklass = mono_class_from_mono_type (ginst->generic_type);
7832 g_assert ((ginst->container = gklass->generic_container) != NULL);
7834 geninst->data.generic_inst = ginst;
7836 ginst->context = g_new0 (MonoGenericContext, 1);
7837 ginst->context->ginst = ginst;
7839 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7840 tb = (MonoReflectionTypeBuilder *) type;
7842 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7843 ginst->is_dynamic = TRUE;
7844 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7845 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7846 MonoReflectionType *rgt = rgi->generic_type;
7848 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7849 tb = (MonoReflectionTypeBuilder *) rgt;
7851 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7852 ginst->is_dynamic = TRUE;
7854 icount = klass->interface_count;
7857 ginst->ifaces = g_new0 (MonoType *, icount);
7858 ginst->count_ifaces = icount;
7860 for (i = 0; i < icount; i++) {
7861 MonoReflectionType *itype;
7864 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7866 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7867 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7868 if (!ginst->ifaces [i])
7869 ginst->ifaces [i] = itype->type;
7872 mono_class_create_generic (ginst);
7874 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7876 mono_loader_unlock ();
7882 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7884 MonoClass *klass, *pklass = NULL;
7885 MonoReflectionType *parent = NULL;
7887 MonoReflectionTypeBuilder *tb = NULL;
7888 MonoGenericInst *ginst;
7891 domain = mono_object_domain (type);
7892 klass = mono_class_from_mono_type (type->type);
7894 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7895 tb = (MonoReflectionTypeBuilder *) type;
7898 parent = tb->parent;
7899 pklass = mono_class_from_mono_type (parent->type);
7902 pklass = klass->parent;
7904 parent = mono_type_get_object (domain, &pklass->byval_arg);
7905 else if (klass->generic_inst && klass->generic_inst->parent) {
7906 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7907 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7911 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7915 ginst = geninst->data.generic_inst;
7917 if (pklass && pklass->generic_inst)
7918 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7923 MonoReflectionMethod*
7924 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7926 MonoMethod *method, *inflated;
7927 MonoReflectionMethodBuilder *mb = NULL;
7928 MonoGenericMethod *gmethod;
7929 MonoGenericContext *context;
7932 MONO_ARCH_SAVE_REGS;
7933 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7934 MonoReflectionTypeBuilder *tb;
7937 mb = (MonoReflectionMethodBuilder *) rmethod;
7938 tb = (MonoReflectionTypeBuilder *) mb->type;
7939 klass = mono_class_from_mono_type (tb->type.type);
7941 method = methodbuilder_to_mono_method (klass, mb);
7943 method = rmethod->method;
7946 count = method->signature->generic_param_count;
7947 if (count != mono_array_length (types))
7950 gmethod = g_new0 (MonoGenericMethod, 1);
7951 gmethod->mtype_argc = count;
7952 gmethod->mtype_argv = g_new0 (MonoType *, count);
7953 for (i = 0; i < count; i++) {
7954 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7955 gmethod->mtype_argv [i] = garg->type;
7958 gmethod->reflection_info = rmethod;
7960 context = g_new0 (MonoGenericContext, 1);
7961 context->ginst = method->klass->generic_inst;
7962 context->gmethod = gmethod;
7964 inflated = mono_class_inflate_generic_method (method, context, NULL);
7966 return mono_method_get_object (
7967 mono_object_domain (rmethod), inflated, NULL);
7971 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7973 MonoGenericMethod *gmethod;
7974 MonoGenericInst *ginst;
7975 MonoGenericContext *context;
7978 ginst = type->type.type->data.generic_inst;
7980 gmethod = g_new0 (MonoGenericMethod, 1);
7981 gmethod->reflection_info = obj;
7983 gmethod->mtype_argc = method->signature->generic_param_count;
7984 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7986 for (i = 0; i < gmethod->mtype_argc; i++) {
7987 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7988 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7990 g_assert (gparam->pklass);
7991 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7994 context = g_new0 (MonoGenericContext, 1);
7995 context->ginst = ginst;
7996 context->gmethod = gmethod;
7998 return mono_class_inflate_generic_method (method, context, ginst->klass);
8002 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8007 klass = mono_class_from_mono_type (type->type.type);
8009 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8010 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8011 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8012 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8013 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8014 method = ((MonoReflectionMethod *) obj)->method;
8016 method = NULL; /* prevent compiler warning */
8017 g_assert_not_reached ();
8020 return inflate_mono_method (type, method, obj);
8024 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8025 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8027 MonoGenericInst *ginst;
8028 MonoDynamicGenericInst *dginst;
8029 MonoClass *klass, *gklass, *pklass;
8032 MONO_ARCH_SAVE_REGS;
8034 klass = mono_class_from_mono_type (type->type.type);
8035 ginst = type->type.type->data.generic_inst;
8037 if (ginst->initialized)
8040 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8042 gklass = mono_class_from_mono_type (ginst->generic_type);
8043 mono_class_init (gklass);
8046 pklass = mono_class_from_mono_type (ginst->parent);
8048 pklass = gklass->parent;
8050 mono_class_setup_parent (klass, pklass);
8052 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8053 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8054 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8055 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8056 dginst->count_events = events ? mono_array_length (events) : 0;
8058 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8059 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8060 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8061 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8062 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8064 for (i = 0; i < dginst->count_methods; i++) {
8065 MonoObject *obj = mono_array_get (methods, gpointer, i);
8067 dginst->methods [i] = inflate_method (type, obj);
8070 for (i = 0; i < dginst->count_ctors; i++) {
8071 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8073 dginst->ctors [i] = inflate_method (type, obj);
8076 for (i = 0; i < dginst->count_fields; i++) {
8077 MonoObject *obj = mono_array_get (fields, gpointer, i);
8078 MonoClassField *field;
8079 MonoInflatedField *ifield;
8081 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8082 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8083 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8084 field = ((MonoReflectionField *) obj)->field;
8086 field = NULL; /* prevent compiler warning */
8087 g_assert_not_reached ();
8090 ifield = g_new0 (MonoInflatedField, 1);
8091 ifield->generic_type = field->type;
8092 ifield->reflection_info = obj;
8094 dginst->fields [i] = *field;
8095 dginst->fields [i].generic_info = ifield;
8096 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8099 for (i = 0; i < dginst->count_properties; i++) {
8100 MonoObject *obj = mono_array_get (properties, gpointer, i);
8101 MonoProperty *property = &dginst->properties [i];
8103 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8104 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8106 property->parent = klass;
8107 property->attrs = pb->attrs;
8108 property->name = mono_string_to_utf8 (pb->name);
8110 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8112 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8113 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8114 *property = *((MonoReflectionProperty *) obj)->property;
8117 property->get = inflate_mono_method (type, property->get, NULL);
8119 property->set = inflate_mono_method (type, property->set, NULL);
8121 g_assert_not_reached ();
8124 for (i = 0; i < dginst->count_events; i++) {
8125 MonoObject *obj = mono_array_get (events, gpointer, i);
8126 MonoEvent *event = &dginst->events [i];
8128 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8129 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8131 event->parent = klass;
8132 event->attrs = eb->attrs;
8133 event->name = mono_string_to_utf8 (eb->name);
8135 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8136 if (eb->remove_method)
8137 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8138 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8139 *event = *((MonoReflectionEvent *) obj)->event;
8142 event->add = inflate_mono_method (type, event->add, NULL);
8144 event->remove = inflate_mono_method (type, event->remove, NULL);
8146 g_assert_not_reached ();
8149 ginst->initialized = TRUE;
8153 ensure_runtime_vtable (MonoClass *klass)
8155 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8156 int i, num, j, onum;
8157 MonoMethod **overrides;
8159 if (!tb || klass->wastypebuilder)
8162 ensure_runtime_vtable (klass->parent);
8164 num = tb->ctors? mono_array_length (tb->ctors): 0;
8165 num += tb->num_methods;
8166 klass->method.count = num;
8167 klass->methods = g_new (MonoMethod*, num);
8168 num = tb->ctors? mono_array_length (tb->ctors): 0;
8169 for (i = 0; i < num; ++i)
8170 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8171 num = tb->num_methods;
8173 for (i = 0; i < num; ++i)
8174 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8176 if (tb->interfaces) {
8177 klass->interface_count = mono_array_length (tb->interfaces);
8178 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8179 for (i = 0; i < klass->interface_count; ++i) {
8180 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8181 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8185 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8186 for (i = 0; i < klass->method.count; ++i)
8187 klass->methods [i]->slot = i;
8192 for (i = 0; i < tb->num_methods; ++i) {
8193 MonoReflectionMethodBuilder *mb =
8194 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8195 if (mb->override_method)
8200 overrides = g_new0 (MonoMethod*, onum * 2);
8204 for (i = 0; i < tb->num_methods; ++i) {
8205 MonoReflectionMethodBuilder *mb =
8206 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8207 if (mb->override_method) {
8208 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8209 overrides [onum * 2] =
8210 mb->override_method->method;
8211 overrides [onum * 2 + 1] =
8214 g_assert (mb->mhandle);
8221 mono_class_setup_vtable (klass, overrides, onum);
8226 typebuilder_setup_fields (MonoClass *klass)
8228 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8229 MonoReflectionFieldBuilder *fb;
8230 MonoClassField *field;
8235 klass->field.count = tb->num_fields;
8236 klass->field.first = 0;
8237 klass->field.last = klass->field.count;
8239 if (!klass->field.count)
8242 klass->fields = g_new0 (MonoClassField, klass->field.count);
8244 for (i = 0; i < klass->field.count; ++i) {
8245 fb = mono_array_get (tb->fields, gpointer, i);
8246 field = &klass->fields [i];
8247 field->name = mono_string_to_utf8 (fb->name);
8249 /* FIXME: handle type modifiers */
8250 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8251 field->type->attrs = fb->attrs;
8253 field->type = fb->type->type;
8255 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8256 field->data = mono_array_addr (fb->rva_data, char, 0);
8257 if (fb->offset != -1)
8258 field->offset = fb->offset;
8259 field->parent = klass;
8261 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8263 if (fb->def_value) {
8264 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8265 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8266 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8267 /* Copy the data from the blob since it might get realloc-ed */
8268 p = assembly->blob.data + idx;
8269 len = mono_metadata_decode_blob_size (p, &p2);
8271 field->data = g_malloc (len);
8272 memcpy ((gpointer)field->data, p, len);
8275 mono_class_layout_fields (klass);
8279 typebuilder_setup_properties (MonoClass *klass)
8281 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8282 MonoReflectionPropertyBuilder *pb;
8285 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8286 klass->property.first = 0;
8287 klass->property.last = klass->property.count;
8289 klass->properties = g_new0 (MonoProperty, klass->property.count);
8290 for (i = 0; i < klass->property.count; ++i) {
8291 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8292 klass->properties [i].parent = klass;
8293 klass->properties [i].attrs = pb->attrs;
8294 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8296 klass->properties [i].get = pb->get_method->mhandle;
8298 klass->properties [i].set = pb->set_method->mhandle;
8302 MonoReflectionEvent *
8303 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8305 MonoEvent *event = g_new0 (MonoEvent, 1);
8309 klass = my_mono_class_from_mono_type (tb->type.type);
8311 event->parent = klass;
8312 event->attrs = eb->attrs;
8313 event->name = mono_string_to_utf8 (eb->name);
8315 event->add = eb->add_method->mhandle;
8316 if (eb->remove_method)
8317 event->remove = eb->remove_method->mhandle;
8318 if (eb->raise_method)
8319 event->raise = eb->raise_method->mhandle;
8321 if (eb->other_methods) {
8322 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8323 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8324 MonoReflectionMethodBuilder *mb =
8325 mono_array_get (eb->other_methods,
8326 MonoReflectionMethodBuilder*, j);
8327 event->other [j] = mb->mhandle;
8331 return mono_event_get_object (mono_object_domain (tb), klass, event);
8335 typebuilder_setup_events (MonoClass *klass)
8337 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8338 MonoReflectionEventBuilder *eb;
8341 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8342 klass->event.first = 0;
8343 klass->event.last = klass->event.count;
8345 klass->events = g_new0 (MonoEvent, klass->event.count);
8346 for (i = 0; i < klass->event.count; ++i) {
8347 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8348 klass->events [i].parent = klass;
8349 klass->events [i].attrs = eb->attrs;
8350 klass->events [i].name = mono_string_to_utf8 (eb->name);
8352 klass->events [i].add = eb->add_method->mhandle;
8353 if (eb->remove_method)
8354 klass->events [i].remove = eb->remove_method->mhandle;
8355 if (eb->raise_method)
8356 klass->events [i].raise = eb->raise_method->mhandle;
8358 if (eb->other_methods) {
8359 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8360 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8361 MonoReflectionMethodBuilder *mb =
8362 mono_array_get (eb->other_methods,
8363 MonoReflectionMethodBuilder*, j);
8364 klass->events [i].other [j] = mb->mhandle;
8371 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8374 MonoReflectionType* res;
8377 MONO_ARCH_SAVE_REGS;
8379 klass = my_mono_class_from_mono_type (tb->type.type);
8381 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8384 * Fields to set in klass:
8385 * the various flags: delegate/unicode/contextbound etc.
8387 klass->flags = tb->attrs;
8389 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8390 /* No need to fully construct the type */
8391 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8393 /* enums are done right away */
8394 if (!klass->enumtype)
8395 ensure_runtime_vtable (klass);
8398 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8399 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8400 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8404 /* fields and object layout */
8405 if (klass->parent) {
8406 if (!klass->parent->size_inited)
8407 mono_class_init (klass->parent);
8408 klass->instance_size += klass->parent->instance_size;
8409 klass->class_size += klass->parent->class_size;
8410 klass->min_align = klass->parent->min_align;
8412 klass->instance_size = sizeof (MonoObject);
8413 klass->min_align = 1;
8416 /* FIXME: handle packing_size and instance_size */
8417 typebuilder_setup_fields (klass);
8419 typebuilder_setup_properties (klass);
8421 typebuilder_setup_events (klass);
8423 klass->wastypebuilder = TRUE;
8425 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8426 g_assert (res != (MonoReflectionType*)tb);
8431 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8433 MonoGenericParam *param;
8436 MONO_ARCH_SAVE_REGS;
8438 param = g_new0 (MonoGenericParam, 1);
8440 if (gparam->mbuilder) {
8441 if (!gparam->mbuilder->generic_container)
8442 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8443 param->owner = gparam->mbuilder->generic_container;
8444 } else if (gparam->tbuilder) {
8445 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8446 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8451 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8452 if (gparam->index >= count)
8455 container = nesting->generic_container;
8456 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8459 g_assert (container);
8460 param->owner = container;
8463 param->method = NULL;
8464 param->name = mono_string_to_utf8 (gparam->name);
8465 param->num = gparam->index;
8467 image = &gparam->tbuilder->module->dynamic_image->image;
8468 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8470 param->pklass->reflection_info = gparam;
8472 gparam->type.type = g_new0 (MonoType, 1);
8473 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8474 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8475 gparam->type.type->data.generic_param = param;
8479 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8481 MonoDynamicImage *assembly = sig->module->dynamic_image;
8482 guint32 na = mono_array_length (sig->arguments);
8487 MONO_ARCH_SAVE_REGS;
8489 p = buf = g_malloc (10 + na * 10);
8491 mono_metadata_encode_value (0x07, p, &p);
8492 mono_metadata_encode_value (na, p, &p);
8493 for (i = 0; i < na; ++i) {
8494 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8495 encode_reflection_type (assembly, type, p, &p);
8499 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8500 p = mono_array_addr (result, char, 0);
8501 memcpy (p, buf, buflen);
8508 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8510 MonoDynamicImage *assembly = sig->module->dynamic_image;
8511 guint32 na = mono_array_length (sig->arguments);
8516 MONO_ARCH_SAVE_REGS;
8518 p = buf = g_malloc (10 + na * 10);
8520 mono_metadata_encode_value (0x06, p, &p);
8521 for (i = 0; i < na; ++i) {
8522 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8523 encode_reflection_type (assembly, type, p, &p);
8527 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8528 p = mono_array_addr (result, char, 0);
8529 memcpy (p, buf, buflen);
8536 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8538 ReflectionMethodBuilder rmb;
8539 MonoMethodSignature *sig;
8542 sig = dynamic_method_to_signature (mb);
8544 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8547 * Resolve references.
8549 rmb.nrefs = mb->nrefs;
8550 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8551 for (i = 0; i < mb->nrefs; ++i) {
8552 gpointer ref = resolve_object (mb->module->image,
8553 mono_array_get (mb->refs, MonoObject*, i));
8556 mono_raise_exception (mono_get_exception_type_load (NULL));
8563 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8567 /* ilgen is no longer needed */
8572 * mono_reflection_lookup_dynamic_token:
8574 * Finish the Builder object pointed to by TOKEN and return the corresponding
8575 * runtime structure.
8578 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8580 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8583 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8586 return resolve_object (image, obj);
8590 resolve_object (MonoImage *image, MonoObject *obj)
8592 gpointer result = NULL;
8594 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8595 result = mono_string_intern ((MonoString*)obj);
8597 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8598 MonoReflectionType *tb = (MonoReflectionType*)obj;
8599 result = mono_class_from_mono_type (tb->type);
8601 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8602 result = ((MonoReflectionMethod*)obj)->method;
8604 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8605 result = ((MonoReflectionMethod*)obj)->method;
8607 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8608 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8609 result = mb->mhandle;
8611 /* Type is not yet created */
8612 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8614 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8617 * Hopefully this has been filled in by calling CreateType() on the
8621 * TODO: This won't work if the application finishes another
8622 * TypeBuilder instance instead of this one.
8624 result = mb->mhandle;
8626 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8627 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8629 result = cb->mhandle;
8631 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8633 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8634 result = cb->mhandle;
8636 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8637 result = ((MonoReflectionField*)obj)->field;
8639 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8640 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8641 result = fb->handle;
8644 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8646 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8647 result = fb->handle;
8649 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8650 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8653 klass = tb->type.type->data.klass;
8654 if (klass->wastypebuilder) {
8655 /* Already created */
8659 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8660 result = tb->type.type->data.klass;
8663 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8664 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8665 MonoMethodSignature *sig;
8668 if (helper->arguments)
8669 nargs = mono_array_length (helper->arguments);
8673 sig = mono_metadata_signature_alloc (image, nargs);
8674 sig->explicit_this = helper->call_conv & 64;
8675 sig->hasthis = helper->call_conv & 32;
8677 if (helper->call_conv == 0) /* unmanaged */
8678 sig->call_convention = helper->unmanaged_call_conv - 1;
8680 if (helper->call_conv & 0x02)
8681 sig->call_convention = MONO_CALL_VARARG;
8683 sig->call_convention = MONO_CALL_DEFAULT;
8685 sig->param_count = nargs;
8686 /* TODO: Copy type ? */
8687 sig->ret = helper->return_type->type;
8688 for (i = 0; i < nargs; ++i) {
8689 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8690 sig->params [i] = rt->type;
8695 g_print (obj->vtable->klass->name);
8696 g_assert_not_reached ();