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;
5336 static MonoClassField *dbnull_value_field;
5338 MonoArray *res = NULL;
5339 MonoReflectionMethod *member = NULL;
5340 MonoReflectionParameter *param = NULL;
5344 if (!dbnull_value_field) {
5345 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5346 mono_class_init (klass);
5347 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5348 g_assert (dbnull_value_field);
5351 if (!System_Reflection_ParameterInfo)
5352 System_Reflection_ParameterInfo = mono_class_from_name (
5353 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5355 if (!method->signature->param_count)
5356 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5358 /* Note: the cache is based on the address of the signature into the method
5359 * since we already cache MethodInfos with the method as keys.
5361 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5363 member = mono_method_get_object (domain, method, NULL);
5364 names = g_new (char *, method->signature->param_count);
5365 mono_method_get_param_names (method, (const char **) names);
5367 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5368 for (i = 0; i < method->signature->param_count; ++i) {
5369 param = (MonoReflectionParameter *)mono_object_new (domain,
5370 System_Reflection_ParameterInfo);
5371 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5372 param->DefaultValueImpl = mono_field_get_value_object (domain, dbnull_value_field, NULL); /* FIXME */
5373 param->MemberImpl = (MonoObject*)member;
5374 param->NameImpl = mono_string_new (domain, names [i]);
5375 param->PositionImpl = i;
5376 param->AttrsImpl = method->signature->params [i]->attrs;
5377 mono_array_set (res, gpointer, i, param);
5380 CACHE_OBJECT (&(method->signature), res, NULL);
5385 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5389 memset (assembly, 0, sizeof (MonoAssemblyName));
5391 assembly->culture = "";
5392 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5394 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5397 while (*p == ' ' || *p == ',') {
5406 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5408 assembly->major = strtoul (p, &s, 10);
5409 if (s == p || *s != '.')
5412 assembly->minor = strtoul (p, &s, 10);
5413 if (s == p || *s != '.')
5416 assembly->build = strtoul (p, &s, 10);
5417 if (s == p || *s != '.')
5420 assembly->revision = strtoul (p, &s, 10);
5424 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5426 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5427 assembly->culture = "";
5430 assembly->culture = p;
5431 while (*p && *p != ',') {
5435 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5437 if (strncmp (p, "null", 4) == 0) {
5442 while (*p && *p != ',') {
5445 len = (p - start + 1);
5446 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5447 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5448 g_strlcpy (assembly->public_key_token, start, len);
5451 while (*p && *p != ',')
5455 while (*p == ' ' || *p == ',') {
5469 * mono_reflection_parse_type:
5472 * Parse a type name as accepted by the GetType () method and output the info
5473 * extracted in the info structure.
5474 * the name param will be mangled, so, make a copy before passing it to this function.
5475 * The fields in info will be valid until the memory pointed to by name is valid.
5476 * Returns 0 on parse error.
5477 * See also mono_type_get_name () below.
5480 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5482 char *start, *p, *w, *last_point, *startn;
5483 int in_modifiers = 0;
5484 int isbyref = 0, rank;
5486 start = p = w = name;
5488 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5489 info->name = info->name_space = NULL;
5490 info->nested = NULL;
5491 info->modifiers = NULL;
5493 /* last_point separates the namespace from the name */
5499 *p = 0; /* NULL terminate the name */
5501 info->nested = g_list_append (info->nested, startn);
5502 /* we have parsed the nesting namespace + name */
5506 info->name_space = start;
5508 info->name = last_point + 1;
5510 info->name_space = (char *)"";
5536 info->name_space = start;
5538 info->name = last_point + 1;
5540 info->name_space = (char *)"";
5547 if (isbyref) /* only one level allowed by the spec */
5550 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5554 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5565 else if (*p != '*') /* '*' means unknown lower bound */
5571 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5583 return 0; /* missing assembly name */
5584 if (!assembly_name_to_aname (&info->assembly, p))
5591 if (info->assembly.name)
5594 *w = 0; /* terminate class name */
5595 if (!info->name || !*info->name)
5597 /* add other consistency checks */
5602 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5609 image = mono_defaults.corlib;
5612 klass = mono_class_from_name_case (image, info->name_space, info->name);
5614 klass = mono_class_from_name (image, info->name_space, info->name);
5617 for (mod = info->nested; mod; mod = mod->next) {
5620 mono_class_init (klass);
5621 nested = klass->nested_classes;
5624 klass = nested->data;
5626 if (g_strcasecmp (klass->name, mod->data) == 0)
5629 if (strcmp (klass->name, mod->data) == 0)
5633 nested = nested->next;
5640 mono_class_init (klass);
5641 for (mod = info->modifiers; mod; mod = mod->next) {
5642 modval = GPOINTER_TO_UINT (mod->data);
5643 if (!modval) { /* byref: must be last modifier */
5644 return &klass->this_arg;
5645 } else if (modval == -1) {
5646 klass = mono_ptr_class_get (&klass->byval_arg);
5647 } else { /* array rank */
5648 klass = mono_array_class_get (klass, modval);
5650 mono_class_init (klass);
5653 return &klass->byval_arg;
5657 * mono_reflection_get_type:
5658 * @image: a metadata context
5659 * @info: type description structure
5660 * @ignorecase: flag for case-insensitive string compares
5661 * @type_resolve: whenever type resolve was already tried
5663 * Build a MonoType from the type description in @info.
5668 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5671 MonoReflectionAssembly *assembly;
5675 type = mono_reflection_get_type_internal (image, info, ignorecase);
5678 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5681 /* FIXME: Enabling this causes regressions (#65577) */
5687 *type_resolve = TRUE;
5691 /* Reconstruct the type name */
5692 fullName = g_string_new ("");
5693 if (info->name_space && (info->name_space [0] != '\0'))
5694 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5696 g_string_printf (fullName, info->name);
5697 for (mod = info->nested; mod; mod = mod->next)
5698 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5701 mono_domain_try_type_resolve (
5702 mono_domain_get (), fullName->str, NULL);
5703 if (assembly && (!image || (assembly->assembly->image == image))) {
5705 if (assembly->assembly->dynamic) {
5706 /* Enumerate all modules */
5707 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5711 if (abuilder->modules) {
5712 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5713 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5714 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5720 if (!type && abuilder->loaded_modules) {
5721 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5722 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5723 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5730 type = mono_reflection_get_type_internal (assembly->assembly->image,
5733 g_string_free (fullName, TRUE);
5738 * mono_reflection_type_from_name:
5740 * @image: a metadata context (can be NULL).
5742 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5743 * it defaults to get the type from @image or, if @image is NULL or loading
5744 * from it fails, uses corlib.
5748 mono_reflection_type_from_name (char *name, MonoImage *image)
5751 MonoTypeNameParse info;
5752 MonoAssembly *assembly;
5754 gboolean type_resolve = FALSE;
5756 /* Make a copy since parse_type modifies its argument */
5757 tmp = g_strdup (name);
5759 /*g_print ("requested type %s\n", str);*/
5760 if (!mono_reflection_parse_type (tmp, &info)) {
5762 g_list_free (info.modifiers);
5763 g_list_free (info.nested);
5767 if (info.assembly.name) {
5768 assembly = mono_assembly_loaded (&info.assembly);
5770 /* then we must load the assembly ourselve - see #60439 */
5771 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5774 g_list_free (info.modifiers);
5775 g_list_free (info.nested);
5779 image = assembly->image;
5780 } else if (image == NULL) {
5781 image = mono_defaults.corlib;
5784 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5785 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5786 image = mono_defaults.corlib;
5787 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5791 g_list_free (info.modifiers);
5792 g_list_free (info.nested);
5797 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5799 int slen, type = t->type;
5804 case MONO_TYPE_BOOLEAN: {
5805 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5810 case MONO_TYPE_CHAR:
5812 case MONO_TYPE_I2: {
5813 guint16 *val = g_malloc (sizeof (guint16));
5818 #if SIZEOF_VOID_P == 4
5824 case MONO_TYPE_I4: {
5825 guint32 *val = g_malloc (sizeof (guint32));
5830 #if SIZEOF_VOID_P == 8
5831 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5836 case MONO_TYPE_I8: {
5837 guint64 *val = g_malloc (sizeof (guint64));
5842 case MONO_TYPE_VALUETYPE:
5843 if (t->data.klass->enumtype) {
5844 type = t->data.klass->enum_basetype->type;
5847 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5850 case MONO_TYPE_STRING:
5851 if (*p == (char)0xFF) {
5855 slen = mono_metadata_decode_value (p, &p);
5857 return mono_string_new_len (mono_domain_get (), p, slen);
5858 case MONO_TYPE_CLASS: {
5861 if (*p == (char)0xFF) {
5866 slen = mono_metadata_decode_value (p, &p);
5867 n = g_memdup (p, slen + 1);
5869 t = mono_reflection_type_from_name (n, image);
5871 g_warning ("Cannot load type '%s'", n);
5875 return mono_type_get_object (mono_domain_get (), t);
5879 case MONO_TYPE_OBJECT: {
5882 MonoClass *subc = NULL;
5887 } else if (subt == 0x0E) {
5888 type = MONO_TYPE_STRING;
5890 } else if (subt == 0x55) {
5893 slen = mono_metadata_decode_value (p, &p);
5894 n = g_memdup (p, slen + 1);
5896 t = mono_reflection_type_from_name (n, image);
5898 g_warning ("Cannot load type '%s'", n);
5901 subc = mono_class_from_mono_type (t);
5902 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5903 MonoType simple_type = {{0}};
5904 simple_type.type = subt;
5905 subc = mono_class_from_mono_type (&simple_type);
5907 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5909 val = load_cattr_value (image, &subc->byval_arg, p, end);
5910 obj = mono_object_new (mono_domain_get (), subc);
5911 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5915 case MONO_TYPE_SZARRAY:
5918 guint32 i, alen, basetype;
5921 if (alen == 0xffffffff) {
5925 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5926 basetype = t->data.klass->byval_arg.type;
5931 case MONO_TYPE_BOOLEAN:
5932 for (i=0;i<alen;i++)
5934 MonoBoolean val=*p++;
5935 mono_array_set(arr,MonoBoolean,i,val);
5938 case MONO_TYPE_CHAR:
5941 for (i=0;i<alen;i++)
5943 guint16 val=read16(p);
5944 mono_array_set(arr,guint16,i,val);
5951 for (i=0;i<alen;i++)
5953 guint32 val=read32(p);
5954 mono_array_set(arr,guint32,i,val);
5961 for (i=0;i<alen;i++)
5963 guint64 val=read64(p);
5964 mono_array_set(arr,guint64,i,val);
5968 case MONO_TYPE_CLASS:
5969 case MONO_TYPE_OBJECT:
5970 case MONO_TYPE_STRING:
5971 for (i = 0; i < alen; i++) {
5972 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5973 mono_array_set (arr, gpointer, i, item);
5977 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5983 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5989 type_is_reference (MonoType *type)
5991 switch (type->type) {
5992 case MONO_TYPE_BOOLEAN:
5993 case MONO_TYPE_CHAR:
6006 case MONO_TYPE_VALUETYPE:
6014 free_param_data (MonoMethodSignature *sig, void **params) {
6016 for (i = 0; i < sig->param_count; ++i) {
6017 if (!type_is_reference (sig->params [i]))
6018 g_free (params [i]);
6023 * Find the method index in the metadata methodDef table.
6024 * Later put these three helper methods in metadata and export them.
6027 find_method_index (MonoMethod *method) {
6028 MonoClass *klass = method->klass;
6031 for (i = 0; i < klass->method.count; ++i) {
6032 if (method == klass->methods [i])
6033 return klass->method.first + 1 + i;
6039 * Find the field index in the metadata FieldDef table.
6042 find_field_index (MonoClass *klass, MonoClassField *field) {
6045 for (i = 0; i < klass->field.count; ++i) {
6046 if (field == &klass->fields [i])
6047 return klass->field.first + 1 + i;
6053 * Find the property index in the metadata Property table.
6056 find_property_index (MonoClass *klass, MonoProperty *property) {
6059 for (i = 0; i < klass->property.count; ++i) {
6060 if (property == &klass->properties [i])
6061 return klass->property.first + 1 + i;
6067 * Find the event index in the metadata Event table.
6070 find_event_index (MonoClass *klass, MonoEvent *event) {
6073 for (i = 0; i < klass->event.count; ++i) {
6074 if (event == &klass->events [i])
6075 return klass->event.first + 1 + i;
6081 create_custom_attr (MonoImage *image, MonoMethod *method,
6082 const char *data, guint32 len)
6084 const char *p = data;
6086 guint32 i, j, num_named;
6090 mono_class_init (method->klass);
6093 attr = mono_object_new (mono_domain_get (), method->klass);
6094 mono_runtime_invoke (method, attr, NULL, NULL);
6098 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6101 /*g_print ("got attr %s\n", method->klass->name);*/
6103 params = g_new (void*, method->signature->param_count);
6107 for (i = 0; i < method->signature->param_count; ++i) {
6108 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6112 attr = mono_object_new (mono_domain_get (), method->klass);
6113 mono_runtime_invoke (method, attr, params, NULL);
6114 free_param_data (method->signature, params);
6116 num_named = read16 (named);
6118 for (j = 0; j < num_named; j++) {
6120 char *name, named_type, data_type;
6121 named_type = *named++;
6122 data_type = *named++; /* type of data */
6123 if (data_type == 0x55) {
6126 type_len = mono_metadata_decode_blob_size (named, &named);
6127 type_name = g_malloc (type_len + 1);
6128 memcpy (type_name, named, type_len);
6129 type_name [type_len] = 0;
6131 /* FIXME: lookup the type and check type consistency */
6132 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6133 /* this seems to be the type of the element of the array */
6134 /* g_print ("skipping 0x%02x after prop\n", *named); */
6137 name_len = mono_metadata_decode_blob_size (named, &named);
6138 name = g_malloc (name_len + 1);
6139 memcpy (name, named, name_len);
6140 name [name_len] = 0;
6142 if (named_type == 0x53) {
6143 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6144 void *val = load_cattr_value (image, field->type, named, &named);
6145 mono_field_set_value (attr, field, val);
6146 if (!type_is_reference (field->type))
6148 } else if (named_type == 0x54) {
6151 MonoType *prop_type;
6153 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6154 /* can we have more that 1 arg in a custom attr named property? */
6155 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6156 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6157 mono_property_set_value (prop, attr, pparams, NULL);
6158 if (!type_is_reference (prop_type))
6159 g_free (pparams [0]);
6168 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6175 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6176 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6177 for (i = 0; i < cinfo->num_attrs; ++i) {
6178 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6179 mono_array_set (result, gpointer, i, attr);
6185 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6187 guint32 mtoken, i, len;
6188 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6190 MonoCustomAttrInfo *ainfo;
6191 GList *tmp, *list = NULL;
6194 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6196 i = mono_metadata_custom_attrs_from_index (image, idx);
6200 while (i < ca->rows) {
6201 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6203 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6206 len = g_list_length (list);
6209 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6210 ainfo->num_attrs = len;
6211 ainfo->image = image;
6212 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6213 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6214 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6215 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6216 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6217 mtoken |= MONO_TOKEN_METHOD_DEF;
6219 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6220 mtoken |= MONO_TOKEN_MEMBER_REF;
6223 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6226 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6227 if (!ainfo->attrs [i].ctor)
6228 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6229 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6230 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6231 ainfo->attrs [i].data = data;
6239 mono_custom_attrs_from_method (MonoMethod *method)
6241 MonoCustomAttrInfo *cinfo;
6244 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6246 idx = find_method_index (method);
6247 idx <<= MONO_CUSTOM_ATTR_BITS;
6248 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6249 return mono_custom_attrs_from_index (method->klass->image, idx);
6253 mono_custom_attrs_from_class (MonoClass *klass)
6255 MonoCustomAttrInfo *cinfo;
6258 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6260 idx = mono_metadata_token_index (klass->type_token);
6261 idx <<= MONO_CUSTOM_ATTR_BITS;
6262 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6263 return mono_custom_attrs_from_index (klass->image, idx);
6267 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6269 MonoCustomAttrInfo *cinfo;
6272 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6274 idx = 1; /* there is only one assembly */
6275 idx <<= MONO_CUSTOM_ATTR_BITS;
6276 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6277 return mono_custom_attrs_from_index (assembly->image, idx);
6280 static MonoCustomAttrInfo*
6281 mono_custom_attrs_from_module (MonoImage *image)
6283 MonoCustomAttrInfo *cinfo;
6286 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6288 idx = 1; /* there is only one module */
6289 idx <<= MONO_CUSTOM_ATTR_BITS;
6290 idx |= MONO_CUSTOM_ATTR_MODULE;
6291 return mono_custom_attrs_from_index (image, idx);
6295 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6297 MonoCustomAttrInfo *cinfo;
6300 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6302 idx = find_property_index (klass, property);
6303 idx <<= MONO_CUSTOM_ATTR_BITS;
6304 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6305 return mono_custom_attrs_from_index (klass->image, idx);
6309 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6311 MonoCustomAttrInfo *cinfo;
6314 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6316 idx = find_event_index (klass, event);
6317 idx <<= MONO_CUSTOM_ATTR_BITS;
6318 idx |= MONO_CUSTOM_ATTR_EVENT;
6319 return mono_custom_attrs_from_index (klass->image, idx);
6323 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6325 MonoCustomAttrInfo *cinfo;
6328 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6330 idx = find_field_index (klass, field);
6331 idx <<= MONO_CUSTOM_ATTR_BITS;
6332 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6333 return mono_custom_attrs_from_index (klass->image, idx);
6337 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6340 guint32 i, idx, method_index;
6341 guint32 param_list, param_last, param_pos, found;
6343 MonoReflectionMethodAux *aux;
6345 if (method->klass->image->dynamic) {
6346 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6347 if (!aux || !aux->param_cattr)
6349 return aux->param_cattr [param];
6352 image = method->klass->image;
6353 method_index = find_method_index (method);
6354 ca = &image->tables [MONO_TABLE_METHOD];
6356 if (method->klass->generic_inst || method->klass->gen_params ||
6357 method->signature->generic_param_count) {
6358 /* FIXME FIXME FIXME */
6362 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6363 if (method_index == ca->rows) {
6364 ca = &image->tables [MONO_TABLE_PARAM];
6365 param_last = ca->rows + 1;
6367 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6368 ca = &image->tables [MONO_TABLE_PARAM];
6371 for (i = param_list; i < param_last; ++i) {
6372 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6373 if (param_pos == param) {
6381 idx <<= MONO_CUSTOM_ATTR_BITS;
6382 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6383 return mono_custom_attrs_from_index (image, idx);
6387 * mono_reflection_get_custom_attrs:
6388 * @obj: a reflection object handle
6390 * Return an array with all the custom attributes defined of the
6391 * reflection handle @obj. The objects are fully build.
6394 mono_reflection_get_custom_attrs (MonoObject *obj)
6398 MonoCustomAttrInfo *cinfo = NULL;
6400 MONO_ARCH_SAVE_REGS;
6402 klass = obj->vtable->klass;
6403 /* FIXME: need to handle: Module */
6404 if (klass == mono_defaults.monotype_class) {
6405 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6406 klass = mono_class_from_mono_type (rtype->type);
6407 cinfo = mono_custom_attrs_from_class (klass);
6408 } else if (strcmp ("Assembly", klass->name) == 0) {
6409 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6410 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6411 } else if (strcmp ("Module", klass->name) == 0) {
6412 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6413 cinfo = mono_custom_attrs_from_module (module->image);
6414 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6415 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6416 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6417 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6418 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6419 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6420 } else if (strcmp ("MonoField", klass->name) == 0) {
6421 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6422 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6423 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6424 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6425 cinfo = mono_custom_attrs_from_method (rmethod->method);
6426 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6427 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6428 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6429 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6430 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6431 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6432 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6433 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6434 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6435 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6436 } else { /* handle other types here... */
6437 g_error ("get custom attrs not yet supported for %s", klass->name);
6441 result = mono_custom_attrs_construct (cinfo);
6443 mono_custom_attrs_free (cinfo);
6445 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6446 result = mono_array_new (mono_domain_get (), klass, 0);
6452 static MonoMethodSignature*
6453 parameters_to_signature (MonoArray *parameters) {
6454 MonoMethodSignature *sig;
6457 count = parameters? mono_array_length (parameters): 0;
6459 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6460 sig->param_count = count;
6461 sig->sentinelpos = -1; /* FIXME */
6462 for (i = 0; i < count; ++i) {
6463 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6464 sig->params [i] = pt->type;
6469 static MonoMethodSignature*
6470 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6471 MonoMethodSignature *sig;
6473 sig = parameters_to_signature (ctor->parameters);
6474 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6475 sig->ret = &mono_defaults.void_class->byval_arg;
6479 static MonoMethodSignature*
6480 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6481 MonoMethodSignature *sig;
6483 sig = parameters_to_signature (method->parameters);
6484 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6485 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6486 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6490 static MonoMethodSignature*
6491 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6492 MonoMethodSignature *sig;
6494 sig = parameters_to_signature (method->parameters);
6495 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6496 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6497 sig->generic_param_count = 0;
6502 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6504 MonoClass *klass = mono_object_class (prop);
6505 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6506 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6507 *name = mono_string_to_utf8 (pb->name);
6508 *type = pb->type->type;
6510 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6511 *name = g_strdup (p->property->name);
6512 if (p->property->get)
6513 *type = p->property->get->signature->ret;
6515 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6520 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6522 MonoClass *klass = mono_object_class (field);
6523 if (strcmp (klass->name, "FieldBuilder") == 0) {
6524 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6525 *name = mono_string_to_utf8 (fb->name);
6526 *type = fb->type->type;
6528 MonoReflectionField *f = (MonoReflectionField *)field;
6529 *name = g_strdup (f->field->name);
6530 *type = f->field->type;
6535 * Encode a value in a custom attribute stream of bytes.
6536 * The value to encode is either supplied as an object in argument val
6537 * (valuetypes are boxed), or as a pointer to the data in the
6539 * @type represents the type of the value
6540 * @buffer is the start of the buffer
6541 * @p the current position in the buffer
6542 * @buflen contains the size of the buffer and is used to return the new buffer size
6543 * if this needs to be realloced.
6544 * @retbuffer and @retp return the start and the position of the buffer
6547 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6549 MonoTypeEnum simple_type;
6551 if ((p-buffer) + 10 >= *buflen) {
6554 newbuf = g_realloc (buffer, *buflen);
6555 p = newbuf + (p-buffer);
6559 argval = ((char*)arg + sizeof (MonoObject));
6560 simple_type = type->type;
6562 switch (simple_type) {
6563 case MONO_TYPE_BOOLEAN:
6568 case MONO_TYPE_CHAR:
6571 swap_with_size (p, argval, 2, 1);
6577 swap_with_size (p, argval, 4, 1);
6583 swap_with_size (p, argval, 8, 1);
6586 case MONO_TYPE_VALUETYPE:
6587 if (type->data.klass->enumtype) {
6588 simple_type = type->data.klass->enum_basetype->type;
6591 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6594 case MONO_TYPE_STRING: {
6601 str = mono_string_to_utf8 ((MonoString*)arg);
6602 slen = strlen (str);
6603 if ((p-buffer) + 10 + slen >= *buflen) {
6607 newbuf = g_realloc (buffer, *buflen);
6608 p = newbuf + (p-buffer);
6611 mono_metadata_encode_value (slen, p, &p);
6612 memcpy (p, str, slen);
6617 case MONO_TYPE_CLASS: {
6625 k = mono_object_class (arg);
6626 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6627 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6628 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6630 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6631 slen = strlen (str);
6632 if ((p-buffer) + 10 + slen >= *buflen) {
6636 newbuf = g_realloc (buffer, *buflen);
6637 p = newbuf + (p-buffer);
6640 mono_metadata_encode_value (slen, p, &p);
6641 memcpy (p, str, slen);
6646 case MONO_TYPE_SZARRAY: {
6648 MonoClass *eclass, *arg_eclass;
6651 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6654 len = mono_array_length ((MonoArray*)arg);
6656 *p++ = (len >> 8) & 0xff;
6657 *p++ = (len >> 16) & 0xff;
6658 *p++ = (len >> 24) & 0xff;
6660 *retbuffer = buffer;
6661 eclass = type->data.klass;
6662 arg_eclass = mono_object_class (arg)->element_class;
6663 if (eclass->valuetype && arg_eclass->valuetype) {
6664 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6665 int elsize = mono_class_array_element_size (eclass);
6666 for (i = 0; i < len; ++i) {
6667 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6671 for (i = 0; i < len; ++i) {
6672 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6677 /* it may be a boxed value or a Type */
6678 case MONO_TYPE_OBJECT: {
6679 MonoClass *klass = mono_object_class (arg);
6683 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6686 } else if (klass->enumtype) {
6688 } else if (klass == mono_defaults.string_class) {
6689 simple_type = MONO_TYPE_STRING;
6692 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6693 *p++ = simple_type = klass->byval_arg.type;
6696 g_error ("unhandled type in custom attr");
6698 str = type_get_qualified_name (klass->enum_basetype, NULL);
6699 slen = strlen (str);
6700 if ((p-buffer) + 10 + slen >= *buflen) {
6704 newbuf = g_realloc (buffer, *buflen);
6705 p = newbuf + (p-buffer);
6708 mono_metadata_encode_value (slen, p, &p);
6709 memcpy (p, str, slen);
6712 simple_type = klass->enum_basetype->type;
6716 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6719 *retbuffer = buffer;
6723 * mono_reflection_get_custom_attrs_blob:
6724 * @ctor: custom attribute constructor
6725 * @ctorArgs: arguments o the constructor
6731 * Creates the blob of data that needs to be saved in the metadata and that represents
6732 * the custom attributed described by @ctor, @ctorArgs etc.
6733 * Returns: a Byte array representing the blob of data.
6736 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6739 MonoMethodSignature *sig;
6744 MONO_ARCH_SAVE_REGS;
6746 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6747 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6749 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6751 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6753 p = buffer = g_malloc (buflen);
6754 /* write the prolog */
6757 for (i = 0; i < sig->param_count; ++i) {
6758 arg = mono_array_get (ctorArgs, MonoObject*, i);
6759 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6763 i += mono_array_length (properties);
6765 i += mono_array_length (fields);
6767 *p++ = (i >> 8) & 0xff;
6770 for (i = 0; i < mono_array_length (properties); ++i) {
6775 prop = mono_array_get (properties, gpointer, i);
6776 get_prop_name_and_type (prop, &pname, &ptype);
6777 *p++ = 0x54; /* PROPERTY signature */
6779 /* Preallocate a large enough buffer */
6780 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6781 char *str = type_get_qualified_name (ptype, NULL);
6787 len += strlen (pname);
6789 if ((p-buffer) + 20 + len >= buflen) {
6793 newbuf = g_realloc (buffer, buflen);
6794 p = newbuf + (p-buffer);
6798 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6799 char *str = type_get_qualified_name (ptype, NULL);
6800 int slen = strlen (str);
6804 * This seems to be optional...
6807 mono_metadata_encode_value (slen, p, &p);
6808 memcpy (p, str, slen);
6812 mono_metadata_encode_value (ptype->type, p, &p);
6813 if (ptype->type == MONO_TYPE_SZARRAY)
6814 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6816 len = strlen (pname);
6817 mono_metadata_encode_value (len, p, &p);
6818 memcpy (p, pname, len);
6820 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6827 for (i = 0; i < mono_array_length (fields); ++i) {
6832 field = mono_array_get (fields, gpointer, i);
6833 get_field_name_and_type (field, &fname, &ftype);
6834 *p++ = 0x53; /* FIELD signature */
6835 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6836 char *str = type_get_qualified_name (ftype, NULL);
6837 int slen = strlen (str);
6838 if ((p-buffer) + 10 + slen >= buflen) {
6842 newbuf = g_realloc (buffer, buflen);
6843 p = newbuf + (p-buffer);
6848 * This seems to be optional...
6851 mono_metadata_encode_value (slen, p, &p);
6852 memcpy (p, str, slen);
6856 mono_metadata_encode_value (ftype->type, p, &p);
6857 if (ftype->type == MONO_TYPE_SZARRAY)
6858 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6860 len = strlen (fname);
6861 mono_metadata_encode_value (len, p, &p);
6862 memcpy (p, fname, len);
6864 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6869 g_assert (p - buffer <= buflen);
6870 buflen = p - buffer;
6871 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6872 p = mono_array_addr (result, char, 0);
6873 memcpy (p, buffer, buflen);
6875 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6881 * mono_reflection_setup_internal_class:
6882 * @tb: a TypeBuilder object
6884 * Creates a MonoClass that represents the TypeBuilder.
6885 * This is a trick that lets us simplify a lot of reflection code
6886 * (and will allow us to support Build and Run assemblies easier).
6889 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6891 MonoClass *klass, *parent;
6893 MONO_ARCH_SAVE_REGS;
6896 /* check so we can compile corlib correctly */
6897 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6898 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6899 parent = tb->parent->type->data.klass;
6901 parent = my_mono_class_from_mono_type (tb->parent->type);
6905 /* the type has already being created: it means we just have to change the parent */
6906 if (tb->type.type) {
6907 klass = mono_class_from_mono_type (tb->type.type);
6908 klass->parent = NULL;
6909 /* fool mono_class_setup_parent */
6910 g_free (klass->supertypes);
6911 klass->supertypes = NULL;
6912 mono_class_setup_parent (klass, parent);
6913 mono_class_setup_mono_type (klass);
6917 klass = g_new0 (MonoClass, 1);
6919 klass->image = &tb->module->dynamic_image->image;
6921 klass->inited = 1; /* we lie to the runtime */
6922 klass->name = mono_string_to_utf8 (tb->name);
6923 klass->name_space = mono_string_to_utf8 (tb->nspace);
6924 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6925 klass->flags = tb->attrs;
6927 klass->element_class = klass;
6928 klass->reflection_info = tb; /* need to pin. */
6930 /* Put into cache so mono_class_get () will find it */
6931 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6934 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6935 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6939 mono_class_setup_parent (klass, parent);
6940 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6941 const char *old_n = klass->name;
6942 /* trick to get relative numbering right when compiling corlib */
6943 klass->name = "BuildingObject";
6944 mono_class_setup_parent (klass, mono_defaults.object_class);
6945 klass->name = old_n;
6947 mono_class_setup_mono_type (klass);
6949 mono_class_setup_supertypes (klass);
6952 * FIXME: handle interfaces.
6955 tb->type.type = &klass->byval_arg;
6957 if (tb->nesting_type) {
6958 g_assert (tb->nesting_type->type);
6959 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6962 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6966 * mono_reflection_setup_generic_class:
6967 * @tb: a TypeBuilder object
6969 * Setup the generic class after all generic parameters have been added.
6972 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6977 MONO_ARCH_SAVE_REGS;
6979 klass = my_mono_class_from_mono_type (tb->type.type);
6981 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6983 if (klass->gen_params || (count == 0))
6986 klass->num_gen_params = count;
6987 klass->gen_params = g_new0 (MonoGenericParam, count);
6989 for (i = 0; i < count; i++) {
6990 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6991 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6996 * mono_reflection_create_internal_class:
6997 * @tb: a TypeBuilder object
6999 * Actually create the MonoClass that is associated with the TypeBuilder.
7002 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7006 MONO_ARCH_SAVE_REGS;
7008 klass = my_mono_class_from_mono_type (tb->type.type);
7010 if (klass->enumtype && klass->enum_basetype == NULL) {
7011 MonoReflectionFieldBuilder *fb;
7013 g_assert (tb->fields != NULL);
7014 g_assert (mono_array_length (tb->fields) >= 1);
7016 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7018 klass->enum_basetype = fb->type->type;
7019 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7020 if (!klass->element_class)
7021 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7022 klass->instance_size = klass->element_class->instance_size;
7023 klass->size_inited = 1;
7025 * this is almost safe to do with enums and it's needed to be able
7026 * to create objects of the enum type (for use in SetConstant).
7028 /* FIXME: Does this mean enums can't have method overrides ? */
7029 mono_class_setup_vtable (klass, NULL, 0);
7033 static MonoMarshalSpec*
7034 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7035 MonoReflectionMarshal *minfo)
7037 MonoMarshalSpec *res;
7039 res = g_new0 (MonoMarshalSpec, 1);
7040 res->native = minfo->type;
7042 switch (minfo->type) {
7043 case MONO_NATIVE_LPARRAY:
7044 res->data.array_data.elem_type = minfo->eltype;
7045 res->data.array_data.param_num = 0; /* Not yet */
7046 res->data.array_data.num_elem = minfo->count;
7049 case MONO_NATIVE_BYVALTSTR:
7050 case MONO_NATIVE_BYVALARRAY:
7051 res->data.array_data.num_elem = minfo->count;
7054 case MONO_NATIVE_CUSTOM:
7055 if (minfo->marshaltyperef)
7056 res->data.custom_data.custom_name =
7057 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7059 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7070 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7071 ReflectionMethodBuilder *rmb,
7072 MonoMethodSignature *sig)
7075 MonoMethodNormal *pm;
7076 MonoMarshalSpec **specs;
7077 MonoReflectionMethodAux *method_aux;
7080 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7081 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7082 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7085 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7087 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7089 pm = (MonoMethodNormal*)m;
7092 m->flags = rmb->attrs;
7093 m->iflags = rmb->iattrs;
7094 m->name = mono_string_to_utf8 (rmb->name);
7098 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7100 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7101 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7104 m->signature->pinvoke = 1;
7105 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7107 m->signature->pinvoke = 1;
7109 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7111 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7112 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7114 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7116 if (klass->image->dynamic)
7117 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7120 } else if (!m->klass->dummy &&
7121 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7122 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7123 MonoMethodHeader *header;
7125 gint32 max_stack, i;
7126 gint32 num_locals = 0;
7127 gint32 num_clauses = 0;
7131 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7132 code_size = rmb->ilgen->code_len;
7133 max_stack = rmb->ilgen->max_stack;
7134 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7135 if (rmb->ilgen->ex_handlers)
7136 num_clauses = method_count_clauses (rmb->ilgen);
7139 code = mono_array_addr (rmb->code, guint8, 0);
7140 code_size = mono_array_length (rmb->code);
7141 /* we probably need to run a verifier on the code... */
7151 header = g_malloc0 (sizeof (MonoMethodHeader) +
7152 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7153 header->code_size = code_size;
7154 header->code = g_malloc (code_size);
7155 memcpy ((char*)header->code, code, code_size);
7156 header->max_stack = max_stack;
7157 header->init_locals = rmb->init_locals;
7158 header->num_locals = num_locals;
7160 for (i = 0; i < num_locals; ++i) {
7161 MonoReflectionLocalBuilder *lb =
7162 mono_array_get (rmb->ilgen->locals,
7163 MonoReflectionLocalBuilder*, i);
7165 header->locals [i] = g_new0 (MonoType, 1);
7166 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7169 header->num_clauses = num_clauses;
7171 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7176 pm->header = header;
7179 if (rmb->generic_params) {
7180 int count = mono_array_length (rmb->generic_params);
7181 pm->gen_params = g_new0 (MonoGenericParam, count);
7182 for (i = 0; i < count; i++) {
7183 MonoReflectionGenericParam *gp =
7184 mono_array_get (rmb->generic_params,
7185 MonoReflectionGenericParam*, i);
7187 pm->gen_params [i] = *gp->type.type->data.generic_param;
7192 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7195 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7197 for (i = 0; i < rmb->nrefs; ++i)
7198 mw->data = g_list_append (mw->data, rmb->refs [i]);
7203 /* Parameter names */
7206 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7207 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7208 for (i = 0; i <= m->signature->param_count; ++i) {
7209 MonoReflectionParamBuilder *pb;
7210 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7212 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7214 if (!method_aux->param_cattr)
7215 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7216 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7222 /* Parameter marshalling */
7225 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7226 MonoReflectionParamBuilder *pb;
7227 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7228 if (pb->marshal_info) {
7230 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7231 specs [pb->position] =
7232 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7236 if (specs != NULL) {
7238 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7239 method_aux->param_marshall = specs;
7246 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7248 ReflectionMethodBuilder rmb;
7249 MonoMethodSignature *sig;
7251 sig = ctor_builder_to_signature (mb);
7253 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7255 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7256 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7258 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7259 /* ilgen is no longer needed */
7267 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7269 ReflectionMethodBuilder rmb;
7270 MonoMethodSignature *sig;
7272 sig = method_builder_to_signature (mb);
7274 reflection_methodbuilder_from_method_builder (&rmb, mb);
7276 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7277 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7279 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7280 /* ilgen is no longer needed */
7286 static MonoClassField*
7287 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7289 MonoClassField *field;
7296 field = g_new0 (MonoClassField, 1);
7298 field->name = mono_string_to_utf8 (fb->name);
7300 /* FIXME: handle type modifiers */
7301 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7302 field->type->attrs = fb->attrs;
7304 field->type = fb->type->type;
7306 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7307 field->data = mono_array_addr (fb->rva_data, char, 0);
7308 if (fb->offset != -1)
7309 field->offset = fb->offset;
7310 field->parent = klass;
7312 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7314 if (fb->def_value) {
7315 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7316 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7317 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7318 /* Copy the data from the blob since it might get realloc-ed */
7319 p = assembly->blob.data + idx;
7320 len = mono_metadata_decode_blob_size (p, &p2);
7322 field->data = g_malloc (len);
7323 memcpy ((gpointer)field->data, p, len);
7330 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7334 MonoReflectionTypeBuilder *tb = NULL;
7335 MonoGenericInst *ginst, *cached;
7340 klass = mono_class_from_mono_type (type->type);
7341 if (!klass->gen_params && !klass->generic_inst &&
7342 !(klass->nested_in && klass->nested_in->gen_params))
7345 mono_loader_lock ();
7347 domain = mono_object_domain (type);
7349 ginst = g_new0 (MonoGenericInst, 1);
7351 if (!klass->generic_inst) {
7352 ginst->type_argc = type_argc;
7353 ginst->type_argv = types;
7355 for (i = 0; i < ginst->type_argc; ++i) {
7356 if (!ginst->is_open)
7357 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7360 ginst->generic_type = &klass->byval_arg;
7362 MonoGenericInst *kginst = klass->generic_inst;
7364 ginst->type_argc = kginst->type_argc;
7365 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7367 for (i = 0; i < ginst->type_argc; i++) {
7368 MonoType *t = kginst->type_argv [i];
7370 if (t->type == MONO_TYPE_VAR)
7371 t = types [t->data.generic_param->num];
7373 if (!ginst->is_open)
7374 ginst->is_open = mono_class_is_open_constructed_type (t);
7376 ginst->type_argv [i] = t;
7379 ginst->generic_type = kginst->generic_type;
7382 geninst = g_new0 (MonoType, 1);
7383 geninst->type = MONO_TYPE_GENERICINST;
7385 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7388 mono_loader_unlock ();
7389 geninst->data.generic_inst = cached;
7393 geninst->data.generic_inst = ginst;
7395 ginst->context = g_new0 (MonoGenericContext, 1);
7396 ginst->context->ginst = ginst;
7398 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7399 tb = (MonoReflectionTypeBuilder *) type;
7401 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7402 ginst->is_dynamic = TRUE;
7403 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7404 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7405 MonoReflectionType *rgt = rgi->generic_type;
7407 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7408 tb = (MonoReflectionTypeBuilder *) rgt;
7410 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7411 ginst->is_dynamic = TRUE;
7413 icount = klass->interface_count;
7415 ginst->ifaces = g_new0 (MonoType *, icount);
7416 ginst->count_ifaces = icount;
7418 for (i = 0; i < icount; i++) {
7419 MonoReflectionType *itype;
7422 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7424 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7425 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7426 if (!ginst->ifaces [i])
7427 ginst->ifaces [i] = itype->type;
7430 mono_class_create_generic (ginst);
7432 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7434 mono_loader_unlock ();
7440 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7442 MonoClass *klass, *pklass = NULL;
7443 MonoReflectionType *parent = NULL;
7445 MonoReflectionTypeBuilder *tb = NULL;
7446 MonoGenericInst *ginst;
7449 domain = mono_object_domain (type);
7450 klass = mono_class_from_mono_type (type->type);
7452 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7453 tb = (MonoReflectionTypeBuilder *) type;
7456 parent = tb->parent;
7457 pklass = mono_class_from_mono_type (parent->type);
7460 pklass = klass->parent;
7462 parent = mono_type_get_object (domain, &pklass->byval_arg);
7465 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7469 ginst = geninst->data.generic_inst;
7471 if (pklass && pklass->generic_inst)
7472 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7477 MonoReflectionMethod*
7478 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7480 MonoMethod *method, *inflated;
7481 MonoReflectionMethodBuilder *mb = NULL;
7482 MonoGenericMethod *gmethod;
7483 MonoGenericContext *context;
7486 MONO_ARCH_SAVE_REGS;
7487 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7488 MonoReflectionTypeBuilder *tb;
7491 mb = (MonoReflectionMethodBuilder *) rmethod;
7492 tb = (MonoReflectionTypeBuilder *) mb->type;
7493 klass = mono_class_from_mono_type (tb->type.type);
7495 method = methodbuilder_to_mono_method (klass, mb);
7497 method = rmethod->method;
7499 count = method->signature->generic_param_count;
7500 if (count != mono_array_length (types))
7503 gmethod = g_new0 (MonoGenericMethod, 1);
7504 gmethod->mtype_argc = count;
7505 gmethod->mtype_argv = g_new0 (MonoType *, count);
7506 for (i = 0; i < count; i++) {
7507 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7508 gmethod->mtype_argv [i] = garg->type;
7511 gmethod->reflection_info = rmethod;
7513 context = g_new0 (MonoGenericContext, 1);
7514 context->ginst = method->klass->generic_inst;
7515 context->gmethod = gmethod;
7517 inflated = mono_class_inflate_generic_method (method, context, NULL);
7519 return mono_method_get_object (
7520 mono_object_domain (rmethod), inflated, NULL);
7524 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7526 MonoGenericMethod *gmethod;
7527 MonoGenericInst *ginst;
7528 MonoGenericContext *context;
7531 ginst = type->type.type->data.generic_inst;
7533 gmethod = g_new0 (MonoGenericMethod, 1);
7534 gmethod->reflection_info = obj;
7536 gmethod->mtype_argc = method->signature->generic_param_count;
7537 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7539 for (i = 0; i < gmethod->mtype_argc; i++) {
7540 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7541 MonoGenericParam *gparam = &mn->gen_params [i];
7543 g_assert (gparam->pklass);
7544 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7547 context = g_new0 (MonoGenericContext, 1);
7548 context->ginst = ginst;
7549 context->gmethod = gmethod;
7551 return mono_class_inflate_generic_method (method, context, ginst->klass);
7555 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7560 klass = mono_class_from_mono_type (type->type.type);
7562 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7563 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7564 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7565 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7566 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7567 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7568 method = ((MonoReflectionMethod *) obj)->method;
7570 method = NULL; /* prevent compiler warning */
7571 g_assert_not_reached ();
7574 return inflate_mono_method (type, method, obj);
7578 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7579 MonoArray *methods, MonoArray *ctors,
7580 MonoArray *fields, MonoArray *properties,
7583 MonoGenericInst *ginst;
7584 MonoDynamicGenericInst *dginst;
7585 MonoClass *klass, *gklass, *pklass;
7588 MONO_ARCH_SAVE_REGS;
7590 klass = mono_class_from_mono_type (type->type.type);
7591 ginst = type->type.type->data.generic_inst;
7593 if (ginst->initialized)
7596 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7598 gklass = mono_class_from_mono_type (ginst->generic_type);
7599 mono_class_init (gklass);
7602 pklass = mono_class_from_mono_type (ginst->parent);
7604 pklass = gklass->parent;
7606 mono_class_setup_parent (klass, pklass);
7608 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7609 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7610 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7611 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7612 dginst->count_events = events ? mono_array_length (events) : 0;
7614 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7615 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7616 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7617 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7618 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7620 for (i = 0; i < dginst->count_methods; i++) {
7621 MonoObject *obj = mono_array_get (methods, gpointer, i);
7623 dginst->methods [i] = inflate_method (type, obj);
7626 for (i = 0; i < dginst->count_ctors; i++) {
7627 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7629 dginst->ctors [i] = inflate_method (type, obj);
7632 for (i = 0; i < dginst->count_fields; i++) {
7633 MonoObject *obj = mono_array_get (fields, gpointer, i);
7634 MonoClassField *field;
7635 MonoInflatedField *ifield;
7637 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7638 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7639 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7640 field = ((MonoReflectionField *) obj)->field;
7642 field = NULL; /* prevent compiler warning */
7643 g_assert_not_reached ();
7646 ifield = g_new0 (MonoInflatedField, 1);
7647 ifield->generic_type = field->type;
7648 ifield->reflection_info = obj;
7650 dginst->fields [i] = *field;
7651 dginst->fields [i].generic_info = ifield;
7652 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7655 for (i = 0; i < dginst->count_properties; i++) {
7656 MonoObject *obj = mono_array_get (properties, gpointer, i);
7657 MonoProperty *property = &dginst->properties [i];
7659 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7660 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7662 property->parent = klass;
7663 property->attrs = pb->attrs;
7664 property->name = mono_string_to_utf8 (pb->name);
7666 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7668 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7669 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7670 *property = *((MonoReflectionProperty *) obj)->property;
7673 property->get = inflate_mono_method (type, property->get, NULL);
7675 property->set = inflate_mono_method (type, property->set, NULL);
7677 g_assert_not_reached ();
7680 for (i = 0; i < dginst->count_events; i++) {
7681 MonoObject *obj = mono_array_get (events, gpointer, i);
7682 MonoEvent *event = &dginst->events [i];
7684 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7685 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7687 event->parent = klass;
7688 event->attrs = eb->attrs;
7689 event->name = mono_string_to_utf8 (eb->name);
7691 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7692 if (eb->remove_method)
7693 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7694 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7695 *event = *((MonoReflectionEvent *) obj)->event;
7698 event->add = inflate_mono_method (type, event->add, NULL);
7700 event->remove = inflate_mono_method (type, event->remove, NULL);
7702 g_assert_not_reached ();
7705 ginst->initialized = TRUE;
7709 ensure_runtime_vtable (MonoClass *klass)
7711 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7712 int i, num, j, onum;
7713 MonoMethod **overrides;
7715 if (!tb || klass->wastypebuilder)
7718 ensure_runtime_vtable (klass->parent);
7720 num = tb->ctors? mono_array_length (tb->ctors): 0;
7721 num += tb->num_methods;
7722 klass->method.count = num;
7723 klass->methods = g_new (MonoMethod*, num);
7724 num = tb->ctors? mono_array_length (tb->ctors): 0;
7725 for (i = 0; i < num; ++i)
7726 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7727 num = tb->num_methods;
7729 for (i = 0; i < num; ++i)
7730 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7732 klass->wastypebuilder = TRUE;
7733 if (tb->interfaces) {
7734 klass->interface_count = mono_array_length (tb->interfaces);
7735 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7736 for (i = 0; i < klass->interface_count; ++i) {
7737 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7738 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7742 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7743 for (i = 0; i < klass->method.count; ++i)
7744 klass->methods [i]->slot = i;
7749 for (i = 0; i < tb->num_methods; ++i) {
7750 MonoReflectionMethodBuilder *mb =
7751 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7752 if (mb->override_method)
7757 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7761 for (i = 0; i < tb->num_methods; ++i) {
7762 MonoReflectionMethodBuilder *mb =
7763 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7764 if (mb->override_method) {
7765 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7766 overrides [onum * 2] =
7767 mb->override_method->method;
7768 overrides [onum * 2 + 1] =
7771 g_assert (mb->mhandle);
7778 mono_class_setup_vtable (klass, overrides, onum);
7782 typebuilder_setup_fields (MonoClass *klass)
7784 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7785 MonoReflectionFieldBuilder *fb;
7786 MonoClassField *field;
7791 klass->field.count = tb->num_fields;
7792 klass->field.first = 0;
7793 klass->field.last = klass->field.count;
7795 if (!klass->field.count)
7798 klass->fields = g_new0 (MonoClassField, klass->field.count);
7800 for (i = 0; i < klass->field.count; ++i) {
7801 fb = mono_array_get (tb->fields, gpointer, i);
7802 field = &klass->fields [i];
7803 field->name = mono_string_to_utf8 (fb->name);
7805 /* FIXME: handle type modifiers */
7806 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7807 field->type->attrs = fb->attrs;
7809 field->type = fb->type->type;
7811 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7812 field->data = mono_array_addr (fb->rva_data, char, 0);
7813 if (fb->offset != -1)
7814 field->offset = fb->offset;
7815 field->parent = klass;
7817 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7819 if (fb->def_value) {
7820 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7821 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7822 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7823 /* Copy the data from the blob since it might get realloc-ed */
7824 p = assembly->blob.data + idx;
7825 len = mono_metadata_decode_blob_size (p, &p2);
7827 field->data = g_malloc (len);
7828 memcpy ((gpointer)field->data, p, len);
7831 mono_class_layout_fields (klass);
7835 typebuilder_setup_properties (MonoClass *klass)
7837 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7838 MonoReflectionPropertyBuilder *pb;
7841 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7842 klass->property.first = 0;
7843 klass->property.last = klass->property.count;
7845 klass->properties = g_new0 (MonoProperty, klass->property.count);
7846 for (i = 0; i < klass->property.count; ++i) {
7847 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7848 klass->properties [i].parent = klass;
7849 klass->properties [i].attrs = pb->attrs;
7850 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7852 klass->properties [i].get = pb->get_method->mhandle;
7854 klass->properties [i].set = pb->set_method->mhandle;
7858 MonoReflectionEvent *
7859 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7861 MonoEvent *event = g_new0 (MonoEvent, 1);
7865 klass = my_mono_class_from_mono_type (tb->type.type);
7867 event->parent = klass;
7868 event->attrs = eb->attrs;
7869 event->name = mono_string_to_utf8 (eb->name);
7871 event->add = eb->add_method->mhandle;
7872 if (eb->remove_method)
7873 event->remove = eb->remove_method->mhandle;
7874 if (eb->raise_method)
7875 event->raise = eb->raise_method->mhandle;
7877 if (eb->other_methods) {
7878 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7879 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7880 MonoReflectionMethodBuilder *mb =
7881 mono_array_get (eb->other_methods,
7882 MonoReflectionMethodBuilder*, j);
7883 event->other [j] = mb->mhandle;
7887 return mono_event_get_object (mono_object_domain (tb), klass, event);
7891 typebuilder_setup_events (MonoClass *klass)
7893 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7894 MonoReflectionEventBuilder *eb;
7897 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7898 klass->event.first = 0;
7899 klass->event.last = klass->event.count;
7901 klass->events = g_new0 (MonoEvent, klass->event.count);
7902 for (i = 0; i < klass->event.count; ++i) {
7903 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7904 klass->events [i].parent = klass;
7905 klass->events [i].attrs = eb->attrs;
7906 klass->events [i].name = mono_string_to_utf8 (eb->name);
7908 klass->events [i].add = eb->add_method->mhandle;
7909 if (eb->remove_method)
7910 klass->events [i].remove = eb->remove_method->mhandle;
7911 if (eb->raise_method)
7912 klass->events [i].raise = eb->raise_method->mhandle;
7914 if (eb->other_methods) {
7915 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7916 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7917 MonoReflectionMethodBuilder *mb =
7918 mono_array_get (eb->other_methods,
7919 MonoReflectionMethodBuilder*, j);
7920 klass->events [i].other [j] = mb->mhandle;
7927 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7930 MonoReflectionType* res;
7933 MONO_ARCH_SAVE_REGS;
7935 klass = my_mono_class_from_mono_type (tb->type.type);
7937 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7940 * Fields to set in klass:
7941 * the various flags: delegate/unicode/contextbound etc.
7943 klass->flags = tb->attrs;
7945 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7946 /* No need to fully construct the type */
7947 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7949 /* enums are done right away */
7950 if (!klass->enumtype)
7951 ensure_runtime_vtable (klass);
7954 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
7955 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
7956 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
7960 /* fields and object layout */
7961 if (klass->parent) {
7962 if (!klass->parent->size_inited)
7963 mono_class_init (klass->parent);
7964 klass->instance_size += klass->parent->instance_size;
7965 klass->class_size += klass->parent->class_size;
7966 klass->min_align = klass->parent->min_align;
7968 klass->instance_size = sizeof (MonoObject);
7969 klass->min_align = 1;
7972 /* FIXME: handle packing_size and instance_size */
7973 typebuilder_setup_fields (klass);
7975 typebuilder_setup_properties (klass);
7977 typebuilder_setup_events (klass);
7979 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7980 /* with enums res == tb: need to fix that. */
7981 if (!klass->enumtype)
7982 g_assert (res != (MonoReflectionType*)tb);
7987 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7989 MonoGenericParam *param;
7992 MONO_ARCH_SAVE_REGS;
7994 param = g_new0 (MonoGenericParam, 1);
7996 param->method = NULL;
7997 param->name = mono_string_to_utf8 (gparam->name);
7998 param->num = gparam->index;
8000 image = &gparam->tbuilder->module->dynamic_image->image;
8001 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8003 param->pklass->reflection_info = gparam;
8005 gparam->type.type = g_new0 (MonoType, 1);
8006 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8007 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8008 gparam->type.type->data.generic_param = param;
8012 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8014 MonoDynamicImage *assembly = sig->module->dynamic_image;
8015 guint32 na = mono_array_length (sig->arguments);
8020 MONO_ARCH_SAVE_REGS;
8022 p = buf = g_malloc (10 + na * 10);
8024 mono_metadata_encode_value (0x07, p, &p);
8025 mono_metadata_encode_value (na, p, &p);
8026 for (i = 0; i < na; ++i) {
8027 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8028 encode_reflection_type (assembly, type, p, &p);
8032 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8033 p = mono_array_addr (result, char, 0);
8034 memcpy (p, buf, buflen);
8041 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8043 MonoDynamicImage *assembly = sig->module->dynamic_image;
8044 guint32 na = mono_array_length (sig->arguments);
8049 MONO_ARCH_SAVE_REGS;
8051 p = buf = g_malloc (10 + na * 10);
8053 mono_metadata_encode_value (0x06, p, &p);
8054 for (i = 0; i < na; ++i) {
8055 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8056 encode_reflection_type (assembly, type, p, &p);
8060 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8061 p = mono_array_addr (result, char, 0);
8062 memcpy (p, buf, buflen);
8069 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8071 ReflectionMethodBuilder rmb;
8072 MonoMethodSignature *sig;
8075 sig = dynamic_method_to_signature (mb);
8077 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8080 * Resolve references.
8082 rmb.nrefs = mb->nrefs;
8083 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8084 for (i = 0; i < mb->nrefs; ++i) {
8085 gpointer ref = resolve_object (mb->module->image,
8086 mono_array_get (mb->refs, MonoObject*, i));
8089 mono_raise_exception (mono_get_exception_type_load (NULL));
8096 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8100 /* ilgen is no longer needed */
8105 * mono_reflection_lookup_dynamic_token:
8107 * Finish the Builder object pointed to by TOKEN and return the corresponding
8108 * runtime structure.
8111 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8113 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8116 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8119 return resolve_object (image, obj);
8123 resolve_object (MonoImage *image, MonoObject *obj)
8125 gpointer result = NULL;
8127 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8128 result = mono_string_intern ((MonoString*)obj);
8131 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8132 MonoReflectionType *tb = (MonoReflectionType*)obj;
8133 result = mono_class_from_mono_type (tb->type);
8136 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8137 result = ((MonoReflectionMethod*)obj)->method;
8140 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8141 result = ((MonoReflectionMethod*)obj)->method;
8144 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8145 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8146 result = mb->mhandle;
8148 /* Type is not yet created */
8149 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8151 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8154 * Hopefully this has been filled in by calling CreateType() on the
8158 * TODO: This won't work if the application finishes another
8159 * TypeBuilder instance instead of this one.
8161 result = mb->mhandle;
8164 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8165 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8167 result = cb->mhandle;
8169 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8171 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8172 result = cb->mhandle;
8175 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8176 result = ((MonoReflectionField*)obj)->field;
8179 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8180 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8181 result = fb->handle;
8184 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8186 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8187 result = fb->handle;
8190 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8191 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8194 klass = tb->type.type->data.klass;
8195 if (klass->wastypebuilder) {
8196 /* Already created */
8200 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8201 result = tb->type.type->data.klass;
8205 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8206 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8207 MonoMethodSignature *sig;
8210 if (helper->arguments)
8211 nargs = mono_array_length (helper->arguments);
8215 sig = mono_metadata_signature_alloc (image, nargs);
8216 sig->explicit_this = helper->call_conv & 64;
8217 sig->hasthis = helper->call_conv & 32;
8219 if (helper->call_conv == 0) /* unmanaged */
8220 sig->call_convention = helper->unmanaged_call_conv - 1;
8222 if (helper->call_conv & 0x02)
8223 sig->call_convention = MONO_CALL_VARARG;
8225 sig->call_convention = MONO_CALL_DEFAULT;
8227 sig->param_count = nargs;
8228 /* TODO: Copy type ? */
8229 sig->ret = helper->return_type->type;
8230 for (i = 0; i < nargs; ++i) {
8231 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8232 sig->params [i] = rt->type;
8238 g_print (obj->vtable->klass->name);
8239 g_assert_not_reached ();