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/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
17 #include "mono/metadata/assembly.h"
18 #include <mono/metadata/exception.h>
27 #include "rawbuffer.h"
28 #include "mono-endian.h"
30 #include <mono/os/gc_wrapper.h>
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA 0x00002000
39 MonoReflectionILGen *ilgen;
40 MonoReflectionType *rtype;
41 MonoArray *parameters;
42 MonoArray *generic_params;
47 guint32 *table_idx; /* note: it's a pointer */
51 MonoBoolean init_locals;
52 MonoArray *return_modreq;
53 MonoArray *return_modopt;
54 MonoArray *param_modreq;
55 MonoArray *param_modopt;
56 MonoArray *permissions;
60 } ReflectionMethodBuilder;
62 const unsigned char table_sizes [64] = {
72 MONO_INTERFACEIMPL_SIZE,
73 MONO_MEMBERREF_SIZE, /* 0x0A */
75 MONO_CUSTOM_ATTR_SIZE,
76 MONO_FIELD_MARSHAL_SIZE,
77 MONO_DECL_SECURITY_SIZE,
78 MONO_CLASS_LAYOUT_SIZE,
79 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
80 MONO_STAND_ALONE_SIGNATURE_SIZE,
84 MONO_PROPERTY_MAP_SIZE,
87 MONO_METHOD_SEMA_SIZE,
89 MONO_MODULEREF_SIZE, /* 0x1A */
95 MONO_ASSEMBLY_SIZE, /* 0x20 */
96 MONO_ASSEMBLY_PROCESSOR_SIZE,
98 MONO_ASSEMBLYREF_SIZE,
99 MONO_ASSEMBLYREFPROC_SIZE,
100 MONO_ASSEMBLYREFOS_SIZE,
104 MONO_NESTED_CLASS_SIZE,
106 MONO_GENERICPARAM_SIZE, /* 0x2A */
107 MONO_METHODSPEC_SIZE,
108 MONO_GENPARCONSTRAINT_SIZE,
114 * These macros can be used to allocate long living atomic data so it won't be
115 * tracked by the garbage collector. We use libgc because it's apparently faster
119 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
120 #define FREE_ATOMIC(ptr)
121 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
123 #define ALLOC_ATOMIC(size) g_malloc (size)
124 #define FREE_ATOMIC(ptr) g_free (ptr)
125 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
128 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
129 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
130 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
131 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
132 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
133 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
134 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
135 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
136 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
137 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
138 static void ensure_runtime_vtable (MonoClass *klass);
139 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
140 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
141 static guint32 type_get_signature_size (MonoType *type);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows)
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
159 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
164 make_room_in_stream (MonoDynamicStream *stream, int size)
166 while (stream->alloc_size <= size) {
167 if (stream->alloc_size < 4096)
168 stream->alloc_size = 4096;
170 stream->alloc_size *= 2;
173 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
175 stream->data = ALLOC_ATOMIC (stream->alloc_size);
179 string_heap_insert (MonoDynamicStream *sh, const char *str)
183 gpointer oldkey, oldval;
185 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
186 return GPOINTER_TO_UINT (oldval);
188 len = strlen (str) + 1;
190 if (idx + len > sh->alloc_size)
191 make_room_in_stream (sh, idx + len);
194 * We strdup the string even if we already copy them in sh->data
195 * so that the string pointers in the hash remain valid even if
196 * we need to realloc sh->data. We may want to avoid that later.
198 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
199 memcpy (sh->data + idx, str, len);
205 string_heap_init (MonoDynamicStream *sh)
208 sh->alloc_size = 4096;
209 sh->data = ALLOC_ATOMIC (4096);
210 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
211 string_heap_insert (sh, "");
214 #if 0 /* never used */
216 string_heap_free (MonoDynamicStream *sh)
218 FREE_ATOMIC (sh->data);
219 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
220 g_hash_table_destroy (sh->hash);
225 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
228 if (stream->alloc_size < stream->index + len)
229 make_room_in_stream (stream, stream->index + len);
230 memcpy (stream->data + stream->index, data, len);
232 stream->index += len;
234 * align index? Not without adding an additional param that controls it since
235 * we may store a blob value in pieces.
241 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memset (stream->data + stream->index, 0, len);
248 stream->index += len;
253 stream_data_align (MonoDynamicStream *stream)
256 guint32 count = stream->index % 4;
258 /* we assume the stream data will be aligned */
260 mono_image_add_stream_data (stream, buf, 4 - count);
264 mono_blob_entry_hash (const char* str)
268 len = mono_metadata_decode_blob_size (str, &str);
272 for (str += 1; str < end; str++)
273 h = (h << 5) - h + *str;
281 mono_blob_entry_equal (const char *str1, const char *str2) {
285 len = mono_metadata_decode_blob_size (str1, &end1);
286 len2 = mono_metadata_decode_blob_size (str2, &end2);
289 return memcmp (end1, end2, len) == 0;
293 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
297 gpointer oldkey, oldval;
299 copy = ALLOC_ATOMIC (s1+s2);
300 memcpy (copy, b1, s1);
301 memcpy (copy + s1, b2, s2);
302 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
304 idx = GPOINTER_TO_UINT (oldval);
306 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
307 mono_image_add_stream_data (&assembly->blob, b2, s2);
308 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
314 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
315 * dest may be misaligned.
318 swap_with_size (char *dest, const char* val, int len, int nelem) {
319 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
322 for (elem = 0; elem < nelem; ++elem) {
348 g_assert_not_reached ();
354 memcpy (dest, val, len * nelem);
359 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
363 guint32 idx = 0, len;
365 len = str->length * 2;
366 mono_metadata_encode_value (len, b, &b);
367 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
369 char *swapped = g_malloc (2 * mono_string_length (str));
370 const char *p = (const char*)mono_string_chars (str);
372 swap_with_size (swapped, p, 2, mono_string_length (str));
373 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
377 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
382 /* modified version needed to handle building corlib */
384 my_mono_class_from_mono_type (MonoType *type) {
385 switch (type->type) {
386 case MONO_TYPE_ARRAY:
388 case MONO_TYPE_SZARRAY:
389 case MONO_TYPE_GENERICINST:
390 return mono_class_from_mono_type (type);
393 g_assert (type->data.generic_param->pklass);
394 return type->data.generic_param->pklass;
396 /* should be always valid when we reach this case... */
397 return type->data.klass;
402 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
407 g_assert_not_reached ();
411 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
412 encode_type (assembly, ginst->generic_type, p, &p);
413 mono_metadata_encode_value (ginst->type_argc, p, &p);
414 for (i = 0; i < ginst->type_argc; ++i)
415 encode_type (assembly, ginst->type_argv [i], p, &p);
421 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
424 g_assert_not_reached ();
429 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
433 case MONO_TYPE_BOOLEAN:
447 case MONO_TYPE_STRING:
448 case MONO_TYPE_OBJECT:
449 case MONO_TYPE_TYPEDBYREF:
450 mono_metadata_encode_value (type->type, p, &p);
453 mono_metadata_encode_value (type->type, p, &p);
454 encode_type (assembly, type->data.type, p, &p);
456 case MONO_TYPE_SZARRAY:
457 mono_metadata_encode_value (type->type, p, &p);
458 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
461 case MONO_TYPE_VALUETYPE:
462 case MONO_TYPE_CLASS: {
463 MonoClass *k = mono_class_from_mono_type (type);
464 mono_metadata_encode_value (type->type, p, &p);
466 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
467 * otherwise two typerefs could point to the same type, leading to
468 * verification errors.
470 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
474 case MONO_TYPE_ARRAY:
475 mono_metadata_encode_value (type->type, p, &p);
476 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
477 mono_metadata_encode_value (type->data.array->rank, p, &p);
478 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
479 mono_metadata_encode_value (0, p, &p);
481 case MONO_TYPE_GENERICINST:
482 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
486 mono_metadata_encode_value (type->type, p, &p);
487 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
491 g_error ("need to encode type %x", type->type);
497 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
500 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
504 encode_type (assembly, type->type, p, endbuf);
508 g_assert_not_reached ();
513 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
518 for (i = 0; i < mono_array_length (modreq); ++i) {
519 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
520 *p = MONO_TYPE_CMOD_REQD;
522 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
526 for (i = 0; i < mono_array_length (modopt); ++i) {
527 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
528 *p = MONO_TYPE_CMOD_OPT;
530 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
537 generic_inst_get_signature_size (MonoGenericInst *ginst)
543 g_assert_not_reached ();
546 size += 1 + type_get_signature_size (ginst->generic_type);
548 for (i = 0; i < ginst->type_argc; ++i)
549 size += type_get_signature_size (ginst->type_argv [i]);
555 type_get_signature_size (MonoType *type)
560 g_assert_not_reached ();
568 case MONO_TYPE_BOOLEAN:
582 case MONO_TYPE_STRING:
583 case MONO_TYPE_OBJECT:
584 case MONO_TYPE_TYPEDBYREF:
587 return size + 1 + type_get_signature_size (type->data.type);
588 case MONO_TYPE_SZARRAY:
589 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
591 case MONO_TYPE_VALUETYPE:
592 case MONO_TYPE_CLASS:
595 case MONO_TYPE_ARRAY:
596 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
597 case MONO_TYPE_GENERICINST:
598 return size + generic_inst_get_signature_size (type->data.generic_inst);
604 g_error ("need to encode type %x", type->type);
610 method_get_signature_size (MonoMethodSignature *sig)
615 size = type_get_signature_size (sig->ret);
616 for (i = 0; i < sig->param_count; i++)
617 size += type_get_signature_size (sig->params [i]);
619 if (sig->generic_param_count)
626 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
631 guint32 nparams = sig->param_count;
632 guint32 size = 11 + method_get_signature_size (sig);
640 p = buf = g_malloc (size);
642 * FIXME: vararg, explicit_this, differenc call_conv values...
644 *p = sig->call_convention;
646 *p |= 0x20; /* hasthis */
647 if (sig->generic_param_count)
648 *p |= 0x10; /* generic */
650 if (sig->generic_param_count)
651 mono_metadata_encode_value (sig->generic_param_count, p, &p);
652 mono_metadata_encode_value (nparams, p, &p);
653 encode_type (assembly, sig->ret, p, &p);
654 for (i = 0; i < nparams; ++i)
655 encode_type (assembly, sig->params [i], p, &p);
657 g_assert (p - buf < size);
658 mono_metadata_encode_value (p-buf, b, &b);
659 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
665 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
668 * FIXME: reuse code from method_encode_signature().
673 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
674 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
675 guint32 size = 21 + nparams * 20;
680 p = buf = g_malloc (size);
681 /* LAMESPEC: all the call conv spec is foobared */
682 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
683 if (mb->call_conv & 2)
684 *p |= 0x5; /* vararg */
685 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
686 *p |= 0x20; /* hasthis */
688 *p |= 0x10; /* generic */
691 mono_metadata_encode_value (ngparams, p, &p);
692 mono_metadata_encode_value (nparams, p, &p);
693 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
694 encode_reflection_type (assembly, mb->rtype, p, &p);
695 for (i = 0; i < nparams; ++i) {
696 MonoArray *modreq = NULL;
697 MonoArray *modopt = NULL;
698 MonoReflectionType *pt;
700 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
701 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
702 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
703 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
704 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
705 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
706 encode_reflection_type (assembly, pt, p, &p);
709 g_assert (p - buf < size);
710 mono_metadata_encode_value (p-buf, b, &b);
711 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
717 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
719 MonoDynamicTable *table;
722 guint32 idx, sig_idx, size;
723 guint nl = mono_array_length (ilgen->locals);
730 p = buf = g_malloc (size);
731 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
732 idx = table->next_idx ++;
734 alloc_table (table, table->rows);
735 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
737 mono_metadata_encode_value (0x07, p, &p);
738 mono_metadata_encode_value (nl, p, &p);
739 for (i = 0; i < nl; ++i) {
740 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
743 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
745 encode_reflection_type (assembly, lb->type, p, &p);
747 g_assert (p - buf < size);
748 mono_metadata_encode_value (p-buf, b, &b);
749 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
752 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
758 method_count_clauses (MonoReflectionILGen *ilgen)
760 guint32 num_clauses = 0;
763 MonoILExceptionInfo *ex_info;
764 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
765 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
766 if (ex_info->handlers)
767 num_clauses += mono_array_length (ex_info->handlers);
775 static MonoExceptionClause*
776 method_encode_clauses (MonoDynamicImage *assembly,
777 MonoReflectionILGen *ilgen, guint32 num_clauses)
779 MonoExceptionClause *clauses;
780 MonoExceptionClause *clause;
781 MonoILExceptionInfo *ex_info;
782 MonoILExceptionBlock *ex_block;
783 guint32 finally_start;
784 int i, j, clause_index;;
786 clauses = g_new0 (MonoExceptionClause, num_clauses);
789 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
790 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
791 finally_start = ex_info->start + ex_info->len;
792 g_assert (ex_info->handlers);
793 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
794 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
795 clause = &(clauses [clause_index]);
797 clause->flags = ex_block->type;
798 clause->try_offset = ex_info->start;
800 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
801 clause->try_len = finally_start - ex_info->start;
803 clause->try_len = ex_info->len;
804 clause->handler_offset = ex_block->start;
805 clause->handler_len = ex_block->len;
806 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
807 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
808 if (ex_block->extype) {
809 mono_g_hash_table_insert (assembly->tokens,
810 GUINT_TO_POINTER (clause->token_or_filter),
813 finally_start = ex_block->start + ex_block->len;
823 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
829 gint32 num_locals = 0;
830 gint32 num_exception = 0;
833 char fat_header [12];
836 guint32 local_sig = 0;
837 guint32 header_size = 12;
840 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
841 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
842 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
843 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
847 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
849 code = mb->ilgen->code;
850 code_size = mb->ilgen->code_len;
851 max_stack = mb->ilgen->max_stack;
852 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
853 if (mb->ilgen->ex_handlers)
854 num_exception = method_count_clauses (mb->ilgen);
858 char *name = mono_string_to_utf8 (mb->name);
859 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
860 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
863 mono_raise_exception (exception);
866 code_size = mono_array_length (code);
867 max_stack = 8; /* we probably need to run a verifier on the code... */
870 /* check for exceptions, maxstack, locals */
871 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
873 if (code_size < 64 && !(code_size & 1)) {
874 flags = (code_size << 2) | 0x2;
875 } else if (code_size < 32 && (code_size & 1)) {
876 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
880 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
881 /* add to the fixup todo list */
882 if (mb->ilgen && mb->ilgen->num_token_fixups)
883 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
884 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
885 return assembly->text_rva + idx;
889 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
891 * FIXME: need to set also the header size in fat_flags.
892 * (and more sects and init locals flags)
896 fat_flags |= METHOD_HEADER_MORE_SECTS;
898 fat_flags |= METHOD_HEADER_INIT_LOCALS;
899 fat_header [0] = fat_flags;
900 fat_header [1] = (header_size / 4 ) << 4;
901 shortp = (guint16*)(fat_header + 2);
902 *shortp = GUINT16_TO_LE (max_stack);
903 intp = (guint32*)(fat_header + 4);
904 *intp = GUINT32_TO_LE (code_size);
905 intp = (guint32*)(fat_header + 8);
906 *intp = GUINT32_TO_LE (local_sig);
907 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
908 /* add to the fixup todo list */
909 if (mb->ilgen && mb->ilgen->num_token_fixups)
910 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
912 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
914 unsigned char sheader [4];
915 MonoExceptionClause clause;
916 MonoILExceptionInfo * ex_info;
917 MonoILExceptionBlock * ex_block;
920 stream_data_align (&assembly->code);
921 /* always use fat format for now */
922 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
923 num_exception *= sizeof (MonoExceptionClause);
924 num_exception += 4; /* include the size of the header */
925 sheader [1] = num_exception & 0xff;
926 sheader [2] = (num_exception >> 8) & 0xff;
927 sheader [3] = (num_exception >> 16) & 0xff;
928 mono_image_add_stream_data (&assembly->code, sheader, 4);
929 /* fat header, so we are already aligned */
931 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
932 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
933 if (ex_info->handlers) {
934 int finally_start = ex_info->start + ex_info->len;
935 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
936 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
937 clause.flags = GUINT32_TO_LE (ex_block->type);
938 clause.try_offset = GUINT32_TO_LE (ex_info->start);
939 /* need fault, too, probably */
940 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
941 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
943 clause.try_len = GUINT32_TO_LE (ex_info->len);
944 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
945 clause.handler_len = GUINT32_TO_LE (ex_block->len);
946 finally_start = ex_block->start + ex_block->len;
947 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
948 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
949 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
950 /*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",
951 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);*/
952 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
955 g_error ("No clauses for ex info block %d", i);
959 return assembly->text_rva + idx;
963 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
966 MonoDynamicTable *table;
969 table = &assembly->tables [table_idx];
971 g_assert (col < table->columns);
973 values = table->values + table->columns;
974 for (i = 1; i <= table->rows; ++i) {
975 if (values [col] == token)
977 values += table->columns;
982 static GHashTable *dynamic_custom_attrs = NULL;
984 static MonoCustomAttrInfo*
985 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
988 MonoCustomAttrInfo *ainfo;
989 MonoReflectionCustomAttr *cattr;
993 /* FIXME: check in assembly the Run flag is set */
995 count = mono_array_length (cattrs);
997 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
999 ainfo->image = image;
1000 ainfo->num_attrs = count;
1001 for (i = 0; i < count; ++i) {
1002 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1003 ainfo->attrs [i].ctor = cattr->ctor->method;
1004 /* FIXME: might want to memdup the data here */
1005 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1006 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1013 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1015 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1020 if (!dynamic_custom_attrs)
1021 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1023 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1027 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1029 /* they are cached, so we don't free them */
1030 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1036 * idx is the table index of the object
1037 * type is one of CUSTOM_ATTR_*
1040 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1042 MonoDynamicTable *table;
1043 MonoReflectionCustomAttr *cattr;
1045 guint32 count, i, token;
1047 char *p = blob_size;
1049 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1052 count = mono_array_length (cattrs);
1053 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1054 table->rows += count;
1055 alloc_table (table, table->rows);
1056 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1057 idx <<= CUSTOM_ATTR_BITS;
1059 for (i = 0; i < count; ++i) {
1060 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1061 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1062 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1063 type = mono_metadata_token_index (token);
1064 type <<= CUSTOM_ATTR_TYPE_BITS;
1065 switch (mono_metadata_token_table (token)) {
1066 case MONO_TABLE_METHOD:
1067 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1069 case MONO_TABLE_MEMBERREF:
1070 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1073 g_warning ("got wrong token in custom attr");
1076 values [MONO_CUSTOM_ATTR_TYPE] = type;
1078 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1079 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1080 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1081 values += MONO_CUSTOM_ATTR_SIZE;
1087 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1088 MonoArray *permissions)
1090 MonoDynamicTable *table;
1092 guint32 count, i, idx;
1093 MonoReflectionPermissionSet *perm;
1098 count = mono_array_length (permissions);
1099 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1100 table->rows += count;
1101 alloc_table (table, table->rows);
1103 for (i = 0; i < mono_array_length (permissions); ++i) {
1104 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1106 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1108 idx = mono_metadata_token_index (parent_token);
1109 idx <<= HAS_DECL_SECURITY_BITS;
1110 switch (mono_metadata_token_table (parent_token)) {
1111 case MONO_TABLE_TYPEDEF:
1112 idx |= HAS_DECL_SECURITY_TYPEDEF;
1114 case MONO_TABLE_METHOD:
1115 idx |= HAS_DECL_SECURITY_METHODDEF;
1117 case MONO_TABLE_ASSEMBLY:
1118 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1121 g_assert_not_reached ();
1124 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1125 values [MONO_DECL_SECURITY_PARENT] = idx;
1126 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1133 * Fill in the MethodDef and ParamDef tables for a method.
1134 * This is used for both normal methods and constructors.
1137 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1139 MonoDynamicTable *table;
1144 /* room in this table is already allocated */
1145 table = &assembly->tables [MONO_TABLE_METHOD];
1146 *mb->table_idx = table->next_idx ++;
1147 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1148 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1149 name = mono_string_to_utf8 (mb->name);
1150 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1152 values [MONO_METHOD_FLAGS] = mb->attrs;
1153 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1154 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1155 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1157 table = &assembly->tables [MONO_TABLE_PARAM];
1158 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1160 mono_image_add_decl_security (assembly,
1161 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1165 MonoDynamicTable *mtable;
1168 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1169 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1172 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1173 if (mono_array_get (mb->pinfo, gpointer, i))
1176 table->rows += count;
1177 alloc_table (table, table->rows);
1178 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1179 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1180 MonoReflectionParamBuilder *pb;
1181 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1182 values [MONO_PARAM_FLAGS] = pb->attrs;
1183 values [MONO_PARAM_SEQUENCE] = i;
1184 if (pb->name != NULL) {
1185 name = mono_string_to_utf8 (pb->name);
1186 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1190 values [MONO_PARAM_NAME] = 0;
1191 values += MONO_PARAM_SIZE;
1192 if (pb->marshal_info) {
1194 alloc_table (mtable, mtable->rows);
1195 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1196 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1197 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1199 pb->table_idx = table->next_idx++;
1206 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1207 MonoReflectionMethodBuilder *mb)
1209 rmb->ilgen = mb->ilgen;
1210 rmb->rtype = mb->rtype;
1211 rmb->parameters = mb->parameters;
1212 rmb->generic_params = mb->generic_params;
1213 rmb->pinfo = mb->pinfo;
1214 rmb->attrs = mb->attrs;
1215 rmb->iattrs = mb->iattrs;
1216 rmb->call_conv = mb->call_conv;
1217 rmb->code = mb->code;
1218 rmb->type = mb->type;
1219 rmb->name = mb->name;
1220 rmb->table_idx = &mb->table_idx;
1221 rmb->init_locals = mb->init_locals;
1222 rmb->return_modreq = mb->return_modreq;
1223 rmb->return_modopt = mb->return_modopt;
1224 rmb->param_modreq = mb->param_modreq;
1225 rmb->param_modopt = mb->param_modopt;
1226 rmb->permissions = mb->permissions;
1227 rmb->mhandle = mb->mhandle;
1233 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1234 MonoReflectionCtorBuilder *mb)
1236 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1238 rmb->ilgen = mb->ilgen;
1239 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1240 rmb->parameters = mb->parameters;
1241 rmb->generic_params = NULL;
1242 rmb->pinfo = mb->pinfo;
1243 rmb->attrs = mb->attrs;
1244 rmb->iattrs = mb->iattrs;
1245 rmb->call_conv = mb->call_conv;
1247 rmb->type = mb->type;
1248 rmb->name = mono_string_new (mono_domain_get (), name);
1249 rmb->table_idx = &mb->table_idx;
1250 rmb->init_locals = mb->init_locals;
1251 rmb->return_modreq = NULL;
1252 rmb->return_modopt = NULL;
1253 rmb->param_modreq = mb->param_modreq;
1254 rmb->param_modopt = mb->param_modopt;
1255 rmb->permissions = mb->permissions;
1256 rmb->mhandle = mb->mhandle;
1262 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1263 MonoReflectionDynamicMethod *mb)
1265 rmb->ilgen = mb->ilgen;
1266 rmb->rtype = mb->rtype;
1267 rmb->parameters = mb->parameters;
1268 rmb->generic_params = NULL;
1270 rmb->attrs = mb->attrs;
1272 rmb->call_conv = mb->call_conv;
1275 rmb->name = mb->name;
1276 rmb->table_idx = NULL;
1277 rmb->init_locals = mb->init_locals;
1278 rmb->return_modreq = NULL;
1279 rmb->return_modopt = NULL;
1280 rmb->param_modreq = NULL;
1281 rmb->param_modopt = NULL;
1282 rmb->permissions = NULL;
1283 rmb->mhandle = mb->mhandle;
1289 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1291 MonoDynamicTable *table;
1294 ReflectionMethodBuilder rmb;
1297 reflection_methodbuilder_from_method_builder (&rmb, mb);
1299 mono_image_basic_method (&rmb, assembly);
1301 if (mb->dll) { /* It's a P/Invoke method */
1303 int charset = mb->charset & 0xf;
1304 int lasterr = mb->charset & 0x40;
1305 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1307 alloc_table (table, table->rows);
1308 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1309 /* map CharSet values to on-disk values */
1311 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1312 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1313 name = mono_string_to_utf8 (mb->dllentry);
1314 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1316 name = mono_string_to_utf8 (mb->dll);
1317 moduleref = string_heap_insert (&assembly->sheap, name);
1319 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1320 table = &assembly->tables [MONO_TABLE_MODULEREF];
1322 alloc_table (table, table->rows);
1323 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1324 values [MONO_IMPLMAP_SCOPE] = table->rows;
1328 if (mb->override_method) {
1329 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1331 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1333 alloc_table (table, table->rows);
1334 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1335 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1336 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1337 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1338 switch (mono_metadata_token_table (tok)) {
1339 case MONO_TABLE_MEMBERREF:
1340 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1342 case MONO_TABLE_METHOD:
1343 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1346 g_assert_not_reached ();
1348 values [MONO_METHODIMPL_DECLARATION] = tok;
1351 if (mb->generic_params) {
1352 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1353 table->rows += mono_array_length (mb->generic_params);
1354 alloc_table (table, table->rows);
1355 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1356 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1358 mono_image_get_generic_param_info (
1359 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1366 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1368 ReflectionMethodBuilder rmb;
1370 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1372 mono_image_basic_method (&rmb, assembly);
1376 type_get_fully_qualified_name (MonoType *type) {
1377 char *name, *result;
1381 name = mono_type_get_name (type);
1382 klass = my_mono_class_from_mono_type (type);
1383 ta = klass->image->assembly;
1385 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1386 name, ta->aname.name,
1387 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1388 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1389 ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
1395 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1399 klass = my_mono_class_from_mono_type (type);
1400 ta = klass->image->assembly;
1401 if (ta == ass || klass->image == mono_defaults.corlib)
1402 return mono_type_get_name (type);
1404 return type_get_fully_qualified_name (type);
1408 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1410 char blob_size [64];
1411 char *b = blob_size;
1416 if (!assembly->save)
1419 p = buf = g_malloc (64);
1421 mono_metadata_encode_value (0x06, p, &p);
1422 /* encode custom attributes before the type */
1423 encode_type (assembly, type, p, &p);
1424 g_assert (p-buf < 64);
1425 mono_metadata_encode_value (p-buf, b, &b);
1426 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1432 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1434 char blob_size [64];
1435 char *b = blob_size;
1440 p = buf = g_malloc (64);
1442 mono_metadata_encode_value (0x06, p, &p);
1443 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1444 /* encode custom attributes before the type */
1445 encode_reflection_type (assembly, fb->type, p, &p);
1446 g_assert (p-buf < 64);
1447 mono_metadata_encode_value (p-buf, b, &b);
1448 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1454 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1455 char blob_size [64];
1456 char *b = blob_size;
1459 guint32 idx = 0, len = 0, dummy = 0;
1461 p = buf = g_malloc (64);
1463 *ret_type = MONO_TYPE_CLASS;
1465 box_val = (char*)&dummy;
1467 box_val = ((char*)val) + sizeof (MonoObject);
1468 *ret_type = val->vtable->klass->byval_arg.type;
1471 switch (*ret_type) {
1472 case MONO_TYPE_BOOLEAN:
1477 case MONO_TYPE_CHAR:
1492 case MONO_TYPE_VALUETYPE:
1493 if (val->vtable->klass->enumtype) {
1494 *ret_type = val->vtable->klass->enum_basetype->type;
1497 g_error ("we can't encode valuetypes");
1498 case MONO_TYPE_CLASS:
1500 case MONO_TYPE_STRING: {
1501 MonoString *str = (MonoString*)val;
1502 /* there is no signature */
1503 len = str->length * 2;
1504 mono_metadata_encode_value (len, b, &b);
1505 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1507 char *swapped = g_malloc (2 * mono_string_length (str));
1508 const char *p = (const char*)mono_string_chars (str);
1510 swap_with_size (swapped, p, 2, mono_string_length (str));
1511 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1515 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1522 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1525 /* there is no signature */
1526 mono_metadata_encode_value (len, b, &b);
1527 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1528 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1529 swap_with_size (blob_size, box_val, len, 1);
1530 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1532 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1540 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1541 char blob_size [64];
1542 char *b = blob_size;
1543 char *p, *buf, *str;
1544 guint32 idx, len, bufsize = 256;
1546 p = buf = g_malloc (bufsize);
1548 switch (minfo->type) {
1549 case MONO_NATIVE_BYVALTSTR:
1550 case MONO_NATIVE_BYVALARRAY:
1551 mono_metadata_encode_value (minfo->type, p, &p);
1552 mono_metadata_encode_value (minfo->count, p, &p);
1554 case MONO_NATIVE_LPARRAY:
1555 mono_metadata_encode_value (minfo->type, p, &p);
1556 if (minfo->eltype || (minfo->count > 0)) {
1557 mono_metadata_encode_value (minfo->eltype, p, &p);
1558 if (minfo->count > 0) {
1559 mono_metadata_encode_value (0, p, &p);
1560 mono_metadata_encode_value (minfo->count, p, &p);
1564 case MONO_NATIVE_CUSTOM:
1565 mono_metadata_encode_value (minfo->type, p, &p);
1567 str = mono_string_to_utf8 (minfo->guid);
1569 mono_metadata_encode_value (len, p, &p);
1570 memcpy (p, str, len);
1574 mono_metadata_encode_value (0, p, &p);
1576 if (minfo->marshaltype) {
1577 str = mono_string_to_utf8 (minfo->marshaltype);
1579 mono_metadata_encode_value (len, p, &p);
1580 if (p + len >= buf + bufsize) {
1583 buf = g_realloc (buf, bufsize);
1586 memcpy (p, str, len);
1590 mono_metadata_encode_value (0, p, &p);
1592 if (minfo->marshaltyperef) {
1593 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1595 mono_metadata_encode_value (len, p, &p);
1596 if (p + len >= buf + bufsize) {
1599 buf = g_realloc (buf, bufsize);
1602 memcpy (p, str, len);
1606 mono_metadata_encode_value (0, p, &p);
1608 if (minfo->mcookie) {
1609 str = mono_string_to_utf8 (minfo->mcookie);
1611 mono_metadata_encode_value (len, p, &p);
1612 if (p + len >= buf + bufsize) {
1615 buf = g_realloc (buf, bufsize);
1618 memcpy (p, str, len);
1622 mono_metadata_encode_value (0, p, &p);
1626 mono_metadata_encode_value (minfo->type, p, &p);
1630 mono_metadata_encode_value (len, b, &b);
1631 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1637 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1639 MonoDynamicTable *table;
1643 /* maybe this fixup should be done in the C# code */
1644 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1645 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1646 table = &assembly->tables [MONO_TABLE_FIELD];
1647 fb->table_idx = table->next_idx ++;
1648 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1649 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1650 name = mono_string_to_utf8 (fb->name);
1651 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1653 values [MONO_FIELD_FLAGS] = fb->attrs;
1654 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1656 if (fb->offset != -1) {
1657 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1659 alloc_table (table, table->rows);
1660 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1661 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1662 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1664 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1665 guint32 field_type = 0;
1666 table = &assembly->tables [MONO_TABLE_CONSTANT];
1668 alloc_table (table, table->rows);
1669 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1670 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1671 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1672 values [MONO_CONSTANT_TYPE] = field_type;
1673 values [MONO_CONSTANT_PADDING] = 0;
1675 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1677 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1679 alloc_table (table, table->rows);
1680 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1681 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1683 * We store it in the code section because it's simpler for now.
1686 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1688 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1689 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1691 if (fb->marshal_info) {
1692 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1694 alloc_table (table, table->rows);
1695 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1696 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1697 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1702 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1706 char *b = blob_size;
1707 guint32 nparams = 0;
1708 MonoReflectionMethodBuilder *mb = fb->get_method;
1709 MonoReflectionMethodBuilder *smb = fb->set_method;
1710 guint32 idx, i, size;
1712 if (mb && mb->parameters)
1713 nparams = mono_array_length (mb->parameters);
1714 if (!mb && smb && smb->parameters)
1715 nparams = mono_array_length (smb->parameters) - 1;
1716 size = 24 + nparams * 10;
1717 buf = p = g_malloc (size);
1720 mono_metadata_encode_value (nparams, p, &p);
1722 encode_reflection_type (assembly, mb->rtype, p, &p);
1723 for (i = 0; i < nparams; ++i) {
1724 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1725 encode_reflection_type (assembly, pt, p, &p);
1728 /* the property type is the last param */
1729 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1730 for (i = 0; i < nparams; ++i) {
1731 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1732 encode_reflection_type (assembly, pt, p, &p);
1736 g_assert (p - buf < size);
1737 mono_metadata_encode_value (p-buf, b, &b);
1738 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1744 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1746 MonoDynamicTable *table;
1749 guint num_methods = 0;
1753 * we need to set things in the following tables:
1754 * PROPERTYMAP (info already filled in _get_type_info ())
1755 * PROPERTY (rows already preallocated in _get_type_info ())
1756 * METHOD (method info already done with the generic method code)
1759 table = &assembly->tables [MONO_TABLE_PROPERTY];
1760 pb->table_idx = table->next_idx ++;
1761 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1762 name = mono_string_to_utf8 (pb->name);
1763 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1765 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1766 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1768 /* FIXME: we still don't handle 'other' methods */
1769 if (pb->get_method) num_methods ++;
1770 if (pb->set_method) num_methods ++;
1772 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1773 table->rows += num_methods;
1774 alloc_table (table, table->rows);
1776 if (pb->get_method) {
1777 semaidx = table->next_idx ++;
1778 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1779 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1780 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1781 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1783 if (pb->set_method) {
1784 semaidx = table->next_idx ++;
1785 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1786 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1787 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1788 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1793 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1795 MonoDynamicTable *table;
1798 guint num_methods = 0;
1802 * we need to set things in the following tables:
1803 * EVENTMAP (info already filled in _get_type_info ())
1804 * EVENT (rows already preallocated in _get_type_info ())
1805 * METHOD (method info already done with the generic method code)
1808 table = &assembly->tables [MONO_TABLE_EVENT];
1809 eb->table_idx = table->next_idx ++;
1810 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1811 name = mono_string_to_utf8 (eb->name);
1812 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1814 values [MONO_EVENT_FLAGS] = eb->attrs;
1815 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1818 * FIXME: we still don't handle 'other' methods
1820 if (eb->add_method) num_methods ++;
1821 if (eb->remove_method) num_methods ++;
1822 if (eb->raise_method) num_methods ++;
1824 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1825 table->rows += num_methods;
1826 alloc_table (table, table->rows);
1828 if (eb->add_method) {
1829 semaidx = table->next_idx ++;
1830 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1831 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1832 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1833 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1835 if (eb->remove_method) {
1836 semaidx = table->next_idx ++;
1837 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1838 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1839 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1840 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1842 if (eb->raise_method) {
1843 semaidx = table->next_idx ++;
1844 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1845 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1846 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1847 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1852 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1854 static MonoClass *NewConstraintAttr;
1855 static MonoMethod *NewConstraintAttr_ctor;
1856 MonoDynamicTable *table;
1858 guint32 token, type;
1859 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1862 if (!NewConstraintAttr)
1863 NewConstraintAttr = mono_class_from_name (
1864 mono_defaults.corlib, "System.Runtime.CompilerServices",
1865 "NewConstraintAttribute");
1866 g_assert (NewConstraintAttr);
1868 if (!NewConstraintAttr_ctor) {
1871 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1872 MonoMethod *m = NewConstraintAttr->methods [i];
1874 if (strcmp (m->name, ".ctor"))
1877 NewConstraintAttr_ctor = m;
1881 g_assert (NewConstraintAttr_ctor);
1884 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1886 alloc_table (table, table->rows);
1888 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1889 owner <<= CUSTOM_ATTR_BITS;
1890 owner |= CUSTOM_ATTR_GENERICPAR;
1891 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1893 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1895 type = mono_metadata_token_index (token);
1896 type <<= CUSTOM_ATTR_TYPE_BITS;
1897 switch (mono_metadata_token_table (token)) {
1898 case MONO_TABLE_METHOD:
1899 type |= CUSTOM_ATTR_TYPE_METHODDEF;
1901 case MONO_TABLE_MEMBERREF:
1902 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1905 g_warning ("got wrong token in custom attr");
1908 values [MONO_CUSTOM_ATTR_TYPE] = type;
1910 buf = p = g_malloc (1);
1911 mono_metadata_encode_value (4, p, &p);
1912 g_assert (p-buf == 1);
1914 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1916 values += MONO_CUSTOM_ATTR_SIZE;
1921 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1923 MonoDynamicTable *table;
1924 guint32 num_constraints, i;
1928 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1929 num_constraints = gparam->iface_constraints ?
1930 mono_array_length (gparam->iface_constraints) : 0;
1931 table->rows += num_constraints;
1932 if (gparam->base_type)
1934 alloc_table (table, table->rows);
1936 if (gparam->base_type) {
1937 table_idx = table->next_idx ++;
1938 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1940 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1941 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1942 assembly, gparam->base_type->type);
1945 for (i = 0; i < num_constraints; i++) {
1946 MonoReflectionType *constraint = mono_array_get (
1947 gparam->iface_constraints, gpointer, i);
1949 table_idx = table->next_idx ++;
1950 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1952 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1953 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1954 assembly, constraint->type);
1957 if (gparam->has_ctor_constraint)
1958 encode_new_constraint (assembly, owner);
1962 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1964 MonoDynamicTable *table;
1965 MonoGenericParam *param;
1969 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1970 table_idx = table->next_idx ++;
1971 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1973 param = gparam->type.type->data.generic_param;
1975 values [MONO_GENERICPARAM_OWNER] = owner;
1976 if (gparam->has_value_type)
1977 values [MONO_GENERICPARAM_FLAGS] = 0x18;
1978 else if (gparam->has_reference_type)
1979 values [MONO_GENERICPARAM_FLAGS] = 0x04;
1981 values [MONO_GENERICPARAM_FLAGS] = 0x00;
1982 values [MONO_GENERICPARAM_NUMBER] = param->num;
1983 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1984 values [MONO_GENERICPARAM_KIND] = 0;
1986 encode_constraints (gparam, table_idx, assembly);
1990 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1992 MonoDynamicTable *table;
1995 guint32 cols [MONO_ASSEMBLY_SIZE];
1999 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2002 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2003 table = &assembly->tables [MONO_TABLE_MODULEREF];
2004 token = table->next_idx ++;
2006 alloc_table (table, table->rows);
2007 values = table->values + token * MONO_MODULEREF_SIZE;
2008 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2010 token <<= RESOLTION_SCOPE_BITS;
2011 token |= RESOLTION_SCOPE_MODULEREF;
2012 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2017 if (image->assembly->dynamic)
2019 memset (cols, 0, sizeof (cols));
2021 /* image->assembly->image is the manifest module */
2022 image = image->assembly->image;
2023 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2026 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2027 token = table->next_idx ++;
2029 alloc_table (table, table->rows);
2030 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2031 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2032 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2033 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2034 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2035 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2036 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2037 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2038 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2040 if (strcmp ("", image->assembly->aname.culture)) {
2041 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2042 image->assembly->aname.culture);
2045 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2046 guchar pubtoken [9];
2048 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2049 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2051 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2053 token <<= RESOLTION_SCOPE_BITS;
2054 token |= RESOLTION_SCOPE_ASSEMBLYREF;
2055 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2060 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2062 MonoDynamicTable *table;
2068 char *b = blob_size;
2070 switch (type->type) {
2071 case MONO_TYPE_FNPTR:
2073 case MONO_TYPE_SZARRAY:
2074 case MONO_TYPE_ARRAY:
2076 case MONO_TYPE_MVAR:
2077 case MONO_TYPE_GENERICINST:
2078 encode_type (assembly, type, p, &p);
2080 case MONO_TYPE_CLASS:
2081 case MONO_TYPE_VALUETYPE: {
2082 MonoClass *k = mono_class_from_mono_type (type);
2083 if (!k || !k->generic_inst)
2085 encode_generic_inst (assembly, k->generic_inst, p, &p);
2092 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2093 if (assembly->save) {
2094 g_assert (p-sig < 128);
2095 mono_metadata_encode_value (p-sig, b, &b);
2096 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2097 alloc_table (table, table->rows + 1);
2098 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2099 values [MONO_TYPESPEC_SIGNATURE] = token;
2102 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2103 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2109 * Despite the name, we handle also TypeSpec (with the above helper).
2112 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2114 MonoDynamicTable *table;
2116 guint32 token, scope, enclosing;
2119 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2122 token = create_typespec (assembly, type);
2125 klass = my_mono_class_from_mono_type (type);
2127 klass = mono_class_from_mono_type (type);
2130 * If it's in the same module and not a generic type parameter:
2132 if ((klass->image == &assembly->image) &&
2133 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2134 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2135 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2136 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2140 if (klass->nested_in) {
2141 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2142 /* get the typeref idx of the enclosing type */
2143 enclosing >>= TYPEDEFORREF_BITS;
2144 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2146 scope = resolution_scope_from_image (assembly, klass->image);
2148 table = &assembly->tables [MONO_TABLE_TYPEREF];
2149 if (assembly->save) {
2150 alloc_table (table, table->rows + 1);
2151 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2152 values [MONO_TYPEREF_SCOPE] = scope;
2153 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2154 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2156 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2157 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2159 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2164 * Insert a memberef row into the metadata: the token that point to the memberref
2165 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2166 * mono_image_get_fieldref_token()).
2167 * The sig param is an index to an already built signature.
2170 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2172 MonoDynamicTable *table;
2174 guint32 token, pclass;
2177 parent = mono_image_typedef_or_ref (assembly, type);
2178 switch (parent & TYPEDEFORREF_MASK) {
2179 case TYPEDEFORREF_TYPEREF:
2180 pclass = MEMBERREF_PARENT_TYPEREF;
2182 case TYPEDEFORREF_TYPESPEC:
2183 pclass = MEMBERREF_PARENT_TYPESPEC;
2185 case TYPEDEFORREF_TYPEDEF:
2186 pclass = MEMBERREF_PARENT_TYPEDEF;
2189 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2192 /* extract the index */
2193 parent >>= TYPEDEFORREF_BITS;
2195 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2197 if (assembly->save) {
2198 alloc_table (table, table->rows + 1);
2199 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2200 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2201 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2202 values [MONO_MEMBERREF_SIGNATURE] = sig;
2205 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2212 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2216 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2219 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2220 method->name, method_encode_signature (assembly, method->signature));
2221 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2226 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2229 ReflectionMethodBuilder rmb;
2231 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2235 reflection_methodbuilder_from_method_builder (&rmb, mb);
2237 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2238 mono_string_to_utf8 (rmb.name),
2239 method_builder_encode_signature (assembly, &rmb));
2240 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2245 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2248 ReflectionMethodBuilder rmb;
2250 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2254 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2256 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2257 mono_string_to_utf8 (rmb.name),
2258 method_builder_encode_signature (assembly, &rmb));
2259 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2264 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2269 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2272 g_assert (f->field->parent);
2273 type = f->field->generic_type ? f->field->generic_type : f->field->type;
2274 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2275 f->field->name, fieldref_encode_signature (assembly, type));
2276 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2281 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2286 guint32 nparams = gmethod->mtype_argc;
2287 guint32 size = 10 + nparams * 10;
2290 char *b = blob_size;
2292 if (!assembly->save)
2295 p = buf = g_malloc (size);
2297 * FIXME: vararg, explicit_this, differenc call_conv values...
2299 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2300 mono_metadata_encode_value (nparams, p, &p);
2302 for (i = 0; i < nparams; i++)
2303 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2306 g_assert (p - buf < size);
2307 mono_metadata_encode_value (p-buf, b, &b);
2308 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2314 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2316 MonoDynamicTable *table;
2318 guint32 token, mtoken = 0, sig;
2319 MonoMethodInflated *imethod;
2320 MonoMethod *declaring;
2322 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2324 g_assert (method->signature->is_inflated);
2325 imethod = (MonoMethodInflated *) method;
2326 declaring = imethod->declaring;
2328 sig = method_encode_signature (assembly, declaring->signature);
2329 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2330 declaring->name, sig);
2332 if (!declaring->signature->generic_param_count)
2335 switch (mono_metadata_token_table (mtoken)) {
2336 case MONO_TABLE_MEMBERREF:
2337 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2339 case MONO_TABLE_METHOD:
2340 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2343 g_assert_not_reached ();
2346 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2348 if (assembly->save) {
2349 alloc_table (table, table->rows + 1);
2350 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2351 values [MONO_METHODSPEC_METHOD] = mtoken;
2352 values [MONO_METHODSPEC_SIGNATURE] = sig;
2355 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2362 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2364 MonoMethodInflated *imethod;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2371 g_assert (m->signature->is_inflated);
2372 imethod = (MonoMethodInflated *) m;
2374 if (imethod->declaring->signature->generic_param_count)
2375 token = method_encode_methodspec (assembly, m);
2377 guint32 sig = method_encode_signature (
2378 assembly, imethod->declaring->signature);
2379 token = mono_image_get_memberref_token (
2380 assembly, &m->klass->byval_arg, m->name, sig);
2383 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2388 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2390 MonoDynamicTable *table;
2397 char *b = blob_size;
2401 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2402 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2403 * Because of this, we must not insert it into the `typeref' hash table.
2406 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2410 g_assert (tb->generic_params);
2411 klass = mono_class_from_mono_type (tb->type.type);
2413 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2414 encode_type (assembly, &klass->byval_arg, p, &p);
2416 count = mono_array_length (tb->generic_params);
2417 mono_metadata_encode_value (count, p, &p);
2418 for (i = 0; i < count; i++) {
2419 MonoReflectionGenericParam *gparam;
2421 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2423 encode_type (assembly, gparam->type.type, p, &p);
2426 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2427 if (assembly->save) {
2428 g_assert (p-sig < 128);
2429 mono_metadata_encode_value (p-sig, b, &b);
2430 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2431 alloc_table (table, table->rows + 1);
2432 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2433 values [MONO_TYPESPEC_SIGNATURE] = token;
2436 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2437 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2443 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2445 MonoDynamicTable *table;
2448 guint32 token, pclass, parent, sig;
2451 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2455 klass = mono_class_from_mono_type (fb->typeb->type);
2456 name = mono_string_to_utf8 (fb->name);
2458 sig = fieldref_encode_signature (assembly, fb->type->type);
2460 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2461 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2463 pclass = MEMBERREF_PARENT_TYPESPEC;
2464 parent >>= TYPEDEFORREF_BITS;
2466 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2468 if (assembly->save) {
2469 alloc_table (table, table->rows + 1);
2470 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2471 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2472 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2473 values [MONO_MEMBERREF_SIGNATURE] = sig;
2476 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2478 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2483 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2491 char *b = blob_size;
2493 if (!assembly->save)
2497 g_assert (helper->type == 2);
2499 if (helper->arguments)
2500 nargs = mono_array_length (helper->arguments);
2504 size = 10 + (nargs * 10);
2506 p = buf = g_malloc (size);
2508 /* Encode calling convention */
2509 /* Change Any to Standard */
2510 if ((helper->call_conv & 0x03) == 0x03)
2511 helper->call_conv = 0x01;
2512 /* explicit_this implies has_this */
2513 if (helper->call_conv & 0x40)
2514 helper->call_conv &= 0x20;
2516 if (helper->call_conv == 0) /* Unmanaged */
2517 *p = helper->unmanaged_call_conv - 1;
2520 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2521 if (helper->call_conv & 0x02) /* varargs */
2526 mono_metadata_encode_value (nargs, p, &p);
2527 encode_reflection_type (assembly, helper->return_type, p, &p);
2528 for (i = 0; i < nargs; ++i) {
2529 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2530 encode_reflection_type (assembly, pt, p, &p);
2533 g_assert (p - buf < size);
2534 mono_metadata_encode_value (p-buf, b, &b);
2535 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2542 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2545 MonoDynamicTable *table;
2548 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2549 idx = table->next_idx ++;
2551 alloc_table (table, table->rows);
2552 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2554 values [MONO_STAND_ALONE_SIGNATURE] =
2555 mono_reflection_encode_sighelper (assembly, helper);
2561 reflection_cc_to_file (int call_conv) {
2562 switch (call_conv & 0x3) {
2564 case 1: return MONO_CALL_DEFAULT;
2565 case 2: return MONO_CALL_VARARG;
2567 g_assert_not_reached ();
2574 MonoMethodSignature *sig;
2580 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2585 MonoMethodSignature *sig;
2588 name = mono_string_to_utf8 (m->name);
2589 nparams = mono_array_length (m->parameters);
2590 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2592 sig->call_convention = reflection_cc_to_file (m->call_conv);
2593 sig->param_count = nparams;
2594 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2595 for (i = 0; i < nparams; ++i) {
2596 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2597 sig->params [i] = t->type;
2600 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2602 if (strcmp (name, am->name) == 0 &&
2603 mono_metadata_type_equal (am->parent, m->parent->type) &&
2604 mono_metadata_signature_equal (am->sig, sig)) {
2607 m->table_idx = am->token & 0xffffff;
2611 am = g_new0 (ArrayMethod, 1);
2614 am->parent = m->parent->type;
2615 am->token = mono_image_get_memberref_token (assembly, am->parent,
2616 name, method_encode_signature (assembly, sig));
2617 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2618 m->table_idx = am->token & 0xffffff;
2623 * Insert into the metadata tables all the info about the TypeBuilder tb.
2624 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2627 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2629 MonoDynamicTable *table;
2631 int i, is_object = 0, is_system = 0;
2634 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2635 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2636 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2637 n = mono_string_to_utf8 (tb->name);
2638 if (strcmp (n, "Object") == 0)
2640 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2642 n = mono_string_to_utf8 (tb->nspace);
2643 if (strcmp (n, "System") == 0)
2645 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2647 if (tb->parent && !(is_system && is_object) &&
2648 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2649 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2651 values [MONO_TYPEDEF_EXTENDS] = 0;
2652 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2653 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2656 * if we have explicitlayout or sequentiallayouts, output data in the
2657 * ClassLayout table.
2659 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2660 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2662 alloc_table (table, table->rows);
2663 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2664 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2665 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2666 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2669 /* handle interfaces */
2670 if (tb->interfaces) {
2671 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2673 table->rows += mono_array_length (tb->interfaces);
2674 alloc_table (table, table->rows);
2675 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2676 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2677 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2678 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2679 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2680 values += MONO_INTERFACEIMPL_SIZE;
2684 /* handle generic parameters */
2685 if (tb->generic_params) {
2686 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2687 table->rows += mono_array_length (tb->generic_params);
2688 alloc_table (table, table->rows);
2689 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2690 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2692 mono_image_get_generic_param_info (
2693 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2699 table = &assembly->tables [MONO_TABLE_FIELD];
2700 table->rows += tb->num_fields;
2701 alloc_table (table, table->rows);
2702 for (i = 0; i < tb->num_fields; ++i)
2703 mono_image_get_field_info (
2704 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2707 /* handle constructors */
2709 table = &assembly->tables [MONO_TABLE_METHOD];
2710 table->rows += mono_array_length (tb->ctors);
2711 alloc_table (table, table->rows);
2712 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2713 mono_image_get_ctor_info (domain,
2714 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2717 /* handle methods */
2719 table = &assembly->tables [MONO_TABLE_METHOD];
2720 table->rows += tb->num_methods;
2721 alloc_table (table, table->rows);
2722 for (i = 0; i < tb->num_methods; ++i)
2723 mono_image_get_method_info (
2724 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2727 /* Do the same with properties etc.. */
2728 if (tb->events && mono_array_length (tb->events)) {
2729 table = &assembly->tables [MONO_TABLE_EVENT];
2730 table->rows += mono_array_length (tb->events);
2731 alloc_table (table, table->rows);
2732 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2734 alloc_table (table, table->rows);
2735 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2736 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2737 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2738 for (i = 0; i < mono_array_length (tb->events); ++i)
2739 mono_image_get_event_info (
2740 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2742 if (tb->properties && mono_array_length (tb->properties)) {
2743 table = &assembly->tables [MONO_TABLE_PROPERTY];
2744 table->rows += mono_array_length (tb->properties);
2745 alloc_table (table, table->rows);
2746 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2748 alloc_table (table, table->rows);
2749 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2750 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2751 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2752 for (i = 0; i < mono_array_length (tb->properties); ++i)
2753 mono_image_get_property_info (
2754 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2757 mono_image_add_decl_security (assembly,
2758 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2762 MonoDynamicTable *ntable;
2764 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2765 ntable->rows += mono_array_length (tb->subtypes);
2766 alloc_table (ntable, ntable->rows);
2767 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2769 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2770 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2772 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2773 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2774 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2775 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2776 mono_string_to_utf8 (tb->name), tb->table_idx,
2777 ntable->next_idx, ntable->rows);*/
2778 values += MONO_NESTED_CLASS_SIZE;
2785 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2789 g_ptr_array_add (types, type);
2791 if (!type->subtypes)
2794 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2795 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2796 collect_types (types, subtype);
2801 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2802 MonoReflectionTypeBuilder **type2)
2804 if ((*type1)->table_idx < (*type2)->table_idx)
2807 if ((*type1)->table_idx > (*type2)->table_idx)
2814 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2819 for (i = 0; i < mono_array_length (pinfo); ++i) {
2820 MonoReflectionParamBuilder *pb;
2821 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2824 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2829 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2832 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2834 for (i = 0; i < tb->num_fields; ++i) {
2835 MonoReflectionFieldBuilder* fb;
2836 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2837 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2841 for (i = 0; i < mono_array_length (tb->events); ++i) {
2842 MonoReflectionEventBuilder* eb;
2843 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2844 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2847 if (tb->properties) {
2848 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2849 MonoReflectionPropertyBuilder* pb;
2850 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2851 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2855 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2856 MonoReflectionCtorBuilder* cb;
2857 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2858 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2859 params_add_cattrs (assembly, cb->pinfo);
2864 for (i = 0; i < tb->num_methods; ++i) {
2865 MonoReflectionMethodBuilder* mb;
2866 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2867 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2868 params_add_cattrs (assembly, mb->pinfo);
2873 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2874 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2879 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2882 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2884 /* no types in the module */
2888 for (i = 0; i < mb->num_types; ++i)
2889 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2893 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2894 MonoDynamicImage *assembly)
2896 MonoDynamicTable *table;
2900 char *b = blob_size;
2903 table = &assembly->tables [MONO_TABLE_FILE];
2905 alloc_table (table, table->rows);
2906 values = table->values + table->next_idx * MONO_FILE_SIZE;
2907 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2908 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2909 if (module->image->dynamic) {
2910 /* This depends on the fact that the main module is emitted last */
2911 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2912 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2916 path = g_strdup (module->image->name);
2918 mono_sha1_get_digest_from_file (path, hash);
2921 mono_metadata_encode_value (20, b, &b);
2922 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2923 mono_image_add_stream_data (&assembly->blob, hash, 20);
2928 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2930 MonoDynamicTable *table;
2934 table = &assembly->tables [MONO_TABLE_MODULE];
2935 mb->table_idx = table->next_idx ++;
2936 name = mono_string_to_utf8 (mb->module.name);
2937 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2939 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2942 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2943 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2944 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2948 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2949 guint32 module_index, guint32 parent_index,
2950 MonoDynamicImage *assembly)
2952 MonoDynamicTable *table;
2956 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2957 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2960 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2962 alloc_table (table, table->rows);
2963 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2965 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2966 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2967 if (klass->nested_in)
2968 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2970 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2971 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2972 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2974 res = table->next_idx;
2978 /* Emit nested types */
2979 if (klass->nested_classes) {
2982 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2983 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2990 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2991 guint32 module_index, guint32 parent_index,
2992 MonoDynamicImage *assembly)
2997 klass = mono_class_from_mono_type (tb->type.type);
2999 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3001 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3002 parent_index, assembly);
3006 * We need to do this ourselves since klass->nested_classes is not set up.
3009 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3010 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3015 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3016 guint32 module_index,
3017 MonoDynamicImage *assembly)
3019 MonoImage *image = module->image;
3023 t = &image->tables [MONO_TABLE_TYPEDEF];
3025 for (i = 0; i < t->rows; ++i) {
3026 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3028 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3029 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3033 #define align_pointer(base,p)\
3035 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3037 (p) += 4 - (__diff & 3);\
3041 compare_semantics (const void *a, const void *b)
3043 const guint32 *a_values = a;
3044 const guint32 *b_values = b;
3045 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3048 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3052 compare_custom_attrs (const void *a, const void *b)
3054 const guint32 *a_values = a;
3055 const guint32 *b_values = b;
3057 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3061 compare_field_marshal (const void *a, const void *b)
3063 const guint32 *a_values = a;
3064 const guint32 *b_values = b;
3066 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3070 compare_nested (const void *a, const void *b)
3072 const guint32 *a_values = a;
3073 const guint32 *b_values = b;
3075 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3079 * build_compressed_metadata() fills in the blob of data that represents the
3080 * raw metadata as it will be saved in the PE file. The five streams are output
3081 * and the metadata tables are comnpressed from the guint32 array representation,
3082 * to the compressed on-disk format.
3085 build_compressed_metadata (MonoDynamicImage *assembly)
3087 MonoDynamicTable *table;
3089 guint64 valid_mask = 0;
3090 guint64 sorted_mask;
3091 guint32 heapt_size = 0;
3092 guint32 meta_size = 256; /* allow for header and other stuff */
3093 guint32 table_offset;
3094 guint32 ntables = 0;
3103 MonoDynamicStream *stream;
3106 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3107 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3108 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3109 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3110 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3112 /* tables that are sorted */
3113 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3114 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3115 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3116 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3117 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3118 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3120 /* Compute table sizes */
3121 /* the MonoImage has already been created in mono_image_basic_init() */
3122 meta = &assembly->image;
3124 /* Setup the info used by compute_sizes () */
3125 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3126 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3127 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3129 meta_size += assembly->blob.index;
3130 meta_size += assembly->guid.index;
3131 meta_size += assembly->sheap.index;
3132 meta_size += assembly->us.index;
3134 for (i=0; i < 64; ++i)
3135 meta->tables [i].rows = assembly->tables [i].rows;
3137 for (i = 0; i < 64; i++){
3138 if (meta->tables [i].rows == 0)
3140 valid_mask |= (guint64)1 << i;
3142 meta->tables [i].row_size = mono_metadata_compute_size (
3143 meta, i, &meta->tables [i].size_bitfield);
3144 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3146 heapt_size += 24; /* #~ header size */
3147 heapt_size += ntables * 4;
3148 meta_size += heapt_size;
3149 meta->raw_metadata = g_malloc0 (meta_size);
3150 p = meta->raw_metadata;
3151 /* the metadata signature */
3152 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3153 /* version numbers and 4 bytes reserved */
3154 int16val = (guint16*)p;
3155 *int16val++ = GUINT16_TO_LE (1);
3156 *int16val = GUINT16_TO_LE (1);
3158 /* version string */
3159 int32val = (guint32*)p;
3160 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3162 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3163 p += GUINT32_FROM_LE (*int32val);
3164 align_pointer (meta->raw_metadata, p);
3165 int16val = (guint16*)p;
3166 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3167 *int16val = GUINT16_TO_LE (5); /* number of streams */
3171 * write the stream info.
3173 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3174 table_offset += 3; table_offset &= ~3;
3176 assembly->tstream.index = heapt_size;
3177 for (i = 0; i < 5; ++i) {
3178 int32val = (guint32*)p;
3179 stream_desc [i].stream->offset = table_offset;
3180 *int32val++ = GUINT32_TO_LE (table_offset);
3181 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3182 table_offset += GUINT32_FROM_LE (*int32val);
3183 table_offset += 3; table_offset &= ~3;
3185 strcpy (p, stream_desc [i].name);
3186 p += strlen (stream_desc [i].name) + 1;
3187 align_pointer (meta->raw_metadata, p);
3190 * now copy the data, the table stream header and contents goes first.
3192 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3193 p = meta->raw_metadata + assembly->tstream.offset;
3194 int32val = (guint32*)p;
3195 *int32val = GUINT32_TO_LE (0); /* reserved */
3198 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3199 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3200 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3201 *p++ = 1; /* version */
3204 *p++ = 1; /* version */
3208 if (meta->idx_string_wide)
3210 if (meta->idx_guid_wide)
3212 if (meta->idx_blob_wide)
3215 *p++ = 0; /* reserved */
3216 int64val = (guint64*)p;
3217 *int64val++ = GUINT64_TO_LE (valid_mask);
3218 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3220 int32val = (guint32*)p;
3221 for (i = 0; i < 64; i++){
3222 if (meta->tables [i].rows == 0)
3224 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3226 p = (unsigned char*)int32val;
3228 /* sort the tables that still need sorting */
3229 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3231 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3232 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3234 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3235 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3237 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3238 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3240 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3242 /* compress the tables */
3243 for (i = 0; i < 64; i++){
3246 guint32 bitfield = meta->tables [i].size_bitfield;
3247 if (!meta->tables [i].rows)
3249 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3250 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3251 meta->tables [i].base = p;
3252 for (row = 1; row <= meta->tables [i].rows; ++row) {
3253 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3254 for (col = 0; col < assembly->tables [i].columns; ++col) {
3255 switch (mono_metadata_table_size (bitfield, col)) {
3257 *p++ = values [col];
3260 *p++ = values [col] & 0xff;
3261 *p++ = (values [col] >> 8) & 0xff;
3264 *p++ = values [col] & 0xff;
3265 *p++ = (values [col] >> 8) & 0xff;
3266 *p++ = (values [col] >> 16) & 0xff;
3267 *p++ = (values [col] >> 24) & 0xff;
3270 g_assert_not_reached ();
3274 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3277 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3278 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3279 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3280 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3281 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3283 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3287 * Some tables in metadata need to be sorted according to some criteria, but
3288 * when methods and fields are first created with reflection, they may be assigned a token
3289 * that doesn't correspond to the final token they will get assigned after the sorting.
3290 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3291 * with the reflection objects that represent them. Once all the tables are set up, the
3292 * reflection objects will contains the correct table index. fixup_method() will fixup the
3293 * tokens for the method with ILGenerator @ilgen.
3296 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3297 guint32 code_idx = GPOINTER_TO_UINT (value);
3298 MonoReflectionILTokenInfo *iltoken;
3299 MonoReflectionFieldBuilder *field;
3300 MonoReflectionCtorBuilder *ctor;
3301 MonoReflectionMethodBuilder *method;
3302 MonoReflectionTypeBuilder *tb;
3303 MonoReflectionArrayMethod *am;
3305 unsigned char *target;
3307 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3308 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3309 target = assembly->code.data + code_idx + iltoken->code_pos;
3310 switch (target [3]) {
3311 case MONO_TABLE_FIELD:
3312 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3313 field = (MonoReflectionFieldBuilder *)iltoken->member;
3314 idx = field->table_idx;
3315 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3316 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3317 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3319 g_assert_not_reached ();
3322 case MONO_TABLE_METHOD:
3323 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3324 method = (MonoReflectionMethodBuilder *)iltoken->member;
3325 idx = method->table_idx;
3326 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3327 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3328 idx = ctor->table_idx;
3329 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3330 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3331 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3332 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3334 g_assert_not_reached ();
3337 case MONO_TABLE_TYPEDEF:
3338 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3339 g_assert_not_reached ();
3340 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3341 idx = tb->table_idx;
3343 case MONO_TABLE_MEMBERREF:
3344 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3345 am = (MonoReflectionArrayMethod*)iltoken->member;
3346 idx = am->table_idx;
3347 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3348 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3349 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3350 g_assert (m->klass->generic_inst);
3352 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3354 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3355 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3356 g_assert (f->generic_type);
3359 g_assert_not_reached ();
3362 case MONO_TABLE_METHODSPEC:
3363 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3364 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3365 g_assert (m->signature->generic_param_count);
3368 g_assert_not_reached ();
3372 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3374 target [0] = idx & 0xff;
3375 target [1] = (idx >> 8) & 0xff;
3376 target [2] = (idx >> 16) & 0xff;
3383 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3384 * value is not known when the table is emitted.
3387 fixup_cattrs (MonoDynamicImage *assembly)
3389 MonoDynamicTable *table;
3391 guint32 type, i, idx, token;
3394 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3396 for (i = 0; i < table->rows; ++i) {
3397 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3399 type = values [MONO_CUSTOM_ATTR_TYPE];
3400 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3401 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3402 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3403 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3406 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3407 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3408 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3409 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3416 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3418 MonoDynamicTable *table;
3422 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3424 alloc_table (table, table->rows);
3425 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3426 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3427 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3428 name = mono_string_to_utf8 (rsrc->name);
3429 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3431 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3436 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3438 MonoDynamicTable *table;
3442 char *b = blob_size;
3444 guint32 idx, offset;
3446 if (rsrc->filename) {
3447 name = mono_string_to_utf8 (rsrc->filename);
3448 sname = g_path_get_basename (name);
3450 table = &assembly->tables [MONO_TABLE_FILE];
3452 alloc_table (table, table->rows);
3453 values = table->values + table->next_idx * MONO_FILE_SIZE;
3454 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3455 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3458 mono_sha1_get_digest_from_file (name, hash);
3459 mono_metadata_encode_value (20, b, &b);
3460 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3461 mono_image_add_stream_data (&assembly->blob, hash, 20);
3463 idx = table->next_idx++;
3465 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3468 offset = mono_array_length (rsrc->data);
3469 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3470 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3471 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3472 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3476 * The entry should be emitted into the MANIFESTRESOURCE table of
3477 * the main module, but that needs to reference the FILE table
3478 * which isn't emitted yet.
3485 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3489 set_version_from_string (MonoString *version, guint32 *values)
3491 gchar *ver, *p, *str;
3494 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3495 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3496 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3497 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3500 ver = str = mono_string_to_utf8 (version);
3501 for (i = 0; i < 4; ++i) {
3502 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3508 /* handle Revision and Build */
3518 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3522 char *b = blob_size;
3527 len = mono_array_length (pkey);
3528 mono_metadata_encode_value (len, b, &b);
3529 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3530 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3532 /* need to get the actual value from the key type... */
3533 assembly->strong_name_size = 128;
3534 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3540 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3542 MonoDynamicTable *table;
3543 MonoDynamicImage *assembly;
3544 MonoReflectionAssemblyBuilder *assemblyb;
3549 guint32 module_index;
3551 assemblyb = moduleb->assemblyb;
3552 assembly = moduleb->dynamic_image;
3553 domain = mono_object_domain (assemblyb);
3555 /* Emit ASSEMBLY table */
3556 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3557 alloc_table (table, 1);
3558 values = table->values + MONO_ASSEMBLY_SIZE;
3559 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3560 name = mono_string_to_utf8 (assemblyb->name);
3561 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3563 if (assemblyb->culture) {
3564 name = mono_string_to_utf8 (assemblyb->culture);
3565 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3568 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3570 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3571 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3572 set_version_from_string (assemblyb->version, values);
3574 /* Emit FILE + EXPORTED_TYPE table */
3576 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3578 MonoReflectionModuleBuilder *file_module =
3579 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3580 if (file_module != moduleb) {
3581 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3583 if (file_module->types) {
3584 for (j = 0; j < file_module->num_types; ++j) {
3585 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3586 mono_image_fill_export_table (domain, tb, module_index, 0,
3592 if (assemblyb->loaded_modules) {
3593 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3594 MonoReflectionModule *file_module =
3595 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3596 mono_image_fill_file_table (domain, file_module, assembly);
3598 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3602 /* Emit MANIFESTRESOURCE table */
3604 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3606 MonoReflectionModuleBuilder *file_module =
3607 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3608 /* The table for the main module is emitted later */
3609 if (file_module != moduleb) {
3611 if (file_module->resources) {
3612 int len = mono_array_length (file_module->resources);
3613 for (j = 0; j < len; ++j) {
3614 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3615 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3623 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3624 * for the modulebuilder @moduleb.
3625 * At the end of the process, method and field tokens are fixed up and the
3626 * on-disk compressed metadata representation is created.
3629 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3631 MonoDynamicTable *table;
3632 MonoDynamicImage *assembly;
3633 MonoReflectionAssemblyBuilder *assemblyb;
3638 assemblyb = moduleb->assemblyb;
3639 assembly = moduleb->dynamic_image;
3640 domain = mono_object_domain (assemblyb);
3642 if (assembly->text_rva)
3645 assembly->text_rva = START_TEXT_RVA;
3647 if (moduleb->is_main) {
3648 mono_image_emit_manifest (moduleb);
3651 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3652 table->rows = 1; /* .<Module> */
3654 alloc_table (table, table->rows);
3656 * Set the first entry.
3658 values = table->values + table->columns;
3659 values [MONO_TYPEDEF_FLAGS] = 0;
3660 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3661 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3662 values [MONO_TYPEDEF_EXTENDS] = 0;
3663 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3664 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3667 * handle global methods
3668 * FIXME: test what to do when global methods are defined in multiple modules.
3670 if (moduleb->global_methods) {
3671 table = &assembly->tables [MONO_TABLE_METHOD];
3672 table->rows += mono_array_length (moduleb->global_methods);
3673 alloc_table (table, table->rows);
3674 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3675 mono_image_get_method_info (
3676 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3678 if (moduleb->global_fields) {
3679 table = &assembly->tables [MONO_TABLE_FIELD];
3680 table->rows += mono_array_length (moduleb->global_fields);
3681 alloc_table (table, table->rows);
3682 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3683 mono_image_get_field_info (
3684 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3687 table = &assembly->tables [MONO_TABLE_MODULE];
3688 alloc_table (table, 1);
3689 mono_image_fill_module_table (domain, moduleb, assembly);
3693 /* Collect all types into a list sorted by their table_idx */
3694 GPtrArray *types = g_ptr_array_new ();
3697 for (i = 0; i < moduleb->num_types; ++i) {
3698 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3699 collect_types (types, type);
3702 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3703 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3704 table->rows += types->len;
3705 alloc_table (table, table->rows);
3707 for (i = 0; i < types->len; ++i) {
3708 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3709 mono_image_get_type_info (domain, type, assembly);
3711 g_ptr_array_free (types, TRUE);
3715 * table->rows is already set above and in mono_image_fill_module_table.
3717 /* add all the custom attributes at the end, once all the indexes are stable */
3718 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3720 module_add_cattrs (assembly, moduleb);
3723 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3724 fixup_cattrs (assembly);
3728 * mono_image_insert_string:
3729 * @module: module builder object
3732 * Insert @str into the user string stream of @module.
3735 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3737 MonoDynamicImage *assembly;
3742 MONO_ARCH_SAVE_REGS;
3744 if (!module->dynamic_image)
3745 mono_image_module_basic_init (module);
3747 assembly = module->dynamic_image;
3749 if (assembly->save) {
3750 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3751 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3752 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3754 char *swapped = g_malloc (2 * mono_string_length (str));
3755 const char *p = (const char*)mono_string_chars (str);
3757 swap_with_size (swapped, p, 2, mono_string_length (str));
3758 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3762 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3764 mono_image_add_stream_data (&assembly->us, "", 1);
3767 idx = assembly->us.index ++;
3769 mono_g_hash_table_insert (assembly->tokens,
3770 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3772 return MONO_TOKEN_STRING | idx;
3776 * mono_image_create_token:
3777 * @assembly: a dynamic assembly
3780 * Get a token to insert in the IL code stream for the given MemberInfo.
3781 * @obj can be one of:
3782 * ConstructorBuilder
3792 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3797 klass = obj->vtable->klass;
3798 if (strcmp (klass->name, "MethodBuilder") == 0) {
3799 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3801 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3802 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3804 token = mono_image_get_methodbuilder_token (assembly, mb);
3805 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3807 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3808 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3810 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3811 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3813 token = mono_image_get_ctorbuilder_token (assembly, mb);
3814 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3816 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3817 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3818 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3819 if (tb->generic_params) {
3820 token = mono_image_get_generic_field_token (assembly, fb);
3822 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3825 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3826 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3827 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3829 else if (strcmp (klass->name, "MonoType") == 0 ||
3830 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3831 MonoReflectionType *tb = (MonoReflectionType *)obj;
3832 token = mono_metadata_token_from_dor (
3833 mono_image_typedef_or_ref (assembly, tb->type));
3835 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3836 MonoReflectionType *tb = (MonoReflectionType *)obj;
3837 token = mono_metadata_token_from_dor (
3838 mono_image_typedef_or_ref (assembly, tb->type));
3840 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3841 strcmp (klass->name, "MonoMethod") == 0) {
3842 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3843 if (m->method->signature->is_inflated) {
3844 token = mono_image_get_methodspec_token (assembly, m->method);
3845 } else if (m->method->signature->generic_param_count) {
3846 g_assert_not_reached ();
3847 } else if ((m->method->klass->image == &assembly->image) &&
3848 !m->method->klass->generic_inst) {
3849 static guint32 method_table_idx = 0xffffff;
3851 * Each token should have a unique index, but the indexes are
3852 * assigned by managed code, so we don't know about them. An
3853 * easy solution is to count backwards...
3855 method_table_idx --;
3856 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3858 token = mono_image_get_methodref_token (assembly, m->method);
3859 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3861 else if (strcmp (klass->name, "MonoField") == 0) {
3862 MonoReflectionField *f = (MonoReflectionField *)obj;
3863 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3864 static guint32 field_table_idx = 0xffffff;
3866 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3868 token = mono_image_get_fieldref_token (assembly, f);
3869 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3871 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3872 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3873 token = mono_image_get_array_token (assembly, m);
3875 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3876 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3877 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3880 g_error ("requested token for %s\n", klass->name);
3882 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3889 guint32 import_lookup_table;
3893 guint32 import_address_table_rva;
3901 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3903 static MonoDynamicImage*
3904 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3905 char *assembly_name, char *module_name)
3907 static const guchar entrycode [16] = {0xff, 0x25, 0};
3908 MonoDynamicImage *image;
3912 * We need to use the current ms version or the ms runtime it won't find
3913 * the support dlls. D'oh!
3914 * const char *version = "mono-" VERSION;
3916 const char *version = "v1.0.3705";
3919 image = GC_MALLOC (sizeof (MonoDynamicImage));
3921 image = g_new0 (MonoDynamicImage, 1);
3924 /* keep in sync with image.c */
3925 image->image.name = assembly_name;
3926 image->image.assembly_name = image->image.name; /* they may be different */
3927 image->image.module_name = module_name;
3928 image->image.version = g_strdup (version);
3929 image->image.dynamic = TRUE;
3931 image->image.references = g_new0 (MonoAssembly*, 1);
3932 image->image.references [0] = NULL;
3934 mono_image_init (&image->image);
3936 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3937 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3938 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3939 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3940 image->handleref = g_hash_table_new (NULL, NULL);
3941 image->tokens = mono_g_hash_table_new (NULL, NULL);
3942 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3943 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3944 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3946 string_heap_init (&image->sheap);
3947 mono_image_add_stream_data (&image->us, "", 1);
3948 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3949 /* import tables... */
3950 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3951 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3952 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3953 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3954 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3955 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3956 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3957 stream_data_align (&image->code);
3959 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3961 for (i=0; i < 64; ++i) {
3962 image->tables [i].next_idx = 1;
3963 image->tables [i].columns = table_sizes [i];
3966 image->image.assembly = (MonoAssembly*)assembly;
3967 image->run = assembly->run;
3968 image->save = assembly->save;
3974 * mono_image_basic_init:
3975 * @assembly: an assembly builder object
3977 * Create the MonoImage that represents the assembly builder and setup some
3978 * of the helper hash table and the basic metadata streams.
3981 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3983 MonoDynamicAssembly *assembly;
3984 MonoDynamicImage *image;
3986 MONO_ARCH_SAVE_REGS;
3988 if (assemblyb->dynamic_assembly)
3992 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3994 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3997 assembly->assembly.dynamic = TRUE;
3998 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3999 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4000 if (assemblyb->culture)
4001 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4003 assembly->assembly.aname.culture = g_strdup ("");
4005 assembly->run = assemblyb->access != 2;
4006 assembly->save = assemblyb->access != 1;
4008 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4009 assembly->assembly.aname.name = image->image.name;
4010 assembly->assembly.image = &image->image;
4012 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4013 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4017 calc_section_size (MonoDynamicImage *assembly)
4021 /* alignment constraints */
4022 assembly->code.index += 3;
4023 assembly->code.index &= ~3;
4024 assembly->meta_size += 3;
4025 assembly->meta_size &= ~3;
4026 assembly->resources.index += 3;
4027 assembly->resources.index &= ~3;
4029 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4030 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4033 if (assembly->win32_res) {
4034 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4036 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4037 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4041 assembly->sections [MONO_SECTION_RELOC].size = 12;
4042 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4052 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4056 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4058 ResTreeNode *t1 = (ResTreeNode*)a;
4059 ResTreeNode *t2 = (ResTreeNode*)b;
4061 return t1->id - t2->id;
4065 * resource_tree_create:
4067 * Organize the resources into a resource tree.
4069 static ResTreeNode *
4070 resource_tree_create (MonoArray *win32_resources)
4072 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4076 tree = g_new0 (ResTreeNode, 1);
4078 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4079 MonoReflectionWin32Resource *win32_res =
4080 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4084 lang_node = g_new0 (ResTreeNode, 1);
4085 lang_node->id = win32_res->lang_id;
4086 lang_node->win32_res = win32_res;
4088 /* Create type node if neccesary */
4090 for (l = tree->children; l; l = l->next)
4091 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4092 type_node = (ResTreeNode*)l->data;
4097 type_node = g_new0 (ResTreeNode, 1);
4098 type_node->id = win32_res->res_type;
4101 * The resource types have to be sorted otherwise
4102 * Windows Explorer can't display the version information.
4104 tree->children = g_slist_insert_sorted (tree->children, type_node,
4105 resource_tree_compare_by_id);
4108 /* Create res node if neccesary */
4110 for (l = type_node->children; l; l = l->next)
4111 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4112 res_node = (ResTreeNode*)l->data;
4117 res_node = g_new0 (ResTreeNode, 1);
4118 res_node->id = win32_res->res_id;
4119 type_node->children = g_slist_append (type_node->children, res_node);
4122 res_node->children = g_slist_append (res_node->children, lang_node);
4129 * resource_tree_encode:
4131 * Encode the resource tree into the format used in the PE file.
4134 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4137 MonoPEResourceDir dir;
4138 MonoPEResourceDirEntry dir_entry;
4139 MonoPEResourceDataEntry data_entry;
4143 * For the format of the resource directory, see the article
4144 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4148 memset (&dir, 0, sizeof (dir));
4149 memset (&dir_entry, 0, sizeof (dir_entry));
4150 memset (&data_entry, 0, sizeof (data_entry));
4152 g_assert (sizeof (dir) == 16);
4153 g_assert (sizeof (dir_entry) == 8);
4154 g_assert (sizeof (data_entry) == 16);
4156 node->offset = p - begin;
4158 /* IMAGE_RESOURCE_DIRECTORY */
4159 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4161 memcpy (p, &dir, sizeof (dir));
4164 /* Reserve space for entries */
4166 p += sizeof (dir_entry) * dir.res_id_entries;
4168 /* Write children */
4169 for (l = node->children; l; l = l->next) {
4170 ResTreeNode *child = (ResTreeNode*)l->data;
4172 if (child->win32_res) {
4174 child->offset = p - begin;
4176 /* IMAGE_RESOURCE_DATA_ENTRY */
4177 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4178 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4180 memcpy (p, &data_entry, sizeof (data_entry));
4181 p += sizeof (data_entry);
4183 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4184 p += data_entry.rde_size;
4187 resource_tree_encode (child, begin, p, &p);
4190 /* IMAGE_RESOURCE_ENTRY */
4191 for (l = node->children; l; l = l->next) {
4192 ResTreeNode *child = (ResTreeNode*)l->data;
4193 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4195 dir_entry.is_dir = child->win32_res ? 0 : 1;
4196 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4198 memcpy (entries, &dir_entry, sizeof (dir_entry));
4199 entries += sizeof (dir_entry);
4206 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4211 MonoReflectionWin32Resource *win32_res;
4214 if (!assemblyb->win32_resources)
4218 * Resources are stored in a three level tree inside the PE file.
4219 * - level one contains a node for each type of resource
4220 * - level two contains a node for each resource
4221 * - level three contains a node for each instance of a resource for a
4222 * specific language.
4225 tree = resource_tree_create (assemblyb->win32_resources);
4227 /* Estimate the size of the encoded tree */
4229 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4230 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4231 size += mono_array_length (win32_res->res_data);
4233 /* Directory structure */
4234 size += mono_array_length (assemblyb->win32_resources) * 256;
4235 p = buf = g_malloc (size);
4237 resource_tree_encode (tree, p, p, &p);
4239 g_assert (p - buf < size);
4241 assembly->win32_res = g_malloc (p - buf);
4242 assembly->win32_res_size = p - buf;
4243 memcpy (assembly->win32_res, buf, p - buf);
4249 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4251 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4254 p += sizeof (MonoPEResourceDir);
4255 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4256 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4257 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4258 if (dir_entry->is_dir)
4259 fixup_resource_directory (res_section, child, rva);
4261 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4262 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4265 p += sizeof (MonoPEResourceDirEntry);
4270 * mono_image_create_pefile:
4271 * @mb: a module builder object
4273 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4274 * assembly->pefile where it can be easily retrieved later in chunks.
4277 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4278 MonoMSDOSHeader *msdos;
4279 MonoDotNetHeader *header;
4280 MonoSectionTable *section;
4281 MonoCLIHeader *cli_header;
4282 guint32 size, image_size, virtual_base, text_offset;
4283 guint32 header_start, section_start, file_offset, virtual_offset;
4284 MonoDynamicImage *assembly;
4285 MonoReflectionAssemblyBuilder *assemblyb;
4286 MonoDynamicStream *pefile;
4288 guint32 *rva, value;
4291 static const unsigned char msheader[] = {
4292 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4293 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4296 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4297 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4298 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4299 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4302 assemblyb = mb->assemblyb;
4304 mono_image_basic_init (assemblyb);
4305 assembly = mb->dynamic_image;
4307 /* already created */
4308 if (assembly->pefile.index)
4311 mono_image_build_metadata (mb);
4313 if (mb->is_main && assemblyb->resources) {
4314 int len = mono_array_length (assemblyb->resources);
4315 for (i = 0; i < len; ++i)
4316 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4319 if (mb->resources) {
4320 int len = mono_array_length (mb->resources);
4321 for (i = 0; i < len; ++i)
4322 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4325 build_compressed_metadata (assembly);
4328 assembly_add_win32_resources (assembly, assemblyb);
4330 nsections = calc_section_size (assembly);
4332 pefile = &assembly->pefile;
4334 /* The DOS header and stub */
4335 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4336 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4338 /* the dotnet header */
4339 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4341 /* the section tables */
4342 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4344 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4345 virtual_offset = VIRT_ALIGN;
4348 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4349 if (!assembly->sections [i].size)
4352 file_offset += FILE_ALIGN - 1;
4353 file_offset &= ~(FILE_ALIGN - 1);
4354 virtual_offset += VIRT_ALIGN - 1;
4355 virtual_offset &= ~(VIRT_ALIGN - 1);
4357 assembly->sections [i].offset = file_offset;
4358 assembly->sections [i].rva = virtual_offset;
4360 file_offset += assembly->sections [i].size;
4361 virtual_offset += assembly->sections [i].size;
4362 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4365 file_offset += FILE_ALIGN - 1;
4366 file_offset &= ~(FILE_ALIGN - 1);
4367 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4369 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4371 /* back-patch info */
4372 msdos = (MonoMSDOSHeader*)pefile->data;
4373 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4374 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4375 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4377 header = (MonoDotNetHeader*)(pefile->data + header_start);
4378 header->pesig [0] = 'P';
4379 header->pesig [1] = 'E';
4381 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4382 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4383 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4384 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4385 if (assemblyb->pekind == 1) {
4387 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4390 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4393 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4395 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4396 header->pe.pe_major = 6;
4397 header->pe.pe_minor = 0;
4398 size = assembly->sections [MONO_SECTION_TEXT].size;
4399 size += FILE_ALIGN - 1;
4400 size &= ~(FILE_ALIGN - 1);
4401 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4402 size = assembly->sections [MONO_SECTION_RSRC].size;
4403 size += FILE_ALIGN - 1;
4404 size &= ~(FILE_ALIGN - 1);
4405 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4406 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4407 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4408 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4409 /* pe_rva_entry_point always at the beginning of the text section */
4410 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4412 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4413 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4414 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4415 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4416 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4417 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4418 size = section_start;
4419 size += FILE_ALIGN - 1;
4420 size &= ~(FILE_ALIGN - 1);
4421 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4423 size += VIRT_ALIGN - 1;
4424 size &= ~(VIRT_ALIGN - 1);
4425 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4428 // Translate the PEFileKind value to the value expected by the Windows loader
4431 short kind = assemblyb->pekind;
4434 // PEFileKinds.ConsoleApplication == 2
4435 // PEFileKinds.WindowApplication == 3
4438 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4439 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4445 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4447 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4448 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4449 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4450 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4451 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4452 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4454 /* fill data directory entries */
4456 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4457 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4459 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4460 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4462 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4463 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4464 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4465 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4466 /* patch imported function RVA name */
4467 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4468 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4470 /* the import table */
4471 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4472 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4473 /* patch imported dll RVA name and other entries in the dir */
4474 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4475 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4476 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4477 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4478 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4479 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4481 p = (assembly->code.data + assembly->ilt_offset);
4482 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4483 *p++ = (value) & 0xff;
4484 *p++ = (value >> 8) & (0xff);
4485 *p++ = (value >> 16) & (0xff);
4486 *p++ = (value >> 24) & (0xff);
4488 /* the CLI header info */
4489 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4490 cli_header->ch_size = GUINT32_FROM_LE (72);
4491 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4492 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4493 if (assemblyb->entry_point) {
4494 guint32 table_idx = 0;
4495 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4496 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4497 table_idx = methodb->table_idx;
4500 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4501 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4504 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4505 /* The embedded managed resources */
4506 text_offset = assembly->text_rva + assembly->code.index;
4507 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4508 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4509 text_offset += assembly->resources.index;
4510 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4511 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4512 text_offset += assembly->meta_size;
4513 if (assembly->strong_name_size) {
4514 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4515 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4516 text_offset += assembly->strong_name_size;
4519 /* write the section tables and section content */
4520 section = (MonoSectionTable*)(pefile->data + section_start);
4521 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4522 static const char *section_names [] = {
4523 ".text", ".rsrc", ".reloc"
4525 if (!assembly->sections [i].size)
4527 strcpy (section->st_name, section_names [i]);
4528 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4529 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4530 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4531 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4532 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4533 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4534 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4536 case MONO_SECTION_TEXT:
4537 /* patch entry point */
4538 p = (assembly->code.data + 2);
4539 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4540 *p++ = (value) & 0xff;
4541 *p++ = (value >> 8) & 0xff;
4542 *p++ = (value >> 16) & 0xff;
4543 *p++ = (value >> 24) & 0xff;
4545 text_offset = assembly->sections [i].offset;
4546 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4547 text_offset += assembly->code.index;
4548 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4549 text_offset += assembly->resources.index;
4550 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4551 text_offset += assembly->meta_size;
4552 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4554 g_free (assembly->image.raw_metadata);
4556 case MONO_SECTION_RELOC:
4557 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4558 *rva = GUINT32_FROM_LE (assembly->text_rva);
4560 *rva = GUINT32_FROM_LE (12);
4562 data16 = (guint16*)rva;
4564 * the entrypoint is always at the start of the text section
4565 * 3 is IMAGE_REL_BASED_HIGHLOW
4566 * 2 is patch_size_rva - text_rva
4568 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4570 *data16 = 0; /* terminate */
4572 case MONO_SECTION_RSRC:
4573 if (assembly->win32_res) {
4574 text_offset = assembly->sections [i].offset;
4576 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4577 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4579 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4583 g_assert_not_reached ();
4588 /* check that the file is properly padded */
4591 FILE *f = fopen ("mypetest.exe", "w");
4592 fwrite (pefile->data, pefile->index, 1, f);
4598 MonoReflectionModule *
4599 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4603 MonoImageOpenStatus status;
4604 MonoDynamicAssembly *assembly;
4606 name = mono_string_to_utf8 (fileName);
4608 image = mono_image_open (name, &status);
4611 if (status == MONO_IMAGE_ERROR_ERRNO)
4612 exc = mono_get_exception_file_not_found (fileName);
4614 exc = mono_get_exception_bad_image_format (name);
4616 mono_raise_exception (exc);
4621 assembly = ab->dynamic_assembly;
4622 image->assembly = (MonoAssembly*)assembly;
4624 mono_assembly_load_references (image, &status);
4626 mono_image_close (image);
4627 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4630 return mono_module_get_object (mono_domain_get (), image);
4634 * We need to return always the same object for MethodInfo, FieldInfo etc..
4635 * but we need to consider the reflected type.
4636 * type uses a different hash, since it uses custom hash/equal functions.
4641 MonoClass *refclass;
4645 reflected_equal (gconstpointer a, gconstpointer b) {
4646 const ReflectedEntry *ea = a;
4647 const ReflectedEntry *eb = b;
4649 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4653 reflected_hash (gconstpointer a) {
4654 const ReflectedEntry *ea = a;
4655 return GPOINTER_TO_UINT (ea->item);
4658 #define CHECK_OBJECT(t,p,k) \
4664 mono_domain_lock (domain); \
4665 if (!domain->refobject_hash) \
4666 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4667 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4668 mono_domain_unlock (domain); \
4674 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4676 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4679 #define CACHE_OBJECT(p,o,k) \
4681 ReflectedEntry *e = ALLOC_REFENTRY; \
4683 e->refclass = (k); \
4684 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4685 mono_domain_unlock (domain); \
4689 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4691 /* this is done only once */
4692 mono_domain_lock (domain);
4693 CACHE_OBJECT (assembly, res, NULL);
4697 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4699 /* this is done only once */
4700 mono_domain_lock (domain);
4701 CACHE_OBJECT (module, res, NULL);
4705 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4707 MonoDynamicImage *image = moduleb->dynamic_image;
4708 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4711 * FIXME: we already created an image in mono_image_basic_init (), but
4712 * we don't know which module it belongs to, since that is only
4713 * determined at assembly save time.
4715 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4716 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4718 moduleb->module.image = &image->image;
4719 moduleb->dynamic_image = image;
4720 register_module (mono_object_domain (moduleb), moduleb, image);
4725 * mono_assembly_get_object:
4726 * @domain: an app domain
4727 * @assembly: an assembly
4729 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4731 MonoReflectionAssembly*
4732 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4734 static MonoClass *System_Reflection_Assembly;
4735 MonoReflectionAssembly *res;
4737 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4738 if (!System_Reflection_Assembly)
4739 System_Reflection_Assembly = mono_class_from_name (
4740 mono_defaults.corlib, "System.Reflection", "Assembly");
4741 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4742 res->assembly = assembly;
4743 CACHE_OBJECT (assembly, res, NULL);
4749 MonoReflectionModule*
4750 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4752 static MonoClass *System_Reflection_Module;
4753 MonoReflectionModule *res;
4755 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4756 if (!System_Reflection_Module)
4757 System_Reflection_Module = mono_class_from_name (
4758 mono_defaults.corlib, "System.Reflection", "Module");
4759 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4762 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4764 res->fqname = mono_string_new (domain, image->name);
4765 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4766 res->scopename = mono_string_new (domain, image->module_name);
4768 mono_image_addref (image);
4770 CACHE_OBJECT (image, res, NULL);
4774 MonoReflectionModule*
4775 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4777 static MonoClass *System_Reflection_Module;
4778 MonoReflectionModule *res;
4779 MonoTableInfo *table;
4780 guint32 cols [MONO_FILE_SIZE];
4782 guint32 i, name_idx;
4785 if (!System_Reflection_Module)
4786 System_Reflection_Module = mono_class_from_name (
4787 mono_defaults.corlib, "System.Reflection", "Module");
4788 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4790 table = &image->tables [MONO_TABLE_FILE];
4791 g_assert (table_index < table->rows);
4792 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4795 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4796 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4798 // Check whenever the row has a corresponding row in the moduleref table
4799 table = &image->tables [MONO_TABLE_MODULEREF];
4800 for (i = 0; i < table->rows; ++i) {
4801 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4802 val = mono_metadata_string_heap (image, name_idx);
4803 if (strcmp (val, name) == 0)
4804 res->image = image->modules [i];
4807 res->fqname = mono_string_new (domain, name);
4808 res->name = mono_string_new (domain, name);
4809 res->scopename = mono_string_new (domain, name);
4810 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4816 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4818 if ((t1->type != t2->type) ||
4819 (t1->byref != t2->byref))
4823 case MONO_TYPE_VOID:
4824 case MONO_TYPE_BOOLEAN:
4825 case MONO_TYPE_CHAR:
4836 case MONO_TYPE_STRING:
4839 case MONO_TYPE_OBJECT:
4840 case MONO_TYPE_TYPEDBYREF:
4842 case MONO_TYPE_VALUETYPE:
4843 case MONO_TYPE_CLASS:
4844 case MONO_TYPE_SZARRAY:
4845 return t1->data.klass == t2->data.klass;
4847 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4848 case MONO_TYPE_ARRAY:
4849 if (t1->data.array->rank != t2->data.array->rank)
4851 return t1->data.array->eklass == t2->data.array->eklass;
4852 case MONO_TYPE_GENERICINST: {
4854 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4856 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4858 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4859 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4865 case MONO_TYPE_MVAR:
4866 return t1->data.generic_param == t2->data.generic_param;
4868 g_error ("implement type compare for %0x!", t1->type);
4876 mymono_metadata_type_hash (MonoType *t1)
4882 hash |= t1->byref << 6; /* do not collide with t1->type values */
4884 case MONO_TYPE_VALUETYPE:
4885 case MONO_TYPE_CLASS:
4886 case MONO_TYPE_SZARRAY:
4887 /* check if the distribution is good enough */
4888 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4890 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4895 static MonoReflectionGenericInst*
4896 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4898 static MonoClass *System_Reflection_MonoGenericInst;
4899 MonoReflectionGenericInst *res;
4900 MonoGenericInst *ginst;
4903 if (!System_Reflection_MonoGenericInst) {
4904 System_Reflection_MonoGenericInst = mono_class_from_name (
4905 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4906 g_assert (System_Reflection_MonoGenericInst);
4909 ginst = geninst->data.generic_inst;
4910 gklass = mono_class_from_mono_type (ginst->generic_type);
4912 mono_class_init (ginst->klass);
4914 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4916 res->type.type = geninst;
4917 if (gklass->wastypebuilder && gklass->reflection_info)
4918 res->generic_type = gklass->reflection_info;
4920 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4926 * mono_type_get_object:
4927 * @domain: an app domain
4930 * Return an System.MonoType object representing the type @type.
4933 mono_type_get_object (MonoDomain *domain, MonoType *type)
4935 MonoReflectionType *res;
4936 MonoClass *klass = mono_class_from_mono_type (type);
4938 mono_domain_lock (domain);
4939 if (!domain->type_hash)
4940 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4941 (GCompareFunc)mymono_metadata_type_equal);
4942 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4943 mono_domain_unlock (domain);
4946 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4947 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4948 mono_g_hash_table_insert (domain->type_hash, type, res);
4949 mono_domain_unlock (domain);
4952 if (klass->reflection_info && !klass->wastypebuilder) {
4953 //g_assert_not_reached ();
4954 /* should this be considered an error condition? */
4956 mono_domain_unlock (domain);
4957 return klass->reflection_info;
4960 mono_class_init (klass);
4961 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4963 mono_g_hash_table_insert (domain->type_hash, type, res);
4964 mono_domain_unlock (domain);
4969 * mono_method_get_object:
4970 * @domain: an app domain
4972 * @refclass: the reflected type (can be NULL)
4974 * Return an System.Reflection.MonoMethod object representing the method @method.
4976 MonoReflectionMethod*
4977 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4980 * We use the same C representation for methods and constructors, but the type
4981 * name in C# is different.
4985 MonoReflectionMethod *ret;
4988 refclass = method->klass;
4990 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4991 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4992 cname = "MonoCMethod";
4994 cname = "MonoMethod";
4995 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4997 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4998 ret->method = method;
4999 ret->name = mono_string_new (domain, method->name);
5000 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5001 CACHE_OBJECT (method, ret, refclass);
5006 * mono_field_get_object:
5007 * @domain: an app domain
5011 * Return an System.Reflection.MonoField object representing the field @field
5014 MonoReflectionField*
5015 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5017 MonoReflectionField *res;
5020 CHECK_OBJECT (MonoReflectionField *, field, klass);
5021 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5022 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5025 res->name = mono_string_new (domain, field->name);
5026 res->attrs = field->type->attrs;
5027 res->type = mono_type_get_object (domain, field->type);
5028 CACHE_OBJECT (field, res, klass);
5033 * mono_property_get_object:
5034 * @domain: an app domain
5036 * @property: a property
5038 * Return an System.Reflection.MonoProperty object representing the property @property
5041 MonoReflectionProperty*
5042 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5044 MonoReflectionProperty *res;
5047 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5048 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5049 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5051 res->property = property;
5052 CACHE_OBJECT (property, res, klass);
5057 * mono_event_get_object:
5058 * @domain: an app domain
5062 * Return an System.Reflection.MonoEvent object representing the event @event
5065 MonoReflectionEvent*
5066 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5068 MonoReflectionEvent *res;
5071 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5072 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5073 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5076 CACHE_OBJECT (event, res, klass);
5081 * mono_param_get_objects:
5082 * @domain: an app domain
5085 * Return an System.Reflection.ParameterInfo array object representing the parameters
5086 * in the method @method.
5089 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5091 static MonoClass *System_Reflection_ParameterInfo;
5092 MonoArray *res = NULL;
5093 MonoReflectionMethod *member = NULL;
5094 MonoReflectionParameter *param = NULL;
5098 if (!System_Reflection_ParameterInfo)
5099 System_Reflection_ParameterInfo = mono_class_from_name (
5100 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5102 if (!method->signature->param_count)
5103 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5105 /* Note: the cache is based on the address of the signature into the method
5106 * since we already cache MethodInfos with the method as keys.
5108 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5110 member = mono_method_get_object (domain, method, NULL);
5111 names = g_new (char *, method->signature->param_count);
5112 mono_method_get_param_names (method, (const char **) names);
5114 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5115 for (i = 0; i < method->signature->param_count; ++i) {
5116 param = (MonoReflectionParameter *)mono_object_new (domain,
5117 System_Reflection_ParameterInfo);
5118 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5119 param->DefaultValueImpl = NULL; /* FIXME */
5120 param->MemberImpl = (MonoObject*)member;
5121 param->NameImpl = mono_string_new (domain, names [i]);
5122 param->PositionImpl = i;
5123 param->AttrsImpl = method->signature->params [i]->attrs;
5124 mono_array_set (res, gpointer, i, param);
5127 CACHE_OBJECT (&(method->signature), res, NULL);
5132 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5136 memset (assembly, 0, sizeof (MonoAssemblyName));
5138 assembly->culture = "";
5139 assembly->public_tok_value = NULL;
5141 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5144 while (*p == ' ' || *p == ',') {
5153 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5155 assembly->major = strtoul (p, &s, 10);
5156 if (s == p || *s != '.')
5159 assembly->minor = strtoul (p, &s, 10);
5160 if (s == p || *s != '.')
5163 assembly->build = strtoul (p, &s, 10);
5164 if (s == p || *s != '.')
5167 assembly->revision = strtoul (p, &s, 10);
5171 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5173 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5174 assembly->culture = g_strdup ("");
5177 assembly->culture = p;
5178 while (*p && *p != ',') {
5182 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5184 if (strncmp (p, "null", 4) == 0) {
5187 assembly->public_tok_value = p;
5188 while (*p && *p != ',') {
5193 while (*p && *p != ',')
5197 while (*p == ' ' || *p == ',') {
5211 * mono_reflection_parse_type:
5214 * Parse a type name as accepted by the GetType () method and output the info
5215 * extracted in the info structure.
5216 * the name param will be mangled, so, make a copy before passing it to this function.
5217 * The fields in info will be valid until the memory pointed to by name is valid.
5218 * Returns 0 on parse error.
5219 * See also mono_type_get_name () below.
5222 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5224 char *start, *p, *w, *last_point, *startn;
5225 int in_modifiers = 0;
5226 int isbyref = 0, rank;
5228 start = p = w = name;
5230 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5231 info->name = info->name_space = NULL;
5232 info->nested = NULL;
5233 info->modifiers = NULL;
5235 /* last_point separates the namespace from the name */
5241 *p = 0; /* NULL terminate the name */
5243 info->nested = g_list_append (info->nested, startn);
5244 /* we have parsed the nesting namespace + name */
5248 info->name_space = start;
5250 info->name = last_point + 1;
5252 info->name_space = (char *)"";
5278 info->name_space = start;
5280 info->name = last_point + 1;
5282 info->name_space = (char *)"";
5289 if (isbyref) /* only one level allowed by the spec */
5292 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5296 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5307 else if (*p != '*') /* '*' means unknown lower bound */
5313 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5325 return 0; /* missing assembly name */
5326 if (!assembly_name_to_aname (&info->assembly, p))
5333 if (info->assembly.name)
5336 *w = 0; /* terminate class name */
5337 if (!info->name || !*info->name)
5339 /* add other consistency checks */
5344 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5351 image = mono_defaults.corlib;
5354 klass = mono_class_from_name_case (image, info->name_space, info->name);
5356 klass = mono_class_from_name (image, info->name_space, info->name);
5359 for (mod = info->nested; mod; mod = mod->next) {
5362 mono_class_init (klass);
5363 nested = klass->nested_classes;
5366 klass = nested->data;
5368 if (g_strcasecmp (klass->name, mod->data) == 0)
5371 if (strcmp (klass->name, mod->data) == 0)
5375 nested = nested->next;
5382 mono_class_init (klass);
5383 for (mod = info->modifiers; mod; mod = mod->next) {
5384 modval = GPOINTER_TO_UINT (mod->data);
5385 if (!modval) { /* byref: must be last modifier */
5386 return &klass->this_arg;
5387 } else if (modval == -1) {
5388 klass = mono_ptr_class_get (&klass->byval_arg);
5389 } else { /* array rank */
5390 klass = mono_array_class_get (klass, modval);
5392 mono_class_init (klass);
5395 return &klass->byval_arg;
5399 * mono_reflection_get_type:
5400 * @image: a metadata context
5401 * @info: type description structure
5402 * @ignorecase: flag for case-insensitive string compares
5404 * Build a MonoType from the type description in @info.
5409 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5412 MonoReflectionAssembly *assembly;
5416 type = mono_reflection_get_type_internal (image, info, ignorecase);
5419 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5422 // Reconstruct the type name
5423 fullName = g_string_new ("");
5424 if (info->name_space && (info->name_space [0] != '\0'))
5425 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5427 g_string_printf (fullName, info->name);
5428 for (mod = info->nested; mod; mod = mod->next)
5429 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5432 mono_domain_try_type_resolve (
5433 mono_domain_get (), fullName->str, NULL);
5434 if (assembly && (!image || (assembly->assembly->image == image))) {
5436 if (assembly->assembly->dynamic) {
5437 /* Enumerate all modules */
5438 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5442 if (abuilder->modules) {
5443 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5444 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5445 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5451 if (!type && abuilder->loaded_modules) {
5452 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5453 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5454 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5461 type = mono_reflection_get_type_internal (assembly->assembly->image,
5464 g_string_free (fullName, TRUE);
5469 * mono_reflection_type_from_name:
5471 * @image: a metadata context (can be NULL).
5473 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5474 * it defaults to get the type from @image or, if @image is NULL or loading
5475 * from it fails, uses corlib.
5479 mono_reflection_type_from_name (char *name, MonoImage *image)
5482 MonoTypeNameParse info;
5483 MonoAssembly *assembly;
5485 /*g_print ("requested type %s\n", str);*/
5486 if (!mono_reflection_parse_type (name, &info)) {
5487 g_list_free (info.modifiers);
5488 g_list_free (info.nested);
5492 if (info.assembly.name) {
5493 assembly = mono_assembly_loaded (&info.assembly);
5494 /* do we need to load if it's not already loaded? */
5496 g_list_free (info.modifiers);
5497 g_list_free (info.nested);
5501 image = assembly->image;
5502 } else if (image == NULL) {
5503 image = mono_defaults.corlib;
5506 type = mono_reflection_get_type (image, &info, FALSE);
5507 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5508 image = mono_defaults.corlib;
5509 type = mono_reflection_get_type (image, &info, FALSE);
5512 g_list_free (info.modifiers);
5513 g_list_free (info.nested);
5518 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5520 int slen, type = t->type;
5525 case MONO_TYPE_BOOLEAN: {
5526 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5531 case MONO_TYPE_CHAR:
5533 case MONO_TYPE_I2: {
5534 guint16 *val = g_malloc (sizeof (guint16));
5539 #if SIZEOF_VOID_P == 4
5545 case MONO_TYPE_I4: {
5546 guint32 *val = g_malloc (sizeof (guint32));
5551 #if SIZEOF_VOID_P == 8
5552 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5557 case MONO_TYPE_I8: {
5558 guint64 *val = g_malloc (sizeof (guint64));
5563 case MONO_TYPE_VALUETYPE:
5564 if (t->data.klass->enumtype) {
5565 type = t->data.klass->enum_basetype->type;
5568 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5571 case MONO_TYPE_STRING:
5572 if (*p == (char)0xFF) {
5576 slen = mono_metadata_decode_value (p, &p);
5578 return mono_string_new_len (mono_domain_get (), p, slen);
5579 case MONO_TYPE_CLASS: {
5582 if (*p == (char)0xFF) {
5587 slen = mono_metadata_decode_value (p, &p);
5588 n = g_memdup (p, slen + 1);
5590 t = mono_reflection_type_from_name (n, image);
5592 g_warning ("Cannot load type '%s'", n);
5596 return mono_type_get_object (mono_domain_get (), t);
5600 case MONO_TYPE_OBJECT: {
5603 MonoClass *subc = NULL;
5608 } else if (subt == 0x0E) {
5609 type = MONO_TYPE_STRING;
5611 } else if (subt == 0x55) {
5614 slen = mono_metadata_decode_value (p, &p);
5615 n = g_memdup (p, slen + 1);
5617 t = mono_reflection_type_from_name (n, image);
5619 g_warning ("Cannot load type '%s'", n);
5622 subc = mono_class_from_mono_type (t);
5623 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5624 MonoType simple_type = {{0}};
5625 simple_type.type = subt;
5626 subc = mono_class_from_mono_type (&simple_type);
5628 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5630 val = load_cattr_value (image, &subc->byval_arg, p, end);
5631 obj = mono_object_new (mono_domain_get (), subc);
5632 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5636 case MONO_TYPE_SZARRAY:
5639 guint32 i, alen, basetype;
5642 if (alen == 0xffffffff) {
5646 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5647 basetype = t->data.klass->byval_arg.type;
5652 case MONO_TYPE_BOOLEAN:
5653 for (i=0;i<alen;i++)
5655 MonoBoolean val=*p++;
5656 mono_array_set(arr,MonoBoolean,i,val);
5659 case MONO_TYPE_CHAR:
5662 for (i=0;i<alen;i++)
5664 guint16 val=read16(p);
5665 mono_array_set(arr,guint16,i,val);
5672 for (i=0;i<alen;i++)
5674 guint32 val=read32(p);
5675 mono_array_set(arr,guint32,i,val);
5682 for (i=0;i<alen;i++)
5684 guint64 val=read64(p);
5685 mono_array_set(arr,guint64,i,val);
5689 case MONO_TYPE_CLASS:
5690 case MONO_TYPE_STRING:
5691 for (i = 0; i < alen; i++) {
5692 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5693 mono_array_set (arr, gpointer, i, item);
5697 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5703 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5709 type_is_reference (MonoType *type)
5711 switch (type->type) {
5712 case MONO_TYPE_BOOLEAN:
5713 case MONO_TYPE_CHAR:
5726 case MONO_TYPE_VALUETYPE:
5734 free_param_data (MonoMethodSignature *sig, void **params) {
5736 for (i = 0; i < sig->param_count; ++i) {
5737 if (!type_is_reference (sig->params [i]))
5738 g_free (params [i]);
5743 * Find the method index in the metadata methodDef table.
5744 * Later put these three helper methods in metadata and export them.
5747 find_method_index (MonoMethod *method) {
5748 MonoClass *klass = method->klass;
5751 for (i = 0; i < klass->method.count; ++i) {
5752 if (method == klass->methods [i])
5753 return klass->method.first + 1 + i;
5759 * Find the field index in the metadata FieldDef table.
5762 find_field_index (MonoClass *klass, MonoClassField *field) {
5765 for (i = 0; i < klass->field.count; ++i) {
5766 if (field == &klass->fields [i])
5767 return klass->field.first + 1 + i;
5773 * Find the property index in the metadata Property table.
5776 find_property_index (MonoClass *klass, MonoProperty *property) {
5779 for (i = 0; i < klass->property.count; ++i) {
5780 if (property == &klass->properties [i])
5781 return klass->property.first + 1 + i;
5787 * Find the event index in the metadata Event table.
5790 find_event_index (MonoClass *klass, MonoEvent *event) {
5793 for (i = 0; i < klass->event.count; ++i) {
5794 if (event == &klass->events [i])
5795 return klass->event.first + 1 + i;
5801 create_custom_attr (MonoImage *image, MonoMethod *method,
5802 const char *data, guint32 len)
5804 const char *p = data;
5806 guint32 i, j, num_named;
5810 mono_class_init (method->klass);
5813 attr = mono_object_new (mono_domain_get (), method->klass);
5814 mono_runtime_invoke (method, attr, NULL, NULL);
5818 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5821 /*g_print ("got attr %s\n", method->klass->name);*/
5823 params = g_new (void*, method->signature->param_count);
5827 for (i = 0; i < method->signature->param_count; ++i) {
5828 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5832 attr = mono_object_new (mono_domain_get (), method->klass);
5833 mono_runtime_invoke (method, attr, params, NULL);
5834 free_param_data (method->signature, params);
5836 num_named = read16 (named);
5838 for (j = 0; j < num_named; j++) {
5840 char *name, named_type, data_type;
5841 named_type = *named++;
5842 data_type = *named++; /* type of data */
5843 if (data_type == 0x55) {
5846 type_len = mono_metadata_decode_blob_size (named, &named);
5847 type_name = g_malloc (type_len + 1);
5848 memcpy (type_name, named, type_len);
5849 type_name [type_len] = 0;
5851 /* FIXME: lookup the type and check type consistency */
5854 if (data_type == MONO_TYPE_SZARRAY)
5855 /* The spec does not mention this */
5857 name_len = mono_metadata_decode_blob_size (named, &named);
5858 name = g_malloc (name_len + 1);
5859 memcpy (name, named, name_len);
5860 name [name_len] = 0;
5862 if (named_type == 0x53) {
5863 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5864 void *val = load_cattr_value (image, field->type, named, &named);
5865 mono_field_set_value (attr, field, val);
5866 if (!type_is_reference (field->type))
5868 } else if (named_type == 0x54) {
5871 MonoType *prop_type;
5873 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5874 /* can we have more that 1 arg in a custom attr named property? */
5875 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5876 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5877 mono_property_set_value (prop, attr, pparams, NULL);
5878 if (!type_is_reference (prop_type))
5879 g_free (pparams [0]);
5888 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5895 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5896 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5897 for (i = 0; i < cinfo->num_attrs; ++i) {
5898 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5899 mono_array_set (result, gpointer, i, attr);
5905 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5907 guint32 mtoken, i, len;
5908 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5910 MonoCustomAttrInfo *ainfo;
5911 GList *tmp, *list = NULL;
5914 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5916 i = mono_metadata_custom_attrs_from_index (image, idx);
5920 while (i < ca->rows) {
5921 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5923 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5926 len = g_list_length (list);
5929 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5930 ainfo->num_attrs = len;
5931 ainfo->image = image;
5932 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5933 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5934 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5935 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5936 case CUSTOM_ATTR_TYPE_METHODDEF:
5937 mtoken |= MONO_TOKEN_METHOD_DEF;
5939 case CUSTOM_ATTR_TYPE_MEMBERREF:
5940 mtoken |= MONO_TOKEN_MEMBER_REF;
5943 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5946 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5947 if (!ainfo->attrs [i].ctor)
5948 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5949 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5950 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5951 ainfo->attrs [i].data = data;
5959 mono_custom_attrs_from_method (MonoMethod *method)
5961 MonoCustomAttrInfo *cinfo;
5964 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5966 idx = find_method_index (method);
5967 idx <<= CUSTOM_ATTR_BITS;
5968 idx |= CUSTOM_ATTR_METHODDEF;
5969 return mono_custom_attrs_from_index (method->klass->image, idx);
5973 mono_custom_attrs_from_class (MonoClass *klass)
5975 MonoCustomAttrInfo *cinfo;
5978 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5980 idx = mono_metadata_token_index (klass->type_token);
5981 idx <<= CUSTOM_ATTR_BITS;
5982 idx |= CUSTOM_ATTR_TYPEDEF;
5983 return mono_custom_attrs_from_index (klass->image, idx);
5987 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5989 MonoCustomAttrInfo *cinfo;
5992 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5994 idx = 1; /* there is only one assembly */
5995 idx <<= CUSTOM_ATTR_BITS;
5996 idx |= CUSTOM_ATTR_ASSEMBLY;
5997 return mono_custom_attrs_from_index (assembly->image, idx);
6000 static MonoCustomAttrInfo*
6001 mono_custom_attrs_from_module (MonoImage *image)
6003 MonoCustomAttrInfo *cinfo;
6006 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6008 idx = 1; /* there is only one module */
6009 idx <<= CUSTOM_ATTR_BITS;
6010 idx |= CUSTOM_ATTR_MODULE;
6011 return mono_custom_attrs_from_index (image, idx);
6015 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6017 MonoCustomAttrInfo *cinfo;
6020 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6022 idx = find_property_index (klass, property);
6023 idx <<= CUSTOM_ATTR_BITS;
6024 idx |= CUSTOM_ATTR_PROPERTY;
6025 return mono_custom_attrs_from_index (klass->image, idx);
6029 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6031 MonoCustomAttrInfo *cinfo;
6034 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6036 idx = find_event_index (klass, event);
6037 idx <<= CUSTOM_ATTR_BITS;
6038 idx |= CUSTOM_ATTR_EVENT;
6039 return mono_custom_attrs_from_index (klass->image, idx);
6043 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6045 MonoCustomAttrInfo *cinfo;
6048 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6050 idx = find_field_index (klass, field);
6051 idx <<= CUSTOM_ATTR_BITS;
6052 idx |= CUSTOM_ATTR_FIELDDEF;
6053 return mono_custom_attrs_from_index (klass->image, idx);
6057 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6060 guint32 i, idx, method_index;
6061 guint32 param_list, param_last, param_pos, found;
6063 MonoReflectionMethodAux *aux;
6065 if (method->klass->image->dynamic) {
6066 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6067 if (!aux || !aux->param_cattr)
6069 return aux->param_cattr [param];
6072 image = method->klass->image;
6073 method_index = find_method_index (method);
6074 ca = &image->tables [MONO_TABLE_METHOD];
6076 if (method->klass->generic_inst || method->klass->gen_params ||
6077 method->signature->generic_param_count) {
6078 // FIXME FIXME FIXME
6082 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6083 if (method_index == ca->rows) {
6084 ca = &image->tables [MONO_TABLE_PARAM];
6085 param_last = ca->rows + 1;
6087 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6088 ca = &image->tables [MONO_TABLE_PARAM];
6091 for (i = param_list; i < param_last; ++i) {
6092 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6093 if (param_pos == param) {
6101 idx <<= CUSTOM_ATTR_BITS;
6102 idx |= CUSTOM_ATTR_PARAMDEF;
6103 return mono_custom_attrs_from_index (image, idx);
6107 * mono_reflection_get_custom_attrs:
6108 * @obj: a reflection object handle
6110 * Return an array with all the custom attributes defined of the
6111 * reflection handle @obj. The objects are fully build.
6114 mono_reflection_get_custom_attrs (MonoObject *obj)
6118 MonoCustomAttrInfo *cinfo = NULL;
6120 MONO_ARCH_SAVE_REGS;
6122 klass = obj->vtable->klass;
6123 /* FIXME: need to handle: Module */
6124 if (klass == mono_defaults.monotype_class) {
6125 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6126 klass = mono_class_from_mono_type (rtype->type);
6127 cinfo = mono_custom_attrs_from_class (klass);
6128 } else if (strcmp ("Assembly", klass->name) == 0) {
6129 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6130 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6131 } else if (strcmp ("Module", klass->name) == 0) {
6132 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6133 cinfo = mono_custom_attrs_from_module (module->image);
6134 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6135 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6136 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6137 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6138 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6139 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6140 } else if (strcmp ("MonoField", klass->name) == 0) {
6141 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6142 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6143 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6144 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6145 cinfo = mono_custom_attrs_from_method (rmethod->method);
6146 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6147 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6148 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6149 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6150 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6151 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6152 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6153 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6155 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6156 } else { /* handle other types here... */
6157 g_error ("get custom attrs not yet supported for %s", klass->name);
6161 result = mono_custom_attrs_construct (cinfo);
6163 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6164 result = mono_array_new (mono_domain_get (), klass, 0);
6170 static MonoMethodSignature*
6171 parameters_to_signature (MonoArray *parameters) {
6172 MonoMethodSignature *sig;
6175 count = parameters? mono_array_length (parameters): 0;
6177 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6178 sig->param_count = count;
6179 sig->sentinelpos = -1; /* FIXME */
6180 for (i = 0; i < count; ++i) {
6181 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6182 sig->params [i] = pt->type;
6187 static MonoMethodSignature*
6188 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6189 MonoMethodSignature *sig;
6191 sig = parameters_to_signature (ctor->parameters);
6192 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6193 sig->ret = &mono_defaults.void_class->byval_arg;
6197 static MonoMethodSignature*
6198 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6199 MonoMethodSignature *sig;
6201 sig = parameters_to_signature (method->parameters);
6202 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6203 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6204 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6208 static MonoMethodSignature*
6209 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6210 MonoMethodSignature *sig;
6212 sig = parameters_to_signature (method->parameters);
6213 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6214 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6215 sig->generic_param_count = 0;
6220 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6222 MonoClass *klass = mono_object_class (prop);
6223 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6224 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6225 *name = mono_string_to_utf8 (pb->name);
6226 *type = pb->type->type;
6228 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6229 *name = g_strdup (p->property->name);
6230 if (p->property->get)
6231 *type = p->property->get->signature->ret;
6233 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6238 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6240 MonoClass *klass = mono_object_class (field);
6241 if (strcmp (klass->name, "FieldBuilder") == 0) {
6242 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6243 *name = mono_string_to_utf8 (fb->name);
6244 *type = fb->type->type;
6246 MonoReflectionField *f = (MonoReflectionField *)field;
6247 *name = g_strdup (f->field->name);
6248 *type = f->field->type;
6253 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6256 MonoTypeEnum simple_type;
6258 if ((p-buffer) + 10 >= *buflen) {
6261 newbuf = g_realloc (buffer, *buflen);
6262 p = newbuf + (p-buffer);
6265 argval = ((char*)arg + sizeof (MonoObject));
6266 simple_type = type->type;
6268 switch (simple_type) {
6269 case MONO_TYPE_BOOLEAN:
6274 case MONO_TYPE_CHAR:
6277 swap_with_size (p, argval, 2, 1);
6283 swap_with_size (p, argval, 4, 1);
6289 swap_with_size (p, argval, 8, 1);
6292 case MONO_TYPE_VALUETYPE:
6293 if (type->data.klass->enumtype) {
6294 simple_type = type->data.klass->enum_basetype->type;
6297 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6300 case MONO_TYPE_STRING: {
6307 str = mono_string_to_utf8 ((MonoString*)arg);
6308 slen = strlen (str);
6309 if ((p-buffer) + 10 + slen >= *buflen) {
6313 newbuf = g_realloc (buffer, *buflen);
6314 p = newbuf + (p-buffer);
6317 mono_metadata_encode_value (slen, p, &p);
6318 memcpy (p, str, slen);
6323 case MONO_TYPE_CLASS: {
6331 k = mono_object_class (arg);
6332 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6333 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6334 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6336 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6337 slen = strlen (str);
6338 if ((p-buffer) + 10 + slen >= *buflen) {
6342 newbuf = g_realloc (buffer, *buflen);
6343 p = newbuf + (p-buffer);
6346 mono_metadata_encode_value (slen, p, &p);
6347 memcpy (p, str, slen);
6352 case MONO_TYPE_SZARRAY: {
6357 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6360 len = mono_array_length ((MonoArray*)arg);
6362 *p++ = (len >> 8) & 0xff;
6363 *p++ = (len >> 16) & 0xff;
6364 *p++ = (len >> 24) & 0xff;
6366 *retbuffer = buffer;
6367 eclass = type->data.klass;
6368 for (i = 0; i < len; ++i) {
6369 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6373 /* it may be a boxed value or a Type */
6374 case MONO_TYPE_OBJECT: {
6375 MonoClass *klass = mono_object_class (arg);
6379 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6382 } else if (klass->enumtype) {
6384 } else if (klass == mono_defaults.string_class) {
6385 simple_type = MONO_TYPE_STRING;
6388 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6389 *p++ = simple_type = klass->byval_arg.type;
6392 g_error ("unhandled type in custom attr");
6394 str = type_get_qualified_name (klass->enum_basetype, NULL);
6395 slen = strlen (str);
6396 if ((p-buffer) + 10 + slen >= *buflen) {
6400 newbuf = g_realloc (buffer, *buflen);
6401 p = newbuf + (p-buffer);
6404 mono_metadata_encode_value (slen, p, &p);
6405 memcpy (p, str, slen);
6408 simple_type = klass->enum_basetype->type;
6412 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6415 *retbuffer = buffer;
6419 * mono_reflection_get_custom_attrs_blob:
6420 * @ctor: custom attribute constructor
6421 * @ctorArgs: arguments o the constructor
6427 * Creates the blob of data that needs to be saved in the metadata and that represents
6428 * the custom attributed described by @ctor, @ctorArgs etc.
6429 * Returns: a Byte array representing the blob of data.
6432 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6435 MonoMethodSignature *sig;
6440 MONO_ARCH_SAVE_REGS;
6442 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6443 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6445 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6447 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6449 p = buffer = g_malloc (buflen);
6450 /* write the prolog */
6453 for (i = 0; i < sig->param_count; ++i) {
6454 arg = mono_array_get (ctorArgs, MonoObject*, i);
6455 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6459 i += mono_array_length (properties);
6461 i += mono_array_length (fields);
6463 *p++ = (i >> 8) & 0xff;
6466 for (i = 0; i < mono_array_length (properties); ++i) {
6471 prop = mono_array_get (properties, gpointer, i);
6472 get_prop_name_and_type (prop, &pname, &ptype);
6473 *p++ = 0x54; /* PROPERTY signature */
6475 /* Preallocate a large enough buffer */
6476 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6477 char *str = type_get_qualified_name (ptype, NULL);
6483 len += strlen (pname);
6485 if ((p-buffer) + 20 + len >= buflen) {
6489 newbuf = g_realloc (buffer, buflen);
6490 p = newbuf + (p-buffer);
6494 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6495 char *str = type_get_qualified_name (ptype, NULL);
6496 int slen = strlen (str);
6500 * This seems to be optional...
6503 mono_metadata_encode_value (slen, p, &p);
6504 memcpy (p, str, slen);
6508 mono_metadata_encode_value (ptype->type, p, &p);
6509 if (ptype->type == MONO_TYPE_SZARRAY)
6510 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6512 len = strlen (pname);
6513 mono_metadata_encode_value (len, p, &p);
6514 memcpy (p, pname, len);
6516 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6523 for (i = 0; i < mono_array_length (fields); ++i) {
6528 field = mono_array_get (fields, gpointer, i);
6529 get_field_name_and_type (field, &fname, &ftype);
6530 *p++ = 0x53; /* FIELD signature */
6531 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6532 char *str = type_get_qualified_name (ftype, NULL);
6533 int slen = strlen (str);
6534 if ((p-buffer) + 10 + slen >= buflen) {
6538 newbuf = g_realloc (buffer, buflen);
6539 p = newbuf + (p-buffer);
6544 * This seems to be optional...
6547 mono_metadata_encode_value (slen, p, &p);
6548 memcpy (p, str, slen);
6552 mono_metadata_encode_value (ftype->type, p, &p);
6554 len = strlen (fname);
6555 mono_metadata_encode_value (len, p, &p);
6556 memcpy (p, fname, len);
6558 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6563 g_assert (p - buffer <= buflen);
6564 buflen = p - buffer;
6565 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6566 p = mono_array_addr (result, char, 0);
6567 memcpy (p, buffer, buflen);
6569 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6575 * mono_reflection_setup_internal_class:
6576 * @tb: a TypeBuilder object
6578 * Creates a MonoClass that represents the TypeBuilder.
6579 * This is a trick that lets us simplify a lot of reflection code
6580 * (and will allow us to support Build and Run assemblies easier).
6583 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6585 MonoClass *klass, *parent;
6587 MONO_ARCH_SAVE_REGS;
6589 klass = g_new0 (MonoClass, 1);
6591 klass->image = &tb->module->dynamic_image->image;
6594 /* check so we can compile corlib correctly */
6595 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6596 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6597 parent = tb->parent->type->data.klass;
6599 parent = my_mono_class_from_mono_type (tb->parent->type);
6603 klass->inited = 1; /* we lie to the runtime */
6604 klass->name = mono_string_to_utf8 (tb->name);
6605 klass->name_space = mono_string_to_utf8 (tb->nspace);
6606 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6607 klass->flags = tb->attrs;
6609 klass->element_class = klass;
6610 klass->reflection_info = tb; /* need to pin. */
6612 /* Put into cache so mono_class_get () will find it */
6613 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6616 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6617 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6621 mono_class_setup_parent (klass, parent);
6622 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6623 const char *old_n = klass->name;
6624 /* trick to get relative numbering right when compiling corlib */
6625 klass->name = "BuildingObject";
6626 mono_class_setup_parent (klass, mono_defaults.object_class);
6627 klass->name = old_n;
6629 mono_class_setup_mono_type (klass);
6631 mono_class_setup_supertypes (klass);
6634 * FIXME: handle interfaces.
6637 tb->type.type = &klass->byval_arg;
6639 if (tb->nesting_type) {
6640 g_assert (tb->nesting_type->type);
6641 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6644 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6648 * mono_reflection_setup_generic_class:
6649 * @tb: a TypeBuilder object
6651 * Setup the generic class after all generic parameters have been added.
6654 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6659 MONO_ARCH_SAVE_REGS;
6661 klass = my_mono_class_from_mono_type (tb->type.type);
6663 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6665 if (klass->gen_params || (count == 0))
6668 klass->num_gen_params = count;
6669 klass->gen_params = g_new0 (MonoGenericParam, count);
6671 for (i = 0; i < count; i++) {
6672 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6673 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6678 * mono_reflection_create_internal_class:
6679 * @tb: a TypeBuilder object
6681 * Actually create the MonoClass that is associated with the TypeBuilder.
6684 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6688 MONO_ARCH_SAVE_REGS;
6690 klass = my_mono_class_from_mono_type (tb->type.type);
6692 if (klass->enumtype && klass->enum_basetype == NULL) {
6693 MonoReflectionFieldBuilder *fb;
6695 g_assert (tb->fields != NULL);
6696 g_assert (mono_array_length (tb->fields) >= 1);
6698 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6700 klass->enum_basetype = fb->type->type;
6701 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6702 if (!klass->element_class)
6703 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6704 klass->instance_size = klass->element_class->instance_size;
6705 klass->size_inited = 1;
6707 * this is almost safe to do with enums and it's needed to be able
6708 * to create objects of the enum type (for use in SetConstant).
6710 /* FIXME: Does this mean enums can't have method overrides ? */
6711 mono_class_setup_vtable (klass, NULL, 0);
6715 static MonoMarshalSpec*
6716 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6717 MonoReflectionMarshal *minfo)
6719 MonoMarshalSpec *res;
6721 res = g_new0 (MonoMarshalSpec, 1);
6722 res->native = minfo->type;
6724 switch (minfo->type) {
6725 case MONO_NATIVE_LPARRAY:
6726 res->data.array_data.elem_type = minfo->eltype;
6727 res->data.array_data.param_num = 0; /* Not yet */
6728 res->data.array_data.num_elem = minfo->count;
6731 case MONO_NATIVE_BYVALTSTR:
6732 case MONO_NATIVE_BYVALARRAY:
6733 res->data.array_data.num_elem = minfo->count;
6736 case MONO_NATIVE_CUSTOM:
6737 if (minfo->marshaltyperef)
6738 res->data.custom_data.custom_name =
6739 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6741 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6752 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6753 ReflectionMethodBuilder *rmb,
6754 MonoMethodSignature *sig)
6757 MonoMethodNormal *pm;
6758 MonoMarshalSpec **specs;
6759 MonoReflectionMethodAux *method_aux;
6762 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6763 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6764 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6767 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6769 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6771 pm = (MonoMethodNormal*)m;
6774 m->flags = rmb->attrs;
6775 m->iflags = rmb->iattrs;
6776 m->name = mono_string_to_utf8 (rmb->name);
6780 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6782 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6783 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6786 m->signature->pinvoke = 1;
6787 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6789 m->signature->pinvoke = 1;
6791 } else if (!m->klass->dummy &&
6792 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6793 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6794 MonoMethodHeader *header;
6796 gint32 max_stack, i;
6797 gint32 num_locals = 0;
6798 gint32 num_clauses = 0;
6802 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6803 code_size = rmb->ilgen->code_len;
6804 max_stack = rmb->ilgen->max_stack;
6805 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6806 if (rmb->ilgen->ex_handlers)
6807 num_clauses = method_count_clauses (rmb->ilgen);
6810 code = mono_array_addr (rmb->code, guint8, 0);
6811 code_size = mono_array_length (rmb->code);
6812 /* we probably need to run a verifier on the code... */
6822 header = g_malloc0 (sizeof (MonoMethodHeader) +
6823 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6824 header->code_size = code_size;
6825 header->code = g_malloc (code_size);
6826 memcpy ((char*)header->code, code, code_size);
6827 header->max_stack = max_stack;
6828 header->init_locals = rmb->init_locals;
6829 header->num_locals = num_locals;
6831 for (i = 0; i < num_locals; ++i) {
6832 MonoReflectionLocalBuilder *lb =
6833 mono_array_get (rmb->ilgen->locals,
6834 MonoReflectionLocalBuilder*, i);
6836 header->locals [i] = g_new0 (MonoType, 1);
6837 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6840 header->num_clauses = num_clauses;
6842 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6847 if (rmb->generic_params) {
6848 int count = mono_array_length (rmb->generic_params);
6849 header->gen_params = g_new0 (MonoGenericParam, count);
6850 for (i = 0; i < count; i++) {
6851 MonoReflectionGenericParam *gp =
6852 mono_array_get (rmb->generic_params,
6853 MonoReflectionGenericParam*, i);
6855 header->gen_params [i] = *gp->type.type->data.generic_param;
6859 pm->header = header;
6863 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6866 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6868 for (i = 0; i < rmb->nrefs; ++i)
6869 mw->data = g_list_append (mw->data, rmb->refs [i]);
6874 /* Parameter names */
6877 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6878 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6879 for (i = 0; i <= m->signature->param_count; ++i) {
6880 MonoReflectionParamBuilder *pb;
6881 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6883 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6885 if (!method_aux->param_cattr)
6886 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6887 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6893 /* Parameter marshalling */
6896 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6897 MonoReflectionParamBuilder *pb;
6898 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6899 if (pb->marshal_info) {
6901 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6902 specs [pb->position] =
6903 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6907 if (specs != NULL) {
6909 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6910 method_aux->param_marshall = specs;
6913 if (klass->image->dynamic && method_aux)
6914 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6920 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6922 ReflectionMethodBuilder rmb;
6923 MonoMethodSignature *sig;
6925 sig = ctor_builder_to_signature (mb);
6927 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6929 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6930 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6932 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6933 /* ilgen is no longer needed */
6941 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6943 ReflectionMethodBuilder rmb;
6944 MonoMethodSignature *sig;
6946 sig = method_builder_to_signature (mb);
6948 reflection_methodbuilder_from_method_builder (&rmb, mb);
6950 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6951 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6953 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6954 /* ilgen is no longer needed */
6960 static MonoClassField*
6961 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6963 MonoClassField *field;
6970 field = g_new0 (MonoClassField, 1);
6972 field->name = mono_string_to_utf8 (fb->name);
6974 /* FIXME: handle type modifiers */
6975 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6976 field->type->attrs = fb->attrs;
6978 field->type = fb->type->type;
6980 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6981 field->data = mono_array_addr (fb->rva_data, char, 0);
6982 if (fb->offset != -1)
6983 field->offset = fb->offset;
6984 field->parent = klass;
6986 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6988 if (fb->def_value) {
6989 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6990 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6991 field->def_value = g_new0 (MonoConstant, 1);
6992 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6993 /* Copy the data from the blob since it might get realloc-ed */
6994 p = assembly->blob.data + idx;
6995 len = mono_metadata_decode_blob_size (p, &p2);
6997 field->def_value->value = g_malloc (len);
6998 memcpy (field->def_value->value, p, len);
7005 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7009 MonoReflectionTypeBuilder *tb = NULL;
7010 MonoGenericInst *ginst;
7015 klass = mono_class_from_mono_type (type->type);
7016 if (!klass->gen_params && !klass->generic_inst &&
7017 !(klass->nested_in && klass->nested_in->gen_params))
7020 mono_loader_lock ();
7022 domain = mono_object_domain (type);
7024 ginst = g_new0 (MonoGenericInst, 1);
7026 if (!klass->generic_inst) {
7027 ginst->type_argc = type_argc;
7028 ginst->type_argv = types;
7030 for (i = 0; i < ginst->type_argc; ++i) {
7031 if (!ginst->is_open)
7032 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7035 ginst->generic_type = &klass->byval_arg;
7037 MonoGenericInst *kginst = klass->generic_inst;
7039 ginst->type_argc = kginst->type_argc;
7040 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7042 for (i = 0; i < ginst->type_argc; i++) {
7043 MonoType *t = kginst->type_argv [i];
7045 if (t->type == MONO_TYPE_VAR)
7046 t = types [t->data.generic_param->num];
7048 if (!ginst->is_open)
7049 ginst->is_open = mono_class_is_open_constructed_type (t);
7051 ginst->type_argv [i] = t;
7054 ginst->generic_type = kginst->generic_type;
7057 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7060 mono_loader_unlock ();
7064 ginst->context = g_new0 (MonoGenericContext, 1);
7065 ginst->context->ginst = ginst;
7067 geninst = g_new0 (MonoType, 1);
7068 geninst->type = MONO_TYPE_GENERICINST;
7069 geninst->data.generic_inst = ginst;
7071 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7072 tb = (MonoReflectionTypeBuilder *) type;
7074 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7075 ginst->is_dynamic = TRUE;
7076 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7077 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7078 MonoReflectionType *rgt = rgi->generic_type;
7080 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7081 tb = (MonoReflectionTypeBuilder *) rgt;
7083 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7084 ginst->is_dynamic = TRUE;
7086 icount = klass->interface_count;
7088 ginst->ifaces = g_new0 (MonoType *, icount);
7089 ginst->count_ifaces = icount;
7091 for (i = 0; i < icount; i++) {
7092 MonoReflectionType *itype;
7095 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7097 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7098 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7099 if (!ginst->ifaces [i])
7100 ginst->ifaces [i] = itype->type;
7103 mono_class_create_generic (ginst);
7105 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7107 mono_loader_unlock ();
7113 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7115 MonoClass *klass, *pklass = NULL;
7116 MonoReflectionType *parent = NULL;
7118 MonoReflectionTypeBuilder *tb = NULL;
7119 MonoGenericInst *ginst;
7122 domain = mono_object_domain (type);
7123 klass = mono_class_from_mono_type (type->type);
7125 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7126 tb = (MonoReflectionTypeBuilder *) type;
7129 parent = tb->parent;
7130 pklass = mono_class_from_mono_type (parent->type);
7133 pklass = klass->parent;
7135 parent = mono_type_get_object (domain, &pklass->byval_arg);
7138 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7142 ginst = geninst->data.generic_inst;
7144 if (pklass && pklass->generic_inst)
7145 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7150 MonoReflectionMethod*
7151 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7153 MonoMethod *method, *inflated;
7154 MonoReflectionMethodBuilder *mb = NULL;
7155 MonoGenericMethod *gmethod;
7156 MonoGenericContext *context;
7159 MONO_ARCH_SAVE_REGS;
7160 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7161 MonoReflectionTypeBuilder *tb;
7164 mb = (MonoReflectionMethodBuilder *) rmethod;
7165 tb = (MonoReflectionTypeBuilder *) mb->type;
7166 klass = mono_class_from_mono_type (tb->type.type);
7168 method = methodbuilder_to_mono_method (klass, mb);
7170 method = rmethod->method;
7172 count = method->signature->generic_param_count;
7173 if (count != mono_array_length (types))
7176 gmethod = g_new0 (MonoGenericMethod, 1);
7177 gmethod->mtype_argc = count;
7178 gmethod->mtype_argv = g_new0 (MonoType *, count);
7179 for (i = 0; i < count; i++) {
7180 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7181 gmethod->mtype_argv [i] = garg->type;
7184 context = g_new0 (MonoGenericContext, 1);
7185 context->ginst = method->klass->generic_inst;
7186 context->gmethod = gmethod;
7188 inflated = mono_class_inflate_generic_method (method, context, NULL);
7190 return mono_method_get_object (
7191 mono_object_domain (rmethod), inflated, NULL);
7195 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7197 MonoGenericMethod *gmethod;
7198 MonoGenericInst *ginst;
7199 MonoGenericContext *context;
7202 ginst = type->type.type->data.generic_inst;
7204 gmethod = g_new0 (MonoGenericMethod, 1);
7205 gmethod->reflection_info = obj;
7207 gmethod->mtype_argc = method->signature->generic_param_count;
7208 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7210 for (i = 0; i < gmethod->mtype_argc; i++) {
7211 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7212 MonoGenericParam *gparam = &mn->header->gen_params [i];
7214 g_assert (gparam->pklass);
7215 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7218 context = g_new0 (MonoGenericContext, 1);
7219 context->ginst = ginst;
7220 context->gmethod = gmethod;
7222 return mono_class_inflate_generic_method (method, context, ginst->klass);
7226 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7231 klass = mono_class_from_mono_type (type->type.type);
7233 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7234 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7235 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7236 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7237 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7238 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7239 method = ((MonoReflectionMethod *) obj)->method;
7241 method = NULL; /* prevent compiler warning */
7242 g_assert_not_reached ();
7245 return inflate_mono_method (type, method, obj);
7249 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7250 MonoArray *methods, MonoArray *ctors,
7251 MonoArray *fields, MonoArray *properties,
7254 MonoGenericInst *ginst;
7255 MonoDynamicGenericInst *dginst;
7256 MonoClass *klass, *gklass, *pklass;
7259 MONO_ARCH_SAVE_REGS;
7261 klass = mono_class_from_mono_type (type->type.type);
7262 ginst = type->type.type->data.generic_inst;
7264 if (ginst->initialized)
7267 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7269 gklass = mono_class_from_mono_type (ginst->generic_type);
7270 mono_class_init (gklass);
7273 pklass = mono_class_from_mono_type (ginst->parent);
7275 pklass = gklass->parent;
7277 mono_class_setup_parent (klass, pklass);
7279 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7280 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7281 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7282 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7283 dginst->count_events = events ? mono_array_length (events) : 0;
7285 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7286 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7287 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7288 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7289 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7291 for (i = 0; i < dginst->count_methods; i++) {
7292 MonoObject *obj = mono_array_get (methods, gpointer, i);
7294 dginst->methods [i] = inflate_method (type, obj);
7297 for (i = 0; i < dginst->count_ctors; i++) {
7298 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7300 dginst->ctors [i] = inflate_method (type, obj);
7303 for (i = 0; i < dginst->count_fields; i++) {
7304 MonoObject *obj = mono_array_get (fields, gpointer, i);
7305 MonoClassField *field;
7307 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7308 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7309 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7310 field = ((MonoReflectionField *) obj)->field;
7312 field = NULL; /* prevent compiler warning */
7313 g_assert_not_reached ();
7316 dginst->fields [i] = *field;
7317 dginst->fields [i].generic_type = field->type;
7318 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7321 for (i = 0; i < dginst->count_properties; i++) {
7322 MonoObject *obj = mono_array_get (properties, gpointer, i);
7323 MonoProperty *property = &dginst->properties [i];
7325 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7326 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7328 property->parent = klass;
7329 property->attrs = pb->attrs;
7330 property->name = mono_string_to_utf8 (pb->name);
7332 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7334 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7335 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7336 *property = *((MonoReflectionProperty *) obj)->property;
7339 property->get = inflate_mono_method (type, property->get, NULL);
7341 property->set = inflate_mono_method (type, property->set, NULL);
7343 g_assert_not_reached ();
7346 for (i = 0; i < dginst->count_events; i++) {
7347 MonoObject *obj = mono_array_get (events, gpointer, i);
7348 MonoEvent *event = &dginst->events [i];
7350 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7351 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7353 event->parent = klass;
7354 event->attrs = eb->attrs;
7355 event->name = mono_string_to_utf8 (eb->name);
7357 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7358 if (eb->remove_method)
7359 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7360 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7361 *event = *((MonoReflectionEvent *) obj)->event;
7364 event->add = inflate_mono_method (type, event->add, NULL);
7366 event->remove = inflate_mono_method (type, event->remove, NULL);
7368 g_assert_not_reached ();
7371 ginst->initialized = TRUE;
7375 ensure_runtime_vtable (MonoClass *klass)
7377 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7378 int i, num, j, onum;
7379 MonoMethod **overrides;
7381 if (!tb || klass->wastypebuilder)
7384 ensure_runtime_vtable (klass->parent);
7386 num = tb->ctors? mono_array_length (tb->ctors): 0;
7387 num += tb->num_methods;
7388 klass->method.count = num;
7389 klass->methods = g_new (MonoMethod*, num);
7390 num = tb->ctors? mono_array_length (tb->ctors): 0;
7391 for (i = 0; i < num; ++i)
7392 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7393 num = tb->num_methods;
7395 for (i = 0; i < num; ++i)
7396 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7398 klass->wastypebuilder = TRUE;
7399 if (tb->interfaces) {
7400 klass->interface_count = mono_array_length (tb->interfaces);
7401 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7402 for (i = 0; i < klass->interface_count; ++i) {
7403 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7404 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7408 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7409 for (i = 0; i < klass->method.count; ++i)
7410 klass->methods [i]->slot = i;
7415 for (i = 0; i < tb->num_methods; ++i) {
7416 MonoReflectionMethodBuilder *mb =
7417 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7418 if (mb->override_method)
7423 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7427 for (i = 0; i < tb->num_methods; ++i) {
7428 MonoReflectionMethodBuilder *mb =
7429 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7430 if (mb->override_method) {
7431 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7432 overrides [onum * 2] =
7433 mb->override_method->method;
7434 overrides [onum * 2 + 1] =
7437 g_assert (mb->mhandle);
7444 mono_class_setup_vtable (klass, overrides, onum);
7448 typebuilder_setup_fields (MonoClass *klass)
7450 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7451 MonoReflectionFieldBuilder *fb;
7452 MonoClassField *field;
7457 klass->field.count = tb->num_fields;
7458 klass->field.first = 0;
7459 klass->field.last = klass->field.count;
7461 if (!klass->field.count)
7464 klass->fields = g_new0 (MonoClassField, klass->field.count);
7466 for (i = 0; i < klass->field.count; ++i) {
7467 fb = mono_array_get (tb->fields, gpointer, i);
7468 field = &klass->fields [i];
7469 field->name = mono_string_to_utf8 (fb->name);
7471 /* FIXME: handle type modifiers */
7472 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7473 field->type->attrs = fb->attrs;
7475 field->type = fb->type->type;
7477 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7478 field->data = mono_array_addr (fb->rva_data, char, 0);
7479 if (fb->offset != -1)
7480 field->offset = fb->offset;
7481 field->parent = klass;
7483 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7485 if (fb->def_value) {
7486 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7487 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7488 field->def_value = g_new0 (MonoConstant, 1);
7489 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7490 /* Copy the data from the blob since it might get realloc-ed */
7491 p = assembly->blob.data + idx;
7492 len = mono_metadata_decode_blob_size (p, &p2);
7494 field->def_value->value = g_malloc (len);
7495 memcpy (field->def_value->value, p, len);
7498 mono_class_layout_fields (klass);
7502 typebuilder_setup_properties (MonoClass *klass)
7504 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7505 MonoReflectionPropertyBuilder *pb;
7508 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7509 klass->property.first = 0;
7510 klass->property.last = klass->property.count;
7512 klass->properties = g_new0 (MonoProperty, klass->property.count);
7513 for (i = 0; i < klass->property.count; ++i) {
7514 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7515 klass->properties [i].parent = klass;
7516 klass->properties [i].attrs = pb->attrs;
7517 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7519 klass->properties [i].get = pb->get_method->mhandle;
7521 klass->properties [i].set = pb->set_method->mhandle;
7525 MonoReflectionEvent *
7526 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7528 MonoEvent *event = g_new0 (MonoEvent, 1);
7532 klass = my_mono_class_from_mono_type (tb->type.type);
7534 event->parent = klass;
7535 event->attrs = eb->attrs;
7536 event->name = mono_string_to_utf8 (eb->name);
7538 event->add = eb->add_method->mhandle;
7539 if (eb->remove_method)
7540 event->remove = eb->remove_method->mhandle;
7541 if (eb->raise_method)
7542 event->raise = eb->raise_method->mhandle;
7544 if (eb->other_methods) {
7545 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7546 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7547 MonoReflectionMethodBuilder *mb =
7548 mono_array_get (eb->other_methods,
7549 MonoReflectionMethodBuilder*, j);
7550 event->other [j] = mb->mhandle;
7554 return mono_event_get_object (mono_object_domain (tb), klass, event);
7558 typebuilder_setup_events (MonoClass *klass)
7560 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7561 MonoReflectionEventBuilder *eb;
7564 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7565 klass->event.first = 0;
7566 klass->event.last = klass->event.count;
7568 klass->events = g_new0 (MonoEvent, klass->event.count);
7569 for (i = 0; i < klass->event.count; ++i) {
7570 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7571 klass->events [i].parent = klass;
7572 klass->events [i].attrs = eb->attrs;
7573 klass->events [i].name = mono_string_to_utf8 (eb->name);
7575 klass->events [i].add = eb->add_method->mhandle;
7576 if (eb->remove_method)
7577 klass->events [i].remove = eb->remove_method->mhandle;
7578 if (eb->raise_method)
7579 klass->events [i].raise = eb->raise_method->mhandle;
7581 if (eb->other_methods) {
7582 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7583 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7584 MonoReflectionMethodBuilder *mb =
7585 mono_array_get (eb->other_methods,
7586 MonoReflectionMethodBuilder*, j);
7587 klass->events [i].other [j] = mb->mhandle;
7594 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7597 MonoReflectionType* res;
7599 MONO_ARCH_SAVE_REGS;
7601 klass = my_mono_class_from_mono_type (tb->type.type);
7603 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7606 * Fields to set in klass:
7607 * the various flags: delegate/unicode/contextbound etc.
7610 klass->flags = tb->attrs;
7612 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7613 /* No need to fully construct the type */
7614 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7616 /* enums are done right away */
7617 if (!klass->enumtype)
7618 ensure_runtime_vtable (klass);
7620 /* fields and object layout */
7621 if (klass->parent) {
7622 if (!klass->parent->size_inited)
7623 mono_class_init (klass->parent);
7624 klass->instance_size += klass->parent->instance_size;
7625 klass->class_size += klass->parent->class_size;
7626 klass->min_align = klass->parent->min_align;
7628 klass->instance_size = sizeof (MonoObject);
7629 klass->min_align = 1;
7632 /* FIXME: handle packing_size and instance_size */
7633 typebuilder_setup_fields (klass);
7635 typebuilder_setup_properties (klass);
7637 typebuilder_setup_events (klass);
7639 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7640 /* with enums res == tb: need to fix that. */
7641 if (!klass->enumtype)
7642 g_assert (res != (MonoReflectionType*)tb);
7647 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7649 MonoGenericParam *param;
7652 MONO_ARCH_SAVE_REGS;
7654 param = g_new0 (MonoGenericParam, 1);
7656 param->method = NULL;
7657 param->name = mono_string_to_utf8 (gparam->name);
7658 param->num = gparam->index;
7660 image = &gparam->tbuilder->module->dynamic_image->image;
7661 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7663 param->pklass->reflection_info = gparam;
7665 gparam->type.type = g_new0 (MonoType, 1);
7666 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7667 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7668 gparam->type.type->data.generic_param = param;
7672 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7674 MonoDynamicImage *assembly = sig->module->dynamic_image;
7675 guint32 na = mono_array_length (sig->arguments);
7680 MONO_ARCH_SAVE_REGS;
7682 p = buf = g_malloc (10 + na * 10);
7684 mono_metadata_encode_value (0x07, p, &p);
7685 mono_metadata_encode_value (na, p, &p);
7686 for (i = 0; i < na; ++i) {
7687 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7688 encode_reflection_type (assembly, type, p, &p);
7692 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7693 p = mono_array_addr (result, char, 0);
7694 memcpy (p, buf, buflen);
7701 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7703 MonoDynamicImage *assembly = sig->module->dynamic_image;
7704 guint32 na = mono_array_length (sig->arguments);
7709 MONO_ARCH_SAVE_REGS;
7711 p = buf = g_malloc (10 + na * 10);
7713 mono_metadata_encode_value (0x06, p, &p);
7714 for (i = 0; i < na; ++i) {
7715 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7716 encode_reflection_type (assembly, type, p, &p);
7720 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7721 p = mono_array_addr (result, char, 0);
7722 memcpy (p, buf, buflen);
7729 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7731 ReflectionMethodBuilder rmb;
7732 MonoMethodSignature *sig;
7735 sig = dynamic_method_to_signature (mb);
7737 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7740 * Resolve references.
7742 rmb.nrefs = mb->nrefs;
7743 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7744 for (i = 0; i < mb->nrefs; ++i) {
7745 gpointer ref = resolve_object (mb->module->image,
7746 mono_array_get (mb->refs, MonoObject*, i));
7749 mono_raise_exception (mono_get_exception_type_load (NULL));
7756 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7760 /* ilgen is no longer needed */
7765 * mono_reflection_lookup_dynamic_token:
7767 * Finish the Builder object pointed to by TOKEN and return the corresponding
7768 * runtime structure.
7771 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7773 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7776 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7779 return resolve_object (image, obj);
7783 resolve_object (MonoImage *image, MonoObject *obj)
7785 gpointer result = NULL;
7787 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7788 result = mono_string_intern ((MonoString*)obj);
7791 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7792 MonoReflectionType *tb = (MonoReflectionType*)obj;
7793 result = mono_class_from_mono_type (tb->type);
7796 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7797 result = ((MonoReflectionMethod*)obj)->method;
7800 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7801 result = ((MonoReflectionMethod*)obj)->method;
7804 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7805 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7806 result = mb->mhandle;
7808 /* Type is not yet created */
7809 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7811 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7814 * Hopefully this has been filled in by calling CreateType() on the
7818 * TODO: This won't work if the application finishes another
7819 * TypeBuilder instance instead of this one.
7821 result = mb->mhandle;
7824 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7825 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7827 result = cb->mhandle;
7829 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7831 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7832 result = cb->mhandle;
7835 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7836 result = ((MonoReflectionField*)obj)->field;
7839 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7840 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7841 result = fb->handle;
7844 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7846 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7847 result = fb->handle;
7850 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7851 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7854 klass = tb->type.type->data.klass;
7855 if (klass->wastypebuilder) {
7856 /* Already created */
7860 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7861 result = tb->type.type->data.klass;
7865 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7866 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7867 MonoMethodSignature *sig;
7870 if (helper->arguments)
7871 nargs = mono_array_length (helper->arguments);
7875 sig = mono_metadata_signature_alloc (image, nargs);
7876 sig->explicit_this = helper->call_conv & 64;
7877 sig->hasthis = helper->call_conv & 32;
7879 if (helper->call_conv == 0) /* unmanaged */
7880 sig->call_convention = helper->unmanaged_call_conv - 1;
7882 if (helper->call_conv & 0x02)
7883 sig->call_convention = MONO_CALL_VARARG;
7885 sig->call_convention = MONO_CALL_DEFAULT;
7887 sig->param_count = nargs;
7888 /* TODO: Copy type ? */
7889 sig->ret = helper->return_type->type;
7890 for (i = 0; i < nargs; ++i) {
7891 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7892 sig->params [i] = rt->type;
7898 g_print (obj->vtable->klass->name);
7899 g_assert_not_reached ();