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);
143 alloc_table (MonoDynamicTable *table, guint nrows)
146 g_assert (table->columns);
147 if (nrows + 1 >= table->alloc_rows) {
148 while (nrows + 1 >= table->alloc_rows)
149 if (table->alloc_rows == 0)
150 table->alloc_rows = 16;
152 table->alloc_rows *= 2;
155 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
157 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
162 make_room_in_stream (MonoDynamicStream *stream, int size)
164 while (stream->alloc_size <= size) {
165 if (stream->alloc_size < 4096)
166 stream->alloc_size = 4096;
168 stream->alloc_size *= 2;
171 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
173 stream->data = ALLOC_ATOMIC (stream->alloc_size);
177 string_heap_insert (MonoDynamicStream *sh, const char *str)
181 gpointer oldkey, oldval;
183 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
184 return GPOINTER_TO_UINT (oldval);
186 len = strlen (str) + 1;
188 if (idx + len > sh->alloc_size)
189 make_room_in_stream (sh, idx + len);
192 * We strdup the string even if we already copy them in sh->data
193 * so that the string pointers in the hash remain valid even if
194 * we need to realloc sh->data. We may want to avoid that later.
196 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
197 memcpy (sh->data + idx, str, len);
203 string_heap_init (MonoDynamicStream *sh)
206 sh->alloc_size = 4096;
207 sh->data = ALLOC_ATOMIC (4096);
208 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
209 string_heap_insert (sh, "");
212 #if 0 /* never used */
214 string_heap_free (MonoDynamicStream *sh)
216 FREE_ATOMIC (sh->data);
217 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
218 g_hash_table_destroy (sh->hash);
223 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
226 if (stream->alloc_size < stream->index + len)
227 make_room_in_stream (stream, stream->index + len);
228 memcpy (stream->data + stream->index, data, len);
230 stream->index += len;
232 * align index? Not without adding an additional param that controls it since
233 * we may store a blob value in pieces.
239 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
242 if (stream->alloc_size < stream->index + len)
243 make_room_in_stream (stream, stream->index + len);
244 memset (stream->data + stream->index, 0, len);
246 stream->index += len;
251 stream_data_align (MonoDynamicStream *stream)
254 guint32 count = stream->index % 4;
256 /* we assume the stream data will be aligned */
258 mono_image_add_stream_data (stream, buf, 4 - count);
262 mono_blob_entry_hash (const char* str)
266 len = mono_metadata_decode_blob_size (str, &str);
270 for (str += 1; str < end; str++)
271 h = (h << 5) - h + *str;
279 mono_blob_entry_equal (const char *str1, const char *str2) {
283 len = mono_metadata_decode_blob_size (str1, &end1);
284 len2 = mono_metadata_decode_blob_size (str2, &end2);
287 return memcmp (end1, end2, len) == 0;
291 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
295 gpointer oldkey, oldval;
297 copy = ALLOC_ATOMIC (s1+s2);
298 memcpy (copy, b1, s1);
299 memcpy (copy + s1, b2, s2);
300 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
302 idx = GPOINTER_TO_UINT (oldval);
304 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
305 mono_image_add_stream_data (&assembly->blob, b2, s2);
306 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
312 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
313 * dest may be misaligned.
316 swap_with_size (char *dest, const char* val, int len, int nelem) {
317 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
320 for (elem = 0; elem < nelem; ++elem) {
346 g_assert_not_reached ();
352 memcpy (dest, val, len * nelem);
357 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
361 guint32 idx = 0, len;
363 len = str->length * 2;
364 mono_metadata_encode_value (len, b, &b);
365 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
367 char *swapped = g_malloc (2 * mono_string_length (str));
368 const char *p = (const char*)mono_string_chars (str);
370 swap_with_size (swapped, p, 2, mono_string_length (str));
371 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
375 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
380 /* modified version needed to handle building corlib */
382 my_mono_class_from_mono_type (MonoType *type) {
383 switch (type->type) {
384 case MONO_TYPE_ARRAY:
386 case MONO_TYPE_SZARRAY:
387 case MONO_TYPE_GENERICINST:
388 return mono_class_from_mono_type (type);
391 g_assert (type->data.generic_param->pklass);
392 return type->data.generic_param->pklass;
394 /* should be always valid when we reach this case... */
395 return type->data.klass;
400 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
405 g_assert_not_reached ();
409 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
410 encode_type (assembly, ginst->generic_type, p, &p);
411 mono_metadata_encode_value (ginst->type_argc, p, &p);
412 for (i = 0; i < ginst->type_argc; ++i)
413 encode_type (assembly, ginst->type_argv [i], p, &p);
419 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
422 g_assert_not_reached ();
427 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
431 case MONO_TYPE_BOOLEAN:
445 case MONO_TYPE_STRING:
446 case MONO_TYPE_OBJECT:
447 case MONO_TYPE_TYPEDBYREF:
448 mono_metadata_encode_value (type->type, p, &p);
451 mono_metadata_encode_value (type->type, p, &p);
452 encode_type (assembly, type->data.type, p, &p);
454 case MONO_TYPE_SZARRAY:
455 mono_metadata_encode_value (type->type, p, &p);
456 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
459 case MONO_TYPE_VALUETYPE:
460 case MONO_TYPE_CLASS: {
461 MonoClass *k = mono_class_from_mono_type (type);
462 mono_metadata_encode_value (type->type, p, &p);
464 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
465 * otherwise two typerefs could point to the same type, leading to
466 * verification errors.
468 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
472 case MONO_TYPE_ARRAY:
473 mono_metadata_encode_value (type->type, p, &p);
474 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
475 mono_metadata_encode_value (type->data.array->rank, p, &p);
476 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
477 mono_metadata_encode_value (0, p, &p);
479 case MONO_TYPE_GENERICINST:
480 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
484 mono_metadata_encode_value (type->type, p, &p);
485 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
489 g_error ("need to encode type %x", type->type);
495 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
498 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
502 encode_type (assembly, type->type, p, endbuf);
506 g_assert_not_reached ();
511 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
516 for (i = 0; i < mono_array_length (modreq); ++i) {
517 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
518 *p = MONO_TYPE_CMOD_REQD;
520 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
524 for (i = 0; i < mono_array_length (modopt); ++i) {
525 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
526 *p = MONO_TYPE_CMOD_OPT;
528 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
535 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
540 guint32 nparams = sig->param_count;
541 guint32 size = 10 + nparams * 10;
549 p = buf = g_malloc (size);
551 * FIXME: vararg, explicit_this, differenc call_conv values...
553 *p = sig->call_convention;
555 *p |= 0x20; /* hasthis */
556 if (sig->generic_param_count)
557 *p |= 0x10; /* generic */
559 if (sig->generic_param_count)
560 mono_metadata_encode_value (sig->generic_param_count, p, &p);
561 mono_metadata_encode_value (nparams, p, &p);
562 encode_type (assembly, sig->ret, p, &p);
563 for (i = 0; i < nparams; ++i)
564 encode_type (assembly, sig->params [i], p, &p);
566 g_assert (p - buf < size);
567 mono_metadata_encode_value (p-buf, b, &b);
568 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
574 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
577 * FIXME: reuse code from method_encode_signature().
582 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
583 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
584 guint32 size = 21 + nparams * 20;
589 p = buf = g_malloc (size);
590 /* LAMESPEC: all the call conv spec is foobared */
591 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
592 if (mb->call_conv & 2)
593 *p |= 0x5; /* vararg */
594 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
595 *p |= 0x20; /* hasthis */
597 *p |= 0x10; /* generic */
600 mono_metadata_encode_value (ngparams, p, &p);
601 mono_metadata_encode_value (nparams, p, &p);
602 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
603 encode_reflection_type (assembly, mb->rtype, p, &p);
604 for (i = 0; i < nparams; ++i) {
605 MonoArray *modreq = NULL;
606 MonoArray *modopt = NULL;
607 MonoReflectionType *pt;
609 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
610 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
611 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
612 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
613 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
614 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
615 encode_reflection_type (assembly, pt, p, &p);
618 g_assert (p - buf < size);
619 mono_metadata_encode_value (p-buf, b, &b);
620 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
626 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
628 MonoDynamicTable *table;
631 guint32 idx, sig_idx, size;
632 guint nl = mono_array_length (ilgen->locals);
639 p = buf = g_malloc (size);
640 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
641 idx = table->next_idx ++;
643 alloc_table (table, table->rows);
644 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
646 mono_metadata_encode_value (0x07, p, &p);
647 mono_metadata_encode_value (nl, p, &p);
648 for (i = 0; i < nl; ++i) {
649 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
650 encode_reflection_type (assembly, lb->type, p, &p);
652 g_assert (p - buf < size);
653 mono_metadata_encode_value (p-buf, b, &b);
654 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
657 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
663 method_count_clauses (MonoReflectionILGen *ilgen)
665 guint32 num_clauses = 0;
668 MonoILExceptionInfo *ex_info;
669 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
670 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
671 if (ex_info->handlers)
672 num_clauses += mono_array_length (ex_info->handlers);
680 static MonoExceptionClause*
681 method_encode_clauses (MonoDynamicImage *assembly,
682 MonoReflectionILGen *ilgen, guint32 num_clauses)
684 MonoExceptionClause *clauses;
685 MonoExceptionClause *clause;
686 MonoILExceptionInfo *ex_info;
687 MonoILExceptionBlock *ex_block;
688 guint32 finally_start;
689 int i, j, clause_index;;
691 clauses = g_new0 (MonoExceptionClause, num_clauses);
694 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
695 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
696 finally_start = ex_info->start + ex_info->len;
697 g_assert (ex_info->handlers);
698 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
699 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
700 clause = &(clauses [clause_index]);
702 clause->flags = ex_block->type;
703 clause->try_offset = ex_info->start;
705 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
706 clause->try_len = finally_start - ex_info->start;
708 clause->try_len = ex_info->len;
709 clause->handler_offset = ex_block->start;
710 clause->handler_len = ex_block->len;
711 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
712 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
713 if (ex_block->extype) {
714 mono_g_hash_table_insert (assembly->tokens,
715 GUINT_TO_POINTER (clause->token_or_filter),
718 finally_start = ex_block->start + ex_block->len;
728 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
734 gint32 num_locals = 0;
735 gint32 num_exception = 0;
738 char fat_header [12];
741 guint32 local_sig = 0;
742 guint32 header_size = 12;
745 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
746 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
747 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
748 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
752 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
754 code = mb->ilgen->code;
755 code_size = mb->ilgen->code_len;
756 max_stack = mb->ilgen->max_stack;
757 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
758 if (mb->ilgen->ex_handlers)
759 num_exception = method_count_clauses (mb->ilgen);
763 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
765 code_size = mono_array_length (code);
766 max_stack = 8; /* we probably need to run a verifier on the code... */
769 /* check for exceptions, maxstack, locals */
770 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
772 if (code_size < 64 && !(code_size & 1)) {
773 flags = (code_size << 2) | 0x2;
774 } else if (code_size < 32 && (code_size & 1)) {
775 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
779 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
780 /* add to the fixup todo list */
781 if (mb->ilgen && mb->ilgen->num_token_fixups)
782 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
783 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
784 return assembly->text_rva + idx;
788 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
790 * FIXME: need to set also the header size in fat_flags.
791 * (and more sects and init locals flags)
795 fat_flags |= METHOD_HEADER_MORE_SECTS;
797 fat_flags |= METHOD_HEADER_INIT_LOCALS;
798 fat_header [0] = fat_flags;
799 fat_header [1] = (header_size / 4 ) << 4;
800 shortp = (guint16*)(fat_header + 2);
801 *shortp = GUINT16_TO_LE (max_stack);
802 intp = (guint32*)(fat_header + 4);
803 *intp = GUINT32_TO_LE (code_size);
804 intp = (guint32*)(fat_header + 8);
805 *intp = GUINT32_TO_LE (local_sig);
806 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
807 /* add to the fixup todo list */
808 if (mb->ilgen && mb->ilgen->num_token_fixups)
809 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
811 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
813 unsigned char sheader [4];
814 MonoExceptionClause clause;
815 MonoILExceptionInfo * ex_info;
816 MonoILExceptionBlock * ex_block;
819 stream_data_align (&assembly->code);
820 /* always use fat format for now */
821 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
822 num_exception *= sizeof (MonoExceptionClause);
823 num_exception += 4; /* include the size of the header */
824 sheader [1] = num_exception & 0xff;
825 sheader [2] = (num_exception >> 8) & 0xff;
826 sheader [3] = (num_exception >> 16) & 0xff;
827 mono_image_add_stream_data (&assembly->code, sheader, 4);
828 /* fat header, so we are already aligned */
830 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
831 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
832 if (ex_info->handlers) {
833 int finally_start = ex_info->start + ex_info->len;
834 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
835 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
836 clause.flags = GUINT32_TO_LE (ex_block->type);
837 clause.try_offset = GUINT32_TO_LE (ex_info->start);
838 /* need fault, too, probably */
839 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
840 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
842 clause.try_len = GUINT32_TO_LE (ex_info->len);
843 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
844 clause.handler_len = GUINT32_TO_LE (ex_block->len);
845 finally_start = ex_block->start + ex_block->len;
846 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
847 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
848 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
849 /*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",
850 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);*/
851 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
854 g_error ("No clauses for ex info block %d", i);
858 return assembly->text_rva + idx;
862 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
865 MonoDynamicTable *table;
868 table = &assembly->tables [table_idx];
870 g_assert (col < table->columns);
872 values = table->values + table->columns;
873 for (i = 1; i <= table->rows; ++i) {
874 if (values [col] == token)
876 values += table->columns;
881 static GHashTable *dynamic_custom_attrs = NULL;
883 static MonoCustomAttrInfo*
884 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
887 MonoCustomAttrInfo *ainfo;
888 MonoReflectionCustomAttr *cattr;
892 /* FIXME: check in assembly the Run flag is set */
894 count = mono_array_length (cattrs);
896 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
898 ainfo->image = image;
899 ainfo->num_attrs = count;
900 for (i = 0; i < count; ++i) {
901 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
902 ainfo->attrs [i].ctor = cattr->ctor->method;
903 /* FIXME: might want to memdup the data here */
904 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
905 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
912 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
914 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
919 if (!dynamic_custom_attrs)
920 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
922 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
926 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
928 /* they are cached, so we don't free them */
929 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
935 * idx is the table index of the object
936 * type is one of CUSTOM_ATTR_*
939 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
941 MonoDynamicTable *table;
942 MonoReflectionCustomAttr *cattr;
944 guint32 count, i, token;
948 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
951 count = mono_array_length (cattrs);
952 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
953 table->rows += count;
954 alloc_table (table, table->rows);
955 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
956 idx <<= CUSTOM_ATTR_BITS;
958 for (i = 0; i < count; ++i) {
959 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
960 values [MONO_CUSTOM_ATTR_PARENT] = idx;
961 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
962 type = mono_metadata_token_index (token);
963 type <<= CUSTOM_ATTR_TYPE_BITS;
964 switch (mono_metadata_token_table (token)) {
965 case MONO_TABLE_METHOD:
966 type |= CUSTOM_ATTR_TYPE_METHODDEF;
968 case MONO_TABLE_MEMBERREF:
969 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
972 g_warning ("got wrong token in custom attr");
975 values [MONO_CUSTOM_ATTR_TYPE] = type;
977 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
978 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
979 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
980 values += MONO_CUSTOM_ATTR_SIZE;
986 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
987 MonoArray *permissions)
989 MonoDynamicTable *table;
991 guint32 count, i, idx;
992 MonoReflectionPermissionSet *perm;
997 count = mono_array_length (permissions);
998 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
999 table->rows += count;
1000 alloc_table (table, table->rows);
1002 for (i = 0; i < mono_array_length (permissions); ++i) {
1003 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1005 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1007 idx = mono_metadata_token_index (parent_token);
1008 idx <<= HAS_DECL_SECURITY_BITS;
1009 switch (mono_metadata_token_table (parent_token)) {
1010 case MONO_TABLE_TYPEDEF:
1011 idx |= HAS_DECL_SECURITY_TYPEDEF;
1013 case MONO_TABLE_METHOD:
1014 idx |= HAS_DECL_SECURITY_METHODDEF;
1016 case MONO_TABLE_ASSEMBLY:
1017 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1020 g_assert_not_reached ();
1023 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1024 values [MONO_DECL_SECURITY_PARENT] = idx;
1025 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1032 * Fill in the MethodDef and ParamDef tables for a method.
1033 * This is used for both normal methods and constructors.
1036 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1038 MonoDynamicTable *table;
1043 /* room in this table is already allocated */
1044 table = &assembly->tables [MONO_TABLE_METHOD];
1045 *mb->table_idx = table->next_idx ++;
1046 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1047 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1048 name = mono_string_to_utf8 (mb->name);
1049 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1051 values [MONO_METHOD_FLAGS] = mb->attrs;
1052 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1053 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1054 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1056 table = &assembly->tables [MONO_TABLE_PARAM];
1057 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1059 mono_image_add_decl_security (assembly,
1060 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1064 MonoDynamicTable *mtable;
1067 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1068 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1071 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1072 if (mono_array_get (mb->pinfo, gpointer, i))
1075 table->rows += count;
1076 alloc_table (table, table->rows);
1077 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1078 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1079 MonoReflectionParamBuilder *pb;
1080 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1081 values [MONO_PARAM_FLAGS] = pb->attrs;
1082 values [MONO_PARAM_SEQUENCE] = i;
1083 if (pb->name != NULL) {
1084 name = mono_string_to_utf8 (pb->name);
1085 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1089 values [MONO_PARAM_NAME] = 0;
1090 values += MONO_PARAM_SIZE;
1091 if (pb->marshal_info) {
1093 alloc_table (mtable, mtable->rows);
1094 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1095 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1096 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1098 pb->table_idx = table->next_idx++;
1105 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1106 MonoReflectionMethodBuilder *mb)
1108 rmb->ilgen = mb->ilgen;
1109 rmb->rtype = mb->rtype;
1110 rmb->parameters = mb->parameters;
1111 rmb->generic_params = mb->generic_params;
1112 rmb->pinfo = mb->pinfo;
1113 rmb->attrs = mb->attrs;
1114 rmb->iattrs = mb->iattrs;
1115 rmb->call_conv = mb->call_conv;
1116 rmb->code = mb->code;
1117 rmb->type = mb->type;
1118 rmb->name = mb->name;
1119 rmb->table_idx = &mb->table_idx;
1120 rmb->init_locals = mb->init_locals;
1121 rmb->return_modreq = mb->return_modreq;
1122 rmb->return_modopt = mb->return_modopt;
1123 rmb->param_modreq = mb->param_modreq;
1124 rmb->param_modopt = mb->param_modopt;
1125 rmb->permissions = mb->permissions;
1126 rmb->mhandle = mb->mhandle;
1132 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1133 MonoReflectionCtorBuilder *mb)
1135 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1137 rmb->ilgen = mb->ilgen;
1138 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1139 rmb->parameters = mb->parameters;
1140 rmb->generic_params = NULL;
1141 rmb->pinfo = mb->pinfo;
1142 rmb->attrs = mb->attrs;
1143 rmb->iattrs = mb->iattrs;
1144 rmb->call_conv = mb->call_conv;
1146 rmb->type = mb->type;
1147 rmb->name = mono_string_new (mono_domain_get (), name);
1148 rmb->table_idx = &mb->table_idx;
1149 rmb->init_locals = mb->init_locals;
1150 rmb->return_modreq = NULL;
1151 rmb->return_modopt = NULL;
1152 rmb->param_modreq = mb->param_modreq;
1153 rmb->param_modopt = mb->param_modopt;
1154 rmb->permissions = mb->permissions;
1155 rmb->mhandle = mb->mhandle;
1161 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1162 MonoReflectionDynamicMethod *mb)
1164 rmb->ilgen = mb->ilgen;
1165 rmb->rtype = mb->rtype;
1166 rmb->parameters = mb->parameters;
1167 rmb->generic_params = NULL;
1169 rmb->attrs = mb->attrs;
1171 rmb->call_conv = mb->call_conv;
1174 rmb->name = mb->name;
1175 rmb->table_idx = NULL;
1176 rmb->init_locals = mb->init_locals;
1177 rmb->return_modreq = NULL;
1178 rmb->return_modopt = NULL;
1179 rmb->param_modreq = NULL;
1180 rmb->param_modopt = NULL;
1181 rmb->permissions = NULL;
1182 rmb->mhandle = mb->mhandle;
1188 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1190 MonoDynamicTable *table;
1193 ReflectionMethodBuilder rmb;
1196 reflection_methodbuilder_from_method_builder (&rmb, mb);
1198 mono_image_basic_method (&rmb, assembly);
1200 if (mb->dll) { /* It's a P/Invoke method */
1202 int charset = mb->charset & 0xf;
1203 int lasterr = mb->charset & 0x40;
1204 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1206 alloc_table (table, table->rows);
1207 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1208 /* map CharSet values to on-disk values */
1210 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1211 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1212 name = mono_string_to_utf8 (mb->dllentry);
1213 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1215 name = mono_string_to_utf8 (mb->dll);
1216 moduleref = string_heap_insert (&assembly->sheap, name);
1218 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1219 table = &assembly->tables [MONO_TABLE_MODULEREF];
1221 alloc_table (table, table->rows);
1222 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1223 values [MONO_IMPLMAP_SCOPE] = table->rows;
1227 if (mb->override_method) {
1228 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1230 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1232 alloc_table (table, table->rows);
1233 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1234 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1235 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1236 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1237 switch (mono_metadata_token_table (tok)) {
1238 case MONO_TABLE_MEMBERREF:
1239 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1241 case MONO_TABLE_METHOD:
1242 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1245 g_assert_not_reached ();
1247 values [MONO_METHODIMPL_DECLARATION] = tok;
1250 if (mb->generic_params) {
1251 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1252 table->rows += mono_array_length (mb->generic_params);
1253 alloc_table (table, table->rows);
1254 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1255 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1257 mono_image_get_generic_param_info (
1258 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1265 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1267 ReflectionMethodBuilder rmb;
1269 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1271 mono_image_basic_method (&rmb, assembly);
1275 type_get_fully_qualified_name (MonoType *type) {
1276 char *name, *result;
1280 name = mono_type_get_name (type);
1281 klass = my_mono_class_from_mono_type (type);
1282 ta = klass->image->assembly;
1284 /* missing public key */
1285 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1286 name, ta->aname.name,
1287 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1288 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
1294 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1298 klass = my_mono_class_from_mono_type (type);
1299 ta = klass->image->assembly;
1300 if (ta == ass || klass->image == mono_defaults.corlib)
1301 return mono_type_get_name (type);
1303 return type_get_fully_qualified_name (type);
1307 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1309 char blob_size [64];
1310 char *b = blob_size;
1315 if (!assembly->save)
1318 p = buf = g_malloc (64);
1320 mono_metadata_encode_value (0x06, p, &p);
1321 /* encode custom attributes before the type */
1322 encode_type (assembly, type, p, &p);
1323 g_assert (p-buf < 64);
1324 mono_metadata_encode_value (p-buf, b, &b);
1325 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1331 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1333 char blob_size [64];
1334 char *b = blob_size;
1339 p = buf = g_malloc (64);
1341 mono_metadata_encode_value (0x06, p, &p);
1342 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1343 /* encode custom attributes before the type */
1344 encode_reflection_type (assembly, fb->type, p, &p);
1345 g_assert (p-buf < 64);
1346 mono_metadata_encode_value (p-buf, b, &b);
1347 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1353 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1354 char blob_size [64];
1355 char *b = blob_size;
1358 guint32 idx = 0, len = 0, dummy = 0;
1360 p = buf = g_malloc (64);
1362 *ret_type = MONO_TYPE_CLASS;
1364 box_val = (char*)&dummy;
1366 box_val = ((char*)val) + sizeof (MonoObject);
1367 *ret_type = val->vtable->klass->byval_arg.type;
1370 switch (*ret_type) {
1371 case MONO_TYPE_BOOLEAN:
1376 case MONO_TYPE_CHAR:
1391 case MONO_TYPE_VALUETYPE:
1392 if (val->vtable->klass->enumtype) {
1393 *ret_type = val->vtable->klass->enum_basetype->type;
1396 g_error ("we can't encode valuetypes");
1397 case MONO_TYPE_CLASS:
1399 case MONO_TYPE_STRING: {
1400 MonoString *str = (MonoString*)val;
1401 /* there is no signature */
1402 len = str->length * 2;
1403 mono_metadata_encode_value (len, b, &b);
1404 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1406 char *swapped = g_malloc (2 * mono_string_length (str));
1407 const char *p = (const char*)mono_string_chars (str);
1409 swap_with_size (swapped, p, 2, mono_string_length (str));
1410 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1414 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1421 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1424 /* there is no signature */
1425 mono_metadata_encode_value (len, b, &b);
1426 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1427 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1428 swap_with_size (blob_size, box_val, len, 1);
1429 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1431 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1439 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1440 char blob_size [64];
1441 char *b = blob_size;
1442 char *p, *buf, *str;
1443 guint32 idx, len, bufsize = 256;
1445 p = buf = g_malloc (bufsize);
1447 switch (minfo->type) {
1448 case MONO_NATIVE_BYVALTSTR:
1449 case MONO_NATIVE_BYVALARRAY:
1450 mono_metadata_encode_value (minfo->type, p, &p);
1451 mono_metadata_encode_value (minfo->count, p, &p);
1453 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1454 case MONO_NATIVE_CUSTOM:
1455 mono_metadata_encode_value (minfo->type, p, &p);
1457 str = mono_string_to_utf8 (minfo->guid);
1459 mono_metadata_encode_value (len, p, &p);
1460 memcpy (p, str, len);
1464 mono_metadata_encode_value (0, p, &p);
1466 if (minfo->marshaltype) {
1467 str = mono_string_to_utf8 (minfo->marshaltype);
1469 mono_metadata_encode_value (len, p, &p);
1470 if (p + len >= buf + bufsize) {
1473 buf = g_realloc (buf, bufsize);
1476 memcpy (p, str, len);
1480 mono_metadata_encode_value (0, p, &p);
1482 if (minfo->marshaltyperef) {
1483 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1485 mono_metadata_encode_value (len, p, &p);
1486 if (p + len >= buf + bufsize) {
1489 buf = g_realloc (buf, bufsize);
1492 memcpy (p, str, len);
1496 mono_metadata_encode_value (0, p, &p);
1498 if (minfo->mcookie) {
1499 str = mono_string_to_utf8 (minfo->mcookie);
1501 mono_metadata_encode_value (len, p, &p);
1502 if (p + len >= buf + bufsize) {
1505 buf = g_realloc (buf, bufsize);
1508 memcpy (p, str, len);
1512 mono_metadata_encode_value (0, p, &p);
1516 mono_metadata_encode_value (minfo->type, p, &p);
1520 mono_metadata_encode_value (len, b, &b);
1521 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1527 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1529 MonoDynamicTable *table;
1533 /* maybe this fixup should be done in the C# code */
1534 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1535 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1536 table = &assembly->tables [MONO_TABLE_FIELD];
1537 fb->table_idx = table->next_idx ++;
1538 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1539 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1540 name = mono_string_to_utf8 (fb->name);
1541 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1543 values [MONO_FIELD_FLAGS] = fb->attrs;
1544 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1546 if (fb->offset != -1) {
1547 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1549 alloc_table (table, table->rows);
1550 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1551 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1552 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1554 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1555 guint32 field_type = 0;
1556 table = &assembly->tables [MONO_TABLE_CONSTANT];
1558 alloc_table (table, table->rows);
1559 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1560 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1561 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1562 values [MONO_CONSTANT_TYPE] = field_type;
1563 values [MONO_CONSTANT_PADDING] = 0;
1565 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1567 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1569 alloc_table (table, table->rows);
1570 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1571 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1573 * We store it in the code section because it's simpler for now.
1576 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1578 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1579 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1581 if (fb->marshal_info) {
1582 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1584 alloc_table (table, table->rows);
1585 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1586 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1587 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1592 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1596 char *b = blob_size;
1597 guint32 nparams = 0;
1598 MonoReflectionMethodBuilder *mb = fb->get_method;
1599 MonoReflectionMethodBuilder *smb = fb->set_method;
1600 guint32 idx, i, size;
1602 if (mb && mb->parameters)
1603 nparams = mono_array_length (mb->parameters);
1604 if (!mb && smb && smb->parameters)
1605 nparams = mono_array_length (smb->parameters) - 1;
1606 size = 24 + nparams * 10;
1607 buf = p = g_malloc (size);
1610 mono_metadata_encode_value (nparams, p, &p);
1612 encode_reflection_type (assembly, mb->rtype, p, &p);
1613 for (i = 0; i < nparams; ++i) {
1614 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1615 encode_reflection_type (assembly, pt, p, &p);
1618 /* the property type is the last param */
1619 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1620 for (i = 0; i < nparams; ++i) {
1621 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1622 encode_reflection_type (assembly, pt, p, &p);
1626 g_assert (p - buf < size);
1627 mono_metadata_encode_value (p-buf, b, &b);
1628 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1634 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1636 MonoDynamicTable *table;
1639 guint num_methods = 0;
1643 * we need to set things in the following tables:
1644 * PROPERTYMAP (info already filled in _get_type_info ())
1645 * PROPERTY (rows already preallocated in _get_type_info ())
1646 * METHOD (method info already done with the generic method code)
1649 table = &assembly->tables [MONO_TABLE_PROPERTY];
1650 pb->table_idx = table->next_idx ++;
1651 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1652 name = mono_string_to_utf8 (pb->name);
1653 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1655 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1656 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1658 /* FIXME: we still don't handle 'other' methods */
1659 if (pb->get_method) num_methods ++;
1660 if (pb->set_method) num_methods ++;
1662 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1663 table->rows += num_methods;
1664 alloc_table (table, table->rows);
1666 if (pb->get_method) {
1667 semaidx = table->next_idx ++;
1668 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1669 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1670 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1671 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1673 if (pb->set_method) {
1674 semaidx = table->next_idx ++;
1675 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1676 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1677 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1678 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1683 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1685 MonoDynamicTable *table;
1688 guint num_methods = 0;
1692 * we need to set things in the following tables:
1693 * EVENTMAP (info already filled in _get_type_info ())
1694 * EVENT (rows already preallocated in _get_type_info ())
1695 * METHOD (method info already done with the generic method code)
1698 table = &assembly->tables [MONO_TABLE_EVENT];
1699 eb->table_idx = table->next_idx ++;
1700 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1701 name = mono_string_to_utf8 (eb->name);
1702 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1704 values [MONO_EVENT_FLAGS] = eb->attrs;
1705 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1708 * FIXME: we still don't handle 'other' methods
1710 if (eb->add_method) num_methods ++;
1711 if (eb->remove_method) num_methods ++;
1712 if (eb->raise_method) num_methods ++;
1714 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1715 table->rows += num_methods;
1716 alloc_table (table, table->rows);
1718 if (eb->add_method) {
1719 semaidx = table->next_idx ++;
1720 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1721 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1722 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1723 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1725 if (eb->remove_method) {
1726 semaidx = table->next_idx ++;
1727 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1728 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1729 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1730 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1732 if (eb->raise_method) {
1733 semaidx = table->next_idx ++;
1734 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1735 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1736 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1737 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1742 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1744 MonoDynamicTable *table;
1745 guint32 num_constraints, i;
1749 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1750 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1751 table->rows += num_constraints;
1752 alloc_table (table, table->rows);
1754 for (i = 0; i < num_constraints; i++) {
1755 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1757 table_idx = table->next_idx ++;
1758 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1760 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1761 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1766 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1768 MonoDynamicTable *table;
1769 MonoGenericParam *param;
1773 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1774 table_idx = table->next_idx ++;
1775 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1777 param = gparam->type.type->data.generic_param;
1779 values [MONO_GENERICPARAM_OWNER] = owner;
1780 values [MONO_GENERICPARAM_FLAGS] = param->flags;
1781 values [MONO_GENERICPARAM_NUMBER] = param->num;
1782 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1783 values [MONO_GENERICPARAM_KIND] = 0;
1784 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1786 if (gparam->constraints)
1787 encode_constraints (gparam, table_idx, assembly);
1791 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1793 MonoDynamicTable *table;
1796 guint32 cols [MONO_ASSEMBLY_SIZE];
1800 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1803 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1804 table = &assembly->tables [MONO_TABLE_MODULEREF];
1805 token = table->next_idx ++;
1807 alloc_table (table, table->rows);
1808 values = table->values + token * MONO_MODULEREF_SIZE;
1809 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1811 token <<= RESOLTION_SCOPE_BITS;
1812 token |= RESOLTION_SCOPE_MODULEREF;
1813 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1818 if (image->assembly->dynamic)
1820 memset (cols, 0, sizeof (cols));
1822 /* image->assembly->image is the manifest module */
1823 image = image->assembly->image;
1824 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1827 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1828 token = table->next_idx ++;
1830 alloc_table (table, table->rows);
1831 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1832 if (strcmp ("corlib", image->assembly_name) == 0)
1833 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1835 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1836 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1837 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1838 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1839 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1840 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1841 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1842 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1844 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1845 guchar pubtoken [9];
1847 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1848 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1851 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1852 * This is currently only a problem with references to System.Xml (see bug#27706),
1853 * but there may be other cases that makes this necessary. Note, we need to set
1854 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1855 * recognized by ms, yuck!
1856 * FIXME: need to add more assembly names, as needed.
1858 if (strcmp (image->assembly_name, "corlib") == 0 ||
1859 strcmp (image->assembly_name, "mscorlib") == 0 ||
1860 strcmp (image->assembly_name, "System") == 0 ||
1861 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1862 strcmp (image->assembly_name, "System.Xml") == 0 ||
1863 strcmp (image->assembly_name, "System.Data") == 0 ||
1864 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1865 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1866 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1867 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1868 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1869 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1870 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1871 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1872 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1873 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1874 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1875 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1876 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1877 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1878 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1879 strcmp (image->assembly_name, "System.Design") == 0 ||
1880 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1881 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1882 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1883 strcmp (image->assembly_name, "System.Management") == 0 ||
1884 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1885 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1886 strcmp (image->assembly_name, "System.Security") == 0 ||
1887 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1888 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1889 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1890 strcmp (image->assembly_name, "System.Web") == 0) {
1891 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1892 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1893 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1894 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1896 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1899 token <<= RESOLTION_SCOPE_BITS;
1900 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1901 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1906 create_typespec (MonoDynamicImage *assembly, MonoType *type)
1908 MonoDynamicTable *table;
1914 char *b = blob_size;
1916 switch (type->type) {
1917 case MONO_TYPE_FNPTR:
1919 case MONO_TYPE_SZARRAY:
1920 case MONO_TYPE_ARRAY:
1922 case MONO_TYPE_MVAR:
1923 case MONO_TYPE_GENERICINST:
1924 encode_type (assembly, type, p, &p);
1926 case MONO_TYPE_CLASS:
1927 case MONO_TYPE_VALUETYPE: {
1928 MonoClass *k = mono_class_from_mono_type (type);
1929 if (!k || !k->generic_inst)
1931 encode_generic_inst (assembly, k->generic_inst, p, &p);
1938 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1939 if (assembly->save) {
1940 g_assert (p-sig < 128);
1941 mono_metadata_encode_value (p-sig, b, &b);
1942 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1943 alloc_table (table, table->rows + 1);
1944 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1945 values [MONO_TYPESPEC_SIGNATURE] = token;
1948 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1949 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1955 * Despite the name, we handle also TypeSpec (with the above helper).
1958 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
1960 MonoDynamicTable *table;
1962 guint32 token, scope, enclosing;
1965 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1968 token = create_typespec (assembly, type);
1971 klass = my_mono_class_from_mono_type (type);
1973 klass = mono_class_from_mono_type (type);
1976 * If it's in the same module and not a generic type parameter:
1978 if ((klass->image == &assembly->image) &&
1979 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
1980 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1981 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1982 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1986 if (klass->nested_in) {
1987 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1988 /* get the typeref idx of the enclosing type */
1989 enclosing >>= TYPEDEFORREF_BITS;
1990 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1992 scope = resolution_scope_from_image (assembly, klass->image);
1994 table = &assembly->tables [MONO_TABLE_TYPEREF];
1995 if (assembly->save) {
1996 alloc_table (table, table->rows + 1);
1997 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1998 values [MONO_TYPEREF_SCOPE] = scope;
1999 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2000 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2002 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2003 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2005 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2010 * Insert a memberef row into the metadata: the token that point to the memberref
2011 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2012 * mono_image_get_fieldref_token()).
2013 * The sig param is an index to an already built signature.
2016 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2018 MonoDynamicTable *table;
2020 guint32 token, pclass;
2023 parent = mono_image_typedef_or_ref (assembly, type);
2024 switch (parent & TYPEDEFORREF_MASK) {
2025 case TYPEDEFORREF_TYPEREF:
2026 pclass = MEMBERREF_PARENT_TYPEREF;
2028 case TYPEDEFORREF_TYPESPEC:
2029 pclass = MEMBERREF_PARENT_TYPESPEC;
2031 case TYPEDEFORREF_TYPEDEF:
2032 pclass = MEMBERREF_PARENT_TYPEDEF;
2035 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2038 /* extract the index */
2039 parent >>= TYPEDEFORREF_BITS;
2041 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2043 if (assembly->save) {
2044 alloc_table (table, table->rows + 1);
2045 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2046 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2047 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2048 values [MONO_MEMBERREF_SIGNATURE] = sig;
2051 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2058 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2062 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2065 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2066 method->name, method_encode_signature (assembly, method->signature));
2067 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2072 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2075 ReflectionMethodBuilder rmb;
2077 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2081 reflection_methodbuilder_from_method_builder (&rmb, mb);
2083 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2084 mono_string_to_utf8 (rmb.name),
2085 method_builder_encode_signature (assembly, &rmb));
2086 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2091 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2094 ReflectionMethodBuilder rmb;
2096 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2100 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2102 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2103 mono_string_to_utf8 (rmb.name),
2104 method_builder_encode_signature (assembly, &rmb));
2105 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2110 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass)
2114 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
2117 field->parent = klass;
2118 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
2119 field->name, fieldref_encode_signature (assembly, field->type));
2120 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
2125 field_encode_inflated_field (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
2131 klass = field->rfield.klass;
2132 name = field->rfield.field->name;
2133 sig = fieldref_encode_signature (assembly, field->declaring->type);
2134 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2140 mono_image_get_inflated_field_token (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
2144 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field->rfield.field));
2147 token = field_encode_inflated_field (assembly, field);
2148 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
2153 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2158 guint32 nparams = gmethod->mtype_argc;
2159 guint32 size = 10 + nparams * 10;
2162 char *b = blob_size;
2164 if (!assembly->save)
2167 p = buf = g_malloc (size);
2169 * FIXME: vararg, explicit_this, differenc call_conv values...
2171 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2172 mono_metadata_encode_value (nparams, p, &p);
2174 for (i = 0; i < nparams; i++)
2175 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2178 g_assert (p - buf < size);
2179 mono_metadata_encode_value (p-buf, b, &b);
2180 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2186 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method,
2187 MonoGenericMethod *gmethod)
2189 MonoDynamicTable *table;
2191 guint32 token, mtoken = 0, sig;
2194 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2197 k = gmethod->klass ? gmethod->klass : method->klass;
2199 sig = method_encode_signature (assembly, method->signature);
2200 mtoken = mono_image_get_memberref_token (assembly, &k->byval_arg, method->name, sig);
2202 if (!method->signature->generic_param_count)
2205 switch (mono_metadata_token_table (mtoken)) {
2206 case MONO_TABLE_MEMBERREF:
2207 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2209 case MONO_TABLE_METHOD:
2210 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2213 g_assert_not_reached ();
2216 sig = encode_generic_method_sig (assembly, gmethod);
2218 if (assembly->save) {
2219 alloc_table (table, table->rows + 1);
2220 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2221 values [MONO_METHODSPEC_METHOD] = mtoken;
2222 values [MONO_METHODSPEC_SIGNATURE] = sig;
2225 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2232 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoReflectionInflatedMethod *m)
2236 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m->rmethod.method));
2239 if (m->declaring->method->signature->generic_param_count)
2240 token = method_encode_methodspec (assembly, m->declaring->method, m->gmethod);
2245 g_assert (m->gmethod);
2246 k = m->gmethod->klass ? m->gmethod->klass : m->gmethod->generic_method->klass;
2248 sig = method_encode_signature (assembly, m->declaring->method->signature);
2249 token = mono_image_get_memberref_token (
2250 assembly, &k->byval_arg, m->gmethod->generic_method->name, sig);
2253 g_hash_table_insert (assembly->handleref, m->rmethod.method, GUINT_TO_POINTER(token));
2258 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2260 MonoDynamicTable *table;
2267 char *b = blob_size;
2270 g_assert (tb->generic_params);
2271 klass = mono_class_from_mono_type (tb->type.type);
2273 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2274 encode_type (assembly, &klass->byval_arg, p, &p);
2276 count = mono_array_length (tb->generic_params);
2277 mono_metadata_encode_value (count, p, &p);
2278 for (i = 0; i < count; i++) {
2279 MonoReflectionGenericParam *gparam;
2281 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2283 encode_type (assembly, gparam->type.type, p, &p);
2286 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2287 if (assembly->save) {
2288 g_assert (p-sig < 128);
2289 mono_metadata_encode_value (p-sig, b, &b);
2290 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2291 alloc_table (table, table->rows + 1);
2292 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2293 values [MONO_TYPESPEC_SIGNATURE] = token;
2296 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2297 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2303 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2305 MonoDynamicTable *table;
2308 guint32 token, pclass, parent, sig;
2311 klass = mono_class_from_mono_type (fb->typeb->type);
2312 name = mono_string_to_utf8 (fb->name);
2314 sig = fieldref_encode_signature (assembly, fb->type->type);
2316 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2317 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2319 pclass = MEMBERREF_PARENT_TYPESPEC;
2320 parent >>= TYPEDEFORREF_BITS;
2322 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2324 if (assembly->save) {
2325 alloc_table (table, table->rows + 1);
2326 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2327 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2328 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2329 values [MONO_MEMBERREF_SIGNATURE] = sig;
2332 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2339 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2347 char *b = blob_size;
2349 if (!assembly->save)
2353 g_assert (helper->type == 2);
2355 if (helper->arguments)
2356 nargs = mono_array_length (helper->arguments);
2360 size = 10 + (nargs * 10);
2362 p = buf = g_malloc (size);
2364 /* Encode calling convention */
2365 /* Change Any to Standard */
2366 if ((helper->call_conv & 0x03) == 0x03)
2367 helper->call_conv = 0x01;
2368 /* explicit_this implies has_this */
2369 if (helper->call_conv & 0x40)
2370 helper->call_conv &= 0x20;
2372 if (helper->call_conv == 0) /* Unmanaged */
2373 *p = helper->unmanaged_call_conv - 1;
2376 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2377 if (helper->call_conv & 0x02) /* varargs */
2382 mono_metadata_encode_value (nargs, p, &p);
2383 encode_reflection_type (assembly, helper->return_type, p, &p);
2384 for (i = 0; i < nargs; ++i) {
2385 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2386 encode_reflection_type (assembly, pt, p, &p);
2389 g_assert (p - buf < size);
2390 mono_metadata_encode_value (p-buf, b, &b);
2391 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2398 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2401 MonoDynamicTable *table;
2404 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2405 idx = table->next_idx ++;
2407 alloc_table (table, table->rows);
2408 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2410 values [MONO_STAND_ALONE_SIGNATURE] =
2411 mono_reflection_encode_sighelper (assembly, helper);
2417 reflection_cc_to_file (int call_conv) {
2418 switch (call_conv & 0x3) {
2420 case 1: return MONO_CALL_DEFAULT;
2421 case 2: return MONO_CALL_VARARG;
2423 g_assert_not_reached ();
2430 MonoMethodSignature *sig;
2436 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2441 MonoMethodSignature *sig;
2444 name = mono_string_to_utf8 (m->name);
2445 nparams = mono_array_length (m->parameters);
2446 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2448 sig->call_convention = reflection_cc_to_file (m->call_conv);
2449 sig->param_count = nparams;
2450 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2451 for (i = 0; i < nparams; ++i) {
2452 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2453 sig->params [i] = t->type;
2456 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2458 if (strcmp (name, am->name) == 0 &&
2459 mono_metadata_type_equal (am->parent, m->parent->type) &&
2460 mono_metadata_signature_equal (am->sig, sig)) {
2463 m->table_idx = am->token & 0xffffff;
2467 am = g_new0 (ArrayMethod, 1);
2470 am->parent = m->parent->type;
2471 am->token = mono_image_get_memberref_token (assembly, am->parent,
2472 name, method_encode_signature (assembly, sig));
2473 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2474 m->table_idx = am->token & 0xffffff;
2479 * Insert into the metadata tables all the info about the TypeBuilder tb.
2480 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2483 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2485 MonoDynamicTable *table;
2487 int i, is_object = 0, is_system = 0;
2490 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2491 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2492 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2493 n = mono_string_to_utf8 (tb->name);
2494 if (strcmp (n, "Object") == 0)
2496 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2498 n = mono_string_to_utf8 (tb->nspace);
2499 if (strcmp (n, "System") == 0)
2501 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2503 if (tb->parent && !(is_system && is_object) &&
2504 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2505 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2507 values [MONO_TYPEDEF_EXTENDS] = 0;
2508 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2509 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2512 * if we have explicitlayout or sequentiallayouts, output data in the
2513 * ClassLayout table.
2515 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2516 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2518 alloc_table (table, table->rows);
2519 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2520 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2521 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2522 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2525 /* handle interfaces */
2526 if (tb->interfaces) {
2527 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2529 table->rows += mono_array_length (tb->interfaces);
2530 alloc_table (table, table->rows);
2531 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2532 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2533 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2534 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2535 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2536 values += MONO_INTERFACEIMPL_SIZE;
2540 /* handle generic parameters */
2541 if (tb->generic_params) {
2542 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2543 table->rows += mono_array_length (tb->generic_params);
2544 alloc_table (table, table->rows);
2545 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2546 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2548 mono_image_get_generic_param_info (
2549 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2555 table = &assembly->tables [MONO_TABLE_FIELD];
2556 table->rows += tb->num_fields;
2557 alloc_table (table, table->rows);
2558 for (i = 0; i < tb->num_fields; ++i)
2559 mono_image_get_field_info (
2560 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2563 /* handle constructors */
2565 table = &assembly->tables [MONO_TABLE_METHOD];
2566 table->rows += mono_array_length (tb->ctors);
2567 alloc_table (table, table->rows);
2568 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2569 mono_image_get_ctor_info (domain,
2570 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2573 /* handle methods */
2575 table = &assembly->tables [MONO_TABLE_METHOD];
2576 table->rows += tb->num_methods;
2577 alloc_table (table, table->rows);
2578 for (i = 0; i < tb->num_methods; ++i)
2579 mono_image_get_method_info (
2580 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2583 /* Do the same with properties etc.. */
2584 if (tb->events && mono_array_length (tb->events)) {
2585 table = &assembly->tables [MONO_TABLE_EVENT];
2586 table->rows += mono_array_length (tb->events);
2587 alloc_table (table, table->rows);
2588 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2590 alloc_table (table, table->rows);
2591 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2592 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2593 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2594 for (i = 0; i < mono_array_length (tb->events); ++i)
2595 mono_image_get_event_info (
2596 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2598 if (tb->properties && mono_array_length (tb->properties)) {
2599 table = &assembly->tables [MONO_TABLE_PROPERTY];
2600 table->rows += mono_array_length (tb->properties);
2601 alloc_table (table, table->rows);
2602 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2604 alloc_table (table, table->rows);
2605 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2606 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2607 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2608 for (i = 0; i < mono_array_length (tb->properties); ++i)
2609 mono_image_get_property_info (
2610 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2613 mono_image_add_decl_security (assembly,
2614 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2618 MonoDynamicTable *ntable;
2620 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2621 ntable->rows += mono_array_length (tb->subtypes);
2622 alloc_table (ntable, ntable->rows);
2623 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2625 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2626 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2628 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2629 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2630 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2631 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2632 mono_string_to_utf8 (tb->name), tb->table_idx,
2633 ntable->next_idx, ntable->rows);*/
2634 values += MONO_NESTED_CLASS_SIZE;
2641 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2645 g_ptr_array_add (types, type);
2647 if (!type->subtypes)
2650 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2651 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2652 collect_types (types, subtype);
2657 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2658 MonoReflectionTypeBuilder **type2)
2660 if ((*type1)->table_idx < (*type2)->table_idx)
2663 if ((*type1)->table_idx > (*type2)->table_idx)
2670 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2675 for (i = 0; i < mono_array_length (pinfo); ++i) {
2676 MonoReflectionParamBuilder *pb;
2677 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2680 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2685 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2688 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2690 for (i = 0; i < tb->num_fields; ++i) {
2691 MonoReflectionFieldBuilder* fb;
2692 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2693 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2697 for (i = 0; i < mono_array_length (tb->events); ++i) {
2698 MonoReflectionEventBuilder* eb;
2699 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2700 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2703 if (tb->properties) {
2704 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2705 MonoReflectionPropertyBuilder* pb;
2706 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2707 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2711 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2712 MonoReflectionCtorBuilder* cb;
2713 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2714 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2715 params_add_cattrs (assembly, cb->pinfo);
2720 for (i = 0; i < tb->num_methods; ++i) {
2721 MonoReflectionMethodBuilder* mb;
2722 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2723 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2724 params_add_cattrs (assembly, mb->pinfo);
2729 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2730 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2735 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2738 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2740 /* no types in the module */
2744 for (i = 0; i < mb->num_types; ++i)
2745 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2749 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2750 MonoDynamicImage *assembly)
2752 MonoDynamicTable *table;
2756 char *b = blob_size;
2759 table = &assembly->tables [MONO_TABLE_FILE];
2761 alloc_table (table, table->rows);
2762 values = table->values + table->next_idx * MONO_FILE_SIZE;
2763 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2764 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2765 if (module->image->dynamic) {
2766 /* This depends on the fact that the main module is emitted last */
2767 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2768 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2772 path = g_strdup (module->image->name);
2774 mono_sha1_get_digest_from_file (path, hash);
2777 mono_metadata_encode_value (20, b, &b);
2778 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2779 mono_image_add_stream_data (&assembly->blob, hash, 20);
2784 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2786 MonoDynamicTable *table;
2790 table = &assembly->tables [MONO_TABLE_MODULE];
2791 mb->table_idx = table->next_idx ++;
2792 name = mono_string_to_utf8 (mb->module.name);
2793 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2795 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2798 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2799 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2800 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2804 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2805 guint32 module_index, guint32 parent_index,
2806 MonoDynamicImage *assembly)
2808 MonoDynamicTable *table;
2812 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2813 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2816 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2818 alloc_table (table, table->rows);
2819 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2821 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2822 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2823 if (klass->nested_in)
2824 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2826 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2827 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2828 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2830 res = table->next_idx;
2834 /* Emit nested types */
2835 if (klass->nested_classes) {
2838 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2839 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2846 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2847 guint32 module_index, guint32 parent_index,
2848 MonoDynamicImage *assembly)
2853 klass = mono_class_from_mono_type (tb->type.type);
2855 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
2857 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
2858 parent_index, assembly);
2862 * We need to do this ourselves since klass->nested_classes is not set up.
2865 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2866 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
2871 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
2872 guint32 module_index,
2873 MonoDynamicImage *assembly)
2875 MonoImage *image = module->image;
2879 t = &image->tables [MONO_TABLE_TYPEDEF];
2881 for (i = 0; i < t->rows; ++i) {
2882 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
2884 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
2885 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
2889 #define align_pointer(base,p)\
2891 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2893 (p) += 4 - (__diff & 3);\
2897 compare_semantics (const void *a, const void *b)
2899 const guint32 *a_values = a;
2900 const guint32 *b_values = b;
2901 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2904 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2908 compare_custom_attrs (const void *a, const void *b)
2910 const guint32 *a_values = a;
2911 const guint32 *b_values = b;
2913 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2917 compare_field_marshal (const void *a, const void *b)
2919 const guint32 *a_values = a;
2920 const guint32 *b_values = b;
2922 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2926 compare_nested (const void *a, const void *b)
2928 const guint32 *a_values = a;
2929 const guint32 *b_values = b;
2931 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2935 * build_compressed_metadata() fills in the blob of data that represents the
2936 * raw metadata as it will be saved in the PE file. The five streams are output
2937 * and the metadata tables are comnpressed from the guint32 array representation,
2938 * to the compressed on-disk format.
2941 build_compressed_metadata (MonoDynamicImage *assembly)
2943 MonoDynamicTable *table;
2945 guint64 valid_mask = 0;
2946 guint64 sorted_mask;
2947 guint32 heapt_size = 0;
2948 guint32 meta_size = 256; /* allow for header and other stuff */
2949 guint32 table_offset;
2950 guint32 ntables = 0;
2959 MonoDynamicStream *stream;
2962 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
2963 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2964 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
2965 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
2966 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
2968 /* tables that are sorted */
2969 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2970 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2971 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2972 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2973 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2974 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2976 /* Compute table sizes */
2977 /* the MonoImage has already been created in mono_image_basic_init() */
2978 meta = &assembly->image;
2980 /* Setup the info used by compute_sizes () */
2981 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2982 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2983 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2985 meta_size += assembly->blob.index;
2986 meta_size += assembly->guid.index;
2987 meta_size += assembly->sheap.index;
2988 meta_size += assembly->us.index;
2990 for (i=0; i < 64; ++i)
2991 meta->tables [i].rows = assembly->tables [i].rows;
2993 for (i = 0; i < 64; i++){
2994 if (meta->tables [i].rows == 0)
2996 valid_mask |= (guint64)1 << i;
2998 meta->tables [i].row_size = mono_metadata_compute_size (
2999 meta, i, &meta->tables [i].size_bitfield);
3000 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3002 heapt_size += 24; /* #~ header size */
3003 heapt_size += ntables * 4;
3004 meta_size += heapt_size;
3005 meta->raw_metadata = g_malloc0 (meta_size);
3006 p = meta->raw_metadata;
3007 /* the metadata signature */
3008 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3009 /* version numbers and 4 bytes reserved */
3010 int16val = (guint16*)p;
3011 *int16val++ = GUINT16_TO_LE (1);
3012 *int16val = GUINT16_TO_LE (1);
3014 /* version string */
3015 int32val = (guint32*)p;
3016 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3018 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3019 p += GUINT32_FROM_LE (*int32val);
3020 align_pointer (meta->raw_metadata, p);
3021 int16val = (guint16*)p;
3022 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3023 *int16val = GUINT16_TO_LE (5); /* number of streams */
3027 * write the stream info.
3029 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3030 table_offset += 3; table_offset &= ~3;
3032 assembly->tstream.index = heapt_size;
3033 for (i = 0; i < 5; ++i) {
3034 int32val = (guint32*)p;
3035 stream_desc [i].stream->offset = table_offset;
3036 *int32val++ = GUINT32_TO_LE (table_offset);
3037 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3038 table_offset += GUINT32_FROM_LE (*int32val);
3039 table_offset += 3; table_offset &= ~3;
3041 strcpy (p, stream_desc [i].name);
3042 p += strlen (stream_desc [i].name) + 1;
3043 align_pointer (meta->raw_metadata, p);
3046 * now copy the data, the table stream header and contents goes first.
3048 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3049 p = meta->raw_metadata + assembly->tstream.offset;
3050 int32val = (guint32*)p;
3051 *int32val = GUINT32_TO_LE (0); /* reserved */
3053 *p++ = 1; /* version */
3055 if (meta->idx_string_wide)
3057 if (meta->idx_guid_wide)
3059 if (meta->idx_blob_wide)
3062 *p++ = 0; /* reserved */
3063 int64val = (guint64*)p;
3064 *int64val++ = GUINT64_TO_LE (valid_mask);
3065 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3067 int32val = (guint32*)p;
3068 for (i = 0; i < 64; i++){
3069 if (meta->tables [i].rows == 0)
3071 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3073 p = (unsigned char*)int32val;
3075 /* sort the tables that still need sorting */
3076 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3078 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3079 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3081 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3082 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3084 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3085 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3087 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3089 /* compress the tables */
3090 for (i = 0; i < 64; i++){
3093 guint32 bitfield = meta->tables [i].size_bitfield;
3094 if (!meta->tables [i].rows)
3096 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3097 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3098 meta->tables [i].base = p;
3099 for (row = 1; row <= meta->tables [i].rows; ++row) {
3100 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3101 for (col = 0; col < assembly->tables [i].columns; ++col) {
3102 switch (mono_metadata_table_size (bitfield, col)) {
3104 *p++ = values [col];
3107 *p++ = values [col] & 0xff;
3108 *p++ = (values [col] >> 8) & 0xff;
3111 *p++ = values [col] & 0xff;
3112 *p++ = (values [col] >> 8) & 0xff;
3113 *p++ = (values [col] >> 16) & 0xff;
3114 *p++ = (values [col] >> 24) & 0xff;
3117 g_assert_not_reached ();
3121 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3124 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3125 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3126 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3127 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3128 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3130 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3134 * Some tables in metadata need to be sorted according to some criteria, but
3135 * when methods and fields are first created with reflection, they may be assigned a token
3136 * that doesn't correspond to the final token they will get assigned after the sorting.
3137 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3138 * with the reflection objects that represent them. Once all the tables are set up, the
3139 * reflection objects will contains the correct table index. fixup_method() will fixup the
3140 * tokens for the method with ILGenerator @ilgen.
3143 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3144 guint32 code_idx = GPOINTER_TO_UINT (value);
3145 MonoReflectionILTokenInfo *iltoken;
3146 MonoReflectionFieldBuilder *field;
3147 MonoReflectionCtorBuilder *ctor;
3148 MonoReflectionMethodBuilder *method;
3149 MonoReflectionTypeBuilder *tb;
3150 MonoReflectionArrayMethod *am;
3152 unsigned char *target;
3154 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3155 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3156 target = assembly->code.data + code_idx + iltoken->code_pos;
3157 switch (target [3]) {
3158 case MONO_TABLE_FIELD:
3159 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3160 field = (MonoReflectionFieldBuilder *)iltoken->member;
3161 idx = field->table_idx;
3162 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3163 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3164 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3166 g_assert_not_reached ();
3169 case MONO_TABLE_METHOD:
3170 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3171 method = (MonoReflectionMethodBuilder *)iltoken->member;
3172 idx = method->table_idx;
3173 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3174 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3175 idx = ctor->table_idx;
3176 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3177 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3178 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3179 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3181 g_assert_not_reached ();
3184 case MONO_TABLE_TYPEDEF:
3185 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3186 g_assert_not_reached ();
3187 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3188 idx = tb->table_idx;
3190 case MONO_TABLE_MEMBERREF:
3191 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3192 am = (MonoReflectionArrayMethod*)iltoken->member;
3193 idx = am->table_idx;
3194 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3195 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3196 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3197 g_assert (m->klass->generic_inst);
3199 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
3200 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor") ||
3201 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedField")) {
3203 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3206 g_assert_not_reached ();
3209 case MONO_TABLE_METHODSPEC:
3210 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3211 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3212 g_assert (m->signature->generic_param_count);
3214 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
3215 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor")) {
3218 g_assert_not_reached ();
3222 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3224 target [0] = idx & 0xff;
3225 target [1] = (idx >> 8) & 0xff;
3226 target [2] = (idx >> 16) & 0xff;
3233 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3234 * value is not known when the table is emitted.
3237 fixup_cattrs (MonoDynamicImage *assembly)
3239 MonoDynamicTable *table;
3241 guint32 type, i, idx, token;
3244 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3246 for (i = 0; i < table->rows; ++i) {
3247 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3249 type = values [MONO_CUSTOM_ATTR_TYPE];
3250 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3251 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3252 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3253 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3256 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3257 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3258 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3259 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3266 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3268 MonoDynamicTable *table;
3272 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3274 alloc_table (table, table->rows);
3275 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3276 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3277 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3278 name = mono_string_to_utf8 (rsrc->name);
3279 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3281 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3286 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3288 MonoDynamicTable *table;
3292 char *b = blob_size;
3294 guint32 idx, offset;
3296 if (rsrc->filename) {
3297 name = mono_string_to_utf8 (rsrc->filename);
3298 sname = g_path_get_basename (name);
3300 table = &assembly->tables [MONO_TABLE_FILE];
3302 alloc_table (table, table->rows);
3303 values = table->values + table->next_idx * MONO_FILE_SIZE;
3304 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3305 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3308 mono_sha1_get_digest_from_file (name, hash);
3309 mono_metadata_encode_value (20, b, &b);
3310 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3311 mono_image_add_stream_data (&assembly->blob, hash, 20);
3313 idx = table->next_idx++;
3315 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3318 offset = mono_array_length (rsrc->data);
3319 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3320 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3321 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3322 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3326 * The entry should be emitted into the MANIFESTRESOURCE table of
3327 * the main module, but that needs to reference the FILE table
3328 * which isn't emitted yet.
3335 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3339 set_version_from_string (MonoString *version, guint32 *values)
3341 gchar *ver, *p, *str;
3344 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3345 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3346 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3347 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3350 ver = str = mono_string_to_utf8 (version);
3351 for (i = 0; i < 4; ++i) {
3352 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3358 /* handle Revision and Build */
3368 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3372 char *b = blob_size;
3377 len = mono_array_length (pkey);
3378 mono_metadata_encode_value (len, b, &b);
3379 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3380 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3382 /* need to get the actual value from the key type... */
3383 assembly->strong_name_size = 128;
3384 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3390 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3392 MonoDynamicTable *table;
3393 MonoDynamicImage *assembly;
3394 MonoReflectionAssemblyBuilder *assemblyb;
3399 guint32 module_index;
3401 assemblyb = moduleb->assemblyb;
3402 assembly = moduleb->dynamic_image;
3403 domain = mono_object_domain (assemblyb);
3405 /* Emit ASSEMBLY table */
3406 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3407 alloc_table (table, 1);
3408 values = table->values + MONO_ASSEMBLY_SIZE;
3409 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3410 name = mono_string_to_utf8 (assemblyb->name);
3411 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3413 if (assemblyb->culture) {
3414 name = mono_string_to_utf8 (assemblyb->culture);
3415 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3418 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3420 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3421 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3422 set_version_from_string (assemblyb->version, values);
3424 /* Emit FILE + EXPORTED_TYPE table */
3426 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3428 MonoReflectionModuleBuilder *file_module =
3429 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3430 if (file_module != moduleb) {
3431 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3433 if (file_module->types) {
3434 for (j = 0; j < file_module->num_types; ++j) {
3435 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3436 mono_image_fill_export_table (domain, tb, module_index, 0,
3442 if (assemblyb->loaded_modules) {
3443 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3444 MonoReflectionModule *file_module =
3445 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3446 mono_image_fill_file_table (domain, file_module, assembly);
3448 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3452 /* Emit MANIFESTRESOURCE table */
3454 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3456 MonoReflectionModuleBuilder *file_module =
3457 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3458 /* The table for the main module is emitted later */
3459 if (file_module != moduleb) {
3461 if (file_module->resources) {
3462 int len = mono_array_length (file_module->resources);
3463 for (j = 0; j < len; ++j) {
3464 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3465 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3473 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3474 * for the modulebuilder @moduleb.
3475 * At the end of the process, method and field tokens are fixed up and the
3476 * on-disk compressed metadata representation is created.
3479 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3481 MonoDynamicTable *table;
3482 MonoDynamicImage *assembly;
3483 MonoReflectionAssemblyBuilder *assemblyb;
3488 assemblyb = moduleb->assemblyb;
3489 assembly = moduleb->dynamic_image;
3490 domain = mono_object_domain (assemblyb);
3492 if (assembly->text_rva)
3495 assembly->text_rva = START_TEXT_RVA;
3497 if (moduleb->is_main) {
3498 mono_image_emit_manifest (moduleb);
3501 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3502 table->rows = 1; /* .<Module> */
3504 alloc_table (table, table->rows);
3506 * Set the first entry.
3508 values = table->values + table->columns;
3509 values [MONO_TYPEDEF_FLAGS] = 0;
3510 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3511 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3512 values [MONO_TYPEDEF_EXTENDS] = 0;
3513 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3514 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3517 * handle global methods
3518 * FIXME: test what to do when global methods are defined in multiple modules.
3520 if (moduleb->global_methods) {
3521 table = &assembly->tables [MONO_TABLE_METHOD];
3522 table->rows += mono_array_length (moduleb->global_methods);
3523 alloc_table (table, table->rows);
3524 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3525 mono_image_get_method_info (
3526 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3528 if (moduleb->global_fields) {
3529 table = &assembly->tables [MONO_TABLE_FIELD];
3530 table->rows += mono_array_length (moduleb->global_fields);
3531 alloc_table (table, table->rows);
3532 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3533 mono_image_get_field_info (
3534 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3537 table = &assembly->tables [MONO_TABLE_MODULE];
3538 alloc_table (table, 1);
3539 mono_image_fill_module_table (domain, moduleb, assembly);
3543 /* Collect all types into a list sorted by their table_idx */
3544 GPtrArray *types = g_ptr_array_new ();
3547 for (i = 0; i < moduleb->num_types; ++i) {
3548 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3549 collect_types (types, type);
3552 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3553 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3554 table->rows += types->len;
3555 alloc_table (table, table->rows);
3557 for (i = 0; i < types->len; ++i) {
3558 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3559 mono_image_get_type_info (domain, type, assembly);
3561 g_ptr_array_free (types, TRUE);
3565 * table->rows is already set above and in mono_image_fill_module_table.
3567 /* add all the custom attributes at the end, once all the indexes are stable */
3568 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3570 module_add_cattrs (assembly, moduleb);
3573 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3574 fixup_cattrs (assembly);
3578 * mono_image_insert_string:
3579 * @module: module builder object
3582 * Insert @str into the user string stream of @module.
3585 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3587 MonoDynamicImage *assembly;
3592 MONO_ARCH_SAVE_REGS;
3594 if (!module->dynamic_image)
3595 mono_image_module_basic_init (module);
3597 assembly = module->dynamic_image;
3599 if (assembly->save) {
3600 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3601 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3602 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3604 char *swapped = g_malloc (2 * mono_string_length (str));
3605 const char *p = (const char*)mono_string_chars (str);
3607 swap_with_size (swapped, p, 2, mono_string_length (str));
3608 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3612 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3614 mono_image_add_stream_data (&assembly->us, "", 1);
3617 idx = assembly->us.index ++;
3619 mono_g_hash_table_insert (assembly->tokens,
3620 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3622 return MONO_TOKEN_STRING | idx;
3626 * mono_image_create_token:
3627 * @assembly: a dynamic assembly
3630 * Get a token to insert in the IL code stream for the given MemberInfo.
3631 * @obj can be one of:
3632 * ConstructorBuilder
3642 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3647 klass = obj->vtable->klass;
3648 if (strcmp (klass->name, "MethodBuilder") == 0) {
3649 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3651 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3652 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3654 token = mono_image_get_methodbuilder_token (assembly, mb);
3655 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3657 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3658 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3660 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3661 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3663 token = mono_image_get_ctorbuilder_token (assembly, mb);
3664 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3666 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3667 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3668 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3669 if (tb->generic_params) {
3670 token = mono_image_get_generic_field_token (assembly, fb);
3672 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3675 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3676 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3677 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3679 else if (strcmp (klass->name, "MonoType") == 0 ||
3680 strcmp (klass->name, "MonoGenericParam") == 0) {
3681 MonoReflectionType *tb = (MonoReflectionType *)obj;
3682 token = mono_metadata_token_from_dor (
3683 mono_image_typedef_or_ref (assembly, tb->type));
3685 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3686 strcmp (klass->name, "MonoMethod") == 0) {
3687 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3688 if (m->method->signature->generic_param_count) {
3689 g_assert_not_reached ();
3690 } else if ((m->method->klass->image == &assembly->image) &&
3691 !m->method->klass->generic_inst) {
3692 static guint32 method_table_idx = 0xffffff;
3694 * Each token should have a unique index, but the indexes are
3695 * assigned by managed code, so we don't know about them. An
3696 * easy solution is to count backwards...
3698 method_table_idx --;
3699 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3701 token = mono_image_get_methodref_token (assembly, m->method);
3702 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3704 else if (strcmp (klass->name, "MonoInflatedMethod") == 0 ||
3705 strcmp (klass->name, "MonoInflatedCtor") == 0) {
3706 MonoReflectionInflatedMethod *m = (MonoReflectionInflatedMethod *)obj;
3707 token = mono_image_get_methodspec_token (assembly, m);
3709 else if (strcmp (klass->name, "MonoInflatedField") == 0) {
3710 MonoReflectionInflatedField *f = (MonoReflectionInflatedField *)obj;
3711 token = mono_image_get_inflated_field_token (assembly, f);
3713 else if (strcmp (klass->name, "MonoField") == 0) {
3714 MonoReflectionField *f = (MonoReflectionField *)obj;
3715 if (f->klass->image == &assembly->image) {
3716 static guint32 field_table_idx = 0xffffff;
3718 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3720 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
3721 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3723 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3724 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3725 token = mono_image_get_array_token (assembly, m);
3727 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3728 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3729 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3732 g_error ("requested token for %s\n", klass->name);
3734 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3741 guint32 import_lookup_table;
3745 guint32 import_address_table_rva;
3753 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3755 static MonoDynamicImage*
3756 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3757 char *assembly_name, char *module_name)
3759 static const guchar entrycode [16] = {0xff, 0x25, 0};
3760 MonoDynamicImage *image;
3764 * We need to use the current ms version or the ms runtime it won't find
3765 * the support dlls. D'oh!
3766 * const char *version = "mono-" VERSION;
3768 const char *version = "v1.0.3705";
3771 image = GC_MALLOC (sizeof (MonoDynamicImage));
3773 image = g_new0 (MonoDynamicImage, 1);
3776 /* keep in sync with image.c */
3777 image->image.name = assembly_name;
3778 image->image.assembly_name = image->image.name; /* they may be different */
3779 image->image.module_name = module_name;
3780 image->image.version = g_strdup (version);
3781 image->image.dynamic = TRUE;
3783 image->image.references = g_new0 (MonoAssembly*, 1);
3784 image->image.references [0] = NULL;
3786 mono_image_init (&image->image);
3788 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3789 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3790 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3791 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3792 image->handleref = g_hash_table_new (NULL, NULL);
3793 image->tokens = mono_g_hash_table_new (NULL, NULL);
3794 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3795 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3797 string_heap_init (&image->sheap);
3798 mono_image_add_stream_data (&image->us, "", 1);
3799 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3800 /* import tables... */
3801 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3802 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3803 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3804 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3805 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3806 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3807 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3808 stream_data_align (&image->code);
3810 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3812 for (i=0; i < 64; ++i) {
3813 image->tables [i].next_idx = 1;
3814 image->tables [i].columns = table_sizes [i];
3817 image->image.assembly = (MonoAssembly*)assembly;
3818 image->run = assembly->run;
3819 image->save = assembly->save;
3825 * mono_image_basic_init:
3826 * @assembly: an assembly builder object
3828 * Create the MonoImage that represents the assembly builder and setup some
3829 * of the helper hash table and the basic metadata streams.
3832 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3834 MonoDynamicAssembly *assembly;
3835 MonoDynamicImage *image;
3837 MONO_ARCH_SAVE_REGS;
3839 if (assemblyb->dynamic_assembly)
3843 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3845 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3848 assembly->assembly.dynamic = TRUE;
3849 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3850 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3851 if (assemblyb->culture)
3852 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3854 assembly->assembly.aname.culture = g_strdup ("");
3856 assembly->run = assemblyb->access != 2;
3857 assembly->save = assemblyb->access != 1;
3859 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
3860 assembly->assembly.aname.name = image->image.name;
3861 assembly->assembly.image = &image->image;
3863 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
3864 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
3868 calc_section_size (MonoDynamicImage *assembly)
3872 /* alignment constraints */
3873 assembly->code.index += 3;
3874 assembly->code.index &= ~3;
3875 assembly->meta_size += 3;
3876 assembly->meta_size &= ~3;
3877 assembly->resources.index += 3;
3878 assembly->resources.index &= ~3;
3880 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3881 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3884 if (assembly->win32_res) {
3885 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
3887 assembly->sections [MONO_SECTION_RSRC].size = res_size;
3888 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
3892 assembly->sections [MONO_SECTION_RELOC].size = 12;
3893 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3903 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
3907 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
3909 ResTreeNode *t1 = (ResTreeNode*)a;
3910 ResTreeNode *t2 = (ResTreeNode*)b;
3912 return t1->id - t2->id;
3916 * resource_tree_create:
3918 * Organize the resources into a resource tree.
3920 static ResTreeNode *
3921 resource_tree_create (MonoArray *win32_resources)
3923 ResTreeNode *tree, *res_node, *type_node, *lang_node;
3927 tree = g_new0 (ResTreeNode, 1);
3929 for (i = 0; i < mono_array_length (win32_resources); ++i) {
3930 MonoReflectionWin32Resource *win32_res =
3931 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
3935 lang_node = g_new0 (ResTreeNode, 1);
3936 lang_node->id = win32_res->lang_id;
3937 lang_node->win32_res = win32_res;
3939 /* Create type node if neccesary */
3941 for (l = tree->children; l; l = l->next)
3942 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
3943 type_node = (ResTreeNode*)l->data;
3948 type_node = g_new0 (ResTreeNode, 1);
3949 type_node->id = win32_res->res_type;
3952 * The resource types have to be sorted otherwise
3953 * Windows Explorer can't display the version information.
3955 tree->children = g_slist_insert_sorted (tree->children, type_node,
3956 resource_tree_compare_by_id);
3959 /* Create res node if neccesary */
3961 for (l = type_node->children; l; l = l->next)
3962 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
3963 res_node = (ResTreeNode*)l->data;
3968 res_node = g_new0 (ResTreeNode, 1);
3969 res_node->id = win32_res->res_id;
3970 type_node->children = g_slist_append (type_node->children, res_node);
3973 res_node->children = g_slist_append (res_node->children, lang_node);
3980 * resource_tree_encode:
3982 * Encode the resource tree into the format used in the PE file.
3985 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
3988 MonoPEResourceDir dir;
3989 MonoPEResourceDirEntry dir_entry;
3990 MonoPEResourceDataEntry data_entry;
3994 * For the format of the resource directory, see the article
3995 * "An In-Depth Look into the Win32 Portable Executable File Format" by
3999 memset (&dir, 0, sizeof (dir));
4000 memset (&dir_entry, 0, sizeof (dir_entry));
4001 memset (&data_entry, 0, sizeof (data_entry));
4003 g_assert (sizeof (dir) == 16);
4004 g_assert (sizeof (dir_entry) == 8);
4005 g_assert (sizeof (data_entry) == 16);
4007 node->offset = p - begin;
4009 /* IMAGE_RESOURCE_DIRECTORY */
4010 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4012 memcpy (p, &dir, sizeof (dir));
4015 /* Reserve space for entries */
4017 p += sizeof (dir_entry) * dir.res_id_entries;
4019 /* Write children */
4020 for (l = node->children; l; l = l->next) {
4021 ResTreeNode *child = (ResTreeNode*)l->data;
4023 if (child->win32_res) {
4025 child->offset = p - begin;
4027 /* IMAGE_RESOURCE_DATA_ENTRY */
4028 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4029 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4031 memcpy (p, &data_entry, sizeof (data_entry));
4032 p += sizeof (data_entry);
4034 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4035 p += data_entry.rde_size;
4038 resource_tree_encode (child, begin, p, &p);
4041 /* IMAGE_RESOURCE_ENTRY */
4042 for (l = node->children; l; l = l->next) {
4043 ResTreeNode *child = (ResTreeNode*)l->data;
4044 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4046 dir_entry.is_dir = child->win32_res ? 0 : 1;
4047 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4049 memcpy (entries, &dir_entry, sizeof (dir_entry));
4050 entries += sizeof (dir_entry);
4057 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4062 MonoReflectionWin32Resource *win32_res;
4065 if (!assemblyb->win32_resources)
4069 * Resources are stored in a three level tree inside the PE file.
4070 * - level one contains a node for each type of resource
4071 * - level two contains a node for each resource
4072 * - level three contains a node for each instance of a resource for a
4073 * specific language.
4076 tree = resource_tree_create (assemblyb->win32_resources);
4078 /* Estimate the size of the encoded tree */
4080 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4081 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4082 size += mono_array_length (win32_res->res_data);
4084 /* Directory structure */
4085 size += mono_array_length (assemblyb->win32_resources) * 256;
4086 p = buf = g_malloc (size);
4088 resource_tree_encode (tree, p, p, &p);
4090 g_assert (p - buf < size);
4092 assembly->win32_res = g_malloc (p - buf);
4093 assembly->win32_res_size = p - buf;
4094 memcpy (assembly->win32_res, buf, p - buf);
4100 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4102 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4105 p += sizeof (MonoPEResourceDir);
4106 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4107 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4108 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4109 if (dir_entry->is_dir)
4110 fixup_resource_directory (res_section, child, rva);
4112 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4113 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4116 p += sizeof (MonoPEResourceDirEntry);
4121 * mono_image_create_pefile:
4122 * @mb: a module builder object
4124 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4125 * assembly->pefile where it can be easily retrieved later in chunks.
4128 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4129 MonoMSDOSHeader *msdos;
4130 MonoDotNetHeader *header;
4131 MonoSectionTable *section;
4132 MonoCLIHeader *cli_header;
4133 guint32 size, image_size, virtual_base, text_offset;
4134 guint32 header_start, section_start, file_offset, virtual_offset;
4135 MonoDynamicImage *assembly;
4136 MonoReflectionAssemblyBuilder *assemblyb;
4137 MonoDynamicStream *pefile;
4139 guint32 *rva, value;
4142 static const unsigned char msheader[] = {
4143 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4144 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4147 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4148 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4149 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4150 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4153 assemblyb = mb->assemblyb;
4155 mono_image_basic_init (assemblyb);
4156 assembly = mb->dynamic_image;
4158 /* already created */
4159 if (assembly->pefile.index)
4162 mono_image_build_metadata (mb);
4164 if (mb->is_main && assemblyb->resources) {
4165 int len = mono_array_length (assemblyb->resources);
4166 for (i = 0; i < len; ++i)
4167 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4170 if (mb->resources) {
4171 int len = mono_array_length (mb->resources);
4172 for (i = 0; i < len; ++i)
4173 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4176 build_compressed_metadata (assembly);
4179 assembly_add_win32_resources (assembly, assemblyb);
4181 nsections = calc_section_size (assembly);
4183 pefile = &assembly->pefile;
4185 /* The DOS header and stub */
4186 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4187 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4189 /* the dotnet header */
4190 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4192 /* the section tables */
4193 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4195 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4196 virtual_offset = VIRT_ALIGN;
4199 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4200 if (!assembly->sections [i].size)
4203 file_offset += FILE_ALIGN - 1;
4204 file_offset &= ~(FILE_ALIGN - 1);
4205 virtual_offset += VIRT_ALIGN - 1;
4206 virtual_offset &= ~(VIRT_ALIGN - 1);
4208 assembly->sections [i].offset = file_offset;
4209 assembly->sections [i].rva = virtual_offset;
4211 file_offset += assembly->sections [i].size;
4212 virtual_offset += assembly->sections [i].size;
4213 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4216 file_offset += FILE_ALIGN - 1;
4217 file_offset &= ~(FILE_ALIGN - 1);
4218 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4220 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4222 /* back-patch info */
4223 msdos = (MonoMSDOSHeader*)pefile->data;
4224 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4225 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4226 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4228 header = (MonoDotNetHeader*)(pefile->data + header_start);
4229 header->pesig [0] = 'P';
4230 header->pesig [1] = 'E';
4232 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4233 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4234 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4235 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4236 if (assemblyb->pekind == 1) {
4238 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4241 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4244 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4246 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4247 header->pe.pe_major = 6;
4248 header->pe.pe_minor = 0;
4249 size = assembly->sections [MONO_SECTION_TEXT].size;
4250 size += FILE_ALIGN - 1;
4251 size &= ~(FILE_ALIGN - 1);
4252 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4253 size = assembly->sections [MONO_SECTION_RSRC].size;
4254 size += FILE_ALIGN - 1;
4255 size &= ~(FILE_ALIGN - 1);
4256 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4257 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4258 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4259 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4260 /* pe_rva_entry_point always at the beginning of the text section */
4261 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4263 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4264 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4265 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4266 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4267 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4268 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4269 size = section_start;
4270 size += FILE_ALIGN - 1;
4271 size &= ~(FILE_ALIGN - 1);
4272 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4274 size += VIRT_ALIGN - 1;
4275 size &= ~(VIRT_ALIGN - 1);
4276 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4279 // Translate the PEFileKind value to the value expected by the Windows loader
4282 short kind = assemblyb->pekind;
4285 // PEFileKinds.ConsoleApplication == 2
4286 // PEFileKinds.WindowApplication == 3
4289 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4290 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4296 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4298 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4299 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4300 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4301 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4302 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4303 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4305 /* fill data directory entries */
4307 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4308 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4310 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4311 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4313 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4314 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4315 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4316 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4317 /* patch imported function RVA name */
4318 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4319 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4321 /* the import table */
4322 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4323 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4324 /* patch imported dll RVA name and other entries in the dir */
4325 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4326 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4327 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4328 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4329 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4330 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4332 p = (assembly->code.data + assembly->ilt_offset);
4333 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4334 *p++ = (value) & 0xff;
4335 *p++ = (value >> 8) & (0xff);
4336 *p++ = (value >> 16) & (0xff);
4337 *p++ = (value >> 24) & (0xff);
4339 /* the CLI header info */
4340 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4341 cli_header->ch_size = GUINT32_FROM_LE (72);
4342 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4343 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4344 if (assemblyb->entry_point) {
4345 guint32 table_idx = 0;
4346 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4347 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4348 table_idx = methodb->table_idx;
4351 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4352 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4355 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4356 /* The embedded managed resources */
4357 text_offset = assembly->text_rva + assembly->code.index;
4358 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4359 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4360 text_offset += assembly->resources.index;
4361 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4362 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4363 text_offset += assembly->meta_size;
4364 if (assembly->strong_name_size) {
4365 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4366 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4367 text_offset += assembly->strong_name_size;
4370 /* write the section tables and section content */
4371 section = (MonoSectionTable*)(pefile->data + section_start);
4372 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4373 static const char *section_names [] = {
4374 ".text", ".rsrc", ".reloc"
4376 if (!assembly->sections [i].size)
4378 strcpy (section->st_name, section_names [i]);
4379 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4380 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4381 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4382 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4383 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4384 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4385 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4387 case MONO_SECTION_TEXT:
4388 /* patch entry point */
4389 p = (assembly->code.data + 2);
4390 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4391 *p++ = (value) & 0xff;
4392 *p++ = (value >> 8) & 0xff;
4393 *p++ = (value >> 16) & 0xff;
4394 *p++ = (value >> 24) & 0xff;
4396 text_offset = assembly->sections [i].offset;
4397 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4398 text_offset += assembly->code.index;
4399 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4400 text_offset += assembly->resources.index;
4401 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4402 text_offset += assembly->meta_size;
4403 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4405 g_free (assembly->image.raw_metadata);
4407 case MONO_SECTION_RELOC:
4408 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4409 *rva = GUINT32_FROM_LE (assembly->text_rva);
4411 *rva = GUINT32_FROM_LE (12);
4413 data16 = (guint16*)rva;
4415 * the entrypoint is always at the start of the text section
4416 * 3 is IMAGE_REL_BASED_HIGHLOW
4417 * 2 is patch_size_rva - text_rva
4419 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4421 *data16 = 0; /* terminate */
4423 case MONO_SECTION_RSRC:
4424 if (assembly->win32_res) {
4425 text_offset = assembly->sections [i].offset;
4427 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4428 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4430 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4434 g_assert_not_reached ();
4439 /* check that the file is properly padded */
4442 FILE *f = fopen ("mypetest.exe", "w");
4443 fwrite (pefile->data, pefile->index, 1, f);
4449 MonoReflectionModule *
4450 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4454 MonoImageOpenStatus status;
4455 MonoDynamicAssembly *assembly;
4457 name = mono_string_to_utf8 (fileName);
4459 image = mono_image_open (name, &status);
4462 if (status == MONO_IMAGE_ERROR_ERRNO)
4463 exc = mono_get_exception_file_not_found (fileName);
4465 exc = mono_get_exception_bad_image_format (name);
4467 mono_raise_exception (exc);
4472 assembly = ab->dynamic_assembly;
4473 image->assembly = (MonoAssembly*)assembly;
4475 mono_assembly_load_references (image, &status);
4477 mono_image_close (image);
4478 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4481 return mono_module_get_object (mono_domain_get (), image);
4485 * We need to return always the same object for MethodInfo, FieldInfo etc..
4486 * but we need to consider the reflected type.
4487 * type uses a different hash, since it uses custom hash/equal functions.
4492 MonoClass *refclass;
4496 reflected_equal (gconstpointer a, gconstpointer b) {
4497 const ReflectedEntry *ea = a;
4498 const ReflectedEntry *eb = b;
4500 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4504 reflected_hash (gconstpointer a) {
4505 const ReflectedEntry *ea = a;
4506 return GPOINTER_TO_UINT (ea->item);
4509 #define CHECK_OBJECT(t,p,k) \
4515 mono_domain_lock (domain); \
4516 if (!domain->refobject_hash) \
4517 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4518 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4519 mono_domain_unlock (domain); \
4525 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4527 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4530 #define CACHE_OBJECT(p,o,k) \
4532 ReflectedEntry *e = ALLOC_REFENTRY; \
4534 e->refclass = (k); \
4535 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4536 mono_domain_unlock (domain); \
4540 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4542 /* this is done only once */
4543 mono_domain_lock (domain);
4544 CACHE_OBJECT (assembly, res, NULL);
4548 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4550 /* this is done only once */
4551 mono_domain_lock (domain);
4552 CACHE_OBJECT (module, res, NULL);
4556 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4558 MonoDynamicImage *image = moduleb->dynamic_image;
4559 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4562 * FIXME: we already created an image in mono_image_basic_init (), but
4563 * we don't know which module it belongs to, since that is only
4564 * determined at assembly save time.
4566 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4567 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4569 moduleb->module.image = &image->image;
4570 moduleb->dynamic_image = image;
4571 register_module (mono_object_domain (moduleb), moduleb, image);
4576 * mono_assembly_get_object:
4577 * @domain: an app domain
4578 * @assembly: an assembly
4580 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4582 MonoReflectionAssembly*
4583 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4585 static MonoClass *System_Reflection_Assembly;
4586 MonoReflectionAssembly *res;
4588 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4589 if (!System_Reflection_Assembly)
4590 System_Reflection_Assembly = mono_class_from_name (
4591 mono_defaults.corlib, "System.Reflection", "Assembly");
4592 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4593 res->assembly = assembly;
4594 CACHE_OBJECT (assembly, res, NULL);
4600 MonoReflectionModule*
4601 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4603 static MonoClass *System_Reflection_Module;
4604 MonoReflectionModule *res;
4606 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4607 if (!System_Reflection_Module)
4608 System_Reflection_Module = mono_class_from_name (
4609 mono_defaults.corlib, "System.Reflection", "Module");
4610 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4613 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4615 res->fqname = mono_string_new (domain, image->name);
4616 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4617 res->scopename = mono_string_new (domain, image->module_name);
4619 mono_image_addref (image);
4621 CACHE_OBJECT (image, res, NULL);
4625 MonoReflectionModule*
4626 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4628 static MonoClass *System_Reflection_Module;
4629 MonoReflectionModule *res;
4630 MonoTableInfo *table;
4631 guint32 cols [MONO_FILE_SIZE];
4633 guint32 i, name_idx;
4636 if (!System_Reflection_Module)
4637 System_Reflection_Module = mono_class_from_name (
4638 mono_defaults.corlib, "System.Reflection", "Module");
4639 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4641 table = &image->tables [MONO_TABLE_FILE];
4642 g_assert (table_index < table->rows);
4643 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4646 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4647 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4649 // Check whenever the row has a corresponding row in the moduleref table
4650 table = &image->tables [MONO_TABLE_MODULEREF];
4651 for (i = 0; i < table->rows; ++i) {
4652 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4653 val = mono_metadata_string_heap (image, name_idx);
4654 if (strcmp (val, name) == 0)
4655 res->image = image->modules [i];
4658 res->fqname = mono_string_new (domain, name);
4659 res->name = mono_string_new (domain, name);
4660 res->scopename = mono_string_new (domain, name);
4661 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4667 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4669 if ((t1->type != t2->type) ||
4670 (t1->byref != t2->byref))
4674 case MONO_TYPE_VOID:
4675 case MONO_TYPE_BOOLEAN:
4676 case MONO_TYPE_CHAR:
4687 case MONO_TYPE_STRING:
4690 case MONO_TYPE_OBJECT:
4691 case MONO_TYPE_TYPEDBYREF:
4693 case MONO_TYPE_VALUETYPE:
4694 case MONO_TYPE_CLASS:
4695 case MONO_TYPE_SZARRAY:
4696 return t1->data.klass == t2->data.klass;
4698 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4699 case MONO_TYPE_ARRAY:
4700 if (t1->data.array->rank != t2->data.array->rank)
4702 return t1->data.array->eklass == t2->data.array->eklass;
4703 case MONO_TYPE_GENERICINST: {
4705 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4707 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4709 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4710 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4716 case MONO_TYPE_MVAR:
4717 return t1->data.generic_param == t2->data.generic_param;
4719 g_error ("implement type compare for %0x!", t1->type);
4727 mymono_metadata_type_hash (MonoType *t1)
4733 hash |= t1->byref << 6; /* do not collide with t1->type values */
4735 case MONO_TYPE_VALUETYPE:
4736 case MONO_TYPE_CLASS:
4737 case MONO_TYPE_SZARRAY:
4738 /* check if the distribution is good enough */
4739 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4741 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4746 static MonoReflectionGenericInst*
4747 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4749 static MonoClass *System_Reflection_MonoGenericInst;
4750 MonoReflectionGenericInst *res;
4751 MonoGenericInst *ginst;
4754 if (!System_Reflection_MonoGenericInst) {
4755 System_Reflection_MonoGenericInst = mono_class_from_name (
4756 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4757 g_assert (System_Reflection_MonoGenericInst);
4760 ginst = geninst->data.generic_inst;
4761 gklass = mono_class_from_mono_type (ginst->generic_type);
4763 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4765 res->type.type = geninst;
4766 if (gklass->wastypebuilder && gklass->reflection_info)
4767 res->generic_type = gklass->reflection_info;
4769 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4775 * mono_type_get_object:
4776 * @domain: an app domain
4779 * Return an System.MonoType object representing the type @type.
4782 mono_type_get_object (MonoDomain *domain, MonoType *type)
4784 MonoReflectionType *res;
4785 MonoClass *klass = mono_class_from_mono_type (type);
4787 mono_domain_lock (domain);
4788 if (!domain->type_hash)
4789 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4790 (GCompareFunc)mymono_metadata_type_equal);
4791 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4792 mono_domain_unlock (domain);
4795 if (type->type == MONO_TYPE_GENERICINST) {
4796 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4797 mono_domain_unlock (domain);
4800 if (klass->reflection_info && !klass->wastypebuilder) {
4801 //g_assert_not_reached ();
4802 /* should this be considered an error condition? */
4804 mono_domain_unlock (domain);
4805 return klass->reflection_info;
4808 mono_class_init (klass);
4809 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4811 mono_g_hash_table_insert (domain->type_hash, type, res);
4812 mono_domain_unlock (domain);
4817 * mono_method_get_object:
4818 * @domain: an app domain
4820 * @refclass: the reflected type (can be NULL)
4822 * Return an System.Reflection.MonoMethod object representing the method @method.
4824 MonoReflectionMethod*
4825 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4828 * We use the same C representation for methods and constructors, but the type
4829 * name in C# is different.
4833 MonoReflectionMethod *ret;
4836 refclass = method->klass;
4838 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4839 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4840 cname = "MonoCMethod";
4842 cname = "MonoMethod";
4843 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4845 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4846 ret->method = method;
4847 ret->name = mono_string_new (domain, method->name);
4848 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4849 CACHE_OBJECT (method, ret, refclass);
4854 * mono_field_get_object:
4855 * @domain: an app domain
4859 * Return an System.Reflection.MonoField object representing the field @field
4862 MonoReflectionField*
4863 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
4865 MonoReflectionField *res;
4868 CHECK_OBJECT (MonoReflectionField *, field, klass);
4869 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
4870 res = (MonoReflectionField *)mono_object_new (domain, oklass);
4873 res->name = mono_string_new (domain, field->name);
4874 res->attrs = field->type->attrs;
4875 res->type = mono_type_get_object (domain, field->type);
4876 CACHE_OBJECT (field, res, klass);
4881 * mono_property_get_object:
4882 * @domain: an app domain
4884 * @property: a property
4886 * Return an System.Reflection.MonoProperty object representing the property @property
4889 MonoReflectionProperty*
4890 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
4892 MonoReflectionProperty *res;
4895 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
4896 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
4897 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
4899 res->property = property;
4900 CACHE_OBJECT (property, res, klass);
4905 * mono_event_get_object:
4906 * @domain: an app domain
4910 * Return an System.Reflection.MonoEvent object representing the event @event
4913 MonoReflectionEvent*
4914 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
4916 MonoReflectionEvent *res;
4919 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
4920 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
4921 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
4924 CACHE_OBJECT (event, res, klass);
4929 * mono_param_get_objects:
4930 * @domain: an app domain
4933 * Return an System.Reflection.ParameterInfo array object representing the parameters
4934 * in the method @method.
4937 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
4939 static MonoClass *System_Reflection_ParameterInfo;
4940 MonoArray *res = NULL;
4941 MonoReflectionMethod *member = NULL;
4942 MonoReflectionParameter *param = NULL;
4946 if (!System_Reflection_ParameterInfo)
4947 System_Reflection_ParameterInfo = mono_class_from_name (
4948 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
4950 if (!method->signature->param_count)
4951 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
4953 /* Note: the cache is based on the address of the signature into the method
4954 * since we already cache MethodInfos with the method as keys.
4956 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
4958 member = mono_method_get_object (domain, method, NULL);
4959 names = g_new (char *, method->signature->param_count);
4960 mono_method_get_param_names (method, (const char **) names);
4962 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
4963 for (i = 0; i < method->signature->param_count; ++i) {
4964 param = (MonoReflectionParameter *)mono_object_new (domain,
4965 System_Reflection_ParameterInfo);
4966 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
4967 param->DefaultValueImpl = NULL; /* FIXME */
4968 param->MemberImpl = (MonoObject*)member;
4969 param->NameImpl = mono_string_new (domain, names [i]);
4970 param->PositionImpl = i;
4971 param->AttrsImpl = method->signature->params [i]->attrs;
4972 mono_array_set (res, gpointer, i, param);
4975 CACHE_OBJECT (&(method->signature), res, NULL);
4980 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
4984 memset (assembly, 0, sizeof (MonoAssemblyName));
4986 assembly->culture = "";
4988 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
4991 while (*p == ' ' || *p == ',') {
5000 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5002 assembly->major = strtoul (p, &s, 10);
5003 if (s == p || *s != '.')
5006 assembly->minor = strtoul (p, &s, 10);
5007 if (s == p || *s != '.')
5010 assembly->build = strtoul (p, &s, 10);
5011 if (s == p || *s != '.')
5014 assembly->revision = strtoul (p, &s, 10);
5017 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5019 if (strncmp (p, "neutral", 7) == 0) {
5020 assembly->culture = "";
5023 assembly->culture = p;
5024 while (*p && *p != ',') {
5028 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5031 while (*s && isxdigit (*s)) {
5035 assembly->hash_len = s - p;
5036 if (!(s-p) || ((s-p) & 1))
5038 assembly->hash_value = s = p;
5039 while (*s && isxdigit (*s)) {
5041 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5044 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5049 while (*p && *p != ',')
5053 while (*p == ' ' || *p == ',') {
5067 * mono_reflection_parse_type:
5070 * Parse a type name as accepted by the GetType () method and output the info
5071 * extracted in the info structure.
5072 * the name param will be mangled, so, make a copy before passing it to this function.
5073 * The fields in info will be valid until the memory pointed to by name is valid.
5074 * Returns 0 on parse error.
5075 * See also mono_type_get_name () below.
5078 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5080 char *start, *p, *w, *last_point, *startn;
5081 int in_modifiers = 0;
5082 int isbyref = 0, rank;
5084 start = p = w = name;
5086 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5087 info->name = info->name_space = NULL;
5088 info->nested = NULL;
5089 info->modifiers = NULL;
5091 /* last_point separates the namespace from the name */
5097 *p = 0; /* NULL terminate the name */
5099 info->nested = g_list_append (info->nested, startn);
5100 /* we have parsed the nesting namespace + name */
5104 info->name_space = start;
5106 info->name = last_point + 1;
5108 info->name_space = (char *)"";
5134 info->name_space = start;
5136 info->name = last_point + 1;
5138 info->name_space = (char *)"";
5145 if (isbyref) /* only one level allowed by the spec */
5148 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5152 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5163 else if (*p != '*') /* '*' means unknown lower bound */
5169 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5181 return 0; /* missing assembly name */
5182 if (!assembly_name_to_aname (&info->assembly, p))
5189 if (info->assembly.name)
5192 *w = 0; /* terminate class name */
5193 if (!info->name || !*info->name)
5195 /* add other consistency checks */
5200 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5207 image = mono_defaults.corlib;
5210 klass = mono_class_from_name_case (image, info->name_space, info->name);
5212 klass = mono_class_from_name (image, info->name_space, info->name);
5215 for (mod = info->nested; mod; mod = mod->next) {
5218 mono_class_init (klass);
5219 nested = klass->nested_classes;
5222 klass = nested->data;
5224 if (g_strcasecmp (klass->name, mod->data) == 0)
5227 if (strcmp (klass->name, mod->data) == 0)
5231 nested = nested->next;
5238 mono_class_init (klass);
5239 for (mod = info->modifiers; mod; mod = mod->next) {
5240 modval = GPOINTER_TO_UINT (mod->data);
5241 if (!modval) { /* byref: must be last modifier */
5242 return &klass->this_arg;
5243 } else if (modval == -1) {
5244 klass = mono_ptr_class_get (&klass->byval_arg);
5245 } else { /* array rank */
5246 klass = mono_array_class_get (klass, modval);
5248 mono_class_init (klass);
5251 return &klass->byval_arg;
5255 * mono_reflection_get_type:
5256 * @image: a metadata context
5257 * @info: type description structure
5258 * @ignorecase: flag for case-insensitive string compares
5260 * Build a MonoType from the type description in @info.
5265 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5268 MonoReflectionAssembly *assembly;
5272 type = mono_reflection_get_type_internal (image, info, ignorecase);
5275 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5278 // Reconstruct the type name
5279 fullName = g_string_new ("");
5280 if (info->name_space && (info->name_space [0] != '\0'))
5281 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5283 g_string_printf (fullName, info->name);
5284 for (mod = info->nested; mod; mod = mod->next)
5285 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5288 mono_domain_try_type_resolve (
5289 mono_domain_get (), fullName->str, NULL);
5290 if (assembly && (!image || (assembly->assembly->image == image)))
5291 type = mono_reflection_get_type_internal (assembly->assembly->image,
5293 g_string_free (fullName, TRUE);
5298 * mono_reflection_type_from_name:
5300 * @image: a metadata context (can be NULL).
5302 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5303 * it defaults to get the type from @image or, if @image is NULL or loading
5304 * from it fails, uses corlib.
5308 mono_reflection_type_from_name (char *name, MonoImage *image)
5311 MonoTypeNameParse info;
5312 MonoAssembly *assembly;
5314 /*g_print ("requested type %s\n", str);*/
5315 if (!mono_reflection_parse_type (name, &info)) {
5316 g_list_free (info.modifiers);
5317 g_list_free (info.nested);
5321 if (info.assembly.name) {
5322 assembly = mono_assembly_loaded (&info.assembly);
5323 /* do we need to load if it's not already loaded? */
5325 g_list_free (info.modifiers);
5326 g_list_free (info.nested);
5330 image = assembly->image;
5331 } else if (image == NULL) {
5332 image = mono_defaults.corlib;
5335 type = mono_reflection_get_type (image, &info, FALSE);
5336 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5337 image = mono_defaults.corlib;
5338 type = mono_reflection_get_type (image, &info, FALSE);
5341 g_list_free (info.modifiers);
5342 g_list_free (info.nested);
5347 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5349 int slen, type = t->type;
5354 case MONO_TYPE_BOOLEAN: {
5355 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5360 case MONO_TYPE_CHAR:
5362 case MONO_TYPE_I2: {
5363 guint16 *val = g_malloc (sizeof (guint16));
5368 #if SIZEOF_VOID_P == 4
5374 case MONO_TYPE_I4: {
5375 guint32 *val = g_malloc (sizeof (guint32));
5380 #if SIZEOF_VOID_P == 8
5381 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5386 case MONO_TYPE_I8: {
5387 guint64 *val = g_malloc (sizeof (guint64));
5392 case MONO_TYPE_VALUETYPE:
5393 if (t->data.klass->enumtype) {
5394 type = t->data.klass->enum_basetype->type;
5397 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5400 case MONO_TYPE_STRING:
5401 if (*p == (char)0xFF) {
5405 slen = mono_metadata_decode_value (p, &p);
5407 return mono_string_new_len (mono_domain_get (), p, slen);
5408 case MONO_TYPE_CLASS: {
5411 if (*p == (char)0xFF) {
5416 slen = mono_metadata_decode_value (p, &p);
5417 n = g_memdup (p, slen + 1);
5419 t = mono_reflection_type_from_name (n, image);
5421 g_warning ("Cannot load type '%s'", n);
5425 return mono_type_get_object (mono_domain_get (), t);
5429 case MONO_TYPE_OBJECT: {
5432 MonoClass *subc = NULL;
5437 } else if (subt == 0x0E) {
5438 type = MONO_TYPE_STRING;
5440 } else if (subt == 0x55) {
5443 slen = mono_metadata_decode_value (p, &p);
5444 n = g_memdup (p, slen + 1);
5446 t = mono_reflection_type_from_name (n, image);
5448 g_warning ("Cannot load type '%s'", n);
5451 subc = mono_class_from_mono_type (t);
5452 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5453 MonoType simple_type = {{0}};
5454 simple_type.type = subt;
5455 subc = mono_class_from_mono_type (&simple_type);
5457 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5459 val = load_cattr_value (image, &subc->byval_arg, p, end);
5460 obj = mono_object_new (mono_domain_get (), subc);
5461 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5465 case MONO_TYPE_SZARRAY:
5468 guint32 i, alen, basetype;
5471 if (alen == 0xffffffff) {
5475 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5476 basetype = t->data.klass->byval_arg.type;
5481 case MONO_TYPE_BOOLEAN:
5482 for (i=0;i<alen;i++)
5484 MonoBoolean val=*p++;
5485 mono_array_set(arr,MonoBoolean,i,val);
5488 case MONO_TYPE_CHAR:
5491 for (i=0;i<alen;i++)
5493 guint16 val=read16(p);
5494 mono_array_set(arr,guint16,i,val);
5501 for (i=0;i<alen;i++)
5503 guint32 val=read32(p);
5504 mono_array_set(arr,guint32,i,val);
5511 for (i=0;i<alen;i++)
5513 guint64 val=read64(p);
5514 mono_array_set(arr,guint64,i,val);
5518 case MONO_TYPE_CLASS:
5519 case MONO_TYPE_STRING:
5520 for (i = 0; i < alen; i++) {
5521 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5522 mono_array_set (arr, gpointer, i, item);
5526 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5532 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5538 type_is_reference (MonoType *type)
5540 switch (type->type) {
5541 case MONO_TYPE_BOOLEAN:
5542 case MONO_TYPE_CHAR:
5555 case MONO_TYPE_VALUETYPE:
5563 free_param_data (MonoMethodSignature *sig, void **params) {
5565 for (i = 0; i < sig->param_count; ++i) {
5566 if (!type_is_reference (sig->params [i]))
5567 g_free (params [i]);
5572 * Find the method index in the metadata methodDef table.
5573 * Later put these three helper methods in metadata and export them.
5576 find_method_index (MonoMethod *method) {
5577 MonoClass *klass = method->klass;
5580 for (i = 0; i < klass->method.count; ++i) {
5581 if (method == klass->methods [i])
5582 return klass->method.first + 1 + i;
5588 * Find the field index in the metadata FieldDef table.
5591 find_field_index (MonoClass *klass, MonoClassField *field) {
5594 for (i = 0; i < klass->field.count; ++i) {
5595 if (field == &klass->fields [i])
5596 return klass->field.first + 1 + i;
5602 * Find the property index in the metadata Property table.
5605 find_property_index (MonoClass *klass, MonoProperty *property) {
5608 for (i = 0; i < klass->property.count; ++i) {
5609 if (property == &klass->properties [i])
5610 return klass->property.first + 1 + i;
5616 * Find the event index in the metadata Event table.
5619 find_event_index (MonoClass *klass, MonoEvent *event) {
5622 for (i = 0; i < klass->event.count; ++i) {
5623 if (event == &klass->events [i])
5624 return klass->event.first + 1 + i;
5630 create_custom_attr (MonoImage *image, MonoMethod *method,
5631 const char *data, guint32 len)
5633 const char *p = data;
5635 guint32 i, j, num_named;
5639 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5642 mono_class_init (method->klass);
5643 /*g_print ("got attr %s\n", method->klass->name);*/
5645 params = g_new (void*, method->signature->param_count);
5649 for (i = 0; i < method->signature->param_count; ++i) {
5650 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5654 attr = mono_object_new (mono_domain_get (), method->klass);
5655 mono_runtime_invoke (method, attr, params, NULL);
5656 free_param_data (method->signature, params);
5658 num_named = read16 (named);
5660 for (j = 0; j < num_named; j++) {
5662 char *name, named_type, data_type;
5663 named_type = *named++;
5664 data_type = *named++; /* type of data */
5665 if (data_type == 0x55) {
5668 type_len = mono_metadata_decode_blob_size (named, &named);
5669 type_name = g_malloc (type_len + 1);
5670 memcpy (type_name, named, type_len);
5671 type_name [type_len] = 0;
5673 /* FIXME: lookup the type and check type consistency */
5676 if (data_type == MONO_TYPE_SZARRAY)
5677 /* The spec does not mention this */
5679 name_len = mono_metadata_decode_blob_size (named, &named);
5680 name = g_malloc (name_len + 1);
5681 memcpy (name, named, name_len);
5682 name [name_len] = 0;
5684 if (named_type == 0x53) {
5685 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5686 void *val = load_cattr_value (image, field->type, named, &named);
5687 mono_field_set_value (attr, field, val);
5688 if (!type_is_reference (field->type))
5690 } else if (named_type == 0x54) {
5693 MonoType *prop_type;
5695 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5696 /* can we have more that 1 arg in a custom attr named property? */
5697 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5698 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5699 mono_property_set_value (prop, attr, pparams, NULL);
5700 if (!type_is_reference (prop_type))
5701 g_free (pparams [0]);
5710 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5717 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5718 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5719 for (i = 0; i < cinfo->num_attrs; ++i) {
5720 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5721 mono_array_set (result, gpointer, i, attr);
5727 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5729 guint32 mtoken, i, len;
5730 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5732 MonoCustomAttrInfo *ainfo;
5733 GList *tmp, *list = NULL;
5736 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5738 i = mono_metadata_custom_attrs_from_index (image, idx);
5742 while (i < ca->rows) {
5743 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5745 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5748 len = g_list_length (list);
5751 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5752 ainfo->num_attrs = len;
5753 ainfo->image = image;
5754 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5755 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5756 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5757 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5758 case CUSTOM_ATTR_TYPE_METHODDEF:
5759 mtoken |= MONO_TOKEN_METHOD_DEF;
5761 case CUSTOM_ATTR_TYPE_MEMBERREF:
5762 mtoken |= MONO_TOKEN_MEMBER_REF;
5765 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5768 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5769 if (!ainfo->attrs [i].ctor)
5770 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5771 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5772 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5773 ainfo->attrs [i].data = data;
5781 mono_custom_attrs_from_method (MonoMethod *method)
5783 MonoCustomAttrInfo *cinfo;
5786 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5788 idx = find_method_index (method);
5789 idx <<= CUSTOM_ATTR_BITS;
5790 idx |= CUSTOM_ATTR_METHODDEF;
5791 return mono_custom_attrs_from_index (method->klass->image, idx);
5795 mono_custom_attrs_from_class (MonoClass *klass)
5797 MonoCustomAttrInfo *cinfo;
5800 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5802 idx = mono_metadata_token_index (klass->type_token);
5803 idx <<= CUSTOM_ATTR_BITS;
5804 idx |= CUSTOM_ATTR_TYPEDEF;
5805 return mono_custom_attrs_from_index (klass->image, idx);
5809 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5811 MonoCustomAttrInfo *cinfo;
5814 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5816 idx = 1; /* there is only one assembly */
5817 idx <<= CUSTOM_ATTR_BITS;
5818 idx |= CUSTOM_ATTR_ASSEMBLY;
5819 return mono_custom_attrs_from_index (assembly->image, idx);
5822 static MonoCustomAttrInfo*
5823 mono_custom_attrs_from_module (MonoImage *image)
5825 MonoCustomAttrInfo *cinfo;
5828 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5830 idx = 1; /* there is only one module */
5831 idx <<= CUSTOM_ATTR_BITS;
5832 idx |= CUSTOM_ATTR_MODULE;
5833 return mono_custom_attrs_from_index (image, idx);
5837 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5839 MonoCustomAttrInfo *cinfo;
5842 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5844 idx = find_property_index (klass, property);
5845 idx <<= CUSTOM_ATTR_BITS;
5846 idx |= CUSTOM_ATTR_PROPERTY;
5847 return mono_custom_attrs_from_index (klass->image, idx);
5851 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
5853 MonoCustomAttrInfo *cinfo;
5856 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
5858 idx = find_event_index (klass, event);
5859 idx <<= CUSTOM_ATTR_BITS;
5860 idx |= CUSTOM_ATTR_EVENT;
5861 return mono_custom_attrs_from_index (klass->image, idx);
5865 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
5867 MonoCustomAttrInfo *cinfo;
5870 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5872 idx = find_field_index (klass, field);
5873 idx <<= CUSTOM_ATTR_BITS;
5874 idx |= CUSTOM_ATTR_FIELDDEF;
5875 return mono_custom_attrs_from_index (klass->image, idx);
5879 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
5882 guint32 i, idx, method_index;
5883 guint32 param_list, param_last, param_pos, found;
5886 /* FIXME: handle dynamic custom attrs for parameters */
5887 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5889 image = method->klass->image;
5890 method_index = find_method_index (method);
5891 ca = &image->tables [MONO_TABLE_METHOD];
5893 if (method->klass->generic_inst || method->klass->gen_params ||
5894 method->signature->generic_param_count) {
5895 // FIXME FIXME FIXME
5899 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
5900 if (method_index == ca->rows) {
5901 ca = &image->tables [MONO_TABLE_PARAM];
5902 param_last = ca->rows + 1;
5904 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
5905 ca = &image->tables [MONO_TABLE_PARAM];
5908 for (i = param_list; i < param_last; ++i) {
5909 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
5910 if (param_pos == param) {
5918 idx <<= CUSTOM_ATTR_BITS;
5919 idx |= CUSTOM_ATTR_PARAMDEF;
5920 return mono_custom_attrs_from_index (image, idx);
5924 * mono_reflection_get_custom_attrs:
5925 * @obj: a reflection object handle
5927 * Return an array with all the custom attributes defined of the
5928 * reflection handle @obj. The objects are fully build.
5931 mono_reflection_get_custom_attrs (MonoObject *obj)
5935 MonoCustomAttrInfo *cinfo = NULL;
5937 MONO_ARCH_SAVE_REGS;
5939 klass = obj->vtable->klass;
5940 /* FIXME: need to handle: Module */
5941 if (klass == mono_defaults.monotype_class) {
5942 MonoReflectionType *rtype = (MonoReflectionType*)obj;
5943 klass = mono_class_from_mono_type (rtype->type);
5944 cinfo = mono_custom_attrs_from_class (klass);
5945 } else if (strcmp ("Assembly", klass->name) == 0) {
5946 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
5947 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
5948 } else if (strcmp ("Module", klass->name) == 0) {
5949 MonoReflectionModule *module = (MonoReflectionModule*)obj;
5950 cinfo = mono_custom_attrs_from_module (module->image);
5951 } else if (strcmp ("MonoProperty", klass->name) == 0) {
5952 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
5953 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
5954 } else if (strcmp ("MonoEvent", klass->name) == 0) {
5955 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
5956 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
5957 } else if (strcmp ("MonoField", klass->name) == 0) {
5958 MonoReflectionField *rfield = (MonoReflectionField*)obj;
5959 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
5960 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
5961 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
5962 cinfo = mono_custom_attrs_from_method (rmethod->method);
5963 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
5964 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
5965 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
5966 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
5967 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
5968 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
5969 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
5970 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
5971 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5972 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
5973 } else { /* handle other types here... */
5974 g_error ("get custom attrs not yet supported for %s", klass->name);
5978 result = mono_custom_attrs_construct (cinfo);
5980 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5981 result = mono_array_new (mono_domain_get (), klass, 0);
5987 static MonoMethodSignature*
5988 parameters_to_signature (MonoArray *parameters) {
5989 MonoMethodSignature *sig;
5992 count = parameters? mono_array_length (parameters): 0;
5994 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
5995 sig->param_count = count;
5996 sig->sentinelpos = -1; /* FIXME */
5997 for (i = 0; i < count; ++i) {
5998 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
5999 sig->params [i] = pt->type;
6004 static MonoMethodSignature*
6005 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6006 MonoMethodSignature *sig;
6008 sig = parameters_to_signature (ctor->parameters);
6009 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6010 sig->ret = &mono_defaults.void_class->byval_arg;
6014 static MonoMethodSignature*
6015 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6016 MonoMethodSignature *sig;
6018 sig = parameters_to_signature (method->parameters);
6019 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6020 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6021 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6025 static MonoMethodSignature*
6026 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6027 MonoMethodSignature *sig;
6029 sig = parameters_to_signature (method->parameters);
6030 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6031 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6032 sig->generic_param_count = 0;
6037 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6039 MonoClass *klass = mono_object_class (prop);
6040 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6041 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6042 *name = mono_string_to_utf8 (pb->name);
6043 *type = pb->type->type;
6045 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6046 *name = g_strdup (p->property->name);
6047 if (p->property->get)
6048 *type = p->property->get->signature->ret;
6050 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6055 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6057 MonoClass *klass = mono_object_class (field);
6058 if (strcmp (klass->name, "FieldBuilder") == 0) {
6059 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6060 *name = mono_string_to_utf8 (fb->name);
6061 *type = fb->type->type;
6063 MonoReflectionField *f = (MonoReflectionField *)field;
6064 *name = g_strdup (f->field->name);
6065 *type = f->field->type;
6070 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6073 MonoTypeEnum simple_type;
6075 if ((p-buffer) + 10 >= *buflen) {
6078 newbuf = g_realloc (buffer, *buflen);
6079 p = newbuf + (p-buffer);
6082 argval = ((char*)arg + sizeof (MonoObject));
6083 simple_type = type->type;
6085 switch (simple_type) {
6086 case MONO_TYPE_BOOLEAN:
6091 case MONO_TYPE_CHAR:
6094 swap_with_size (p, argval, 2, 1);
6100 swap_with_size (p, argval, 4, 1);
6106 swap_with_size (p, argval, 8, 1);
6109 case MONO_TYPE_VALUETYPE:
6110 if (type->data.klass->enumtype) {
6111 simple_type = type->data.klass->enum_basetype->type;
6114 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6117 case MONO_TYPE_STRING: {
6124 str = mono_string_to_utf8 ((MonoString*)arg);
6125 slen = strlen (str);
6126 if ((p-buffer) + 10 + slen >= *buflen) {
6130 newbuf = g_realloc (buffer, *buflen);
6131 p = newbuf + (p-buffer);
6134 mono_metadata_encode_value (slen, p, &p);
6135 memcpy (p, str, slen);
6140 case MONO_TYPE_CLASS: {
6148 k = mono_object_class (arg);
6149 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6150 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6151 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6153 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6154 slen = strlen (str);
6155 if ((p-buffer) + 10 + slen >= *buflen) {
6159 newbuf = g_realloc (buffer, *buflen);
6160 p = newbuf + (p-buffer);
6163 mono_metadata_encode_value (slen, p, &p);
6164 memcpy (p, str, slen);
6169 case MONO_TYPE_SZARRAY: {
6174 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6177 len = mono_array_length ((MonoArray*)arg);
6179 *p++ = (len >> 8) & 0xff;
6180 *p++ = (len >> 16) & 0xff;
6181 *p++ = (len >> 24) & 0xff;
6183 *retbuffer = buffer;
6184 eclass = type->data.klass;
6185 for (i = 0; i < len; ++i) {
6186 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6190 /* it may be a boxed value or a Type */
6191 case MONO_TYPE_OBJECT: {
6192 MonoClass *klass = mono_object_class (arg);
6196 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6199 } else if (klass->enumtype) {
6201 } else if (klass == mono_defaults.string_class) {
6202 simple_type = MONO_TYPE_STRING;
6205 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6206 *p++ = simple_type = klass->byval_arg.type;
6209 g_error ("unhandled type in custom attr");
6211 str = type_get_qualified_name (klass->enum_basetype, NULL);
6212 slen = strlen (str);
6213 if ((p-buffer) + 10 + slen >= *buflen) {
6217 newbuf = g_realloc (buffer, *buflen);
6218 p = newbuf + (p-buffer);
6221 mono_metadata_encode_value (slen, p, &p);
6222 memcpy (p, str, slen);
6225 simple_type = klass->enum_basetype->type;
6229 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6232 *retbuffer = buffer;
6236 * mono_reflection_get_custom_attrs_blob:
6237 * @ctor: custom attribute constructor
6238 * @ctorArgs: arguments o the constructor
6244 * Creates the blob of data that needs to be saved in the metadata and that represents
6245 * the custom attributed described by @ctor, @ctorArgs etc.
6246 * Returns: a Byte array representing the blob of data.
6249 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6252 MonoMethodSignature *sig;
6257 MONO_ARCH_SAVE_REGS;
6259 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6260 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6262 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6264 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6266 p = buffer = g_malloc (buflen);
6267 /* write the prolog */
6270 for (i = 0; i < sig->param_count; ++i) {
6271 arg = mono_array_get (ctorArgs, MonoObject*, i);
6272 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6276 i += mono_array_length (properties);
6278 i += mono_array_length (fields);
6280 *p++ = (i >> 8) & 0xff;
6283 for (i = 0; i < mono_array_length (properties); ++i) {
6288 prop = mono_array_get (properties, gpointer, i);
6289 get_prop_name_and_type (prop, &pname, &ptype);
6290 *p++ = 0x54; /* PROPERTY signature */
6292 /* Preallocate a large enough buffer */
6293 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6294 char *str = type_get_qualified_name (ptype, NULL);
6300 len += strlen (pname);
6302 if ((p-buffer) + 20 + len >= buflen) {
6306 newbuf = g_realloc (buffer, buflen);
6307 p = newbuf + (p-buffer);
6311 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6312 char *str = type_get_qualified_name (ptype, NULL);
6313 int slen = strlen (str);
6317 * This seems to be optional...
6320 mono_metadata_encode_value (slen, p, &p);
6321 memcpy (p, str, slen);
6325 mono_metadata_encode_value (ptype->type, p, &p);
6326 if (ptype->type == MONO_TYPE_SZARRAY)
6327 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6329 len = strlen (pname);
6330 mono_metadata_encode_value (len, p, &p);
6331 memcpy (p, pname, len);
6333 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6340 for (i = 0; i < mono_array_length (fields); ++i) {
6345 field = mono_array_get (fields, gpointer, i);
6346 get_field_name_and_type (field, &fname, &ftype);
6347 *p++ = 0x53; /* FIELD signature */
6348 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6349 char *str = type_get_qualified_name (ftype, NULL);
6350 int slen = strlen (str);
6351 if ((p-buffer) + 10 + slen >= buflen) {
6355 newbuf = g_realloc (buffer, buflen);
6356 p = newbuf + (p-buffer);
6361 * This seems to be optional...
6364 mono_metadata_encode_value (slen, p, &p);
6365 memcpy (p, str, slen);
6369 mono_metadata_encode_value (ftype->type, p, &p);
6371 len = strlen (fname);
6372 mono_metadata_encode_value (len, p, &p);
6373 memcpy (p, fname, len);
6375 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6380 g_assert (p - buffer <= buflen);
6381 buflen = p - buffer;
6382 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6383 p = mono_array_addr (result, char, 0);
6384 memcpy (p, buffer, buflen);
6386 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6392 * mono_reflection_setup_internal_class:
6393 * @tb: a TypeBuilder object
6395 * Creates a MonoClass that represents the TypeBuilder.
6396 * This is a trick that lets us simplify a lot of reflection code
6397 * (and will allow us to support Build and Run assemblies easier).
6400 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6402 MonoClass *klass, *parent;
6404 MONO_ARCH_SAVE_REGS;
6406 klass = g_new0 (MonoClass, 1);
6408 klass->image = &tb->module->dynamic_image->image;
6411 /* check so we can compile corlib correctly */
6412 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6413 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6414 parent = tb->parent->type->data.klass;
6416 parent = my_mono_class_from_mono_type (tb->parent->type);
6420 klass->inited = 1; /* we lie to the runtime */
6421 klass->name = mono_string_to_utf8 (tb->name);
6422 klass->name_space = mono_string_to_utf8 (tb->nspace);
6423 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6424 klass->flags = tb->attrs;
6426 klass->element_class = klass;
6427 klass->reflection_info = tb; /* need to pin. */
6429 /* Put into cache so mono_class_get () will find it */
6430 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6433 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6434 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6438 mono_class_setup_parent (klass, parent);
6439 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6440 const char *old_n = klass->name;
6441 /* trick to get relative numbering right when compiling corlib */
6442 klass->name = "BuildingObject";
6443 mono_class_setup_parent (klass, mono_defaults.object_class);
6444 klass->name = old_n;
6446 mono_class_setup_mono_type (klass);
6448 mono_class_setup_supertypes (klass);
6451 * FIXME: handle interfaces.
6454 tb->type.type = &klass->byval_arg;
6456 if (tb->nesting_type) {
6457 g_assert (tb->nesting_type->type);
6458 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6461 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6465 * mono_reflection_setup_generic_class:
6466 * @tb: a TypeBuilder object
6468 * Setup the generic class after all generic parameters have been added.
6471 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6476 MONO_ARCH_SAVE_REGS;
6478 klass = my_mono_class_from_mono_type (tb->type.type);
6480 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6482 if (klass->gen_params || (count == 0))
6485 klass->num_gen_params = count;
6486 klass->gen_params = g_new0 (MonoGenericParam, count);
6488 for (i = 0; i < count; i++) {
6489 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6490 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6493 ensure_runtime_vtable (klass);
6497 * mono_reflection_create_internal_class:
6498 * @tb: a TypeBuilder object
6500 * Actually create the MonoClass that is associated with the TypeBuilder.
6503 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6507 MONO_ARCH_SAVE_REGS;
6509 klass = my_mono_class_from_mono_type (tb->type.type);
6511 if (klass->enumtype && klass->enum_basetype == NULL) {
6512 MonoReflectionFieldBuilder *fb;
6514 g_assert (tb->fields != NULL);
6515 g_assert (mono_array_length (tb->fields) >= 1);
6517 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6519 klass->enum_basetype = fb->type->type;
6520 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6521 if (!klass->element_class)
6522 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6523 klass->instance_size = klass->element_class->instance_size;
6524 klass->size_inited = 1;
6526 * this is almost safe to do with enums and it's needed to be able
6527 * to create objects of the enum type (for use in SetConstant).
6529 /* FIXME: Does this mean enums can't have method overrides ? */
6530 mono_class_setup_vtable (klass, NULL, 0);
6534 static MonoMarshalSpec*
6535 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6536 MonoReflectionMarshal *minfo)
6538 MonoMarshalSpec *res;
6540 res = g_new0 (MonoMarshalSpec, 1);
6541 res->native = minfo->type;
6543 switch (minfo->type) {
6544 case MONO_NATIVE_LPARRAY:
6545 res->data.array_data.elem_type = minfo->eltype;
6546 res->data.array_data.param_num = 0; /* Not yet */
6547 res->data.array_data.num_elem = minfo->count;
6550 case MONO_NATIVE_BYVALTSTR:
6551 case MONO_NATIVE_BYVALARRAY:
6552 res->data.array_data.num_elem = minfo->count;
6555 case MONO_NATIVE_CUSTOM:
6556 if (minfo->marshaltyperef)
6557 res->data.custom_data.custom_name =
6558 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6560 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6571 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6572 ReflectionMethodBuilder *rmb,
6573 MonoMethodSignature *sig)
6576 MonoMethodNormal *pm;
6577 MonoMarshalSpec **specs;
6578 MonoReflectionMethodAux *method_aux;
6581 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6582 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6583 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6586 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6588 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6590 pm = (MonoMethodNormal*)m;
6593 m->flags = rmb->attrs;
6594 m->iflags = rmb->iattrs;
6595 m->name = mono_string_to_utf8 (rmb->name);
6599 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6601 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6602 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6605 m->signature->pinvoke = 1;
6606 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6608 m->signature->pinvoke = 1;
6610 } else if (!m->klass->dummy &&
6611 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6612 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6613 MonoMethodHeader *header;
6615 gint32 max_stack, i;
6616 gint32 num_locals = 0;
6617 gint32 num_clauses = 0;
6621 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6622 code_size = rmb->ilgen->code_len;
6623 max_stack = rmb->ilgen->max_stack;
6624 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6625 if (rmb->ilgen->ex_handlers)
6626 num_clauses = method_count_clauses (rmb->ilgen);
6629 code = mono_array_addr (rmb->code, guint8, 0);
6630 code_size = mono_array_length (rmb->code);
6631 /* we probably need to run a verifier on the code... */
6641 header = g_malloc0 (sizeof (MonoMethodHeader) +
6642 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6643 header->code_size = code_size;
6644 header->code = g_malloc (code_size);
6645 memcpy ((char*)header->code, code, code_size);
6646 header->max_stack = max_stack;
6647 header->init_locals = rmb->init_locals;
6648 header->num_locals = num_locals;
6650 for (i = 0; i < num_locals; ++i) {
6651 MonoReflectionLocalBuilder *lb =
6652 mono_array_get (rmb->ilgen->locals,
6653 MonoReflectionLocalBuilder*, i);
6655 header->locals [i] = g_new0 (MonoType, 1);
6656 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6659 header->num_clauses = num_clauses;
6661 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6666 if (rmb->generic_params) {
6667 int count = mono_array_length (rmb->generic_params);
6668 header->gen_params = g_new0 (MonoGenericParam, count);
6669 for (i = 0; i < count; i++) {
6670 MonoReflectionGenericParam *gp =
6671 mono_array_get (rmb->generic_params,
6672 MonoReflectionGenericParam*, i);
6674 header->gen_params [i] = *gp->type.type->data.generic_param;
6678 pm->header = header;
6682 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6685 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6687 for (i = 0; i < rmb->nrefs; ++i)
6688 mw->data = g_list_append (mw->data, rmb->refs [i]);
6693 /* Parameter names */
6694 if (rmb->parameters) {
6696 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6697 method_aux->param_names = g_new0 (char *, m->signature->param_count);
6698 for (i = 0; i < m->signature->param_count; ++i) {
6699 MonoReflectionParamBuilder *pb;
6700 if ((pb = mono_array_get (rmb->parameters, MonoReflectionParamBuilder*, i))) {
6702 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6707 /* Parameter marshalling */
6710 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6711 MonoReflectionParamBuilder *pb;
6712 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6713 if (pb->marshal_info) {
6715 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6716 specs [pb->position] =
6717 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6721 if (specs != NULL) {
6723 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6724 method_aux->param_marshall = specs;
6727 if (klass->image->dynamic && method_aux)
6728 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6734 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6736 ReflectionMethodBuilder rmb;
6737 MonoMethodSignature *sig;
6739 sig = ctor_builder_to_signature (mb);
6741 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6743 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6744 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6746 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6747 /* ilgen is no longer needed */
6755 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6757 ReflectionMethodBuilder rmb;
6758 MonoMethodSignature *sig;
6760 sig = method_builder_to_signature (mb);
6762 reflection_methodbuilder_from_method_builder (&rmb, mb);
6764 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6765 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6767 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6768 /* ilgen is no longer needed */
6774 static MonoClassField*
6775 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6777 MonoClassField *field;
6784 field = g_new0 (MonoClassField, 1);
6786 field->name = mono_string_to_utf8 (fb->name);
6788 /* FIXME: handle type modifiers */
6789 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6790 field->type->attrs = fb->attrs;
6792 field->type = fb->type->type;
6794 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6795 field->data = mono_array_addr (fb->rva_data, char, 0);
6796 if (fb->offset != -1)
6797 field->offset = fb->offset;
6798 field->parent = klass;
6800 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6802 if (fb->def_value) {
6803 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6804 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6805 field->def_value = g_new0 (MonoConstant, 1);
6806 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6807 /* Copy the data from the blob since it might get realloc-ed */
6808 p = assembly->blob.data + idx;
6809 len = mono_metadata_decode_blob_size (p, &p2);
6811 field->def_value->value = g_malloc (len);
6812 memcpy (field->def_value->value, p, len);
6818 static MonoReflectionInflatedMethod*
6819 inflated_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass,
6820 MonoReflectionMethod *declaring, MonoGenericMethod *gmethod)
6824 MonoReflectionInflatedMethod *ret;
6827 refclass = method->klass;
6829 CHECK_OBJECT (MonoReflectionInflatedMethod *, method, refclass);
6830 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
6831 cname = "MonoInflatedCtor";
6833 cname = "MonoInflatedMethod";
6834 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
6837 ret = (MonoReflectionInflatedMethod*)mono_object_new (domain, klass);
6838 ret->rmethod.method = method;
6839 ret->rmethod.name = mono_string_new (domain, method->name);
6840 ret->rmethod.reftype = mono_type_get_object (domain, &refclass->byval_arg);
6841 ret->declaring = declaring;
6842 ret->gmethod = gmethod;
6843 CACHE_OBJECT (method, ret, refclass);
6848 mono_reflection_bind_generic_parameters (MonoType *type, MonoArray *types)
6850 MonoClass *klass, *pklass = NULL;
6851 MonoReflectionTypeBuilder *tb = NULL;
6852 MonoGenericInst *ginst;
6853 MonoType *geninst, *parent = NULL;
6856 klass = mono_class_from_mono_type (type);
6857 if (!klass->gen_params && !klass->generic_inst)
6860 if (klass->wastypebuilder && klass->reflection_info) {
6861 tb = klass->reflection_info;
6864 parent = tb->parent->type;
6865 pklass = mono_class_from_mono_type (parent);
6868 pklass = klass->parent;
6870 parent = &pklass->byval_arg;
6873 geninst = g_new0 (MonoType, 1);
6874 geninst->type = MONO_TYPE_GENERICINST;
6875 geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1);
6877 if (pklass && pklass->generic_inst)
6878 parent = mono_reflection_bind_generic_parameters (parent, types);
6882 pklass = mono_defaults.object_class;
6884 icount = klass->interface_count;
6885 ginst->ifaces = g_new0 (MonoType *, icount);
6887 for (i = 0; i < icount; i++) {
6891 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i)->type;
6893 itype = &klass->interfaces [i]->byval_arg;
6894 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, types);
6895 if (!ginst->ifaces [i])
6896 ginst->ifaces [i] = itype;
6900 ginst->parent = parent;
6902 if (klass->gen_params) {
6903 ginst->type_argc = mono_array_length (types);
6904 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6906 for (i = 0; i < ginst->type_argc; ++i) {
6907 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6909 ginst->type_argv [i] = garg->type;
6911 if (!ginst->is_open)
6912 ginst->is_open = mono_class_is_open_constructed_type (garg->type);
6915 ginst->generic_type = &klass->byval_arg;
6917 MonoGenericInst *kginst = klass->generic_inst;
6919 ginst->type_argc = kginst->type_argc;
6920 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6922 for (i = 0; i < ginst->type_argc; i++) {
6923 MonoType *t = kginst->type_argv [i];
6925 if (t->type == MONO_TYPE_VAR) {
6926 int num = t->data.generic_param->num;
6927 MonoReflectionType *garg = mono_array_get (types, gpointer, num);
6932 if (!ginst->is_open)
6933 ginst->is_open = mono_class_is_open_constructed_type (t);
6935 ginst->type_argv [i] = t;
6938 ginst->generic_type = kginst->generic_type;
6941 mono_class_from_generic (ginst);
6946 MonoReflectionInflatedMethod*
6947 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
6949 MonoMethod *method, *inflated;
6950 MonoReflectionMethodBuilder *mb = NULL;
6951 MonoReflectionMethod *declaring;
6952 MonoGenericMethod *gmethod;
6955 MONO_ARCH_SAVE_REGS;
6956 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
6957 MonoReflectionTypeBuilder *tb;
6960 mb = (MonoReflectionMethodBuilder *) rmethod;
6961 tb = (MonoReflectionTypeBuilder *) mb->type;
6962 klass = mono_class_from_mono_type (tb->type.type);
6964 method = methodbuilder_to_mono_method (klass, mb);
6965 declaring = rmethod;
6966 } else if (!strcmp (rmethod->object.vtable->klass->name, "MonoInflatedMethod") ||
6967 !strcmp (rmethod->object.vtable->klass->name, "MonoInflatedCtor")) {
6968 method = ((MonoReflectionInflatedMethod *) rmethod)->rmethod.method;
6969 declaring = ((MonoReflectionInflatedMethod *) rmethod)->declaring;
6971 method = rmethod->method;
6972 declaring = rmethod;
6975 count = method->signature->generic_param_count;
6976 if (count != mono_array_length (types))
6979 gmethod = g_new0 (MonoGenericMethod, 1);
6980 gmethod->generic_method = method;
6981 gmethod->mtype_argc = count;
6982 gmethod->mtype_argv = g_new0 (MonoType *, count);
6983 for (i = 0; i < count; i++) {
6984 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6985 gmethod->mtype_argv [i] = garg->type;
6988 gmethod->generic_inst = method->klass->generic_inst;
6989 gmethod->klass = method->klass;
6991 inflated = mono_class_inflate_generic_method (method, gmethod);
6993 return inflated_method_get_object (
6994 mono_object_domain (rmethod), inflated, NULL, declaring, gmethod);
6997 MonoReflectionInflatedMethod*
6998 mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type,
6999 MonoReflectionGenericInst *reflected_type,
7002 MonoMethod *method = NULL, *inflated;
7003 MonoReflectionInflatedMethod *res;
7004 MonoReflectionMethod *declaring;
7005 MonoClass *klass, *refclass;
7006 MonoGenericMethod *gmethod;
7007 MonoGenericInst *ginst;
7009 MONO_ARCH_SAVE_REGS;
7011 klass = mono_class_from_mono_type (declaring_type->type.type);
7012 refclass = mono_class_from_mono_type (reflected_type->type.type);
7013 ginst = declaring_type->type.type->data.generic_inst;
7015 if (!strcmp (obj->vtable->klass->name, "MethodBuilder")) {
7016 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7017 declaring = (MonoReflectionMethod *) obj;
7018 } else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
7019 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7020 declaring = (MonoReflectionMethod *) obj;
7021 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7022 !strcmp (obj->vtable->klass->name, "MonoCMethod")) {
7023 method = ((MonoReflectionMethod *) obj)->method;
7024 declaring = (MonoReflectionMethod *) obj;
7025 } else if (!strcmp (obj->vtable->klass->name, "MonoInflatedMethod") ||
7026 !strcmp (obj->vtable->klass->name, "MonoInflatedCtor")) {
7027 method = ((MonoReflectionInflatedMethod *) obj)->rmethod.method;
7028 declaring = ((MonoReflectionInflatedMethod *) obj)->declaring;
7030 g_assert_not_reached ();
7032 gmethod = g_new0 (MonoGenericMethod, 1);
7033 gmethod->generic_method = method;
7034 gmethod->generic_inst = ginst;
7035 gmethod->klass = ginst->klass;
7037 inflated = mono_class_inflate_generic_method (method, gmethod);
7039 res = inflated_method_get_object (
7040 mono_object_domain (declaring_type), inflated, refclass, declaring, gmethod);
7045 MonoReflectionInflatedField*
7046 mono_reflection_inflate_field (MonoReflectionGenericInst *declaring_type,
7047 MonoReflectionGenericInst *reflected_type,
7050 static MonoClass *System_Reflection_MonoInflatedField;
7051 MonoGenericInst *ginst, *type_ginst;
7052 MonoClassField *field = NULL, *inflated;
7053 MonoReflectionInflatedField *res;
7057 MONO_ARCH_SAVE_REGS;
7059 if (!System_Reflection_MonoInflatedField) {
7060 System_Reflection_MonoInflatedField = mono_class_from_name (
7061 mono_defaults.corlib, "System.Reflection", "MonoInflatedField");
7062 g_assert (System_Reflection_MonoInflatedField);
7065 klass = mono_class_from_mono_type (reflected_type->type.type);
7066 type_ginst = reflected_type->type.type->data.generic_inst;
7068 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
7069 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7070 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7071 field = ((MonoReflectionField *) obj)->field;
7073 g_assert_not_reached ();
7075 ginst = g_new0 (MonoGenericInst, 1);
7076 ginst->generic_type = reflected_type->type.type;
7077 ginst->type_argc = type_ginst->type_argc;
7078 ginst->type_argv = type_ginst->type_argv;
7080 inflated = g_new0 (MonoClassField, 1);
7082 inflated->type = mono_class_inflate_generic_type (field->type, ginst, NULL);
7084 domain = mono_object_domain (obj);
7086 res = (MonoReflectionInflatedField *)mono_object_new (domain, System_Reflection_MonoInflatedField);
7087 res->declaring = field;
7088 res->declaring_type = declaring_type;
7089 res->reflected_type = reflected_type;
7090 res->rfield.klass = klass;
7091 res->rfield.field = inflated;
7092 res->rfield.name = mono_string_new (domain, inflated->name);
7093 res->rfield.attrs = inflated->type->attrs;
7094 res->rfield.type = mono_type_get_object (domain, inflated->type);
7095 CACHE_OBJECT (inflated, res, field->parent);
7100 ensure_runtime_vtable (MonoClass *klass)
7102 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7103 int i, num, j, onum;
7104 MonoMethod **overrides;
7106 if (!tb || klass->wastypebuilder)
7109 ensure_runtime_vtable (klass->parent);
7111 num = tb->ctors? mono_array_length (tb->ctors): 0;
7112 num += tb->num_methods;
7113 klass->method.count = num;
7114 klass->methods = g_new (MonoMethod*, num);
7115 num = tb->ctors? mono_array_length (tb->ctors): 0;
7116 for (i = 0; i < num; ++i)
7117 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7118 num = tb->num_methods;
7120 for (i = 0; i < num; ++i)
7121 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7123 klass->wastypebuilder = TRUE;
7124 if (tb->interfaces) {
7125 klass->interface_count = mono_array_length (tb->interfaces);
7126 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7127 for (i = 0; i < klass->interface_count; ++i) {
7128 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7129 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7133 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7134 for (i = 0; i < klass->method.count; ++i)
7135 klass->methods [i]->slot = i;
7140 for (i = 0; i < tb->num_methods; ++i) {
7141 MonoReflectionMethodBuilder *mb =
7142 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7143 if (mb->override_method)
7148 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7152 for (i = 0; i < tb->num_methods; ++i) {
7153 MonoReflectionMethodBuilder *mb =
7154 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7155 if (mb->override_method) {
7156 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7157 overrides [onum * 2] =
7158 mb->override_method->method;
7159 overrides [onum * 2 + 1] =
7162 g_assert (mb->mhandle);
7169 mono_class_setup_vtable (klass, overrides, onum);
7173 typebuilder_setup_fields (MonoClass *klass)
7175 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7176 MonoReflectionFieldBuilder *fb;
7177 MonoClassField *field;
7182 klass->field.count = tb->num_fields;
7183 klass->field.first = 0;
7184 klass->field.last = klass->field.count;
7186 if (!klass->field.count)
7189 klass->fields = g_new0 (MonoClassField, klass->field.count);
7191 for (i = 0; i < klass->field.count; ++i) {
7192 fb = mono_array_get (tb->fields, gpointer, i);
7193 field = &klass->fields [i];
7194 field->name = mono_string_to_utf8 (fb->name);
7196 /* FIXME: handle type modifiers */
7197 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7198 field->type->attrs = fb->attrs;
7200 field->type = fb->type->type;
7202 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7203 field->data = mono_array_addr (fb->rva_data, char, 0);
7204 if (fb->offset != -1)
7205 field->offset = fb->offset;
7206 field->parent = klass;
7208 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7210 if (fb->def_value) {
7211 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7212 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7213 field->def_value = g_new0 (MonoConstant, 1);
7214 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7215 /* Copy the data from the blob since it might get realloc-ed */
7216 p = assembly->blob.data + idx;
7217 len = mono_metadata_decode_blob_size (p, &p2);
7219 field->def_value->value = g_malloc (len);
7220 memcpy (field->def_value->value, p, len);
7223 mono_class_layout_fields (klass);
7227 typebuilder_setup_properties (MonoClass *klass)
7229 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7230 MonoReflectionPropertyBuilder *pb;
7233 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7234 klass->property.first = 0;
7235 klass->property.last = klass->property.count;
7237 klass->properties = g_new0 (MonoProperty, klass->property.count);
7238 for (i = 0; i < klass->property.count; ++i) {
7239 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7240 klass->properties [i].attrs = pb->attrs;
7241 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7243 klass->properties [i].get = pb->get_method->mhandle;
7245 klass->properties [i].set = pb->set_method->mhandle;
7250 typebuilder_setup_events (MonoClass *klass)
7252 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7253 MonoReflectionEventBuilder *eb;
7256 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7257 klass->event.first = 0;
7258 klass->event.last = klass->event.count;
7260 klass->events = g_new0 (MonoEvent, klass->event.count);
7261 for (i = 0; i < klass->event.count; ++i) {
7262 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7263 klass->events [i].attrs = eb->attrs;
7264 klass->events [i].name = mono_string_to_utf8 (eb->name);
7266 klass->events [i].add = eb->add_method->mhandle;
7267 if (eb->remove_method)
7268 klass->events [i].remove = eb->remove_method->mhandle;
7269 if (eb->raise_method)
7270 klass->events [i].raise = eb->raise_method->mhandle;
7272 if (eb->other_methods) {
7273 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7274 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7275 MonoReflectionMethodBuilder *mb =
7276 mono_array_get (eb->other_methods,
7277 MonoReflectionMethodBuilder*, j);
7278 klass->events [i].other [j] = mb->mhandle;
7285 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7288 MonoReflectionType* res;
7290 MONO_ARCH_SAVE_REGS;
7292 klass = my_mono_class_from_mono_type (tb->type.type);
7294 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7297 * Fields to set in klass:
7298 * the various flags: delegate/unicode/contextbound etc.
7301 klass->flags = tb->attrs;
7303 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7304 /* No need to fully construct the type */
7305 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7307 /* enums are done right away */
7308 if (!klass->enumtype)
7309 ensure_runtime_vtable (klass);
7311 /* fields and object layout */
7312 if (klass->parent) {
7313 if (!klass->parent->size_inited)
7314 mono_class_init (klass->parent);
7315 klass->instance_size += klass->parent->instance_size;
7316 klass->class_size += klass->parent->class_size;
7317 klass->min_align = klass->parent->min_align;
7319 klass->instance_size = sizeof (MonoObject);
7320 klass->min_align = 1;
7323 /* FIXME: handle packing_size and instance_size */
7324 typebuilder_setup_fields (klass);
7326 typebuilder_setup_properties (klass);
7328 typebuilder_setup_events (klass);
7330 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7331 /* with enums res == tb: need to fix that. */
7332 if (!klass->enumtype)
7333 g_assert (res != (MonoReflectionType*)tb);
7337 MonoReflectionGenericParam *
7338 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7340 static MonoClass *System_Reflection_MonoGenericParam;
7342 MonoGenericParam *param;
7343 MonoReflectionGenericParam *res;
7346 if (!System_Reflection_MonoGenericParam) {
7347 System_Reflection_MonoGenericParam = mono_class_from_name (
7348 mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7349 g_assert (System_Reflection_MonoGenericParam);
7352 param = g_new0 (MonoGenericParam, 1);
7355 tb = (MonoReflectionTypeBuilder *) mb->type;
7357 domain = mono_object_domain (tb);
7358 image = (MonoImage*)tb->module->dynamic_image;
7360 param->method = NULL;
7361 param->name = mono_string_to_utf8 (name);
7364 res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7365 res->type.type = g_new0 (MonoType, 1);
7366 res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7367 res->type.type->data.generic_param = param;
7369 res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7377 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7379 MonoGenericParam *param;
7380 MonoReflectionMethodBuilder *mb = NULL;
7381 MonoReflectionTypeBuilder *tb;
7385 param = gparam->type.type->data.generic_param;
7386 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7387 param->constraints = g_new0 (MonoClass *, count + 1);
7388 for (i = 0; i < count; i++) {
7389 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7391 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7394 if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7395 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7396 tb = (MonoReflectionTypeBuilder *) mb->type;
7398 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7400 image = (MonoImage*)tb->module->dynamic_image;
7402 param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7404 gparam->initialized = TRUE;
7408 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7410 MonoDynamicImage *assembly = sig->module->dynamic_image;
7411 guint32 na = mono_array_length (sig->arguments);
7416 MONO_ARCH_SAVE_REGS;
7418 p = buf = g_malloc (10 + na * 10);
7420 mono_metadata_encode_value (0x07, p, &p);
7421 mono_metadata_encode_value (na, p, &p);
7422 for (i = 0; i < na; ++i) {
7423 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7424 encode_reflection_type (assembly, type, p, &p);
7428 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7429 p = mono_array_addr (result, char, 0);
7430 memcpy (p, buf, buflen);
7437 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7439 MonoDynamicImage *assembly = sig->module->dynamic_image;
7440 guint32 na = mono_array_length (sig->arguments);
7445 MONO_ARCH_SAVE_REGS;
7447 p = buf = g_malloc (10 + na * 10);
7449 mono_metadata_encode_value (0x06, p, &p);
7450 for (i = 0; i < na; ++i) {
7451 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7452 encode_reflection_type (assembly, type, p, &p);
7456 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7457 p = mono_array_addr (result, char, 0);
7458 memcpy (p, buf, buflen);
7465 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7467 ReflectionMethodBuilder rmb;
7468 MonoMethodSignature *sig;
7471 sig = dynamic_method_to_signature (mb);
7473 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7476 * Resolve references.
7478 rmb.nrefs = mb->nrefs;
7479 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7480 for (i = 0; i < mb->nrefs; ++i) {
7481 gpointer ref = resolve_object (mb->module->image,
7482 mono_array_get (mb->refs, MonoObject*, i));
7485 mono_raise_exception (mono_get_exception_type_load (NULL));
7492 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7496 /* ilgen is no longer needed */
7501 * mono_reflection_lookup_dynamic_token:
7503 * Finish the Builder object pointed to by TOKEN and return the corresponding
7504 * runtime structure.
7507 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7509 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7512 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7515 return resolve_object (image, obj);
7519 resolve_object (MonoImage *image, MonoObject *obj)
7521 gpointer result = NULL;
7523 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7524 result = mono_string_intern ((MonoString*)obj);
7527 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7528 MonoReflectionType *tb = (MonoReflectionType*)obj;
7529 result = mono_class_from_mono_type (tb->type);
7532 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7533 result = ((MonoReflectionMethod*)obj)->method;
7536 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7537 result = ((MonoReflectionMethod*)obj)->method;
7540 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7541 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7542 result = mb->mhandle;
7544 /* Type is not yet created */
7545 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7547 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7550 * Hopefully this has been filled in by calling CreateType() on the
7554 * TODO: This won't work if the application finishes another
7555 * TypeBuilder instance instead of this one.
7557 result = mb->mhandle;
7560 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7561 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7563 result = cb->mhandle;
7565 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7567 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7568 result = cb->mhandle;
7571 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7572 result = ((MonoReflectionField*)obj)->field;
7575 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7576 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7577 result = fb->handle;
7580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7582 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7583 result = fb->handle;
7586 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7587 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7590 klass = tb->type.type->data.klass;
7591 if (klass->wastypebuilder) {
7592 /* Already created */
7596 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7597 result = tb->type.type->data.klass;
7601 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7602 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7603 MonoMethodSignature *sig;
7606 if (helper->arguments)
7607 nargs = mono_array_length (helper->arguments);
7611 sig = mono_metadata_signature_alloc (image, nargs);
7612 sig->explicit_this = helper->call_conv & 64;
7613 sig->hasthis = helper->call_conv & 32;
7615 if (helper->call_conv == 0) /* unmanaged */
7616 sig->call_convention = helper->unmanaged_call_conv - 1;
7618 if (helper->call_conv & 0x02)
7619 sig->call_convention = MONO_CALL_VARARG;
7621 sig->call_convention = MONO_CALL_DEFAULT;
7623 sig->param_count = nargs;
7624 /* TODO: Copy type ? */
7625 sig->ret = helper->return_type->type;
7626 for (i = 0; i < nargs; ++i) {
7627 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7628 sig->params [i] = rt->type;
7634 g_print (obj->vtable->klass->name);
7635 g_assert_not_reached ();