2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
158 alloc_table (MonoDynamicTable *table, guint nrows)
161 g_assert (table->columns);
162 if (nrows + 1 >= table->alloc_rows) {
163 while (nrows + 1 >= table->alloc_rows)
164 if (table->alloc_rows == 0)
165 table->alloc_rows = 16;
167 table->alloc_rows *= 2;
170 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
172 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
177 make_room_in_stream (MonoDynamicStream *stream, int size)
179 while (stream->alloc_size <= size) {
180 if (stream->alloc_size < 4096)
181 stream->alloc_size = 4096;
183 stream->alloc_size *= 2;
186 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
188 stream->data = ALLOC_ATOMIC (stream->alloc_size);
192 string_heap_insert (MonoDynamicStream *sh, const char *str)
196 gpointer oldkey, oldval;
198 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
199 return GPOINTER_TO_UINT (oldval);
201 len = strlen (str) + 1;
203 if (idx + len > sh->alloc_size)
204 make_room_in_stream (sh, idx + len);
207 * We strdup the string even if we already copy them in sh->data
208 * so that the string pointers in the hash remain valid even if
209 * we need to realloc sh->data. We may want to avoid that later.
211 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
212 memcpy (sh->data + idx, str, len);
218 string_heap_init (MonoDynamicStream *sh)
221 sh->alloc_size = 4096;
222 sh->data = ALLOC_ATOMIC (4096);
223 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
224 string_heap_insert (sh, "");
227 #if 0 /* never used */
229 string_heap_free (MonoDynamicStream *sh)
231 FREE_ATOMIC (sh->data);
232 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
233 g_hash_table_destroy (sh->hash);
238 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
241 if (stream->alloc_size < stream->index + len)
242 make_room_in_stream (stream, stream->index + len);
243 memcpy (stream->data + stream->index, data, len);
245 stream->index += len;
247 * align index? Not without adding an additional param that controls it since
248 * we may store a blob value in pieces.
254 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
257 if (stream->alloc_size < stream->index + len)
258 make_room_in_stream (stream, stream->index + len);
259 memset (stream->data + stream->index, 0, len);
261 stream->index += len;
266 stream_data_align (MonoDynamicStream *stream)
269 guint32 count = stream->index % 4;
271 /* we assume the stream data will be aligned */
273 mono_image_add_stream_data (stream, buf, 4 - count);
277 mono_blob_entry_hash (const char* str)
281 len = mono_metadata_decode_blob_size (str, &str);
285 for (str += 1; str < end; str++)
286 h = (h << 5) - h + *str;
294 mono_blob_entry_equal (const char *str1, const char *str2) {
298 len = mono_metadata_decode_blob_size (str1, &end1);
299 len2 = mono_metadata_decode_blob_size (str2, &end2);
302 return memcmp (end1, end2, len) == 0;
306 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
310 gpointer oldkey, oldval;
312 copy = ALLOC_ATOMIC (s1+s2);
313 memcpy (copy, b1, s1);
314 memcpy (copy + s1, b2, s2);
315 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
317 idx = GPOINTER_TO_UINT (oldval);
319 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
320 mono_image_add_stream_data (&assembly->blob, b2, s2);
321 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
327 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
328 * dest may be misaligned.
331 swap_with_size (char *dest, const char* val, int len, int nelem) {
332 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
335 for (elem = 0; elem < nelem; ++elem) {
361 g_assert_not_reached ();
367 memcpy (dest, val, len * nelem);
372 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
376 guint32 idx = 0, len;
378 len = str->length * 2;
379 mono_metadata_encode_value (len, b, &b);
380 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
382 char *swapped = g_malloc (2 * mono_string_length (str));
383 const char *p = (const char*)mono_string_chars (str);
385 swap_with_size (swapped, p, 2, mono_string_length (str));
386 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
390 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
395 /* modified version needed to handle building corlib */
397 my_mono_class_from_mono_type (MonoType *type) {
398 switch (type->type) {
399 case MONO_TYPE_ARRAY:
401 case MONO_TYPE_SZARRAY:
402 case MONO_TYPE_GENERICINST:
403 return mono_class_from_mono_type (type);
406 g_assert (type->data.generic_param->pklass);
407 return type->data.generic_param->pklass;
409 /* should be always valid when we reach this case... */
410 return type->data.klass;
415 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
420 g_assert_not_reached ();
424 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
425 encode_type (assembly, ginst->generic_type, p, &p);
426 mono_metadata_encode_value (ginst->type_argc, p, &p);
427 for (i = 0; i < ginst->type_argc; ++i)
428 encode_type (assembly, ginst->type_argv [i], p, &p);
434 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
437 g_assert_not_reached ();
442 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
446 case MONO_TYPE_BOOLEAN:
460 case MONO_TYPE_STRING:
461 case MONO_TYPE_OBJECT:
462 case MONO_TYPE_TYPEDBYREF:
463 mono_metadata_encode_value (type->type, p, &p);
466 mono_metadata_encode_value (type->type, p, &p);
467 encode_type (assembly, type->data.type, p, &p);
469 case MONO_TYPE_SZARRAY:
470 mono_metadata_encode_value (type->type, p, &p);
471 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
474 case MONO_TYPE_VALUETYPE:
475 case MONO_TYPE_CLASS: {
476 MonoClass *k = mono_class_from_mono_type (type);
477 mono_metadata_encode_value (type->type, p, &p);
479 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
480 * otherwise two typerefs could point to the same type, leading to
481 * verification errors.
483 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
487 case MONO_TYPE_ARRAY:
488 mono_metadata_encode_value (type->type, p, &p);
489 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
490 mono_metadata_encode_value (type->data.array->rank, p, &p);
491 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
492 mono_metadata_encode_value (0, p, &p);
494 case MONO_TYPE_GENERICINST:
495 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
499 mono_metadata_encode_value (type->type, p, &p);
500 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
504 g_error ("need to encode type %x", type->type);
510 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
513 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
517 encode_type (assembly, type->type, p, endbuf);
521 g_assert_not_reached ();
526 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
531 for (i = 0; i < mono_array_length (modreq); ++i) {
532 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
533 *p = MONO_TYPE_CMOD_REQD;
535 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
539 for (i = 0; i < mono_array_length (modopt); ++i) {
540 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
541 *p = MONO_TYPE_CMOD_OPT;
543 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
550 generic_inst_get_signature_size (MonoGenericInst *ginst)
556 g_assert_not_reached ();
559 size += 1 + type_get_signature_size (ginst->generic_type);
561 for (i = 0; i < ginst->type_argc; ++i)
562 size += type_get_signature_size (ginst->type_argv [i]);
568 type_get_signature_size (MonoType *type)
573 g_assert_not_reached ();
581 case MONO_TYPE_BOOLEAN:
595 case MONO_TYPE_STRING:
596 case MONO_TYPE_OBJECT:
597 case MONO_TYPE_TYPEDBYREF:
600 return size + 1 + type_get_signature_size (type->data.type);
601 case MONO_TYPE_SZARRAY:
602 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
604 case MONO_TYPE_VALUETYPE:
605 case MONO_TYPE_CLASS:
608 case MONO_TYPE_ARRAY:
609 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
610 case MONO_TYPE_GENERICINST:
611 return size + generic_inst_get_signature_size (type->data.generic_inst);
617 g_error ("need to encode type %x", type->type);
623 method_get_signature_size (MonoMethodSignature *sig)
628 size = type_get_signature_size (sig->ret);
629 for (i = 0; i < sig->param_count; i++)
630 size += type_get_signature_size (sig->params [i]);
632 if (sig->generic_param_count)
634 if (sig->sentinelpos >= 0)
641 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
646 guint32 nparams = sig->param_count;
647 guint32 size = 11 + method_get_signature_size (sig);
655 p = buf = g_malloc (size);
657 * FIXME: vararg, explicit_this, differenc call_conv values...
659 *p = sig->call_convention;
661 *p |= 0x20; /* hasthis */
662 if (sig->generic_param_count)
663 *p |= 0x10; /* generic */
665 if (sig->generic_param_count)
666 mono_metadata_encode_value (sig->generic_param_count, p, &p);
667 mono_metadata_encode_value (nparams, p, &p);
668 encode_type (assembly, sig->ret, p, &p);
669 for (i = 0; i < nparams; ++i) {
670 if (i == sig->sentinelpos)
671 *p++ = MONO_TYPE_SENTINEL;
672 encode_type (assembly, sig->params [i], p, &p);
675 g_assert (p - buf < size);
676 mono_metadata_encode_value (p-buf, b, &b);
677 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
683 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
686 * FIXME: reuse code from method_encode_signature().
691 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
692 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
693 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
694 guint32 size = 21 + nparams * 20 + notypes * 20;
699 p = buf = g_malloc (size);
700 /* LAMESPEC: all the call conv spec is foobared */
701 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
702 if (mb->call_conv & 2)
703 *p |= 0x5; /* vararg */
704 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
705 *p |= 0x20; /* hasthis */
707 *p |= 0x10; /* generic */
710 mono_metadata_encode_value (ngparams, p, &p);
711 mono_metadata_encode_value (nparams + notypes, p, &p);
712 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
713 encode_reflection_type (assembly, mb->rtype, p, &p);
714 for (i = 0; i < nparams; ++i) {
715 MonoArray *modreq = NULL;
716 MonoArray *modopt = NULL;
717 MonoReflectionType *pt;
719 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
720 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
721 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
722 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
723 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
724 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
725 encode_reflection_type (assembly, pt, p, &p);
728 *p++ = MONO_TYPE_SENTINEL;
729 for (i = 0; i < notypes; ++i) {
730 MonoReflectionType *pt;
732 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
733 encode_reflection_type (assembly, pt, p, &p);
737 g_assert (p - buf < size);
738 mono_metadata_encode_value (p-buf, b, &b);
739 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
745 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
747 MonoDynamicTable *table;
750 guint32 idx, sig_idx, size;
751 guint nl = mono_array_length (ilgen->locals);
758 p = buf = g_malloc (size);
759 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
760 idx = table->next_idx ++;
762 alloc_table (table, table->rows);
763 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
765 mono_metadata_encode_value (0x07, p, &p);
766 mono_metadata_encode_value (nl, p, &p);
767 for (i = 0; i < nl; ++i) {
768 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
771 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
773 encode_reflection_type (assembly, lb->type, p, &p);
775 g_assert (p - buf < size);
776 mono_metadata_encode_value (p-buf, b, &b);
777 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
780 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
786 method_count_clauses (MonoReflectionILGen *ilgen)
788 guint32 num_clauses = 0;
791 MonoILExceptionInfo *ex_info;
792 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
793 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
794 if (ex_info->handlers)
795 num_clauses += mono_array_length (ex_info->handlers);
803 static MonoExceptionClause*
804 method_encode_clauses (MonoDynamicImage *assembly,
805 MonoReflectionILGen *ilgen, guint32 num_clauses)
807 MonoExceptionClause *clauses;
808 MonoExceptionClause *clause;
809 MonoILExceptionInfo *ex_info;
810 MonoILExceptionBlock *ex_block;
811 guint32 finally_start;
812 int i, j, clause_index;;
814 clauses = g_new0 (MonoExceptionClause, num_clauses);
817 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
818 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
819 finally_start = ex_info->start + ex_info->len;
820 g_assert (ex_info->handlers);
821 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
822 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
823 clause = &(clauses [clause_index]);
825 clause->flags = ex_block->type;
826 clause->try_offset = ex_info->start;
828 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
829 clause->try_len = finally_start - ex_info->start;
831 clause->try_len = ex_info->len;
832 clause->handler_offset = ex_block->start;
833 clause->handler_len = ex_block->len;
834 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
835 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
836 if (ex_block->extype) {
837 mono_g_hash_table_insert (assembly->tokens,
838 GUINT_TO_POINTER (clause->token_or_filter),
841 finally_start = ex_block->start + ex_block->len;
851 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
857 gint32 num_locals = 0;
858 gint32 num_exception = 0;
861 char fat_header [12];
864 guint32 local_sig = 0;
865 guint32 header_size = 12;
868 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
869 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
870 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
871 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
875 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
877 code = mb->ilgen->code;
878 code_size = mb->ilgen->code_len;
879 max_stack = mb->ilgen->max_stack;
880 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
881 if (mb->ilgen->ex_handlers)
882 num_exception = method_count_clauses (mb->ilgen);
886 char *name = mono_string_to_utf8 (mb->name);
887 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
888 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
891 mono_raise_exception (exception);
894 code_size = mono_array_length (code);
895 max_stack = 8; /* we probably need to run a verifier on the code... */
898 /* check for exceptions, maxstack, locals */
899 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
901 if (code_size < 64 && !(code_size & 1)) {
902 flags = (code_size << 2) | 0x2;
903 } else if (code_size < 32 && (code_size & 1)) {
904 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
908 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
909 /* add to the fixup todo list */
910 if (mb->ilgen && mb->ilgen->num_token_fixups)
911 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
912 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
913 return assembly->text_rva + idx;
917 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
919 * FIXME: need to set also the header size in fat_flags.
920 * (and more sects and init locals flags)
924 fat_flags |= METHOD_HEADER_MORE_SECTS;
926 fat_flags |= METHOD_HEADER_INIT_LOCALS;
927 fat_header [0] = fat_flags;
928 fat_header [1] = (header_size / 4 ) << 4;
929 shortp = (guint16*)(fat_header + 2);
930 *shortp = GUINT16_TO_LE (max_stack);
931 intp = (guint32*)(fat_header + 4);
932 *intp = GUINT32_TO_LE (code_size);
933 intp = (guint32*)(fat_header + 8);
934 *intp = GUINT32_TO_LE (local_sig);
935 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
936 /* add to the fixup todo list */
937 if (mb->ilgen && mb->ilgen->num_token_fixups)
938 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
940 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
942 unsigned char sheader [4];
943 MonoExceptionClause clause;
944 MonoILExceptionInfo * ex_info;
945 MonoILExceptionBlock * ex_block;
948 stream_data_align (&assembly->code);
949 /* always use fat format for now */
950 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
951 num_exception *= sizeof (MonoExceptionClause);
952 num_exception += 4; /* include the size of the header */
953 sheader [1] = num_exception & 0xff;
954 sheader [2] = (num_exception >> 8) & 0xff;
955 sheader [3] = (num_exception >> 16) & 0xff;
956 mono_image_add_stream_data (&assembly->code, sheader, 4);
957 /* fat header, so we are already aligned */
959 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
960 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
961 if (ex_info->handlers) {
962 int finally_start = ex_info->start + ex_info->len;
963 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
964 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
965 clause.flags = GUINT32_TO_LE (ex_block->type);
966 clause.try_offset = GUINT32_TO_LE (ex_info->start);
967 /* need fault, too, probably */
968 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
969 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
971 clause.try_len = GUINT32_TO_LE (ex_info->len);
972 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
973 clause.handler_len = GUINT32_TO_LE (ex_block->len);
974 finally_start = ex_block->start + ex_block->len;
975 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
976 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
977 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
978 /*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",
979 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);*/
980 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
983 g_error ("No clauses for ex info block %d", i);
987 return assembly->text_rva + idx;
991 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
994 MonoDynamicTable *table;
997 table = &assembly->tables [table_idx];
999 g_assert (col < table->columns);
1001 values = table->values + table->columns;
1002 for (i = 1; i <= table->rows; ++i) {
1003 if (values [col] == token)
1005 values += table->columns;
1010 static GHashTable *dynamic_custom_attrs = NULL;
1012 static MonoCustomAttrInfo*
1013 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1016 MonoCustomAttrInfo *ainfo;
1017 MonoReflectionCustomAttr *cattr;
1021 /* FIXME: check in assembly the Run flag is set */
1023 count = mono_array_length (cattrs);
1025 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1027 ainfo->image = image;
1028 ainfo->num_attrs = count;
1029 for (i = 0; i < count; ++i) {
1030 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1031 ainfo->attrs [i].ctor = cattr->ctor->method;
1032 /* FIXME: might want to memdup the data here */
1033 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1034 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1041 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1043 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1048 if (!dynamic_custom_attrs)
1049 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1051 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1052 ainfo->cached = TRUE;
1056 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1058 /* they are cached, so we don't free them */
1059 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1065 * idx is the table index of the object
1066 * type is one of MONO_CUSTOM_ATTR_*
1069 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1071 MonoDynamicTable *table;
1072 MonoReflectionCustomAttr *cattr;
1074 guint32 count, i, token;
1076 char *p = blob_size;
1078 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1081 count = mono_array_length (cattrs);
1082 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1083 table->rows += count;
1084 alloc_table (table, table->rows);
1085 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1086 idx <<= MONO_CUSTOM_ATTR_BITS;
1088 for (i = 0; i < count; ++i) {
1089 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1090 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1091 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1092 type = mono_metadata_token_index (token);
1093 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1094 switch (mono_metadata_token_table (token)) {
1095 case MONO_TABLE_METHOD:
1096 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1098 case MONO_TABLE_MEMBERREF:
1099 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1102 g_warning ("got wrong token in custom attr");
1105 values [MONO_CUSTOM_ATTR_TYPE] = type;
1107 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1108 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1109 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1110 values += MONO_CUSTOM_ATTR_SIZE;
1116 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1117 MonoArray *permissions)
1119 MonoDynamicTable *table;
1121 guint32 count, i, idx;
1122 MonoReflectionPermissionSet *perm;
1127 count = mono_array_length (permissions);
1128 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1129 table->rows += count;
1130 alloc_table (table, table->rows);
1132 for (i = 0; i < mono_array_length (permissions); ++i) {
1133 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1135 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1137 idx = mono_metadata_token_index (parent_token);
1138 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1139 switch (mono_metadata_token_table (parent_token)) {
1140 case MONO_TABLE_TYPEDEF:
1141 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1143 case MONO_TABLE_METHOD:
1144 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1146 case MONO_TABLE_ASSEMBLY:
1147 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1150 g_assert_not_reached ();
1153 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1154 values [MONO_DECL_SECURITY_PARENT] = idx;
1155 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1162 * Fill in the MethodDef and ParamDef tables for a method.
1163 * This is used for both normal methods and constructors.
1166 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1168 MonoDynamicTable *table;
1173 /* room in this table is already allocated */
1174 table = &assembly->tables [MONO_TABLE_METHOD];
1175 *mb->table_idx = table->next_idx ++;
1176 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1177 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1178 name = mono_string_to_utf8 (mb->name);
1179 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1181 values [MONO_METHOD_FLAGS] = mb->attrs;
1182 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1183 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1184 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1186 table = &assembly->tables [MONO_TABLE_PARAM];
1187 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1189 mono_image_add_decl_security (assembly,
1190 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1194 MonoDynamicTable *mtable;
1197 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1198 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1201 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1202 if (mono_array_get (mb->pinfo, gpointer, i))
1205 table->rows += count;
1206 alloc_table (table, table->rows);
1207 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1208 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1209 MonoReflectionParamBuilder *pb;
1210 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1211 values [MONO_PARAM_FLAGS] = pb->attrs;
1212 values [MONO_PARAM_SEQUENCE] = i;
1213 if (pb->name != NULL) {
1214 name = mono_string_to_utf8 (pb->name);
1215 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1218 values [MONO_PARAM_NAME] = 0;
1220 values += MONO_PARAM_SIZE;
1221 if (pb->marshal_info) {
1223 alloc_table (mtable, mtable->rows);
1224 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1225 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1226 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1228 pb->table_idx = table->next_idx++;
1229 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1230 guint32 field_type = 0;
1231 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1233 alloc_table (mtable, mtable->rows);
1234 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1235 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1236 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1237 mvalues [MONO_CONSTANT_TYPE] = field_type;
1238 mvalues [MONO_CONSTANT_PADDING] = 0;
1246 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1247 MonoReflectionMethodBuilder *mb)
1249 rmb->ilgen = mb->ilgen;
1250 rmb->rtype = mb->rtype;
1251 rmb->parameters = mb->parameters;
1252 rmb->generic_params = mb->generic_params;
1253 rmb->opt_types = NULL;
1254 rmb->pinfo = mb->pinfo;
1255 rmb->attrs = mb->attrs;
1256 rmb->iattrs = mb->iattrs;
1257 rmb->call_conv = mb->call_conv;
1258 rmb->code = mb->code;
1259 rmb->type = mb->type;
1260 rmb->name = mb->name;
1261 rmb->table_idx = &mb->table_idx;
1262 rmb->init_locals = mb->init_locals;
1263 rmb->return_modreq = mb->return_modreq;
1264 rmb->return_modopt = mb->return_modopt;
1265 rmb->param_modreq = mb->param_modreq;
1266 rmb->param_modopt = mb->param_modopt;
1267 rmb->permissions = mb->permissions;
1268 rmb->mhandle = mb->mhandle;
1273 rmb->charset = rmb->charset & 0xf;
1274 rmb->lasterr = rmb->charset & 0x40;
1275 rmb->native_cc = rmb->native_cc;
1276 rmb->dllentry = mb->dllentry;
1282 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1283 MonoReflectionCtorBuilder *mb)
1285 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = NULL;
1291 rmb->opt_types = NULL;
1292 rmb->pinfo = mb->pinfo;
1293 rmb->attrs = mb->attrs;
1294 rmb->iattrs = mb->iattrs;
1295 rmb->call_conv = mb->call_conv;
1297 rmb->type = mb->type;
1298 rmb->name = mono_string_new (mono_domain_get (), name);
1299 rmb->table_idx = &mb->table_idx;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = NULL;
1302 rmb->return_modopt = NULL;
1303 rmb->param_modreq = mb->param_modreq;
1304 rmb->param_modopt = mb->param_modopt;
1305 rmb->permissions = mb->permissions;
1306 rmb->mhandle = mb->mhandle;
1312 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1313 MonoReflectionDynamicMethod *mb)
1315 rmb->ilgen = mb->ilgen;
1316 rmb->rtype = mb->rtype;
1317 rmb->parameters = mb->parameters;
1318 rmb->generic_params = NULL;
1319 rmb->opt_types = NULL;
1321 rmb->attrs = mb->attrs;
1323 rmb->call_conv = mb->call_conv;
1326 rmb->name = mb->name;
1327 rmb->table_idx = NULL;
1328 rmb->init_locals = mb->init_locals;
1329 rmb->return_modreq = NULL;
1330 rmb->return_modopt = NULL;
1331 rmb->param_modreq = NULL;
1332 rmb->param_modopt = NULL;
1333 rmb->permissions = NULL;
1334 rmb->mhandle = mb->mhandle;
1340 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1342 MonoDynamicTable *table;
1345 ReflectionMethodBuilder rmb;
1348 reflection_methodbuilder_from_method_builder (&rmb, mb);
1350 mono_image_basic_method (&rmb, assembly);
1352 if (mb->dll) { /* It's a P/Invoke method */
1354 int charset = mb->charset & 0xf;
1355 int lasterr = mb->charset & 0x40;
1356 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1358 alloc_table (table, table->rows);
1359 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1360 /* map CharSet values to on-disk values */
1362 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1363 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1364 name = mono_string_to_utf8 (mb->dllentry);
1365 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1367 name = mono_string_to_utf8 (mb->dll);
1368 moduleref = string_heap_insert (&assembly->sheap, name);
1370 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1371 table = &assembly->tables [MONO_TABLE_MODULEREF];
1373 alloc_table (table, table->rows);
1374 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1375 values [MONO_IMPLMAP_SCOPE] = table->rows;
1379 if (mb->override_method) {
1380 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1382 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1384 alloc_table (table, table->rows);
1385 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1386 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1387 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1389 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1390 switch (mono_metadata_token_table (tok)) {
1391 case MONO_TABLE_MEMBERREF:
1392 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1394 case MONO_TABLE_METHOD:
1395 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1398 g_assert_not_reached ();
1400 values [MONO_METHODIMPL_DECLARATION] = tok;
1403 if (mb->generic_params) {
1404 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1405 table->rows += mono_array_length (mb->generic_params);
1406 alloc_table (table, table->rows);
1407 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1408 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1410 mono_image_get_generic_param_info (
1411 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1418 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1420 ReflectionMethodBuilder rmb;
1422 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1424 mono_image_basic_method (&rmb, assembly);
1428 type_get_fully_qualified_name (MonoType *type) {
1429 char *name, *result;
1433 name = mono_type_get_name (type);
1434 klass = my_mono_class_from_mono_type (type);
1435 ta = klass->image->assembly;
1437 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1438 name, ta->aname.name,
1439 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1440 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1441 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1447 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1451 klass = my_mono_class_from_mono_type (type);
1452 ta = klass->image->assembly;
1453 if (ta == ass || klass->image == mono_defaults.corlib)
1454 return mono_type_get_name (type);
1456 return type_get_fully_qualified_name (type);
1460 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1462 char blob_size [64];
1463 char *b = blob_size;
1468 if (!assembly->save)
1471 p = buf = g_malloc (64);
1473 mono_metadata_encode_value (0x06, p, &p);
1474 /* encode custom attributes before the type */
1475 encode_type (assembly, type, p, &p);
1476 g_assert (p-buf < 64);
1477 mono_metadata_encode_value (p-buf, b, &b);
1478 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1484 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1486 char blob_size [64];
1487 char *b = blob_size;
1492 p = buf = g_malloc (64);
1494 mono_metadata_encode_value (0x06, p, &p);
1495 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1496 /* encode custom attributes before the type */
1497 encode_reflection_type (assembly, fb->type, p, &p);
1498 g_assert (p-buf < 64);
1499 mono_metadata_encode_value (p-buf, b, &b);
1500 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1506 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1507 char blob_size [64];
1508 char *b = blob_size;
1511 guint32 idx = 0, len = 0, dummy = 0;
1513 p = buf = g_malloc (64);
1515 *ret_type = MONO_TYPE_CLASS;
1517 box_val = (char*)&dummy;
1519 box_val = ((char*)val) + sizeof (MonoObject);
1520 *ret_type = val->vtable->klass->byval_arg.type;
1523 switch (*ret_type) {
1524 case MONO_TYPE_BOOLEAN:
1529 case MONO_TYPE_CHAR:
1544 case MONO_TYPE_VALUETYPE:
1545 if (val->vtable->klass->enumtype) {
1546 *ret_type = val->vtable->klass->enum_basetype->type;
1549 g_error ("we can't encode valuetypes");
1550 case MONO_TYPE_CLASS:
1552 case MONO_TYPE_STRING: {
1553 MonoString *str = (MonoString*)val;
1554 /* there is no signature */
1555 len = str->length * 2;
1556 mono_metadata_encode_value (len, b, &b);
1557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1559 char *swapped = g_malloc (2 * mono_string_length (str));
1560 const char *p = (const char*)mono_string_chars (str);
1562 swap_with_size (swapped, p, 2, mono_string_length (str));
1563 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1574 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1577 /* there is no signature */
1578 mono_metadata_encode_value (len, b, &b);
1579 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1580 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1581 swap_with_size (blob_size, box_val, len, 1);
1582 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1584 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1592 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1593 char blob_size [64];
1594 char *b = blob_size;
1595 char *p, *buf, *str;
1596 guint32 idx, len, bufsize = 256;
1598 p = buf = g_malloc (bufsize);
1600 switch (minfo->type) {
1601 case MONO_NATIVE_BYVALTSTR:
1602 case MONO_NATIVE_BYVALARRAY:
1603 mono_metadata_encode_value (minfo->type, p, &p);
1604 mono_metadata_encode_value (minfo->count, p, &p);
1606 case MONO_NATIVE_LPARRAY:
1607 mono_metadata_encode_value (minfo->type, p, &p);
1608 if (minfo->eltype || (minfo->count > 0)) {
1609 mono_metadata_encode_value (minfo->eltype, p, &p);
1610 if (minfo->count > 0) {
1611 mono_metadata_encode_value (0, p, &p);
1612 mono_metadata_encode_value (minfo->count, p, &p);
1616 case MONO_NATIVE_CUSTOM:
1617 mono_metadata_encode_value (minfo->type, p, &p);
1619 str = mono_string_to_utf8 (minfo->guid);
1621 mono_metadata_encode_value (len, p, &p);
1622 memcpy (p, str, len);
1626 mono_metadata_encode_value (0, p, &p);
1628 if (minfo->marshaltype) {
1629 str = mono_string_to_utf8 (minfo->marshaltype);
1631 mono_metadata_encode_value (len, p, &p);
1632 if (p + len >= buf + bufsize) {
1635 buf = g_realloc (buf, bufsize);
1638 memcpy (p, str, len);
1642 mono_metadata_encode_value (0, p, &p);
1644 if (minfo->marshaltyperef) {
1645 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1647 mono_metadata_encode_value (len, p, &p);
1648 if (p + len >= buf + bufsize) {
1651 buf = g_realloc (buf, bufsize);
1654 memcpy (p, str, len);
1658 mono_metadata_encode_value (0, p, &p);
1660 if (minfo->mcookie) {
1661 str = mono_string_to_utf8 (minfo->mcookie);
1663 mono_metadata_encode_value (len, p, &p);
1664 if (p + len >= buf + bufsize) {
1667 buf = g_realloc (buf, bufsize);
1670 memcpy (p, str, len);
1674 mono_metadata_encode_value (0, p, &p);
1678 mono_metadata_encode_value (minfo->type, p, &p);
1682 mono_metadata_encode_value (len, b, &b);
1683 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1689 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1691 MonoDynamicTable *table;
1695 /* maybe this fixup should be done in the C# code */
1696 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1697 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1698 table = &assembly->tables [MONO_TABLE_FIELD];
1699 fb->table_idx = table->next_idx ++;
1700 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1701 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1702 name = mono_string_to_utf8 (fb->name);
1703 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1705 values [MONO_FIELD_FLAGS] = fb->attrs;
1706 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1708 if (fb->offset != -1) {
1709 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1711 alloc_table (table, table->rows);
1712 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1713 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1714 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1716 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1717 guint32 field_type = 0;
1718 table = &assembly->tables [MONO_TABLE_CONSTANT];
1720 alloc_table (table, table->rows);
1721 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1722 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1723 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1724 values [MONO_CONSTANT_TYPE] = field_type;
1725 values [MONO_CONSTANT_PADDING] = 0;
1727 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1729 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1731 alloc_table (table, table->rows);
1732 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1733 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1735 * We store it in the code section because it's simpler for now.
1738 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1740 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1741 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1743 if (fb->marshal_info) {
1744 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1746 alloc_table (table, table->rows);
1747 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1748 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1749 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1754 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1758 char *b = blob_size;
1759 guint32 nparams = 0;
1760 MonoReflectionMethodBuilder *mb = fb->get_method;
1761 MonoReflectionMethodBuilder *smb = fb->set_method;
1762 guint32 idx, i, size;
1764 if (mb && mb->parameters)
1765 nparams = mono_array_length (mb->parameters);
1766 if (!mb && smb && smb->parameters)
1767 nparams = mono_array_length (smb->parameters) - 1;
1768 size = 24 + nparams * 10;
1769 buf = p = g_malloc (size);
1772 mono_metadata_encode_value (nparams, p, &p);
1774 encode_reflection_type (assembly, mb->rtype, p, &p);
1775 for (i = 0; i < nparams; ++i) {
1776 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1777 encode_reflection_type (assembly, pt, p, &p);
1780 /* the property type is the last param */
1781 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1782 for (i = 0; i < nparams; ++i) {
1783 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1784 encode_reflection_type (assembly, pt, p, &p);
1788 g_assert (p - buf < size);
1789 mono_metadata_encode_value (p-buf, b, &b);
1790 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1796 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1798 MonoDynamicTable *table;
1801 guint num_methods = 0;
1805 * we need to set things in the following tables:
1806 * PROPERTYMAP (info already filled in _get_type_info ())
1807 * PROPERTY (rows already preallocated in _get_type_info ())
1808 * METHOD (method info already done with the generic method code)
1811 table = &assembly->tables [MONO_TABLE_PROPERTY];
1812 pb->table_idx = table->next_idx ++;
1813 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1814 name = mono_string_to_utf8 (pb->name);
1815 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1817 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1818 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1820 /* FIXME: we still don't handle 'other' methods */
1821 if (pb->get_method) num_methods ++;
1822 if (pb->set_method) num_methods ++;
1824 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1825 table->rows += num_methods;
1826 alloc_table (table, table->rows);
1828 if (pb->get_method) {
1829 semaidx = table->next_idx ++;
1830 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1831 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1832 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1833 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1835 if (pb->set_method) {
1836 semaidx = table->next_idx ++;
1837 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1838 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1839 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1840 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1845 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1847 MonoDynamicTable *table;
1850 guint num_methods = 0;
1854 * we need to set things in the following tables:
1855 * EVENTMAP (info already filled in _get_type_info ())
1856 * EVENT (rows already preallocated in _get_type_info ())
1857 * METHOD (method info already done with the generic method code)
1860 table = &assembly->tables [MONO_TABLE_EVENT];
1861 eb->table_idx = table->next_idx ++;
1862 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1863 name = mono_string_to_utf8 (eb->name);
1864 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1866 values [MONO_EVENT_FLAGS] = eb->attrs;
1867 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1870 * FIXME: we still don't handle 'other' methods
1872 if (eb->add_method) num_methods ++;
1873 if (eb->remove_method) num_methods ++;
1874 if (eb->raise_method) num_methods ++;
1876 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1877 table->rows += num_methods;
1878 alloc_table (table, table->rows);
1880 if (eb->add_method) {
1881 semaidx = table->next_idx ++;
1882 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1883 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1884 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1885 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1887 if (eb->remove_method) {
1888 semaidx = table->next_idx ++;
1889 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1890 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1891 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1892 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1894 if (eb->raise_method) {
1895 semaidx = table->next_idx ++;
1896 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1897 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1898 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1899 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1904 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1906 static MonoClass *NewConstraintAttr;
1907 static MonoMethod *NewConstraintAttr_ctor;
1908 MonoDynamicTable *table;
1910 guint32 token, type;
1911 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1914 if (!NewConstraintAttr)
1915 NewConstraintAttr = mono_class_from_name (
1916 mono_defaults.corlib, "System.Runtime.CompilerServices",
1917 "NewConstraintAttribute");
1918 g_assert (NewConstraintAttr);
1920 if (!NewConstraintAttr_ctor) {
1923 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1924 MonoMethod *m = NewConstraintAttr->methods [i];
1926 if (strcmp (m->name, ".ctor"))
1929 NewConstraintAttr_ctor = m;
1933 g_assert (NewConstraintAttr_ctor);
1936 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1938 alloc_table (table, table->rows);
1940 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1941 owner <<= MONO_CUSTOM_ATTR_BITS;
1942 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1943 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1945 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1947 type = mono_metadata_token_index (token);
1948 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1949 switch (mono_metadata_token_table (token)) {
1950 case MONO_TABLE_METHOD:
1951 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1953 case MONO_TABLE_MEMBERREF:
1954 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1957 g_warning ("got wrong token in custom attr");
1960 values [MONO_CUSTOM_ATTR_TYPE] = type;
1962 buf = p = g_malloc (1);
1963 mono_metadata_encode_value (4, p, &p);
1964 g_assert (p-buf == 1);
1966 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1968 values += MONO_CUSTOM_ATTR_SIZE;
1973 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1975 MonoDynamicTable *table;
1976 guint32 num_constraints, i;
1980 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1981 num_constraints = gparam->iface_constraints ?
1982 mono_array_length (gparam->iface_constraints) : 0;
1983 table->rows += num_constraints;
1984 if (gparam->base_type)
1986 alloc_table (table, table->rows);
1988 if (gparam->base_type) {
1989 table_idx = table->next_idx ++;
1990 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1992 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1993 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1994 assembly, gparam->base_type->type);
1997 for (i = 0; i < num_constraints; i++) {
1998 MonoReflectionType *constraint = mono_array_get (
1999 gparam->iface_constraints, gpointer, i);
2001 table_idx = table->next_idx ++;
2002 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2004 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2005 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2006 assembly, constraint->type);
2009 if (gparam->has_ctor_constraint)
2010 encode_new_constraint (assembly, owner);
2014 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2016 GenericParamTableEntry *entry;
2019 * The GenericParam table must be sorted according to the `owner' field.
2020 * We need to do this sorting prior to writing the GenericParamConstraint
2021 * table, since we have to use the final GenericParam table indices there
2022 * and they must also be sorted.
2025 entry = g_new0 (GenericParamTableEntry, 1);
2026 entry->owner = owner;
2027 entry->gparam = gparam;
2029 g_ptr_array_add (assembly->gen_params, entry);
2033 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2035 MonoDynamicTable *table;
2036 MonoGenericParam *param;
2040 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2041 table_idx = table->next_idx ++;
2042 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2044 param = entry->gparam->type.type->data.generic_param;
2046 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2047 if (entry->gparam->has_value_type)
2048 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2049 else if (entry->gparam->has_reference_type)
2050 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2052 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2053 values [MONO_GENERICPARAM_NUMBER] = param->num;
2054 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2055 values [MONO_GENERICPARAM_KIND] = 0;
2057 encode_constraints (entry->gparam, table_idx, assembly);
2061 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2063 MonoDynamicTable *table;
2066 guint32 cols [MONO_ASSEMBLY_SIZE];
2070 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2073 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2074 table = &assembly->tables [MONO_TABLE_MODULEREF];
2075 token = table->next_idx ++;
2077 alloc_table (table, table->rows);
2078 values = table->values + token * MONO_MODULEREF_SIZE;
2079 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2081 token <<= MONO_RESOLTION_SCOPE_BITS;
2082 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2083 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2088 if (image->assembly->dynamic)
2090 memset (cols, 0, sizeof (cols));
2092 /* image->assembly->image is the manifest module */
2093 image = image->assembly->image;
2094 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2097 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2098 token = table->next_idx ++;
2100 alloc_table (table, table->rows);
2101 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2102 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2103 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2104 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2105 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2106 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2107 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2108 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2109 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2111 if (strcmp ("", image->assembly->aname.culture)) {
2112 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2113 image->assembly->aname.culture);
2116 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2117 guchar pubtoken [9];
2119 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2120 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2122 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2124 token <<= MONO_RESOLTION_SCOPE_BITS;
2125 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2126 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2131 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2133 MonoDynamicTable *table;
2139 char *b = blob_size;
2141 switch (type->type) {
2142 case MONO_TYPE_FNPTR:
2144 case MONO_TYPE_SZARRAY:
2145 case MONO_TYPE_ARRAY:
2147 case MONO_TYPE_MVAR:
2148 case MONO_TYPE_GENERICINST:
2149 encode_type (assembly, type, p, &p);
2151 case MONO_TYPE_CLASS:
2152 case MONO_TYPE_VALUETYPE: {
2153 MonoClass *k = mono_class_from_mono_type (type);
2154 if (!k || !k->generic_inst)
2156 encode_generic_inst (assembly, k->generic_inst, p, &p);
2163 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2164 if (assembly->save) {
2165 g_assert (p-sig < 128);
2166 mono_metadata_encode_value (p-sig, b, &b);
2167 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2168 alloc_table (table, table->rows + 1);
2169 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2170 values [MONO_TYPESPEC_SIGNATURE] = token;
2173 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2174 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2180 * Despite the name, we handle also TypeSpec (with the above helper).
2183 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2185 MonoDynamicTable *table;
2187 guint32 token, scope, enclosing;
2190 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2193 token = create_typespec (assembly, type);
2196 klass = my_mono_class_from_mono_type (type);
2198 klass = mono_class_from_mono_type (type);
2201 * If it's in the same module and not a generic type parameter:
2203 if ((klass->image == &assembly->image) &&
2204 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2205 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2206 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2207 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2211 if (klass->nested_in) {
2212 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2213 /* get the typeref idx of the enclosing type */
2214 enclosing >>= MONO_TYPEDEFORREF_BITS;
2215 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2217 scope = resolution_scope_from_image (assembly, klass->image);
2219 table = &assembly->tables [MONO_TABLE_TYPEREF];
2220 if (assembly->save) {
2221 alloc_table (table, table->rows + 1);
2222 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2223 values [MONO_TYPEREF_SCOPE] = scope;
2224 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2225 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2227 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2228 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2230 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2235 * Insert a memberef row into the metadata: the token that point to the memberref
2236 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2237 * mono_image_get_fieldref_token()).
2238 * The sig param is an index to an already built signature.
2241 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2243 MonoDynamicTable *table;
2245 guint32 token, pclass;
2248 parent = mono_image_typedef_or_ref (assembly, type);
2249 switch (parent & MONO_TYPEDEFORREF_MASK) {
2250 case MONO_TYPEDEFORREF_TYPEREF:
2251 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2253 case MONO_TYPEDEFORREF_TYPESPEC:
2254 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2256 case MONO_TYPEDEFORREF_TYPEDEF:
2257 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2260 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2263 /* extract the index */
2264 parent >>= MONO_TYPEDEFORREF_BITS;
2266 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2268 if (assembly->save) {
2269 alloc_table (table, table->rows + 1);
2270 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2271 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2272 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2273 values [MONO_MEMBERREF_SIGNATURE] = sig;
2276 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2283 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2286 MonoMethodSignature *sig;
2288 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2293 * A methodref signature can't contain an unmanaged calling convention.
2295 sig = mono_metadata_signature_dup (method->signature);
2296 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2297 sig->call_convention = MONO_CALL_DEFAULT;
2298 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2299 method->name, method_encode_signature (assembly, sig));
2301 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2306 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2307 const gchar *name, guint32 sig)
2309 MonoDynamicTable *table;
2313 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2315 if (assembly->save) {
2316 alloc_table (table, table->rows + 1);
2317 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2318 values [MONO_MEMBERREF_CLASS] = original;
2319 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2320 values [MONO_MEMBERREF_SIGNATURE] = sig;
2323 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2330 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2333 ReflectionMethodBuilder rmb;
2335 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2339 reflection_methodbuilder_from_method_builder (&rmb, mb);
2341 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2342 mono_string_to_utf8 (rmb.name),
2343 method_builder_encode_signature (assembly, &rmb));
2344 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2349 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2352 ReflectionMethodBuilder rmb;
2354 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2358 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2360 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2361 mono_string_to_utf8 (rmb.name),
2362 method_builder_encode_signature (assembly, &rmb));
2363 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2368 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2373 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2376 g_assert (f->field->parent);
2377 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2378 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2379 f->field->name, fieldref_encode_signature (assembly, type));
2380 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2385 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2390 guint32 nparams = gmethod->mtype_argc;
2391 guint32 size = 10 + nparams * 10;
2394 char *b = blob_size;
2396 if (!assembly->save)
2399 p = buf = g_malloc (size);
2401 * FIXME: vararg, explicit_this, differenc call_conv values...
2403 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2404 mono_metadata_encode_value (nparams, p, &p);
2406 for (i = 0; i < nparams; i++)
2407 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2410 g_assert (p - buf < size);
2411 mono_metadata_encode_value (p-buf, b, &b);
2412 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2418 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2420 MonoDynamicTable *table;
2422 guint32 token, mtoken = 0, sig;
2423 MonoMethodInflated *imethod;
2424 MonoMethod *declaring;
2426 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2428 g_assert (method->signature->is_inflated);
2429 imethod = (MonoMethodInflated *) method;
2430 declaring = imethod->declaring;
2432 sig = method_encode_signature (assembly, declaring->signature);
2433 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2434 declaring->name, sig);
2436 if (!declaring->signature->generic_param_count)
2439 switch (mono_metadata_token_table (mtoken)) {
2440 case MONO_TABLE_MEMBERREF:
2441 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2443 case MONO_TABLE_METHOD:
2444 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2447 g_assert_not_reached ();
2450 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2452 if (assembly->save) {
2453 alloc_table (table, table->rows + 1);
2454 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2455 values [MONO_METHODSPEC_METHOD] = mtoken;
2456 values [MONO_METHODSPEC_SIGNATURE] = sig;
2459 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2466 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2468 MonoMethodInflated *imethod;
2471 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2475 g_assert (m->signature->is_inflated);
2476 imethod = (MonoMethodInflated *) m;
2478 if (imethod->declaring->signature->generic_param_count)
2479 token = method_encode_methodspec (assembly, m);
2481 guint32 sig = method_encode_signature (
2482 assembly, imethod->declaring->signature);
2483 token = mono_image_get_memberref_token (
2484 assembly, &m->klass->byval_arg, m->name, sig);
2487 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2492 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2494 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2497 sig = method_encode_signature (assembly, imethod->declaring->signature);
2498 token = mono_image_get_memberref_token (
2499 assembly, &m->klass->byval_arg, m->name, sig);
2505 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2507 MonoDynamicTable *table;
2514 char *b = blob_size;
2518 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2519 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2520 * Because of this, we must not insert it into the `typeref' hash table.
2523 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2527 g_assert (tb->generic_params);
2528 klass = mono_class_from_mono_type (tb->type.type);
2530 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2531 encode_type (assembly, &klass->byval_arg, p, &p);
2533 count = mono_array_length (tb->generic_params);
2534 mono_metadata_encode_value (count, p, &p);
2535 for (i = 0; i < count; i++) {
2536 MonoReflectionGenericParam *gparam;
2538 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2540 encode_type (assembly, gparam->type.type, p, &p);
2543 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2544 if (assembly->save) {
2545 g_assert (p-sig < 128);
2546 mono_metadata_encode_value (p-sig, b, &b);
2547 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2548 alloc_table (table, table->rows + 1);
2549 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2550 values [MONO_TYPESPEC_SIGNATURE] = token;
2553 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2554 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2560 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2562 MonoDynamicTable *table;
2565 guint32 token, pclass, parent, sig;
2568 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2572 klass = mono_class_from_mono_type (fb->typeb->type);
2573 name = mono_string_to_utf8 (fb->name);
2575 sig = fieldref_encode_signature (assembly, fb->type->type);
2577 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2578 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2580 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2581 parent >>= MONO_TYPEDEFORREF_BITS;
2583 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2585 if (assembly->save) {
2586 alloc_table (table, table->rows + 1);
2587 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2588 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2589 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2590 values [MONO_MEMBERREF_SIGNATURE] = sig;
2593 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2595 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2600 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2608 char *b = blob_size;
2610 if (!assembly->save)
2614 g_assert (helper->type == 2);
2616 if (helper->arguments)
2617 nargs = mono_array_length (helper->arguments);
2621 size = 10 + (nargs * 10);
2623 p = buf = g_malloc (size);
2625 /* Encode calling convention */
2626 /* Change Any to Standard */
2627 if ((helper->call_conv & 0x03) == 0x03)
2628 helper->call_conv = 0x01;
2629 /* explicit_this implies has_this */
2630 if (helper->call_conv & 0x40)
2631 helper->call_conv &= 0x20;
2633 if (helper->call_conv == 0) /* Unmanaged */
2634 *p = helper->unmanaged_call_conv - 1;
2637 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2638 if (helper->call_conv & 0x02) /* varargs */
2643 mono_metadata_encode_value (nargs, p, &p);
2644 encode_reflection_type (assembly, helper->return_type, p, &p);
2645 for (i = 0; i < nargs; ++i) {
2646 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2647 encode_reflection_type (assembly, pt, p, &p);
2650 g_assert (p - buf < size);
2651 mono_metadata_encode_value (p-buf, b, &b);
2652 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2659 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2662 MonoDynamicTable *table;
2665 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2666 idx = table->next_idx ++;
2668 alloc_table (table, table->rows);
2669 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2671 values [MONO_STAND_ALONE_SIGNATURE] =
2672 mono_reflection_encode_sighelper (assembly, helper);
2678 reflection_cc_to_file (int call_conv) {
2679 switch (call_conv & 0x3) {
2681 case 1: return MONO_CALL_DEFAULT;
2682 case 2: return MONO_CALL_VARARG;
2684 g_assert_not_reached ();
2691 MonoMethodSignature *sig;
2697 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2702 MonoMethodSignature *sig;
2705 name = mono_string_to_utf8 (m->name);
2706 nparams = mono_array_length (m->parameters);
2707 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2709 sig->sentinelpos = -1;
2710 sig->call_convention = reflection_cc_to_file (m->call_conv);
2711 sig->param_count = nparams;
2712 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2713 for (i = 0; i < nparams; ++i) {
2714 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2715 sig->params [i] = t->type;
2718 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2720 if (strcmp (name, am->name) == 0 &&
2721 mono_metadata_type_equal (am->parent, m->parent->type) &&
2722 mono_metadata_signature_equal (am->sig, sig)) {
2725 m->table_idx = am->token & 0xffffff;
2729 am = g_new0 (ArrayMethod, 1);
2732 am->parent = m->parent->type;
2733 am->token = mono_image_get_memberref_token (assembly, am->parent,
2734 name, method_encode_signature (assembly, sig));
2735 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2736 m->table_idx = am->token & 0xffffff;
2741 * Insert into the metadata tables all the info about the TypeBuilder tb.
2742 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2745 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2747 MonoDynamicTable *table;
2749 int i, is_object = 0, is_system = 0;
2752 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2753 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2754 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2755 n = mono_string_to_utf8 (tb->name);
2756 if (strcmp (n, "Object") == 0)
2758 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2760 n = mono_string_to_utf8 (tb->nspace);
2761 if (strcmp (n, "System") == 0)
2763 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2765 if (tb->parent && !(is_system && is_object) &&
2766 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2767 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2769 values [MONO_TYPEDEF_EXTENDS] = 0;
2770 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2771 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2774 * if we have explicitlayout or sequentiallayouts, output data in the
2775 * ClassLayout table.
2777 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2778 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2779 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2781 alloc_table (table, table->rows);
2782 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2783 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2784 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2785 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2788 /* handle interfaces */
2789 if (tb->interfaces) {
2790 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2792 table->rows += mono_array_length (tb->interfaces);
2793 alloc_table (table, table->rows);
2794 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2795 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2796 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2797 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2798 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2799 values += MONO_INTERFACEIMPL_SIZE;
2805 table = &assembly->tables [MONO_TABLE_FIELD];
2806 table->rows += tb->num_fields;
2807 alloc_table (table, table->rows);
2808 for (i = 0; i < tb->num_fields; ++i)
2809 mono_image_get_field_info (
2810 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2813 /* handle constructors */
2815 table = &assembly->tables [MONO_TABLE_METHOD];
2816 table->rows += mono_array_length (tb->ctors);
2817 alloc_table (table, table->rows);
2818 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2819 mono_image_get_ctor_info (domain,
2820 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2823 /* handle methods */
2825 table = &assembly->tables [MONO_TABLE_METHOD];
2826 table->rows += tb->num_methods;
2827 alloc_table (table, table->rows);
2828 for (i = 0; i < tb->num_methods; ++i)
2829 mono_image_get_method_info (
2830 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2833 /* Do the same with properties etc.. */
2834 if (tb->events && mono_array_length (tb->events)) {
2835 table = &assembly->tables [MONO_TABLE_EVENT];
2836 table->rows += mono_array_length (tb->events);
2837 alloc_table (table, table->rows);
2838 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2840 alloc_table (table, table->rows);
2841 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2842 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2843 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2844 for (i = 0; i < mono_array_length (tb->events); ++i)
2845 mono_image_get_event_info (
2846 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2848 if (tb->properties && mono_array_length (tb->properties)) {
2849 table = &assembly->tables [MONO_TABLE_PROPERTY];
2850 table->rows += mono_array_length (tb->properties);
2851 alloc_table (table, table->rows);
2852 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2854 alloc_table (table, table->rows);
2855 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2856 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2857 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2858 for (i = 0; i < mono_array_length (tb->properties); ++i)
2859 mono_image_get_property_info (
2860 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2863 /* handle generic parameters */
2864 if (tb->generic_params) {
2865 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2866 table->rows += mono_array_length (tb->generic_params);
2867 alloc_table (table, table->rows);
2868 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2869 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2871 mono_image_get_generic_param_info (
2872 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2876 mono_image_add_decl_security (assembly,
2877 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2881 MonoDynamicTable *ntable;
2883 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2884 ntable->rows += mono_array_length (tb->subtypes);
2885 alloc_table (ntable, ntable->rows);
2886 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2888 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2889 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2891 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2892 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2893 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2894 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2895 mono_string_to_utf8 (tb->name), tb->table_idx,
2896 ntable->next_idx, ntable->rows);*/
2897 values += MONO_NESTED_CLASS_SIZE;
2904 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2908 g_ptr_array_add (types, type);
2910 if (!type->subtypes)
2913 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2914 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2915 collect_types (types, subtype);
2920 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2921 MonoReflectionTypeBuilder **type2)
2923 if ((*type1)->table_idx < (*type2)->table_idx)
2926 if ((*type1)->table_idx > (*type2)->table_idx)
2933 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2938 for (i = 0; i < mono_array_length (pinfo); ++i) {
2939 MonoReflectionParamBuilder *pb;
2940 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2943 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2948 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2951 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2953 for (i = 0; i < tb->num_fields; ++i) {
2954 MonoReflectionFieldBuilder* fb;
2955 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2956 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2960 for (i = 0; i < mono_array_length (tb->events); ++i) {
2961 MonoReflectionEventBuilder* eb;
2962 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2963 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2966 if (tb->properties) {
2967 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2968 MonoReflectionPropertyBuilder* pb;
2969 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2970 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2974 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2975 MonoReflectionCtorBuilder* cb;
2976 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2977 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2978 params_add_cattrs (assembly, cb->pinfo);
2983 for (i = 0; i < tb->num_methods; ++i) {
2984 MonoReflectionMethodBuilder* mb;
2985 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2986 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2987 params_add_cattrs (assembly, mb->pinfo);
2992 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2993 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2998 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3001 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3003 /* no types in the module */
3007 for (i = 0; i < mb->num_types; ++i)
3008 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3012 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
3013 MonoDynamicImage *assembly)
3015 MonoDynamicTable *table;
3019 char *b = blob_size;
3022 table = &assembly->tables [MONO_TABLE_FILE];
3024 alloc_table (table, table->rows);
3025 values = table->values + table->next_idx * MONO_FILE_SIZE;
3026 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3027 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3028 if (module->image->dynamic) {
3029 /* This depends on the fact that the main module is emitted last */
3030 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3031 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3035 path = g_strdup (module->image->name);
3037 mono_sha1_get_digest_from_file (path, hash);
3040 mono_metadata_encode_value (20, b, &b);
3041 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3042 mono_image_add_stream_data (&assembly->blob, hash, 20);
3047 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3049 MonoDynamicTable *table;
3053 table = &assembly->tables [MONO_TABLE_MODULE];
3054 mb->table_idx = table->next_idx ++;
3055 name = mono_string_to_utf8 (mb->module.name);
3056 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3058 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3061 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3062 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3063 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3067 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3068 guint32 module_index, guint32 parent_index,
3069 MonoDynamicImage *assembly)
3071 MonoDynamicTable *table;
3075 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3076 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3079 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3081 alloc_table (table, table->rows);
3082 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3084 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3085 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3086 if (klass->nested_in)
3087 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3089 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3090 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3091 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3093 res = table->next_idx;
3097 /* Emit nested types */
3098 if (klass->nested_classes) {
3101 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3102 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3109 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3110 guint32 module_index, guint32 parent_index,
3111 MonoDynamicImage *assembly)
3116 klass = mono_class_from_mono_type (tb->type.type);
3118 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3120 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3121 parent_index, assembly);
3125 * We need to do this ourselves since klass->nested_classes is not set up.
3128 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3129 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3134 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3135 guint32 module_index,
3136 MonoDynamicImage *assembly)
3138 MonoImage *image = module->image;
3142 t = &image->tables [MONO_TABLE_TYPEDEF];
3144 for (i = 0; i < t->rows; ++i) {
3145 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3147 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3148 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3152 #define align_pointer(base,p)\
3154 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3156 (p) += 4 - (__diff & 3);\
3160 compare_semantics (const void *a, const void *b)
3162 const guint32 *a_values = a;
3163 const guint32 *b_values = b;
3164 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3167 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3171 compare_custom_attrs (const void *a, const void *b)
3173 const guint32 *a_values = a;
3174 const guint32 *b_values = b;
3176 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3180 compare_field_marshal (const void *a, const void *b)
3182 const guint32 *a_values = a;
3183 const guint32 *b_values = b;
3185 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3189 compare_nested (const void *a, const void *b)
3191 const guint32 *a_values = a;
3192 const guint32 *b_values = b;
3194 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3198 compare_genericparam (const void *a, const void *b)
3200 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3201 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3203 return (*a_entry)->owner - (*b_entry)->owner;
3207 pad_heap (MonoDynamicStream *sh)
3209 if (sh->index & 3) {
3210 int sz = 4 - (sh->index & 3);
3211 memset (sh->data + sh->index, 0, sz);
3218 MonoDynamicStream *stream;
3222 * build_compressed_metadata() fills in the blob of data that represents the
3223 * raw metadata as it will be saved in the PE file. The five streams are output
3224 * and the metadata tables are comnpressed from the guint32 array representation,
3225 * to the compressed on-disk format.
3228 build_compressed_metadata (MonoDynamicImage *assembly)
3230 MonoDynamicTable *table;
3232 guint64 valid_mask = 0;
3233 guint64 sorted_mask;
3234 guint32 heapt_size = 0;
3235 guint32 meta_size = 256; /* allow for header and other stuff */
3236 guint32 table_offset;
3237 guint32 ntables = 0;
3243 struct StreamDesc stream_desc [5];
3245 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3246 for (i = 0; i < assembly->gen_params->len; i++){
3247 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3248 write_generic_param_entry (assembly, entry);
3251 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3252 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3253 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3254 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3255 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3257 /* tables that are sorted */
3258 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3259 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3260 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3261 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3262 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3263 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3265 /* Compute table sizes */
3266 /* the MonoImage has already been created in mono_image_basic_init() */
3267 meta = &assembly->image;
3269 /* sizes should be multiple of 4 */
3270 pad_heap (&assembly->blob);
3271 pad_heap (&assembly->guid);
3272 pad_heap (&assembly->sheap);
3273 pad_heap (&assembly->us);
3275 /* Setup the info used by compute_sizes () */
3276 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3277 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3278 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3280 meta_size += assembly->blob.index;
3281 meta_size += assembly->guid.index;
3282 meta_size += assembly->sheap.index;
3283 meta_size += assembly->us.index;
3285 for (i=0; i < 64; ++i)
3286 meta->tables [i].rows = assembly->tables [i].rows;
3288 for (i = 0; i < 64; i++){
3289 if (meta->tables [i].rows == 0)
3291 valid_mask |= (guint64)1 << i;
3293 meta->tables [i].row_size = mono_metadata_compute_size (
3294 meta, i, &meta->tables [i].size_bitfield);
3295 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3297 heapt_size += 24; /* #~ header size */
3298 heapt_size += ntables * 4;
3299 /* make multiple of 4 */
3302 meta_size += heapt_size;
3303 meta->raw_metadata = g_malloc0 (meta_size);
3304 p = meta->raw_metadata;
3305 /* the metadata signature */
3306 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3307 /* version numbers and 4 bytes reserved */
3308 int16val = (guint16*)p;
3309 *int16val++ = GUINT16_TO_LE (1);
3310 *int16val = GUINT16_TO_LE (1);
3312 /* version string */
3313 int32val = (guint32*)p;
3314 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3316 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3317 p += GUINT32_FROM_LE (*int32val);
3318 align_pointer (meta->raw_metadata, p);
3319 int16val = (guint16*)p;
3320 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3321 *int16val = GUINT16_TO_LE (5); /* number of streams */
3325 * write the stream info.
3327 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3328 table_offset += 3; table_offset &= ~3;
3330 assembly->tstream.index = heapt_size;
3331 for (i = 0; i < 5; ++i) {
3332 int32val = (guint32*)p;
3333 stream_desc [i].stream->offset = table_offset;
3334 *int32val++ = GUINT32_TO_LE (table_offset);
3335 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3336 table_offset += GUINT32_FROM_LE (*int32val);
3337 table_offset += 3; table_offset &= ~3;
3339 strcpy (p, stream_desc [i].name);
3340 p += strlen (stream_desc [i].name) + 1;
3341 align_pointer (meta->raw_metadata, p);
3344 * now copy the data, the table stream header and contents goes first.
3346 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3347 p = meta->raw_metadata + assembly->tstream.offset;
3348 int32val = (guint32*)p;
3349 *int32val = GUINT32_TO_LE (0); /* reserved */
3352 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3353 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3354 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3355 *p++ = 1; /* version */
3358 *p++ = 1; /* version */
3362 if (meta->idx_string_wide)
3364 if (meta->idx_guid_wide)
3366 if (meta->idx_blob_wide)
3369 *p++ = 0; /* reserved */
3370 int64val = (guint64*)p;
3371 *int64val++ = GUINT64_TO_LE (valid_mask);
3372 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3374 int32val = (guint32*)p;
3375 for (i = 0; i < 64; i++){
3376 if (meta->tables [i].rows == 0)
3378 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3380 p = (unsigned char*)int32val;
3382 /* sort the tables that still need sorting */
3383 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3385 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3386 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3388 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3389 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3391 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3392 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3394 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3397 /* compress the tables */
3398 for (i = 0; i < 64; i++){
3401 guint32 bitfield = meta->tables [i].size_bitfield;
3402 if (!meta->tables [i].rows)
3404 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3405 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3406 meta->tables [i].base = p;
3407 for (row = 1; row <= meta->tables [i].rows; ++row) {
3408 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3409 for (col = 0; col < assembly->tables [i].columns; ++col) {
3410 switch (mono_metadata_table_size (bitfield, col)) {
3412 *p++ = values [col];
3415 *p++ = values [col] & 0xff;
3416 *p++ = (values [col] >> 8) & 0xff;
3419 *p++ = values [col] & 0xff;
3420 *p++ = (values [col] >> 8) & 0xff;
3421 *p++ = (values [col] >> 16) & 0xff;
3422 *p++ = (values [col] >> 24) & 0xff;
3425 g_assert_not_reached ();
3429 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3432 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3433 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3434 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3435 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3436 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3438 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3442 * Some tables in metadata need to be sorted according to some criteria, but
3443 * when methods and fields are first created with reflection, they may be assigned a token
3444 * that doesn't correspond to the final token they will get assigned after the sorting.
3445 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3446 * with the reflection objects that represent them. Once all the tables are set up, the
3447 * reflection objects will contains the correct table index. fixup_method() will fixup the
3448 * tokens for the method with ILGenerator @ilgen.
3451 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3452 guint32 code_idx = GPOINTER_TO_UINT (value);
3453 MonoReflectionILTokenInfo *iltoken;
3454 MonoReflectionFieldBuilder *field;
3455 MonoReflectionCtorBuilder *ctor;
3456 MonoReflectionMethodBuilder *method;
3457 MonoReflectionTypeBuilder *tb;
3458 MonoReflectionArrayMethod *am;
3460 unsigned char *target;
3462 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3463 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3464 target = assembly->code.data + code_idx + iltoken->code_pos;
3465 switch (target [3]) {
3466 case MONO_TABLE_FIELD:
3467 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3468 field = (MonoReflectionFieldBuilder *)iltoken->member;
3469 idx = field->table_idx;
3470 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3471 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3472 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3474 g_assert_not_reached ();
3477 case MONO_TABLE_METHOD:
3478 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3479 method = (MonoReflectionMethodBuilder *)iltoken->member;
3480 idx = method->table_idx;
3481 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3482 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3483 idx = ctor->table_idx;
3484 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3485 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3486 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3487 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3489 g_assert_not_reached ();
3492 case MONO_TABLE_TYPEDEF:
3493 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3494 g_assert_not_reached ();
3495 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3496 idx = tb->table_idx;
3498 case MONO_TABLE_MEMBERREF:
3499 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3500 am = (MonoReflectionArrayMethod*)iltoken->member;
3501 idx = am->table_idx;
3502 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3503 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3504 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3505 g_assert (m->klass->generic_inst);
3507 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3509 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3510 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3511 g_assert (f->generic_info);
3513 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3516 g_assert_not_reached ();
3519 case MONO_TABLE_METHODSPEC:
3520 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3521 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3522 g_assert (m->signature->generic_param_count);
3525 g_assert_not_reached ();
3529 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3531 target [0] = idx & 0xff;
3532 target [1] = (idx >> 8) & 0xff;
3533 target [2] = (idx >> 16) & 0xff;
3540 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3541 * value is not known when the table is emitted.
3544 fixup_cattrs (MonoDynamicImage *assembly)
3546 MonoDynamicTable *table;
3548 guint32 type, i, idx, token;
3551 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3553 for (i = 0; i < table->rows; ++i) {
3554 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3556 type = values [MONO_CUSTOM_ATTR_TYPE];
3557 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3558 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3559 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3560 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3563 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3564 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3565 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3566 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3573 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3575 MonoDynamicTable *table;
3579 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3581 alloc_table (table, table->rows);
3582 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3583 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3584 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3585 name = mono_string_to_utf8 (rsrc->name);
3586 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3588 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3593 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3595 MonoDynamicTable *table;
3599 char *b = blob_size;
3601 guint32 idx, offset;
3603 if (rsrc->filename) {
3604 name = mono_string_to_utf8 (rsrc->filename);
3605 sname = g_path_get_basename (name);
3607 table = &assembly->tables [MONO_TABLE_FILE];
3609 alloc_table (table, table->rows);
3610 values = table->values + table->next_idx * MONO_FILE_SIZE;
3611 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3612 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3615 mono_sha1_get_digest_from_file (name, hash);
3616 mono_metadata_encode_value (20, b, &b);
3617 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3618 mono_image_add_stream_data (&assembly->blob, hash, 20);
3620 idx = table->next_idx++;
3622 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3625 offset = mono_array_length (rsrc->data);
3626 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3627 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3628 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3629 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3633 * The entry should be emitted into the MANIFESTRESOURCE table of
3634 * the main module, but that needs to reference the FILE table
3635 * which isn't emitted yet.
3642 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3646 set_version_from_string (MonoString *version, guint32 *values)
3648 gchar *ver, *p, *str;
3651 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3652 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3653 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3654 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3657 ver = str = mono_string_to_utf8 (version);
3658 for (i = 0; i < 4; ++i) {
3659 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3665 /* handle Revision and Build */
3675 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3679 char *b = blob_size;
3684 len = mono_array_length (pkey);
3685 mono_metadata_encode_value (len, b, &b);
3686 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3687 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3689 /* need to get the actual value from the key type... */
3690 assembly->strong_name_size = 128;
3691 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3697 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3699 MonoDynamicTable *table;
3700 MonoDynamicImage *assembly;
3701 MonoReflectionAssemblyBuilder *assemblyb;
3706 guint32 module_index;
3708 assemblyb = moduleb->assemblyb;
3709 assembly = moduleb->dynamic_image;
3710 domain = mono_object_domain (assemblyb);
3712 /* Emit ASSEMBLY table */
3713 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3714 alloc_table (table, 1);
3715 values = table->values + MONO_ASSEMBLY_SIZE;
3716 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3717 name = mono_string_to_utf8 (assemblyb->name);
3718 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3720 if (assemblyb->culture) {
3721 name = mono_string_to_utf8 (assemblyb->culture);
3722 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3725 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3727 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3728 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3729 set_version_from_string (assemblyb->version, values);
3731 /* Emit FILE + EXPORTED_TYPE table */
3733 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3735 MonoReflectionModuleBuilder *file_module =
3736 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3737 if (file_module != moduleb) {
3738 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3740 if (file_module->types) {
3741 for (j = 0; j < file_module->num_types; ++j) {
3742 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3743 mono_image_fill_export_table (domain, tb, module_index, 0,
3749 if (assemblyb->loaded_modules) {
3750 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3751 MonoReflectionModule *file_module =
3752 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3753 mono_image_fill_file_table (domain, file_module, assembly);
3755 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3759 /* Emit MANIFESTRESOURCE table */
3761 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3763 MonoReflectionModuleBuilder *file_module =
3764 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3765 /* The table for the main module is emitted later */
3766 if (file_module != moduleb) {
3768 if (file_module->resources) {
3769 int len = mono_array_length (file_module->resources);
3770 for (j = 0; j < len; ++j) {
3771 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3772 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3780 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3781 * for the modulebuilder @moduleb.
3782 * At the end of the process, method and field tokens are fixed up and the
3783 * on-disk compressed metadata representation is created.
3786 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3788 MonoDynamicTable *table;
3789 MonoDynamicImage *assembly;
3790 MonoReflectionAssemblyBuilder *assemblyb;
3795 assemblyb = moduleb->assemblyb;
3796 assembly = moduleb->dynamic_image;
3797 domain = mono_object_domain (assemblyb);
3799 if (assembly->text_rva)
3802 assembly->text_rva = START_TEXT_RVA;
3804 if (moduleb->is_main) {
3805 mono_image_emit_manifest (moduleb);
3808 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3809 table->rows = 1; /* .<Module> */
3811 alloc_table (table, table->rows);
3813 * Set the first entry.
3815 values = table->values + table->columns;
3816 values [MONO_TYPEDEF_FLAGS] = 0;
3817 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3818 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3819 values [MONO_TYPEDEF_EXTENDS] = 0;
3820 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3821 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3824 * handle global methods
3825 * FIXME: test what to do when global methods are defined in multiple modules.
3827 if (moduleb->global_methods) {
3828 table = &assembly->tables [MONO_TABLE_METHOD];
3829 table->rows += mono_array_length (moduleb->global_methods);
3830 alloc_table (table, table->rows);
3831 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3832 mono_image_get_method_info (
3833 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3835 if (moduleb->global_fields) {
3836 table = &assembly->tables [MONO_TABLE_FIELD];
3837 table->rows += mono_array_length (moduleb->global_fields);
3838 alloc_table (table, table->rows);
3839 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3840 mono_image_get_field_info (
3841 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3844 table = &assembly->tables [MONO_TABLE_MODULE];
3845 alloc_table (table, 1);
3846 mono_image_fill_module_table (domain, moduleb, assembly);
3850 /* Collect all types into a list sorted by their table_idx */
3851 GPtrArray *types = g_ptr_array_new ();
3854 for (i = 0; i < moduleb->num_types; ++i) {
3855 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3856 collect_types (types, type);
3859 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3860 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3861 table->rows += types->len;
3862 alloc_table (table, table->rows);
3864 for (i = 0; i < types->len; ++i) {
3865 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3866 mono_image_get_type_info (domain, type, assembly);
3868 g_ptr_array_free (types, TRUE);
3872 * table->rows is already set above and in mono_image_fill_module_table.
3874 /* add all the custom attributes at the end, once all the indexes are stable */
3875 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3877 module_add_cattrs (assembly, moduleb);
3880 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3881 fixup_cattrs (assembly);
3885 * mono_image_insert_string:
3886 * @module: module builder object
3889 * Insert @str into the user string stream of @module.
3892 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3894 MonoDynamicImage *assembly;
3899 MONO_ARCH_SAVE_REGS;
3901 if (!module->dynamic_image)
3902 mono_image_module_basic_init (module);
3904 assembly = module->dynamic_image;
3906 if (assembly->save) {
3907 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3908 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3909 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3911 char *swapped = g_malloc (2 * mono_string_length (str));
3912 const char *p = (const char*)mono_string_chars (str);
3914 swap_with_size (swapped, p, 2, mono_string_length (str));
3915 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3919 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3921 mono_image_add_stream_data (&assembly->us, "", 1);
3924 idx = assembly->us.index ++;
3926 mono_g_hash_table_insert (assembly->tokens,
3927 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3929 return MONO_TOKEN_STRING | idx;
3933 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3934 MonoArray *opt_param_types)
3939 klass = obj->vtable->klass;
3940 if (strcmp (klass->name, "MonoMethod") == 0) {
3941 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3942 MonoMethodSignature *sig, *old;
3943 guint32 sig_token, parent;
3946 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3948 nargs = mono_array_length (opt_param_types);
3949 old = method->signature;
3950 sig = mono_metadata_signature_alloc (
3951 &assembly->image, old->param_count + nargs);
3953 sig->hasthis = old->hasthis;
3954 sig->explicit_this = old->explicit_this;
3955 sig->call_convention = old->call_convention;
3956 sig->generic_param_count = old->generic_param_count;
3957 sig->param_count = old->param_count + nargs;
3958 sig->sentinelpos = old->param_count;
3959 sig->ret = old->ret;
3961 for (i = 0; i < old->param_count; i++)
3962 sig->params [i] = old->params [i];
3964 for (i = 0; i < nargs; i++) {
3965 MonoReflectionType *rt = mono_array_get (
3966 opt_param_types, MonoReflectionType *, i);
3967 sig->params [old->param_count + i] = rt->type;
3970 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3971 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3972 parent >>= MONO_TYPEDEFORREF_BITS;
3974 parent <<= MONO_MEMBERREF_PARENT_BITS;
3975 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3977 sig_token = method_encode_signature (assembly, sig);
3978 token = mono_image_get_varargs_method_token (
3979 assembly, parent, method->name, sig_token);
3980 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3981 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3982 ReflectionMethodBuilder rmb;
3983 guint32 parent, sig;
3985 reflection_methodbuilder_from_method_builder (&rmb, mb);
3986 rmb.opt_types = opt_param_types;
3988 sig = method_builder_encode_signature (assembly, &rmb);
3990 parent = mono_image_create_token (assembly, obj, TRUE);
3991 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3993 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3994 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3996 token = mono_image_get_varargs_method_token (
3997 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3999 g_error ("requested method token for %s\n", klass->name);
4005 * mono_image_create_token:
4006 * @assembly: a dynamic assembly
4009 * Get a token to insert in the IL code stream for the given MemberInfo.
4010 * @obj can be one of:
4011 * ConstructorBuilder
4021 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4022 gboolean create_methodspec)
4027 klass = obj->vtable->klass;
4028 if (strcmp (klass->name, "MethodBuilder") == 0) {
4029 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4031 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4032 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4034 token = mono_image_get_methodbuilder_token (assembly, mb);
4035 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4037 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4038 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4040 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4041 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4043 token = mono_image_get_ctorbuilder_token (assembly, mb);
4044 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4046 else if (strcmp (klass->name, "FieldBuilder") == 0) {
4047 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4048 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4049 if (tb->generic_params) {
4050 token = mono_image_get_generic_field_token (assembly, fb);
4052 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4055 else if (strcmp (klass->name, "TypeBuilder") == 0) {
4056 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4057 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4059 else if (strcmp (klass->name, "MonoType") == 0 ||
4060 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4061 MonoReflectionType *tb = (MonoReflectionType *)obj;
4062 token = mono_metadata_token_from_dor (
4063 mono_image_typedef_or_ref (assembly, tb->type));
4065 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4066 MonoReflectionType *tb = (MonoReflectionType *)obj;
4067 token = mono_metadata_token_from_dor (
4068 mono_image_typedef_or_ref (assembly, tb->type));
4070 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4071 strcmp (klass->name, "MonoMethod") == 0) {
4072 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4073 if (m->method->signature->is_inflated) {
4074 if (create_methodspec)
4075 token = mono_image_get_methodspec_token (
4076 assembly, m->method);
4078 token = mono_image_get_inflated_method_token (
4079 assembly, m->method);
4080 } else if (m->method->signature->generic_param_count) {
4081 g_assert_not_reached ();
4082 } else if ((m->method->klass->image == &assembly->image) &&
4083 !m->method->klass->generic_inst) {
4084 static guint32 method_table_idx = 0xffffff;
4085 if (m->method->klass->wastypebuilder) {
4086 /* we use the same token as the one that was assigned
4087 * to the Methodbuilder.
4088 * FIXME: do the equivalent for Fields.
4090 token = m->method->token;
4093 * Each token should have a unique index, but the indexes are
4094 * assigned by managed code, so we don't know about them. An
4095 * easy solution is to count backwards...
4097 method_table_idx --;
4098 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4101 token = mono_image_get_methodref_token (assembly, m->method);
4102 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4104 else if (strcmp (klass->name, "MonoField") == 0) {
4105 MonoReflectionField *f = (MonoReflectionField *)obj;
4106 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4107 static guint32 field_table_idx = 0xffffff;
4109 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4111 token = mono_image_get_fieldref_token (assembly, f);
4112 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4114 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4115 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4116 token = mono_image_get_array_token (assembly, m);
4118 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4119 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4120 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4123 g_error ("requested token for %s\n", klass->name);
4125 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4132 guint32 import_lookup_table;
4136 guint32 import_address_table_rva;
4144 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4146 static MonoDynamicImage*
4147 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4148 char *assembly_name, char *module_name)
4150 static const guchar entrycode [16] = {0xff, 0x25, 0};
4151 MonoDynamicImage *image;
4154 const char *version = mono_get_runtime_version ();
4157 image = GC_MALLOC (sizeof (MonoDynamicImage));
4159 image = g_new0 (MonoDynamicImage, 1);
4162 /* keep in sync with image.c */
4163 image->image.name = assembly_name;
4164 image->image.assembly_name = image->image.name; /* they may be different */
4165 image->image.module_name = module_name;
4166 image->image.version = g_strdup (version);
4167 image->image.dynamic = TRUE;
4169 image->image.references = g_new0 (MonoAssembly*, 1);
4170 image->image.references [0] = NULL;
4172 mono_image_init (&image->image);
4174 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4175 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4176 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4177 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4178 image->handleref = g_hash_table_new (NULL, NULL);
4179 image->tokens = mono_g_hash_table_new (NULL, NULL);
4180 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4181 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4182 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4183 image->gen_params = g_ptr_array_new ();
4185 string_heap_init (&image->sheap);
4186 mono_image_add_stream_data (&image->us, "", 1);
4187 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4188 /* import tables... */
4189 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4190 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4191 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4192 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4193 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4194 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4195 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4196 stream_data_align (&image->code);
4198 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4200 for (i=0; i < 64; ++i) {
4201 image->tables [i].next_idx = 1;
4202 image->tables [i].columns = table_sizes [i];
4205 image->image.assembly = (MonoAssembly*)assembly;
4206 image->run = assembly->run;
4207 image->save = assembly->save;
4213 * mono_image_basic_init:
4214 * @assembly: an assembly builder object
4216 * Create the MonoImage that represents the assembly builder and setup some
4217 * of the helper hash table and the basic metadata streams.
4220 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4222 MonoDynamicAssembly *assembly;
4223 MonoDynamicImage *image;
4225 MONO_ARCH_SAVE_REGS;
4227 if (assemblyb->dynamic_assembly)
4231 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4233 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4236 assembly->assembly.dynamic = TRUE;
4237 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4238 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4239 if (assemblyb->culture)
4240 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4242 assembly->assembly.aname.culture = g_strdup ("");
4244 assembly->run = assemblyb->access != 2;
4245 assembly->save = assemblyb->access != 1;
4247 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4248 assembly->assembly.aname.name = image->image.name;
4249 assembly->assembly.image = &image->image;
4251 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4252 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4256 calc_section_size (MonoDynamicImage *assembly)
4260 /* alignment constraints */
4261 assembly->code.index += 3;
4262 assembly->code.index &= ~3;
4263 assembly->meta_size += 3;
4264 assembly->meta_size &= ~3;
4265 assembly->resources.index += 3;
4266 assembly->resources.index &= ~3;
4268 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4269 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4272 if (assembly->win32_res) {
4273 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4275 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4276 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4280 assembly->sections [MONO_SECTION_RELOC].size = 12;
4281 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4291 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4295 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4297 ResTreeNode *t1 = (ResTreeNode*)a;
4298 ResTreeNode *t2 = (ResTreeNode*)b;
4300 return t1->id - t2->id;
4304 * resource_tree_create:
4306 * Organize the resources into a resource tree.
4308 static ResTreeNode *
4309 resource_tree_create (MonoArray *win32_resources)
4311 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4315 tree = g_new0 (ResTreeNode, 1);
4317 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4318 MonoReflectionWin32Resource *win32_res =
4319 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4323 lang_node = g_new0 (ResTreeNode, 1);
4324 lang_node->id = win32_res->lang_id;
4325 lang_node->win32_res = win32_res;
4327 /* Create type node if neccesary */
4329 for (l = tree->children; l; l = l->next)
4330 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4331 type_node = (ResTreeNode*)l->data;
4336 type_node = g_new0 (ResTreeNode, 1);
4337 type_node->id = win32_res->res_type;
4340 * The resource types have to be sorted otherwise
4341 * Windows Explorer can't display the version information.
4343 tree->children = g_slist_insert_sorted (tree->children, type_node,
4344 resource_tree_compare_by_id);
4347 /* Create res node if neccesary */
4349 for (l = type_node->children; l; l = l->next)
4350 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4351 res_node = (ResTreeNode*)l->data;
4356 res_node = g_new0 (ResTreeNode, 1);
4357 res_node->id = win32_res->res_id;
4358 type_node->children = g_slist_append (type_node->children, res_node);
4361 res_node->children = g_slist_append (res_node->children, lang_node);
4368 * resource_tree_encode:
4370 * Encode the resource tree into the format used in the PE file.
4373 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4376 MonoPEResourceDir dir;
4377 MonoPEResourceDirEntry dir_entry;
4378 MonoPEResourceDataEntry data_entry;
4382 * For the format of the resource directory, see the article
4383 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4387 memset (&dir, 0, sizeof (dir));
4388 memset (&dir_entry, 0, sizeof (dir_entry));
4389 memset (&data_entry, 0, sizeof (data_entry));
4391 g_assert (sizeof (dir) == 16);
4392 g_assert (sizeof (dir_entry) == 8);
4393 g_assert (sizeof (data_entry) == 16);
4395 node->offset = p - begin;
4397 /* IMAGE_RESOURCE_DIRECTORY */
4398 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4400 memcpy (p, &dir, sizeof (dir));
4403 /* Reserve space for entries */
4405 p += sizeof (dir_entry) * dir.res_id_entries;
4407 /* Write children */
4408 for (l = node->children; l; l = l->next) {
4409 ResTreeNode *child = (ResTreeNode*)l->data;
4411 if (child->win32_res) {
4413 child->offset = p - begin;
4415 /* IMAGE_RESOURCE_DATA_ENTRY */
4416 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4417 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4419 memcpy (p, &data_entry, sizeof (data_entry));
4420 p += sizeof (data_entry);
4422 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4423 p += data_entry.rde_size;
4426 resource_tree_encode (child, begin, p, &p);
4429 /* IMAGE_RESOURCE_ENTRY */
4430 for (l = node->children; l; l = l->next) {
4431 ResTreeNode *child = (ResTreeNode*)l->data;
4432 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4434 dir_entry.is_dir = child->win32_res ? 0 : 1;
4435 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4437 memcpy (entries, &dir_entry, sizeof (dir_entry));
4438 entries += sizeof (dir_entry);
4445 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4450 MonoReflectionWin32Resource *win32_res;
4453 if (!assemblyb->win32_resources)
4457 * Resources are stored in a three level tree inside the PE file.
4458 * - level one contains a node for each type of resource
4459 * - level two contains a node for each resource
4460 * - level three contains a node for each instance of a resource for a
4461 * specific language.
4464 tree = resource_tree_create (assemblyb->win32_resources);
4466 /* Estimate the size of the encoded tree */
4468 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4469 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4470 size += mono_array_length (win32_res->res_data);
4472 /* Directory structure */
4473 size += mono_array_length (assemblyb->win32_resources) * 256;
4474 p = buf = g_malloc (size);
4476 resource_tree_encode (tree, p, p, &p);
4478 g_assert (p - buf < size);
4480 assembly->win32_res = g_malloc (p - buf);
4481 assembly->win32_res_size = p - buf;
4482 memcpy (assembly->win32_res, buf, p - buf);
4488 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4490 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4493 p += sizeof (MonoPEResourceDir);
4494 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4495 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4496 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4497 if (dir_entry->is_dir)
4498 fixup_resource_directory (res_section, child, rva);
4500 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4501 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4504 p += sizeof (MonoPEResourceDirEntry);
4509 * mono_image_create_pefile:
4510 * @mb: a module builder object
4512 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4513 * assembly->pefile where it can be easily retrieved later in chunks.
4516 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4517 MonoMSDOSHeader *msdos;
4518 MonoDotNetHeader *header;
4519 MonoSectionTable *section;
4520 MonoCLIHeader *cli_header;
4521 guint32 size, image_size, virtual_base, text_offset;
4522 guint32 header_start, section_start, file_offset, virtual_offset;
4523 MonoDynamicImage *assembly;
4524 MonoReflectionAssemblyBuilder *assemblyb;
4525 MonoDynamicStream *pefile;
4527 guint32 *rva, value;
4530 static const unsigned char msheader[] = {
4531 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4532 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4533 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4534 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4535 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4536 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4537 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4538 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4541 assemblyb = mb->assemblyb;
4543 mono_image_basic_init (assemblyb);
4544 assembly = mb->dynamic_image;
4546 /* already created */
4547 if (assembly->pefile.index)
4550 mono_image_build_metadata (mb);
4552 if (mb->is_main && assemblyb->resources) {
4553 int len = mono_array_length (assemblyb->resources);
4554 for (i = 0; i < len; ++i)
4555 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4558 if (mb->resources) {
4559 int len = mono_array_length (mb->resources);
4560 for (i = 0; i < len; ++i)
4561 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4564 build_compressed_metadata (assembly);
4567 assembly_add_win32_resources (assembly, assemblyb);
4569 nsections = calc_section_size (assembly);
4571 pefile = &assembly->pefile;
4573 /* The DOS header and stub */
4574 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4575 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4577 /* the dotnet header */
4578 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4580 /* the section tables */
4581 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4583 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4584 virtual_offset = VIRT_ALIGN;
4587 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4588 if (!assembly->sections [i].size)
4591 file_offset += FILE_ALIGN - 1;
4592 file_offset &= ~(FILE_ALIGN - 1);
4593 virtual_offset += VIRT_ALIGN - 1;
4594 virtual_offset &= ~(VIRT_ALIGN - 1);
4596 assembly->sections [i].offset = file_offset;
4597 assembly->sections [i].rva = virtual_offset;
4599 file_offset += assembly->sections [i].size;
4600 virtual_offset += assembly->sections [i].size;
4601 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4604 file_offset += FILE_ALIGN - 1;
4605 file_offset &= ~(FILE_ALIGN - 1);
4606 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4608 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4610 /* back-patch info */
4611 msdos = (MonoMSDOSHeader*)pefile->data;
4612 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4613 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4614 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4616 header = (MonoDotNetHeader*)(pefile->data + header_start);
4617 header->pesig [0] = 'P';
4618 header->pesig [1] = 'E';
4620 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4621 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4622 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4623 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4624 if (assemblyb->pekind == 1) {
4626 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4629 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4632 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4634 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4635 header->pe.pe_major = 6;
4636 header->pe.pe_minor = 0;
4637 size = assembly->sections [MONO_SECTION_TEXT].size;
4638 size += FILE_ALIGN - 1;
4639 size &= ~(FILE_ALIGN - 1);
4640 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4641 size = assembly->sections [MONO_SECTION_RSRC].size;
4642 size += FILE_ALIGN - 1;
4643 size &= ~(FILE_ALIGN - 1);
4644 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4645 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4646 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4647 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4648 /* pe_rva_entry_point always at the beginning of the text section */
4649 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4651 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4652 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4653 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4654 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4655 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4656 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4657 size = section_start;
4658 size += FILE_ALIGN - 1;
4659 size &= ~(FILE_ALIGN - 1);
4660 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4662 size += VIRT_ALIGN - 1;
4663 size &= ~(VIRT_ALIGN - 1);
4664 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4667 // Translate the PEFileKind value to the value expected by the Windows loader
4673 // PEFileKinds.Dll == 1
4674 // PEFileKinds.ConsoleApplication == 2
4675 // PEFileKinds.WindowApplication == 3
4678 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4679 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4681 if (assemblyb->pekind == 3)
4686 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4688 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4689 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4690 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4691 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4692 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4693 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4695 /* fill data directory entries */
4697 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4698 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4700 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4701 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4703 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4704 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4705 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4706 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4707 /* patch imported function RVA name */
4708 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4709 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4711 /* the import table */
4712 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4713 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4714 /* patch imported dll RVA name and other entries in the dir */
4715 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4716 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4717 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4718 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4719 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4720 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4722 p = (assembly->code.data + assembly->ilt_offset);
4723 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4724 *p++ = (value) & 0xff;
4725 *p++ = (value >> 8) & (0xff);
4726 *p++ = (value >> 16) & (0xff);
4727 *p++ = (value >> 24) & (0xff);
4729 /* the CLI header info */
4730 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4731 cli_header->ch_size = GUINT32_FROM_LE (72);
4732 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4733 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4734 if (assemblyb->entry_point) {
4735 guint32 table_idx = 0;
4736 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4737 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4738 table_idx = methodb->table_idx;
4741 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4742 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4745 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4746 /* The embedded managed resources */
4747 text_offset = assembly->text_rva + assembly->code.index;
4748 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4749 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4750 text_offset += assembly->resources.index;
4751 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4752 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4753 text_offset += assembly->meta_size;
4754 if (assembly->strong_name_size) {
4755 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4756 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4757 text_offset += assembly->strong_name_size;
4760 /* write the section tables and section content */
4761 section = (MonoSectionTable*)(pefile->data + section_start);
4762 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4763 static const char *section_names [] = {
4764 ".text", ".rsrc", ".reloc"
4766 if (!assembly->sections [i].size)
4768 strcpy (section->st_name, section_names [i]);
4769 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4770 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4771 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4772 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4773 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4774 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4775 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4777 case MONO_SECTION_TEXT:
4778 /* patch entry point */
4779 p = (assembly->code.data + 2);
4780 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4781 *p++ = (value) & 0xff;
4782 *p++ = (value >> 8) & 0xff;
4783 *p++ = (value >> 16) & 0xff;
4784 *p++ = (value >> 24) & 0xff;
4786 text_offset = assembly->sections [i].offset;
4787 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4788 text_offset += assembly->code.index;
4789 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4790 text_offset += assembly->resources.index;
4791 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4792 text_offset += assembly->meta_size;
4793 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4795 g_free (assembly->image.raw_metadata);
4797 case MONO_SECTION_RELOC:
4798 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4799 *rva = GUINT32_FROM_LE (assembly->text_rva);
4801 *rva = GUINT32_FROM_LE (12);
4803 data16 = (guint16*)rva;
4805 * the entrypoint is always at the start of the text section
4806 * 3 is IMAGE_REL_BASED_HIGHLOW
4807 * 2 is patch_size_rva - text_rva
4809 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4811 *data16 = 0; /* terminate */
4813 case MONO_SECTION_RSRC:
4814 if (assembly->win32_res) {
4815 text_offset = assembly->sections [i].offset;
4817 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4818 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4820 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4824 g_assert_not_reached ();
4829 /* check that the file is properly padded */
4832 FILE *f = fopen ("mypetest.exe", "w");
4833 fwrite (pefile->data, pefile->index, 1, f);
4839 MonoReflectionModule *
4840 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4844 MonoImageOpenStatus status;
4845 MonoDynamicAssembly *assembly;
4847 name = mono_string_to_utf8 (fileName);
4849 image = mono_image_open (name, &status);
4852 if (status == MONO_IMAGE_ERROR_ERRNO)
4853 exc = mono_get_exception_file_not_found (fileName);
4855 exc = mono_get_exception_bad_image_format (name);
4857 mono_raise_exception (exc);
4862 assembly = ab->dynamic_assembly;
4863 image->assembly = (MonoAssembly*)assembly;
4865 mono_assembly_load_references (image, &status);
4867 mono_image_close (image);
4868 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4871 return mono_module_get_object (mono_domain_get (), image);
4875 * We need to return always the same object for MethodInfo, FieldInfo etc..
4876 * but we need to consider the reflected type.
4877 * type uses a different hash, since it uses custom hash/equal functions.
4882 MonoClass *refclass;
4886 reflected_equal (gconstpointer a, gconstpointer b) {
4887 const ReflectedEntry *ea = a;
4888 const ReflectedEntry *eb = b;
4890 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4894 reflected_hash (gconstpointer a) {
4895 const ReflectedEntry *ea = a;
4896 return GPOINTER_TO_UINT (ea->item);
4899 #define CHECK_OBJECT(t,p,k) \
4905 mono_domain_lock (domain); \
4906 if (!domain->refobject_hash) \
4907 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4908 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4909 mono_domain_unlock (domain); \
4915 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4917 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4920 #define CACHE_OBJECT(p,o,k) \
4922 ReflectedEntry *e = ALLOC_REFENTRY; \
4924 e->refclass = (k); \
4925 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4926 mono_domain_unlock (domain); \
4930 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4932 /* this is done only once */
4933 mono_domain_lock (domain);
4934 CACHE_OBJECT (assembly, res, NULL);
4938 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4940 /* this is done only once */
4941 mono_domain_lock (domain);
4942 CACHE_OBJECT (module, res, NULL);
4946 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4948 MonoDynamicImage *image = moduleb->dynamic_image;
4949 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4952 * FIXME: we already created an image in mono_image_basic_init (), but
4953 * we don't know which module it belongs to, since that is only
4954 * determined at assembly save time.
4956 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4957 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4959 moduleb->module.image = &image->image;
4960 moduleb->dynamic_image = image;
4961 register_module (mono_object_domain (moduleb), moduleb, image);
4966 * mono_assembly_get_object:
4967 * @domain: an app domain
4968 * @assembly: an assembly
4970 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4972 MonoReflectionAssembly*
4973 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4975 static MonoClass *System_Reflection_Assembly;
4976 MonoReflectionAssembly *res;
4978 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4979 if (!System_Reflection_Assembly)
4980 System_Reflection_Assembly = mono_class_from_name (
4981 mono_defaults.corlib, "System.Reflection", "Assembly");
4982 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4983 res->assembly = assembly;
4984 CACHE_OBJECT (assembly, res, NULL);
4990 MonoReflectionModule*
4991 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4993 static MonoClass *System_Reflection_Module;
4994 MonoReflectionModule *res;
4996 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4997 if (!System_Reflection_Module)
4998 System_Reflection_Module = mono_class_from_name (
4999 mono_defaults.corlib, "System.Reflection", "Module");
5000 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5003 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5005 res->fqname = mono_string_new (domain, image->name);
5006 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5007 res->scopename = mono_string_new (domain, image->module_name);
5009 mono_image_addref (image);
5011 CACHE_OBJECT (image, res, NULL);
5015 MonoReflectionModule*
5016 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5018 static MonoClass *System_Reflection_Module;
5019 MonoReflectionModule *res;
5020 MonoTableInfo *table;
5021 guint32 cols [MONO_FILE_SIZE];
5023 guint32 i, name_idx;
5026 if (!System_Reflection_Module)
5027 System_Reflection_Module = mono_class_from_name (
5028 mono_defaults.corlib, "System.Reflection", "Module");
5029 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5031 table = &image->tables [MONO_TABLE_FILE];
5032 g_assert (table_index < table->rows);
5033 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5036 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5037 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5039 /* Check whenever the row has a corresponding row in the moduleref table */
5040 table = &image->tables [MONO_TABLE_MODULEREF];
5041 for (i = 0; i < table->rows; ++i) {
5042 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5043 val = mono_metadata_string_heap (image, name_idx);
5044 if (strcmp (val, name) == 0)
5045 res->image = image->modules [i];
5048 res->fqname = mono_string_new (domain, name);
5049 res->name = mono_string_new (domain, name);
5050 res->scopename = mono_string_new (domain, name);
5051 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5057 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5059 if ((t1->type != t2->type) ||
5060 (t1->byref != t2->byref))
5064 case MONO_TYPE_VOID:
5065 case MONO_TYPE_BOOLEAN:
5066 case MONO_TYPE_CHAR:
5077 case MONO_TYPE_STRING:
5080 case MONO_TYPE_OBJECT:
5081 case MONO_TYPE_TYPEDBYREF:
5083 case MONO_TYPE_VALUETYPE:
5084 case MONO_TYPE_CLASS:
5085 case MONO_TYPE_SZARRAY:
5086 return t1->data.klass == t2->data.klass;
5088 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5089 case MONO_TYPE_ARRAY:
5090 if (t1->data.array->rank != t2->data.array->rank)
5092 return t1->data.array->eklass == t2->data.array->eklass;
5093 case MONO_TYPE_GENERICINST: {
5095 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5097 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5099 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5100 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5106 case MONO_TYPE_MVAR:
5107 return t1->data.generic_param == t2->data.generic_param;
5109 g_error ("implement type compare for %0x!", t1->type);
5117 mymono_metadata_type_hash (MonoType *t1)
5123 hash |= t1->byref << 6; /* do not collide with t1->type values */
5125 case MONO_TYPE_VALUETYPE:
5126 case MONO_TYPE_CLASS:
5127 case MONO_TYPE_SZARRAY:
5128 /* check if the distribution is good enough */
5129 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5131 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5136 static MonoReflectionGenericInst*
5137 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5139 static MonoClass *System_Reflection_MonoGenericInst;
5140 MonoReflectionGenericInst *res;
5141 MonoGenericInst *ginst;
5144 if (!System_Reflection_MonoGenericInst) {
5145 System_Reflection_MonoGenericInst = mono_class_from_name (
5146 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5147 g_assert (System_Reflection_MonoGenericInst);
5150 ginst = geninst->data.generic_inst;
5151 gklass = mono_class_from_mono_type (ginst->generic_type);
5153 mono_class_init (ginst->klass);
5155 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5157 res->type.type = geninst;
5158 if (gklass->wastypebuilder && gklass->reflection_info)
5159 res->generic_type = gklass->reflection_info;
5161 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5167 * mono_type_get_object:
5168 * @domain: an app domain
5171 * Return an System.MonoType object representing the type @type.
5174 mono_type_get_object (MonoDomain *domain, MonoType *type)
5176 MonoReflectionType *res;
5177 MonoClass *klass = mono_class_from_mono_type (type);
5179 mono_domain_lock (domain);
5180 if (!domain->type_hash)
5181 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5182 (GCompareFunc)mymono_metadata_type_equal);
5183 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5184 mono_domain_unlock (domain);
5187 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5188 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5189 mono_g_hash_table_insert (domain->type_hash, type, res);
5190 mono_domain_unlock (domain);
5193 if (klass->reflection_info && !klass->wastypebuilder) {
5194 /* g_assert_not_reached (); */
5195 /* should this be considered an error condition? */
5197 mono_domain_unlock (domain);
5198 return klass->reflection_info;
5201 mono_class_init (klass);
5202 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5204 mono_g_hash_table_insert (domain->type_hash, type, res);
5205 mono_domain_unlock (domain);
5210 * mono_method_get_object:
5211 * @domain: an app domain
5213 * @refclass: the reflected type (can be NULL)
5215 * Return an System.Reflection.MonoMethod object representing the method @method.
5217 MonoReflectionMethod*
5218 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5221 * We use the same C representation for methods and constructors, but the type
5222 * name in C# is different.
5226 MonoReflectionMethod *ret;
5229 refclass = method->klass;
5231 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5232 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5233 cname = "MonoCMethod";
5235 cname = "MonoMethod";
5236 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5238 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5239 ret->method = method;
5240 ret->name = mono_string_new (domain, method->name);
5241 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5242 CACHE_OBJECT (method, ret, refclass);
5247 * mono_field_get_object:
5248 * @domain: an app domain
5252 * Return an System.Reflection.MonoField object representing the field @field
5255 MonoReflectionField*
5256 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5258 MonoReflectionField *res;
5261 CHECK_OBJECT (MonoReflectionField *, field, klass);
5262 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5263 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5266 res->name = mono_string_new (domain, field->name);
5267 if (field->generic_info)
5268 res->attrs = field->generic_info->generic_type->attrs;
5270 res->attrs = field->type->attrs;
5271 res->type = mono_type_get_object (domain, field->type);
5272 CACHE_OBJECT (field, res, klass);
5277 * mono_property_get_object:
5278 * @domain: an app domain
5280 * @property: a property
5282 * Return an System.Reflection.MonoProperty object representing the property @property
5285 MonoReflectionProperty*
5286 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5288 MonoReflectionProperty *res;
5291 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5292 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5293 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5295 res->property = property;
5296 CACHE_OBJECT (property, res, klass);
5301 * mono_event_get_object:
5302 * @domain: an app domain
5306 * Return an System.Reflection.MonoEvent object representing the event @event
5309 MonoReflectionEvent*
5310 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5312 MonoReflectionEvent *res;
5315 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5316 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5317 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5320 CACHE_OBJECT (event, res, klass);
5325 * mono_param_get_objects:
5326 * @domain: an app domain
5329 * Return an System.Reflection.ParameterInfo array object representing the parameters
5330 * in the method @method.
5333 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5335 static MonoClass *System_Reflection_ParameterInfo;
5337 MonoArray *res = NULL;
5338 MonoReflectionMethod *member = NULL;
5339 MonoReflectionParameter *param = NULL;
5340 char **names, **blobs = NULL;
5341 MonoObject *dbnull = mono_get_dbnull_object (domain);
5344 if (!System_Reflection_ParameterInfo)
5345 System_Reflection_ParameterInfo = mono_class_from_name (
5346 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5348 if (!method->signature->param_count)
5349 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5351 /* Note: the cache is based on the address of the signature into the method
5352 * since we already cache MethodInfos with the method as keys.
5354 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5356 member = mono_method_get_object (domain, method, NULL);
5357 names = g_new (char *, method->signature->param_count);
5358 mono_method_get_param_names (method, (const char **) names);
5360 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5361 for (i = 0; i < method->signature->param_count; ++i) {
5362 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5363 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5364 param->MemberImpl = (MonoObject*)member;
5365 param->NameImpl = mono_string_new (domain, names [i]);
5366 param->PositionImpl = i;
5367 param->AttrsImpl = method->signature->params [i]->attrs;
5369 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5370 param->DefaultValueImpl = dbnull;
5372 MonoType *type = param->ClassImpl->type;
5375 blobs = g_new0 (char *, method->signature->param_count);
5376 get_default_param_value_blobs (method, blobs);
5379 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5381 if (!param->DefaultValueImpl) {
5382 param->DefaultValueImpl = dbnull;
5386 mono_array_set (res, gpointer, i, param);
5391 CACHE_OBJECT (&(method->signature), res, NULL);
5396 mono_get_dbnull_object (MonoDomain *domain)
5400 static MonoClassField *dbnull_value_field = NULL;
5402 if (!dbnull_value_field) {
5403 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5404 mono_class_init (klass);
5405 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5406 g_assert (dbnull_value_field);
5408 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5415 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5417 guint32 param_index, i, lastp, crow = 0;
5418 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5421 MonoClass *klass = method->klass;
5422 MonoImage *image = klass->image;
5423 MonoDomain *domain = mono_domain_get ();
5424 MonoMethodSignature *methodsig = method->signature;
5426 MonoTableInfo *constt;
5427 MonoTableInfo *methodt;
5428 MonoTableInfo *paramt;
5430 if (!methodsig->param_count)
5433 if (klass->generic_inst) {
5434 return; /* FIXME - ??? */
5437 mono_class_init (klass);
5439 if (klass->image->dynamic) {
5443 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5444 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5445 constt = &image->tables [MONO_TABLE_CONSTANT];
5447 for (i = 0; i < klass->method.count; ++i) {
5448 if (method == klass->methods [i]) {
5449 idx = klass->method.first + i;
5454 g_assert (idx != -1);
5456 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5457 if (idx + 1 < methodt->rows)
5458 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5460 lastp = paramt->rows + 1;
5462 for (i = param_index; i < lastp; ++i) {
5465 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5466 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5468 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5471 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5476 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5477 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5484 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5493 klass = mono_class_from_mono_type (type);
5494 if (klass->valuetype) {
5495 object = mono_object_new (domain, klass);
5496 retval = ((gchar *) object + sizeof (MonoObject));
5501 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5508 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5512 memset (assembly, 0, sizeof (MonoAssemblyName));
5514 assembly->culture = "";
5515 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5517 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5520 while (*p == ' ' || *p == ',') {
5529 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5531 assembly->major = strtoul (p, &s, 10);
5532 if (s == p || *s != '.')
5535 assembly->minor = strtoul (p, &s, 10);
5536 if (s == p || *s != '.')
5539 assembly->build = strtoul (p, &s, 10);
5540 if (s == p || *s != '.')
5543 assembly->revision = strtoul (p, &s, 10);
5547 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5549 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5550 assembly->culture = "";
5553 assembly->culture = p;
5554 while (*p && *p != ',') {
5558 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5560 if (strncmp (p, "null", 4) == 0) {
5565 while (*p && *p != ',') {
5568 len = (p - start + 1);
5569 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5570 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5571 g_strlcpy (assembly->public_key_token, start, len);
5574 while (*p && *p != ',')
5578 while (*p == ' ' || *p == ',') {
5592 * mono_reflection_parse_type:
5595 * Parse a type name as accepted by the GetType () method and output the info
5596 * extracted in the info structure.
5597 * the name param will be mangled, so, make a copy before passing it to this function.
5598 * The fields in info will be valid until the memory pointed to by name is valid.
5599 * Returns 0 on parse error.
5600 * See also mono_type_get_name () below.
5603 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5605 char *start, *p, *w, *last_point, *startn;
5606 int in_modifiers = 0;
5607 int isbyref = 0, rank;
5609 start = p = w = name;
5611 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5612 info->name = info->name_space = NULL;
5613 info->nested = NULL;
5614 info->modifiers = NULL;
5616 /* last_point separates the namespace from the name */
5622 *p = 0; /* NULL terminate the name */
5624 info->nested = g_list_append (info->nested, startn);
5625 /* we have parsed the nesting namespace + name */
5629 info->name_space = start;
5631 info->name = last_point + 1;
5633 info->name_space = (char *)"";
5659 info->name_space = start;
5661 info->name = last_point + 1;
5663 info->name_space = (char *)"";
5670 if (isbyref) /* only one level allowed by the spec */
5673 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5677 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5688 else if (*p != '*') /* '*' means unknown lower bound */
5694 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5706 return 0; /* missing assembly name */
5707 if (!assembly_name_to_aname (&info->assembly, p))
5714 if (info->assembly.name)
5717 *w = 0; /* terminate class name */
5718 if (!info->name || !*info->name)
5720 /* add other consistency checks */
5725 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5732 image = mono_defaults.corlib;
5735 klass = mono_class_from_name_case (image, info->name_space, info->name);
5737 klass = mono_class_from_name (image, info->name_space, info->name);
5740 for (mod = info->nested; mod; mod = mod->next) {
5743 mono_class_init (klass);
5744 nested = klass->nested_classes;
5747 klass = nested->data;
5749 if (g_strcasecmp (klass->name, mod->data) == 0)
5752 if (strcmp (klass->name, mod->data) == 0)
5756 nested = nested->next;
5763 mono_class_init (klass);
5764 for (mod = info->modifiers; mod; mod = mod->next) {
5765 modval = GPOINTER_TO_UINT (mod->data);
5766 if (!modval) { /* byref: must be last modifier */
5767 return &klass->this_arg;
5768 } else if (modval == -1) {
5769 klass = mono_ptr_class_get (&klass->byval_arg);
5770 } else { /* array rank */
5771 klass = mono_array_class_get (klass, modval);
5773 mono_class_init (klass);
5776 return &klass->byval_arg;
5780 * mono_reflection_get_type:
5781 * @image: a metadata context
5782 * @info: type description structure
5783 * @ignorecase: flag for case-insensitive string compares
5784 * @type_resolve: whenever type resolve was already tried
5786 * Build a MonoType from the type description in @info.
5791 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5794 MonoReflectionAssembly *assembly;
5798 type = mono_reflection_get_type_internal (image, info, ignorecase);
5801 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5804 /* FIXME: Enabling this causes regressions (#65577) */
5810 *type_resolve = TRUE;
5814 /* Reconstruct the type name */
5815 fullName = g_string_new ("");
5816 if (info->name_space && (info->name_space [0] != '\0'))
5817 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5819 g_string_printf (fullName, info->name);
5820 for (mod = info->nested; mod; mod = mod->next)
5821 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5824 mono_domain_try_type_resolve (
5825 mono_domain_get (), fullName->str, NULL);
5826 if (assembly && (!image || (assembly->assembly->image == image))) {
5828 if (assembly->assembly->dynamic) {
5829 /* Enumerate all modules */
5830 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5834 if (abuilder->modules) {
5835 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5836 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5837 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5843 if (!type && abuilder->loaded_modules) {
5844 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5845 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5846 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5853 type = mono_reflection_get_type_internal (assembly->assembly->image,
5856 g_string_free (fullName, TRUE);
5861 * mono_reflection_type_from_name:
5863 * @image: a metadata context (can be NULL).
5865 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5866 * it defaults to get the type from @image or, if @image is NULL or loading
5867 * from it fails, uses corlib.
5871 mono_reflection_type_from_name (char *name, MonoImage *image)
5874 MonoTypeNameParse info;
5875 MonoAssembly *assembly;
5877 gboolean type_resolve = FALSE;
5879 /* Make a copy since parse_type modifies its argument */
5880 tmp = g_strdup (name);
5882 /*g_print ("requested type %s\n", str);*/
5883 if (!mono_reflection_parse_type (tmp, &info)) {
5885 g_list_free (info.modifiers);
5886 g_list_free (info.nested);
5890 if (info.assembly.name) {
5891 assembly = mono_assembly_loaded (&info.assembly);
5893 /* then we must load the assembly ourselve - see #60439 */
5894 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5897 g_list_free (info.modifiers);
5898 g_list_free (info.nested);
5902 image = assembly->image;
5903 } else if (image == NULL) {
5904 image = mono_defaults.corlib;
5907 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5908 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5909 image = mono_defaults.corlib;
5910 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5914 g_list_free (info.modifiers);
5915 g_list_free (info.nested);
5920 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5922 int slen, type = t->type;
5927 case MONO_TYPE_BOOLEAN: {
5928 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5933 case MONO_TYPE_CHAR:
5935 case MONO_TYPE_I2: {
5936 guint16 *val = g_malloc (sizeof (guint16));
5941 #if SIZEOF_VOID_P == 4
5947 case MONO_TYPE_I4: {
5948 guint32 *val = g_malloc (sizeof (guint32));
5953 #if SIZEOF_VOID_P == 8
5954 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5959 case MONO_TYPE_I8: {
5960 guint64 *val = g_malloc (sizeof (guint64));
5965 case MONO_TYPE_VALUETYPE:
5966 if (t->data.klass->enumtype) {
5967 type = t->data.klass->enum_basetype->type;
5970 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5973 case MONO_TYPE_STRING:
5974 if (*p == (char)0xFF) {
5978 slen = mono_metadata_decode_value (p, &p);
5980 return mono_string_new_len (mono_domain_get (), p, slen);
5981 case MONO_TYPE_CLASS: {
5984 if (*p == (char)0xFF) {
5989 slen = mono_metadata_decode_value (p, &p);
5990 n = g_memdup (p, slen + 1);
5992 t = mono_reflection_type_from_name (n, image);
5994 g_warning ("Cannot load type '%s'", n);
5998 return mono_type_get_object (mono_domain_get (), t);
6002 case MONO_TYPE_OBJECT: {
6005 MonoClass *subc = NULL;
6010 } else if (subt == 0x0E) {
6011 type = MONO_TYPE_STRING;
6013 } else if (subt == 0x55) {
6016 slen = mono_metadata_decode_value (p, &p);
6017 n = g_memdup (p, slen + 1);
6019 t = mono_reflection_type_from_name (n, image);
6021 g_warning ("Cannot load type '%s'", n);
6024 subc = mono_class_from_mono_type (t);
6025 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6026 MonoType simple_type = {{0}};
6027 simple_type.type = subt;
6028 subc = mono_class_from_mono_type (&simple_type);
6030 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6032 val = load_cattr_value (image, &subc->byval_arg, p, end);
6033 obj = mono_object_new (mono_domain_get (), subc);
6034 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6038 case MONO_TYPE_SZARRAY:
6041 guint32 i, alen, basetype;
6044 if (alen == 0xffffffff) {
6048 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6049 basetype = t->data.klass->byval_arg.type;
6054 case MONO_TYPE_BOOLEAN:
6055 for (i=0;i<alen;i++)
6057 MonoBoolean val=*p++;
6058 mono_array_set(arr,MonoBoolean,i,val);
6061 case MONO_TYPE_CHAR:
6064 for (i=0;i<alen;i++)
6066 guint16 val=read16(p);
6067 mono_array_set(arr,guint16,i,val);
6074 for (i=0;i<alen;i++)
6076 guint32 val=read32(p);
6077 mono_array_set(arr,guint32,i,val);
6084 for (i=0;i<alen;i++)
6086 guint64 val=read64(p);
6087 mono_array_set(arr,guint64,i,val);
6091 case MONO_TYPE_CLASS:
6092 case MONO_TYPE_OBJECT:
6093 case MONO_TYPE_STRING:
6094 for (i = 0; i < alen; i++) {
6095 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6096 mono_array_set (arr, gpointer, i, item);
6100 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6106 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6112 type_is_reference (MonoType *type)
6114 switch (type->type) {
6115 case MONO_TYPE_BOOLEAN:
6116 case MONO_TYPE_CHAR:
6129 case MONO_TYPE_VALUETYPE:
6137 free_param_data (MonoMethodSignature *sig, void **params) {
6139 for (i = 0; i < sig->param_count; ++i) {
6140 if (!type_is_reference (sig->params [i]))
6141 g_free (params [i]);
6146 * Find the method index in the metadata methodDef table.
6147 * Later put these three helper methods in metadata and export them.
6150 find_method_index (MonoMethod *method) {
6151 MonoClass *klass = method->klass;
6154 for (i = 0; i < klass->method.count; ++i) {
6155 if (method == klass->methods [i])
6156 return klass->method.first + 1 + i;
6162 * Find the field index in the metadata FieldDef table.
6165 find_field_index (MonoClass *klass, MonoClassField *field) {
6168 for (i = 0; i < klass->field.count; ++i) {
6169 if (field == &klass->fields [i])
6170 return klass->field.first + 1 + i;
6176 * Find the property index in the metadata Property table.
6179 find_property_index (MonoClass *klass, MonoProperty *property) {
6182 for (i = 0; i < klass->property.count; ++i) {
6183 if (property == &klass->properties [i])
6184 return klass->property.first + 1 + i;
6190 * Find the event index in the metadata Event table.
6193 find_event_index (MonoClass *klass, MonoEvent *event) {
6196 for (i = 0; i < klass->event.count; ++i) {
6197 if (event == &klass->events [i])
6198 return klass->event.first + 1 + i;
6204 create_custom_attr (MonoImage *image, MonoMethod *method,
6205 const char *data, guint32 len)
6207 const char *p = data;
6209 guint32 i, j, num_named;
6213 mono_class_init (method->klass);
6216 attr = mono_object_new (mono_domain_get (), method->klass);
6217 mono_runtime_invoke (method, attr, NULL, NULL);
6221 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6224 /*g_print ("got attr %s\n", method->klass->name);*/
6226 params = g_new (void*, method->signature->param_count);
6230 for (i = 0; i < method->signature->param_count; ++i) {
6231 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6235 attr = mono_object_new (mono_domain_get (), method->klass);
6236 mono_runtime_invoke (method, attr, params, NULL);
6237 free_param_data (method->signature, params);
6239 num_named = read16 (named);
6241 for (j = 0; j < num_named; j++) {
6243 char *name, named_type, data_type;
6244 named_type = *named++;
6245 data_type = *named++; /* type of data */
6246 if (data_type == 0x55) {
6249 type_len = mono_metadata_decode_blob_size (named, &named);
6250 type_name = g_malloc (type_len + 1);
6251 memcpy (type_name, named, type_len);
6252 type_name [type_len] = 0;
6254 /* FIXME: lookup the type and check type consistency */
6255 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6256 /* this seems to be the type of the element of the array */
6257 /* g_print ("skipping 0x%02x after prop\n", *named); */
6260 name_len = mono_metadata_decode_blob_size (named, &named);
6261 name = g_malloc (name_len + 1);
6262 memcpy (name, named, name_len);
6263 name [name_len] = 0;
6265 if (named_type == 0x53) {
6266 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6267 void *val = load_cattr_value (image, field->type, named, &named);
6268 mono_field_set_value (attr, field, val);
6269 if (!type_is_reference (field->type))
6271 } else if (named_type == 0x54) {
6274 MonoType *prop_type;
6276 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6277 /* can we have more that 1 arg in a custom attr named property? */
6278 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6279 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6280 mono_property_set_value (prop, attr, pparams, NULL);
6281 if (!type_is_reference (prop_type))
6282 g_free (pparams [0]);
6291 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6298 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6299 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6300 for (i = 0; i < cinfo->num_attrs; ++i) {
6301 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6302 mono_array_set (result, gpointer, i, attr);
6308 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6310 guint32 mtoken, i, len;
6311 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6313 MonoCustomAttrInfo *ainfo;
6314 GList *tmp, *list = NULL;
6317 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6319 i = mono_metadata_custom_attrs_from_index (image, idx);
6323 while (i < ca->rows) {
6324 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6326 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6329 len = g_list_length (list);
6332 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6333 ainfo->num_attrs = len;
6334 ainfo->image = image;
6335 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6336 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6337 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6338 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6339 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6340 mtoken |= MONO_TOKEN_METHOD_DEF;
6342 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6343 mtoken |= MONO_TOKEN_MEMBER_REF;
6346 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6349 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6350 if (!ainfo->attrs [i].ctor)
6351 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6352 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6353 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6354 ainfo->attrs [i].data = data;
6362 mono_custom_attrs_from_method (MonoMethod *method)
6364 MonoCustomAttrInfo *cinfo;
6367 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6369 idx = find_method_index (method);
6370 idx <<= MONO_CUSTOM_ATTR_BITS;
6371 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6372 return mono_custom_attrs_from_index (method->klass->image, idx);
6376 mono_custom_attrs_from_class (MonoClass *klass)
6378 MonoCustomAttrInfo *cinfo;
6381 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6383 idx = mono_metadata_token_index (klass->type_token);
6384 idx <<= MONO_CUSTOM_ATTR_BITS;
6385 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6386 return mono_custom_attrs_from_index (klass->image, idx);
6390 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6392 MonoCustomAttrInfo *cinfo;
6395 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6397 idx = 1; /* there is only one assembly */
6398 idx <<= MONO_CUSTOM_ATTR_BITS;
6399 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6400 return mono_custom_attrs_from_index (assembly->image, idx);
6403 static MonoCustomAttrInfo*
6404 mono_custom_attrs_from_module (MonoImage *image)
6406 MonoCustomAttrInfo *cinfo;
6409 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6411 idx = 1; /* there is only one module */
6412 idx <<= MONO_CUSTOM_ATTR_BITS;
6413 idx |= MONO_CUSTOM_ATTR_MODULE;
6414 return mono_custom_attrs_from_index (image, idx);
6418 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6420 MonoCustomAttrInfo *cinfo;
6423 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6425 idx = find_property_index (klass, property);
6426 idx <<= MONO_CUSTOM_ATTR_BITS;
6427 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6428 return mono_custom_attrs_from_index (klass->image, idx);
6432 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6434 MonoCustomAttrInfo *cinfo;
6437 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6439 idx = find_event_index (klass, event);
6440 idx <<= MONO_CUSTOM_ATTR_BITS;
6441 idx |= MONO_CUSTOM_ATTR_EVENT;
6442 return mono_custom_attrs_from_index (klass->image, idx);
6446 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6448 MonoCustomAttrInfo *cinfo;
6451 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6453 idx = find_field_index (klass, field);
6454 idx <<= MONO_CUSTOM_ATTR_BITS;
6455 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6456 return mono_custom_attrs_from_index (klass->image, idx);
6460 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6463 guint32 i, idx, method_index;
6464 guint32 param_list, param_last, param_pos, found;
6466 MonoReflectionMethodAux *aux;
6468 if (method->klass->image->dynamic) {
6469 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6470 if (!aux || !aux->param_cattr)
6472 return aux->param_cattr [param];
6475 image = method->klass->image;
6476 method_index = find_method_index (method);
6477 ca = &image->tables [MONO_TABLE_METHOD];
6479 if (method->klass->generic_inst || method->klass->gen_params ||
6480 method->signature->generic_param_count) {
6481 /* FIXME FIXME FIXME */
6485 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6486 if (method_index == ca->rows) {
6487 ca = &image->tables [MONO_TABLE_PARAM];
6488 param_last = ca->rows + 1;
6490 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6491 ca = &image->tables [MONO_TABLE_PARAM];
6494 for (i = param_list; i < param_last; ++i) {
6495 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6496 if (param_pos == param) {
6504 idx <<= MONO_CUSTOM_ATTR_BITS;
6505 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6506 return mono_custom_attrs_from_index (image, idx);
6510 * mono_reflection_get_custom_attrs:
6511 * @obj: a reflection object handle
6513 * Return an array with all the custom attributes defined of the
6514 * reflection handle @obj. The objects are fully build.
6517 mono_reflection_get_custom_attrs (MonoObject *obj)
6521 MonoCustomAttrInfo *cinfo = NULL;
6523 MONO_ARCH_SAVE_REGS;
6525 klass = obj->vtable->klass;
6526 /* FIXME: need to handle: Module */
6527 if (klass == mono_defaults.monotype_class) {
6528 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6529 klass = mono_class_from_mono_type (rtype->type);
6530 cinfo = mono_custom_attrs_from_class (klass);
6531 } else if (strcmp ("Assembly", klass->name) == 0) {
6532 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6533 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6534 } else if (strcmp ("Module", klass->name) == 0) {
6535 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6536 cinfo = mono_custom_attrs_from_module (module->image);
6537 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6538 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6539 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6540 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6541 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6542 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6543 } else if (strcmp ("MonoField", klass->name) == 0) {
6544 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6545 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6546 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6547 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6548 cinfo = mono_custom_attrs_from_method (rmethod->method);
6549 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6550 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6551 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6552 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6553 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6554 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6555 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6556 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6557 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6558 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6559 } else { /* handle other types here... */
6560 g_error ("get custom attrs not yet supported for %s", klass->name);
6564 result = mono_custom_attrs_construct (cinfo);
6566 mono_custom_attrs_free (cinfo);
6568 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6569 result = mono_array_new (mono_domain_get (), klass, 0);
6575 static MonoMethodSignature*
6576 parameters_to_signature (MonoArray *parameters) {
6577 MonoMethodSignature *sig;
6580 count = parameters? mono_array_length (parameters): 0;
6582 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6583 sig->param_count = count;
6584 sig->sentinelpos = -1; /* FIXME */
6585 for (i = 0; i < count; ++i) {
6586 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6587 sig->params [i] = pt->type;
6592 static MonoMethodSignature*
6593 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6594 MonoMethodSignature *sig;
6596 sig = parameters_to_signature (ctor->parameters);
6597 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6598 sig->ret = &mono_defaults.void_class->byval_arg;
6602 static MonoMethodSignature*
6603 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6604 MonoMethodSignature *sig;
6606 sig = parameters_to_signature (method->parameters);
6607 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6608 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6609 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6613 static MonoMethodSignature*
6614 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6615 MonoMethodSignature *sig;
6617 sig = parameters_to_signature (method->parameters);
6618 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6619 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6620 sig->generic_param_count = 0;
6625 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6627 MonoClass *klass = mono_object_class (prop);
6628 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6629 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6630 *name = mono_string_to_utf8 (pb->name);
6631 *type = pb->type->type;
6633 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6634 *name = g_strdup (p->property->name);
6635 if (p->property->get)
6636 *type = p->property->get->signature->ret;
6638 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6643 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6645 MonoClass *klass = mono_object_class (field);
6646 if (strcmp (klass->name, "FieldBuilder") == 0) {
6647 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6648 *name = mono_string_to_utf8 (fb->name);
6649 *type = fb->type->type;
6651 MonoReflectionField *f = (MonoReflectionField *)field;
6652 *name = g_strdup (f->field->name);
6653 *type = f->field->type;
6658 * Encode a value in a custom attribute stream of bytes.
6659 * The value to encode is either supplied as an object in argument val
6660 * (valuetypes are boxed), or as a pointer to the data in the
6662 * @type represents the type of the value
6663 * @buffer is the start of the buffer
6664 * @p the current position in the buffer
6665 * @buflen contains the size of the buffer and is used to return the new buffer size
6666 * if this needs to be realloced.
6667 * @retbuffer and @retp return the start and the position of the buffer
6670 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6672 MonoTypeEnum simple_type;
6674 if ((p-buffer) + 10 >= *buflen) {
6677 newbuf = g_realloc (buffer, *buflen);
6678 p = newbuf + (p-buffer);
6682 argval = ((char*)arg + sizeof (MonoObject));
6683 simple_type = type->type;
6685 switch (simple_type) {
6686 case MONO_TYPE_BOOLEAN:
6691 case MONO_TYPE_CHAR:
6694 swap_with_size (p, argval, 2, 1);
6700 swap_with_size (p, argval, 4, 1);
6706 swap_with_size (p, argval, 8, 1);
6709 case MONO_TYPE_VALUETYPE:
6710 if (type->data.klass->enumtype) {
6711 simple_type = type->data.klass->enum_basetype->type;
6714 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6717 case MONO_TYPE_STRING: {
6724 str = mono_string_to_utf8 ((MonoString*)arg);
6725 slen = strlen (str);
6726 if ((p-buffer) + 10 + slen >= *buflen) {
6730 newbuf = g_realloc (buffer, *buflen);
6731 p = newbuf + (p-buffer);
6734 mono_metadata_encode_value (slen, p, &p);
6735 memcpy (p, str, slen);
6740 case MONO_TYPE_CLASS: {
6748 k = mono_object_class (arg);
6749 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6750 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6751 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6753 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6754 slen = strlen (str);
6755 if ((p-buffer) + 10 + slen >= *buflen) {
6759 newbuf = g_realloc (buffer, *buflen);
6760 p = newbuf + (p-buffer);
6763 mono_metadata_encode_value (slen, p, &p);
6764 memcpy (p, str, slen);
6769 case MONO_TYPE_SZARRAY: {
6771 MonoClass *eclass, *arg_eclass;
6774 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6777 len = mono_array_length ((MonoArray*)arg);
6779 *p++ = (len >> 8) & 0xff;
6780 *p++ = (len >> 16) & 0xff;
6781 *p++ = (len >> 24) & 0xff;
6783 *retbuffer = buffer;
6784 eclass = type->data.klass;
6785 arg_eclass = mono_object_class (arg)->element_class;
6786 if (eclass->valuetype && arg_eclass->valuetype) {
6787 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6788 int elsize = mono_class_array_element_size (eclass);
6789 for (i = 0; i < len; ++i) {
6790 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6794 for (i = 0; i < len; ++i) {
6795 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6800 /* it may be a boxed value or a Type */
6801 case MONO_TYPE_OBJECT: {
6802 MonoClass *klass = mono_object_class (arg);
6806 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6809 } else if (klass->enumtype) {
6811 } else if (klass == mono_defaults.string_class) {
6812 simple_type = MONO_TYPE_STRING;
6815 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6816 *p++ = simple_type = klass->byval_arg.type;
6819 g_error ("unhandled type in custom attr");
6821 str = type_get_qualified_name (klass->enum_basetype, NULL);
6822 slen = strlen (str);
6823 if ((p-buffer) + 10 + slen >= *buflen) {
6827 newbuf = g_realloc (buffer, *buflen);
6828 p = newbuf + (p-buffer);
6831 mono_metadata_encode_value (slen, p, &p);
6832 memcpy (p, str, slen);
6835 simple_type = klass->enum_basetype->type;
6839 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6842 *retbuffer = buffer;
6846 * mono_reflection_get_custom_attrs_blob:
6847 * @ctor: custom attribute constructor
6848 * @ctorArgs: arguments o the constructor
6854 * Creates the blob of data that needs to be saved in the metadata and that represents
6855 * the custom attributed described by @ctor, @ctorArgs etc.
6856 * Returns: a Byte array representing the blob of data.
6859 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6862 MonoMethodSignature *sig;
6867 MONO_ARCH_SAVE_REGS;
6869 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6870 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6872 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6874 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6876 p = buffer = g_malloc (buflen);
6877 /* write the prolog */
6880 for (i = 0; i < sig->param_count; ++i) {
6881 arg = mono_array_get (ctorArgs, MonoObject*, i);
6882 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6886 i += mono_array_length (properties);
6888 i += mono_array_length (fields);
6890 *p++ = (i >> 8) & 0xff;
6893 for (i = 0; i < mono_array_length (properties); ++i) {
6898 prop = mono_array_get (properties, gpointer, i);
6899 get_prop_name_and_type (prop, &pname, &ptype);
6900 *p++ = 0x54; /* PROPERTY signature */
6902 /* Preallocate a large enough buffer */
6903 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6904 char *str = type_get_qualified_name (ptype, NULL);
6910 len += strlen (pname);
6912 if ((p-buffer) + 20 + len >= buflen) {
6916 newbuf = g_realloc (buffer, buflen);
6917 p = newbuf + (p-buffer);
6921 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6922 char *str = type_get_qualified_name (ptype, NULL);
6923 int slen = strlen (str);
6927 * This seems to be optional...
6930 mono_metadata_encode_value (slen, p, &p);
6931 memcpy (p, str, slen);
6935 mono_metadata_encode_value (ptype->type, p, &p);
6936 if (ptype->type == MONO_TYPE_SZARRAY)
6937 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6939 len = strlen (pname);
6940 mono_metadata_encode_value (len, p, &p);
6941 memcpy (p, pname, len);
6943 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6950 for (i = 0; i < mono_array_length (fields); ++i) {
6955 field = mono_array_get (fields, gpointer, i);
6956 get_field_name_and_type (field, &fname, &ftype);
6957 *p++ = 0x53; /* FIELD signature */
6958 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6959 char *str = type_get_qualified_name (ftype, NULL);
6960 int slen = strlen (str);
6961 if ((p-buffer) + 10 + slen >= buflen) {
6965 newbuf = g_realloc (buffer, buflen);
6966 p = newbuf + (p-buffer);
6971 * This seems to be optional...
6974 mono_metadata_encode_value (slen, p, &p);
6975 memcpy (p, str, slen);
6979 mono_metadata_encode_value (ftype->type, p, &p);
6980 if (ftype->type == MONO_TYPE_SZARRAY)
6981 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6983 len = strlen (fname);
6984 mono_metadata_encode_value (len, p, &p);
6985 memcpy (p, fname, len);
6987 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6992 g_assert (p - buffer <= buflen);
6993 buflen = p - buffer;
6994 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6995 p = mono_array_addr (result, char, 0);
6996 memcpy (p, buffer, buflen);
6998 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7004 * mono_reflection_setup_internal_class:
7005 * @tb: a TypeBuilder object
7007 * Creates a MonoClass that represents the TypeBuilder.
7008 * This is a trick that lets us simplify a lot of reflection code
7009 * (and will allow us to support Build and Run assemblies easier).
7012 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7014 MonoClass *klass, *parent;
7016 MONO_ARCH_SAVE_REGS;
7019 /* check so we can compile corlib correctly */
7020 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7021 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7022 parent = tb->parent->type->data.klass;
7024 parent = my_mono_class_from_mono_type (tb->parent->type);
7028 /* the type has already being created: it means we just have to change the parent */
7029 if (tb->type.type) {
7030 klass = mono_class_from_mono_type (tb->type.type);
7031 klass->parent = NULL;
7032 /* fool mono_class_setup_parent */
7033 g_free (klass->supertypes);
7034 klass->supertypes = NULL;
7035 mono_class_setup_parent (klass, parent);
7036 mono_class_setup_mono_type (klass);
7040 klass = g_new0 (MonoClass, 1);
7042 klass->image = &tb->module->dynamic_image->image;
7044 klass->inited = 1; /* we lie to the runtime */
7045 klass->name = mono_string_to_utf8 (tb->name);
7046 klass->name_space = mono_string_to_utf8 (tb->nspace);
7047 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7048 klass->flags = tb->attrs;
7050 klass->element_class = klass;
7051 klass->reflection_info = tb; /* need to pin. */
7053 /* Put into cache so mono_class_get () will find it */
7054 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
7057 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7058 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
7062 mono_class_setup_parent (klass, parent);
7063 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7064 const char *old_n = klass->name;
7065 /* trick to get relative numbering right when compiling corlib */
7066 klass->name = "BuildingObject";
7067 mono_class_setup_parent (klass, mono_defaults.object_class);
7068 klass->name = old_n;
7070 mono_class_setup_mono_type (klass);
7072 mono_class_setup_supertypes (klass);
7075 * FIXME: handle interfaces.
7078 tb->type.type = &klass->byval_arg;
7080 if (tb->nesting_type) {
7081 g_assert (tb->nesting_type->type);
7082 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7085 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7089 * mono_reflection_setup_generic_class:
7090 * @tb: a TypeBuilder object
7092 * Setup the generic class after all generic parameters have been added.
7095 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7100 MONO_ARCH_SAVE_REGS;
7102 klass = my_mono_class_from_mono_type (tb->type.type);
7104 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7106 if (klass->gen_params || (count == 0))
7109 klass->num_gen_params = count;
7110 klass->gen_params = g_new0 (MonoGenericParam, count);
7112 for (i = 0; i < count; i++) {
7113 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7114 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7119 * mono_reflection_create_internal_class:
7120 * @tb: a TypeBuilder object
7122 * Actually create the MonoClass that is associated with the TypeBuilder.
7125 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7129 MONO_ARCH_SAVE_REGS;
7131 klass = my_mono_class_from_mono_type (tb->type.type);
7133 if (klass->enumtype && klass->enum_basetype == NULL) {
7134 MonoReflectionFieldBuilder *fb;
7136 g_assert (tb->fields != NULL);
7137 g_assert (mono_array_length (tb->fields) >= 1);
7139 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7141 klass->enum_basetype = fb->type->type;
7142 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7143 if (!klass->element_class)
7144 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7145 klass->instance_size = klass->element_class->instance_size;
7146 klass->size_inited = 1;
7148 * this is almost safe to do with enums and it's needed to be able
7149 * to create objects of the enum type (for use in SetConstant).
7151 /* FIXME: Does this mean enums can't have method overrides ? */
7152 mono_class_setup_vtable (klass, NULL, 0);
7156 static MonoMarshalSpec*
7157 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7158 MonoReflectionMarshal *minfo)
7160 MonoMarshalSpec *res;
7162 res = g_new0 (MonoMarshalSpec, 1);
7163 res->native = minfo->type;
7165 switch (minfo->type) {
7166 case MONO_NATIVE_LPARRAY:
7167 res->data.array_data.elem_type = minfo->eltype;
7168 res->data.array_data.param_num = 0; /* Not yet */
7169 res->data.array_data.num_elem = minfo->count;
7172 case MONO_NATIVE_BYVALTSTR:
7173 case MONO_NATIVE_BYVALARRAY:
7174 res->data.array_data.num_elem = minfo->count;
7177 case MONO_NATIVE_CUSTOM:
7178 if (minfo->marshaltyperef)
7179 res->data.custom_data.custom_name =
7180 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7182 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7193 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7194 ReflectionMethodBuilder *rmb,
7195 MonoMethodSignature *sig)
7198 MonoMethodNormal *pm;
7199 MonoMarshalSpec **specs;
7200 MonoReflectionMethodAux *method_aux;
7203 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7204 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7205 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7208 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7210 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7212 pm = (MonoMethodNormal*)m;
7215 m->flags = rmb->attrs;
7216 m->iflags = rmb->iattrs;
7217 m->name = mono_string_to_utf8 (rmb->name);
7221 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7223 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7224 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7227 m->signature->pinvoke = 1;
7228 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7229 m->signature->pinvoke = 1;
7231 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7233 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7234 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7236 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7238 if (klass->image->dynamic)
7239 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7242 } else if (!m->klass->dummy &&
7243 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7244 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7245 MonoMethodHeader *header;
7247 gint32 max_stack, i;
7248 gint32 num_locals = 0;
7249 gint32 num_clauses = 0;
7253 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7254 code_size = rmb->ilgen->code_len;
7255 max_stack = rmb->ilgen->max_stack;
7256 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7257 if (rmb->ilgen->ex_handlers)
7258 num_clauses = method_count_clauses (rmb->ilgen);
7261 code = mono_array_addr (rmb->code, guint8, 0);
7262 code_size = mono_array_length (rmb->code);
7263 /* we probably need to run a verifier on the code... */
7273 header = g_malloc0 (sizeof (MonoMethodHeader) +
7274 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7275 header->code_size = code_size;
7276 header->code = g_malloc (code_size);
7277 memcpy ((char*)header->code, code, code_size);
7278 header->max_stack = max_stack;
7279 header->init_locals = rmb->init_locals;
7280 header->num_locals = num_locals;
7282 for (i = 0; i < num_locals; ++i) {
7283 MonoReflectionLocalBuilder *lb =
7284 mono_array_get (rmb->ilgen->locals,
7285 MonoReflectionLocalBuilder*, i);
7287 header->locals [i] = g_new0 (MonoType, 1);
7288 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7291 header->num_clauses = num_clauses;
7293 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7298 pm->header = header;
7301 if (rmb->generic_params) {
7302 int count = mono_array_length (rmb->generic_params);
7303 pm->gen_params = g_new0 (MonoGenericParam, count);
7304 for (i = 0; i < count; i++) {
7305 MonoReflectionGenericParam *gp =
7306 mono_array_get (rmb->generic_params,
7307 MonoReflectionGenericParam*, i);
7309 pm->gen_params [i] = *gp->type.type->data.generic_param;
7314 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7317 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7319 for (i = 0; i < rmb->nrefs; ++i)
7320 mw->data = g_list_append (mw->data, rmb->refs [i]);
7325 /* Parameter names */
7328 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7329 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7330 for (i = 0; i <= m->signature->param_count; ++i) {
7331 MonoReflectionParamBuilder *pb;
7332 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7334 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7336 if (!method_aux->param_cattr)
7337 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7338 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7344 /* Parameter marshalling */
7347 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7348 MonoReflectionParamBuilder *pb;
7349 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7350 if (pb->marshal_info) {
7352 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7353 specs [pb->position] =
7354 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7358 if (specs != NULL) {
7360 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7361 method_aux->param_marshall = specs;
7364 if (klass->image->dynamic && method_aux)
7365 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7371 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7373 ReflectionMethodBuilder rmb;
7374 MonoMethodSignature *sig;
7376 sig = ctor_builder_to_signature (mb);
7378 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7380 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7381 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7383 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7384 /* ilgen is no longer needed */
7392 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7394 ReflectionMethodBuilder rmb;
7395 MonoMethodSignature *sig;
7397 sig = method_builder_to_signature (mb);
7399 reflection_methodbuilder_from_method_builder (&rmb, mb);
7401 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7402 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7404 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7405 /* ilgen is no longer needed */
7411 static MonoClassField*
7412 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7414 MonoClassField *field;
7421 field = g_new0 (MonoClassField, 1);
7423 field->name = mono_string_to_utf8 (fb->name);
7425 /* FIXME: handle type modifiers */
7426 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7427 field->type->attrs = fb->attrs;
7429 field->type = fb->type->type;
7431 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7432 field->data = mono_array_addr (fb->rva_data, char, 0);
7433 if (fb->offset != -1)
7434 field->offset = fb->offset;
7435 field->parent = klass;
7437 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7439 if (fb->def_value) {
7440 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7441 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7442 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7443 /* Copy the data from the blob since it might get realloc-ed */
7444 p = assembly->blob.data + idx;
7445 len = mono_metadata_decode_blob_size (p, &p2);
7447 field->data = g_malloc (len);
7448 memcpy ((gpointer)field->data, p, len);
7455 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7459 MonoReflectionTypeBuilder *tb = NULL;
7460 MonoGenericInst *ginst, *cached;
7465 klass = mono_class_from_mono_type (type->type);
7466 if (!klass->gen_params && !klass->generic_inst &&
7467 !(klass->nested_in && klass->nested_in->gen_params))
7470 mono_loader_lock ();
7472 domain = mono_object_domain (type);
7474 ginst = g_new0 (MonoGenericInst, 1);
7476 if (!klass->generic_inst) {
7477 ginst->type_argc = type_argc;
7478 ginst->type_argv = types;
7480 for (i = 0; i < ginst->type_argc; ++i) {
7481 if (!ginst->is_open)
7482 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7485 ginst->generic_type = &klass->byval_arg;
7487 MonoGenericInst *kginst = klass->generic_inst;
7489 ginst->type_argc = kginst->type_argc;
7490 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7492 for (i = 0; i < ginst->type_argc; i++) {
7493 MonoType *t = kginst->type_argv [i];
7495 if (t->type == MONO_TYPE_VAR)
7496 t = types [t->data.generic_param->num];
7498 if (!ginst->is_open)
7499 ginst->is_open = mono_class_is_open_constructed_type (t);
7501 ginst->type_argv [i] = t;
7504 ginst->generic_type = kginst->generic_type;
7507 geninst = g_new0 (MonoType, 1);
7508 geninst->type = MONO_TYPE_GENERICINST;
7510 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7513 mono_loader_unlock ();
7514 geninst->data.generic_inst = cached;
7518 geninst->data.generic_inst = ginst;
7520 ginst->context = g_new0 (MonoGenericContext, 1);
7521 ginst->context->ginst = ginst;
7523 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7524 tb = (MonoReflectionTypeBuilder *) type;
7526 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7527 ginst->is_dynamic = TRUE;
7528 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7529 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7530 MonoReflectionType *rgt = rgi->generic_type;
7532 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7533 tb = (MonoReflectionTypeBuilder *) rgt;
7535 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7536 ginst->is_dynamic = TRUE;
7538 icount = klass->interface_count;
7540 ginst->ifaces = g_new0 (MonoType *, icount);
7541 ginst->count_ifaces = icount;
7543 for (i = 0; i < icount; i++) {
7544 MonoReflectionType *itype;
7547 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7549 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7550 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7551 if (!ginst->ifaces [i])
7552 ginst->ifaces [i] = itype->type;
7555 mono_class_create_generic (ginst);
7557 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7559 mono_loader_unlock ();
7565 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7567 MonoClass *klass, *pklass = NULL;
7568 MonoReflectionType *parent = NULL;
7570 MonoReflectionTypeBuilder *tb = NULL;
7571 MonoGenericInst *ginst;
7574 domain = mono_object_domain (type);
7575 klass = mono_class_from_mono_type (type->type);
7577 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7578 tb = (MonoReflectionTypeBuilder *) type;
7581 parent = tb->parent;
7582 pklass = mono_class_from_mono_type (parent->type);
7585 pklass = klass->parent;
7587 parent = mono_type_get_object (domain, &pklass->byval_arg);
7590 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7594 ginst = geninst->data.generic_inst;
7596 if (pklass && pklass->generic_inst)
7597 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7602 MonoReflectionMethod*
7603 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7605 MonoMethod *method, *inflated;
7606 MonoReflectionMethodBuilder *mb = NULL;
7607 MonoGenericMethod *gmethod;
7608 MonoGenericContext *context;
7611 MONO_ARCH_SAVE_REGS;
7612 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7613 MonoReflectionTypeBuilder *tb;
7616 mb = (MonoReflectionMethodBuilder *) rmethod;
7617 tb = (MonoReflectionTypeBuilder *) mb->type;
7618 klass = mono_class_from_mono_type (tb->type.type);
7620 method = methodbuilder_to_mono_method (klass, mb);
7622 method = rmethod->method;
7624 count = method->signature->generic_param_count;
7625 if (count != mono_array_length (types))
7628 gmethod = g_new0 (MonoGenericMethod, 1);
7629 gmethod->mtype_argc = count;
7630 gmethod->mtype_argv = g_new0 (MonoType *, count);
7631 for (i = 0; i < count; i++) {
7632 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7633 gmethod->mtype_argv [i] = garg->type;
7636 gmethod->reflection_info = rmethod;
7638 context = g_new0 (MonoGenericContext, 1);
7639 context->ginst = method->klass->generic_inst;
7640 context->gmethod = gmethod;
7642 inflated = mono_class_inflate_generic_method (method, context, NULL);
7644 return mono_method_get_object (
7645 mono_object_domain (rmethod), inflated, NULL);
7649 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7651 MonoGenericMethod *gmethod;
7652 MonoGenericInst *ginst;
7653 MonoGenericContext *context;
7656 ginst = type->type.type->data.generic_inst;
7658 gmethod = g_new0 (MonoGenericMethod, 1);
7659 gmethod->reflection_info = obj;
7661 gmethod->mtype_argc = method->signature->generic_param_count;
7662 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7664 for (i = 0; i < gmethod->mtype_argc; i++) {
7665 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7666 MonoGenericParam *gparam = &mn->gen_params [i];
7668 g_assert (gparam->pklass);
7669 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7672 context = g_new0 (MonoGenericContext, 1);
7673 context->ginst = ginst;
7674 context->gmethod = gmethod;
7676 return mono_class_inflate_generic_method (method, context, ginst->klass);
7680 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7685 klass = mono_class_from_mono_type (type->type.type);
7687 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7688 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7689 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7690 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7691 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7692 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7693 method = ((MonoReflectionMethod *) obj)->method;
7695 method = NULL; /* prevent compiler warning */
7696 g_assert_not_reached ();
7699 return inflate_mono_method (type, method, obj);
7703 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7704 MonoArray *methods, MonoArray *ctors,
7705 MonoArray *fields, MonoArray *properties,
7708 MonoGenericInst *ginst;
7709 MonoDynamicGenericInst *dginst;
7710 MonoClass *klass, *gklass, *pklass;
7713 MONO_ARCH_SAVE_REGS;
7715 klass = mono_class_from_mono_type (type->type.type);
7716 ginst = type->type.type->data.generic_inst;
7718 if (ginst->initialized)
7721 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7723 gklass = mono_class_from_mono_type (ginst->generic_type);
7724 mono_class_init (gklass);
7727 pklass = mono_class_from_mono_type (ginst->parent);
7729 pklass = gklass->parent;
7731 mono_class_setup_parent (klass, pklass);
7733 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7734 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7735 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7736 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7737 dginst->count_events = events ? mono_array_length (events) : 0;
7739 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7740 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7741 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7742 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7743 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7745 for (i = 0; i < dginst->count_methods; i++) {
7746 MonoObject *obj = mono_array_get (methods, gpointer, i);
7748 dginst->methods [i] = inflate_method (type, obj);
7751 for (i = 0; i < dginst->count_ctors; i++) {
7752 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7754 dginst->ctors [i] = inflate_method (type, obj);
7757 for (i = 0; i < dginst->count_fields; i++) {
7758 MonoObject *obj = mono_array_get (fields, gpointer, i);
7759 MonoClassField *field;
7760 MonoInflatedField *ifield;
7762 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7763 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7764 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7765 field = ((MonoReflectionField *) obj)->field;
7767 field = NULL; /* prevent compiler warning */
7768 g_assert_not_reached ();
7771 ifield = g_new0 (MonoInflatedField, 1);
7772 ifield->generic_type = field->type;
7773 ifield->reflection_info = obj;
7775 dginst->fields [i] = *field;
7776 dginst->fields [i].generic_info = ifield;
7777 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7780 for (i = 0; i < dginst->count_properties; i++) {
7781 MonoObject *obj = mono_array_get (properties, gpointer, i);
7782 MonoProperty *property = &dginst->properties [i];
7784 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7785 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7787 property->parent = klass;
7788 property->attrs = pb->attrs;
7789 property->name = mono_string_to_utf8 (pb->name);
7791 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7793 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7794 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7795 *property = *((MonoReflectionProperty *) obj)->property;
7798 property->get = inflate_mono_method (type, property->get, NULL);
7800 property->set = inflate_mono_method (type, property->set, NULL);
7802 g_assert_not_reached ();
7805 for (i = 0; i < dginst->count_events; i++) {
7806 MonoObject *obj = mono_array_get (events, gpointer, i);
7807 MonoEvent *event = &dginst->events [i];
7809 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7810 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7812 event->parent = klass;
7813 event->attrs = eb->attrs;
7814 event->name = mono_string_to_utf8 (eb->name);
7816 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7817 if (eb->remove_method)
7818 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7819 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7820 *event = *((MonoReflectionEvent *) obj)->event;
7823 event->add = inflate_mono_method (type, event->add, NULL);
7825 event->remove = inflate_mono_method (type, event->remove, NULL);
7827 g_assert_not_reached ();
7830 ginst->initialized = TRUE;
7834 ensure_runtime_vtable (MonoClass *klass)
7836 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7837 int i, num, j, onum;
7838 MonoMethod **overrides;
7840 if (!tb || klass->wastypebuilder)
7843 ensure_runtime_vtable (klass->parent);
7845 num = tb->ctors? mono_array_length (tb->ctors): 0;
7846 num += tb->num_methods;
7847 klass->method.count = num;
7848 klass->methods = g_new (MonoMethod*, num);
7849 num = tb->ctors? mono_array_length (tb->ctors): 0;
7850 for (i = 0; i < num; ++i)
7851 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7852 num = tb->num_methods;
7854 for (i = 0; i < num; ++i)
7855 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7857 klass->wastypebuilder = TRUE;
7858 if (tb->interfaces) {
7859 klass->interface_count = mono_array_length (tb->interfaces);
7860 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7861 for (i = 0; i < klass->interface_count; ++i) {
7862 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7863 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7867 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7868 for (i = 0; i < klass->method.count; ++i)
7869 klass->methods [i]->slot = i;
7874 for (i = 0; i < tb->num_methods; ++i) {
7875 MonoReflectionMethodBuilder *mb =
7876 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7877 if (mb->override_method)
7882 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7886 for (i = 0; i < tb->num_methods; ++i) {
7887 MonoReflectionMethodBuilder *mb =
7888 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7889 if (mb->override_method) {
7890 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7891 overrides [onum * 2] =
7892 mb->override_method->method;
7893 overrides [onum * 2 + 1] =
7896 g_assert (mb->mhandle);
7903 mono_class_setup_vtable (klass, overrides, onum);
7907 typebuilder_setup_fields (MonoClass *klass)
7909 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7910 MonoReflectionFieldBuilder *fb;
7911 MonoClassField *field;
7916 klass->field.count = tb->num_fields;
7917 klass->field.first = 0;
7918 klass->field.last = klass->field.count;
7920 if (!klass->field.count)
7923 klass->fields = g_new0 (MonoClassField, klass->field.count);
7925 for (i = 0; i < klass->field.count; ++i) {
7926 fb = mono_array_get (tb->fields, gpointer, i);
7927 field = &klass->fields [i];
7928 field->name = mono_string_to_utf8 (fb->name);
7930 /* FIXME: handle type modifiers */
7931 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7932 field->type->attrs = fb->attrs;
7934 field->type = fb->type->type;
7936 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7937 field->data = mono_array_addr (fb->rva_data, char, 0);
7938 if (fb->offset != -1)
7939 field->offset = fb->offset;
7940 field->parent = klass;
7942 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7944 if (fb->def_value) {
7945 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7946 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7947 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7948 /* Copy the data from the blob since it might get realloc-ed */
7949 p = assembly->blob.data + idx;
7950 len = mono_metadata_decode_blob_size (p, &p2);
7952 field->data = g_malloc (len);
7953 memcpy ((gpointer)field->data, p, len);
7956 mono_class_layout_fields (klass);
7960 typebuilder_setup_properties (MonoClass *klass)
7962 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7963 MonoReflectionPropertyBuilder *pb;
7966 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7967 klass->property.first = 0;
7968 klass->property.last = klass->property.count;
7970 klass->properties = g_new0 (MonoProperty, klass->property.count);
7971 for (i = 0; i < klass->property.count; ++i) {
7972 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7973 klass->properties [i].parent = klass;
7974 klass->properties [i].attrs = pb->attrs;
7975 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7977 klass->properties [i].get = pb->get_method->mhandle;
7979 klass->properties [i].set = pb->set_method->mhandle;
7983 MonoReflectionEvent *
7984 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7986 MonoEvent *event = g_new0 (MonoEvent, 1);
7990 klass = my_mono_class_from_mono_type (tb->type.type);
7992 event->parent = klass;
7993 event->attrs = eb->attrs;
7994 event->name = mono_string_to_utf8 (eb->name);
7996 event->add = eb->add_method->mhandle;
7997 if (eb->remove_method)
7998 event->remove = eb->remove_method->mhandle;
7999 if (eb->raise_method)
8000 event->raise = eb->raise_method->mhandle;
8002 if (eb->other_methods) {
8003 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8004 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8005 MonoReflectionMethodBuilder *mb =
8006 mono_array_get (eb->other_methods,
8007 MonoReflectionMethodBuilder*, j);
8008 event->other [j] = mb->mhandle;
8012 return mono_event_get_object (mono_object_domain (tb), klass, event);
8016 typebuilder_setup_events (MonoClass *klass)
8018 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8019 MonoReflectionEventBuilder *eb;
8022 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8023 klass->event.first = 0;
8024 klass->event.last = klass->event.count;
8026 klass->events = g_new0 (MonoEvent, klass->event.count);
8027 for (i = 0; i < klass->event.count; ++i) {
8028 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8029 klass->events [i].parent = klass;
8030 klass->events [i].attrs = eb->attrs;
8031 klass->events [i].name = mono_string_to_utf8 (eb->name);
8033 klass->events [i].add = eb->add_method->mhandle;
8034 if (eb->remove_method)
8035 klass->events [i].remove = eb->remove_method->mhandle;
8036 if (eb->raise_method)
8037 klass->events [i].raise = eb->raise_method->mhandle;
8039 if (eb->other_methods) {
8040 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8041 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8042 MonoReflectionMethodBuilder *mb =
8043 mono_array_get (eb->other_methods,
8044 MonoReflectionMethodBuilder*, j);
8045 klass->events [i].other [j] = mb->mhandle;
8052 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8055 MonoReflectionType* res;
8058 MONO_ARCH_SAVE_REGS;
8060 klass = my_mono_class_from_mono_type (tb->type.type);
8062 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8065 * Fields to set in klass:
8066 * the various flags: delegate/unicode/contextbound etc.
8068 klass->flags = tb->attrs;
8070 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8071 /* No need to fully construct the type */
8072 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8074 /* enums are done right away */
8075 if (!klass->enumtype)
8076 ensure_runtime_vtable (klass);
8079 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8080 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8081 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8085 /* fields and object layout */
8086 if (klass->parent) {
8087 if (!klass->parent->size_inited)
8088 mono_class_init (klass->parent);
8089 klass->instance_size += klass->parent->instance_size;
8090 klass->class_size += klass->parent->class_size;
8091 klass->min_align = klass->parent->min_align;
8093 klass->instance_size = sizeof (MonoObject);
8094 klass->min_align = 1;
8097 /* FIXME: handle packing_size and instance_size */
8098 typebuilder_setup_fields (klass);
8100 typebuilder_setup_properties (klass);
8102 typebuilder_setup_events (klass);
8104 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8105 /* with enums res == tb: need to fix that. */
8106 if (!klass->enumtype)
8107 g_assert (res != (MonoReflectionType*)tb);
8112 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8114 MonoGenericParam *param;
8117 MONO_ARCH_SAVE_REGS;
8119 param = g_new0 (MonoGenericParam, 1);
8121 param->method = NULL;
8122 param->name = mono_string_to_utf8 (gparam->name);
8123 param->num = gparam->index;
8125 image = &gparam->tbuilder->module->dynamic_image->image;
8126 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8128 param->pklass->reflection_info = gparam;
8130 gparam->type.type = g_new0 (MonoType, 1);
8131 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8132 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8133 gparam->type.type->data.generic_param = param;
8137 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8139 MonoDynamicImage *assembly = sig->module->dynamic_image;
8140 guint32 na = mono_array_length (sig->arguments);
8145 MONO_ARCH_SAVE_REGS;
8147 p = buf = g_malloc (10 + na * 10);
8149 mono_metadata_encode_value (0x07, p, &p);
8150 mono_metadata_encode_value (na, p, &p);
8151 for (i = 0; i < na; ++i) {
8152 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8153 encode_reflection_type (assembly, type, p, &p);
8157 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8158 p = mono_array_addr (result, char, 0);
8159 memcpy (p, buf, buflen);
8166 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8168 MonoDynamicImage *assembly = sig->module->dynamic_image;
8169 guint32 na = mono_array_length (sig->arguments);
8174 MONO_ARCH_SAVE_REGS;
8176 p = buf = g_malloc (10 + na * 10);
8178 mono_metadata_encode_value (0x06, p, &p);
8179 for (i = 0; i < na; ++i) {
8180 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8181 encode_reflection_type (assembly, type, p, &p);
8185 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8186 p = mono_array_addr (result, char, 0);
8187 memcpy (p, buf, buflen);
8194 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8196 ReflectionMethodBuilder rmb;
8197 MonoMethodSignature *sig;
8200 sig = dynamic_method_to_signature (mb);
8202 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8205 * Resolve references.
8207 rmb.nrefs = mb->nrefs;
8208 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8209 for (i = 0; i < mb->nrefs; ++i) {
8210 gpointer ref = resolve_object (mb->module->image,
8211 mono_array_get (mb->refs, MonoObject*, i));
8214 mono_raise_exception (mono_get_exception_type_load (NULL));
8221 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8225 /* ilgen is no longer needed */
8230 * mono_reflection_lookup_dynamic_token:
8232 * Finish the Builder object pointed to by TOKEN and return the corresponding
8233 * runtime structure.
8236 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8238 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8241 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8244 return resolve_object (image, obj);
8248 resolve_object (MonoImage *image, MonoObject *obj)
8250 gpointer result = NULL;
8252 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8253 result = mono_string_intern ((MonoString*)obj);
8256 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8257 MonoReflectionType *tb = (MonoReflectionType*)obj;
8258 result = mono_class_from_mono_type (tb->type);
8261 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8262 result = ((MonoReflectionMethod*)obj)->method;
8265 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8266 result = ((MonoReflectionMethod*)obj)->method;
8269 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8270 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8271 result = mb->mhandle;
8273 /* Type is not yet created */
8274 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8276 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8279 * Hopefully this has been filled in by calling CreateType() on the
8283 * TODO: This won't work if the application finishes another
8284 * TypeBuilder instance instead of this one.
8286 result = mb->mhandle;
8289 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8290 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8292 result = cb->mhandle;
8294 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8296 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8297 result = cb->mhandle;
8300 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8301 result = ((MonoReflectionField*)obj)->field;
8304 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8305 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8306 result = fb->handle;
8309 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8311 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8312 result = fb->handle;
8315 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8319 klass = tb->type.type->data.klass;
8320 if (klass->wastypebuilder) {
8321 /* Already created */
8325 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8326 result = tb->type.type->data.klass;
8330 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8331 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8332 MonoMethodSignature *sig;
8335 if (helper->arguments)
8336 nargs = mono_array_length (helper->arguments);
8340 sig = mono_metadata_signature_alloc (image, nargs);
8341 sig->explicit_this = helper->call_conv & 64;
8342 sig->hasthis = helper->call_conv & 32;
8344 if (helper->call_conv == 0) /* unmanaged */
8345 sig->call_convention = helper->unmanaged_call_conv - 1;
8347 if (helper->call_conv & 0x02)
8348 sig->call_convention = MONO_CALL_VARARG;
8350 sig->call_convention = MONO_CALL_DEFAULT;
8352 sig->param_count = nargs;
8353 /* TODO: Copy type ? */
8354 sig->ret = helper->return_type->type;
8355 for (i = 0; i < nargs; ++i) {
8356 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8357 sig->params [i] = rt->type;
8363 g_print (obj->vtable->klass->name);
8364 g_assert_not_reached ();