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 = 11 + 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 char *name = mono_string_to_utf8 (mb->name);
764 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
765 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
768 mono_raise_exception (exception);
771 code_size = mono_array_length (code);
772 max_stack = 8; /* we probably need to run a verifier on the code... */
775 /* check for exceptions, maxstack, locals */
776 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
778 if (code_size < 64 && !(code_size & 1)) {
779 flags = (code_size << 2) | 0x2;
780 } else if (code_size < 32 && (code_size & 1)) {
781 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
785 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
786 /* add to the fixup todo list */
787 if (mb->ilgen && mb->ilgen->num_token_fixups)
788 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
789 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
790 return assembly->text_rva + idx;
794 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
796 * FIXME: need to set also the header size in fat_flags.
797 * (and more sects and init locals flags)
801 fat_flags |= METHOD_HEADER_MORE_SECTS;
803 fat_flags |= METHOD_HEADER_INIT_LOCALS;
804 fat_header [0] = fat_flags;
805 fat_header [1] = (header_size / 4 ) << 4;
806 shortp = (guint16*)(fat_header + 2);
807 *shortp = GUINT16_TO_LE (max_stack);
808 intp = (guint32*)(fat_header + 4);
809 *intp = GUINT32_TO_LE (code_size);
810 intp = (guint32*)(fat_header + 8);
811 *intp = GUINT32_TO_LE (local_sig);
812 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
813 /* add to the fixup todo list */
814 if (mb->ilgen && mb->ilgen->num_token_fixups)
815 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
817 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
819 unsigned char sheader [4];
820 MonoExceptionClause clause;
821 MonoILExceptionInfo * ex_info;
822 MonoILExceptionBlock * ex_block;
825 stream_data_align (&assembly->code);
826 /* always use fat format for now */
827 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
828 num_exception *= sizeof (MonoExceptionClause);
829 num_exception += 4; /* include the size of the header */
830 sheader [1] = num_exception & 0xff;
831 sheader [2] = (num_exception >> 8) & 0xff;
832 sheader [3] = (num_exception >> 16) & 0xff;
833 mono_image_add_stream_data (&assembly->code, sheader, 4);
834 /* fat header, so we are already aligned */
836 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
837 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
838 if (ex_info->handlers) {
839 int finally_start = ex_info->start + ex_info->len;
840 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
841 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
842 clause.flags = GUINT32_TO_LE (ex_block->type);
843 clause.try_offset = GUINT32_TO_LE (ex_info->start);
844 /* need fault, too, probably */
845 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
846 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
848 clause.try_len = GUINT32_TO_LE (ex_info->len);
849 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
850 clause.handler_len = GUINT32_TO_LE (ex_block->len);
851 finally_start = ex_block->start + ex_block->len;
852 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
853 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
854 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
855 /*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",
856 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);*/
857 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
860 g_error ("No clauses for ex info block %d", i);
864 return assembly->text_rva + idx;
868 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
871 MonoDynamicTable *table;
874 table = &assembly->tables [table_idx];
876 g_assert (col < table->columns);
878 values = table->values + table->columns;
879 for (i = 1; i <= table->rows; ++i) {
880 if (values [col] == token)
882 values += table->columns;
887 static GHashTable *dynamic_custom_attrs = NULL;
889 static MonoCustomAttrInfo*
890 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
893 MonoCustomAttrInfo *ainfo;
894 MonoReflectionCustomAttr *cattr;
898 /* FIXME: check in assembly the Run flag is set */
900 count = mono_array_length (cattrs);
902 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
904 ainfo->image = image;
905 ainfo->num_attrs = count;
906 for (i = 0; i < count; ++i) {
907 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
908 ainfo->attrs [i].ctor = cattr->ctor->method;
909 /* FIXME: might want to memdup the data here */
910 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
911 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
918 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
920 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
925 if (!dynamic_custom_attrs)
926 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
928 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
932 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
934 /* they are cached, so we don't free them */
935 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
941 * idx is the table index of the object
942 * type is one of CUSTOM_ATTR_*
945 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
947 MonoDynamicTable *table;
948 MonoReflectionCustomAttr *cattr;
950 guint32 count, i, token;
954 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
957 count = mono_array_length (cattrs);
958 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
959 table->rows += count;
960 alloc_table (table, table->rows);
961 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
962 idx <<= CUSTOM_ATTR_BITS;
964 for (i = 0; i < count; ++i) {
965 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
966 values [MONO_CUSTOM_ATTR_PARENT] = idx;
967 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
968 type = mono_metadata_token_index (token);
969 type <<= CUSTOM_ATTR_TYPE_BITS;
970 switch (mono_metadata_token_table (token)) {
971 case MONO_TABLE_METHOD:
972 type |= CUSTOM_ATTR_TYPE_METHODDEF;
974 case MONO_TABLE_MEMBERREF:
975 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
978 g_warning ("got wrong token in custom attr");
981 values [MONO_CUSTOM_ATTR_TYPE] = type;
983 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
984 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
985 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
986 values += MONO_CUSTOM_ATTR_SIZE;
992 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
993 MonoArray *permissions)
995 MonoDynamicTable *table;
997 guint32 count, i, idx;
998 MonoReflectionPermissionSet *perm;
1003 count = mono_array_length (permissions);
1004 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1005 table->rows += count;
1006 alloc_table (table, table->rows);
1008 for (i = 0; i < mono_array_length (permissions); ++i) {
1009 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1011 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1013 idx = mono_metadata_token_index (parent_token);
1014 idx <<= HAS_DECL_SECURITY_BITS;
1015 switch (mono_metadata_token_table (parent_token)) {
1016 case MONO_TABLE_TYPEDEF:
1017 idx |= HAS_DECL_SECURITY_TYPEDEF;
1019 case MONO_TABLE_METHOD:
1020 idx |= HAS_DECL_SECURITY_METHODDEF;
1022 case MONO_TABLE_ASSEMBLY:
1023 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1026 g_assert_not_reached ();
1029 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1030 values [MONO_DECL_SECURITY_PARENT] = idx;
1031 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1038 * Fill in the MethodDef and ParamDef tables for a method.
1039 * This is used for both normal methods and constructors.
1042 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1044 MonoDynamicTable *table;
1049 /* room in this table is already allocated */
1050 table = &assembly->tables [MONO_TABLE_METHOD];
1051 *mb->table_idx = table->next_idx ++;
1052 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1053 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1054 name = mono_string_to_utf8 (mb->name);
1055 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1057 values [MONO_METHOD_FLAGS] = mb->attrs;
1058 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1059 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1060 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1062 table = &assembly->tables [MONO_TABLE_PARAM];
1063 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1065 mono_image_add_decl_security (assembly,
1066 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1070 MonoDynamicTable *mtable;
1073 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1074 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1077 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1078 if (mono_array_get (mb->pinfo, gpointer, i))
1081 table->rows += count;
1082 alloc_table (table, table->rows);
1083 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1084 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1085 MonoReflectionParamBuilder *pb;
1086 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1087 values [MONO_PARAM_FLAGS] = pb->attrs;
1088 values [MONO_PARAM_SEQUENCE] = i;
1089 if (pb->name != NULL) {
1090 name = mono_string_to_utf8 (pb->name);
1091 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1095 values [MONO_PARAM_NAME] = 0;
1096 values += MONO_PARAM_SIZE;
1097 if (pb->marshal_info) {
1099 alloc_table (mtable, mtable->rows);
1100 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1101 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1102 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1104 pb->table_idx = table->next_idx++;
1111 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1112 MonoReflectionMethodBuilder *mb)
1114 rmb->ilgen = mb->ilgen;
1115 rmb->rtype = mb->rtype;
1116 rmb->parameters = mb->parameters;
1117 rmb->generic_params = mb->generic_params;
1118 rmb->pinfo = mb->pinfo;
1119 rmb->attrs = mb->attrs;
1120 rmb->iattrs = mb->iattrs;
1121 rmb->call_conv = mb->call_conv;
1122 rmb->code = mb->code;
1123 rmb->type = mb->type;
1124 rmb->name = mb->name;
1125 rmb->table_idx = &mb->table_idx;
1126 rmb->init_locals = mb->init_locals;
1127 rmb->return_modreq = mb->return_modreq;
1128 rmb->return_modopt = mb->return_modopt;
1129 rmb->param_modreq = mb->param_modreq;
1130 rmb->param_modopt = mb->param_modopt;
1131 rmb->permissions = mb->permissions;
1132 rmb->mhandle = mb->mhandle;
1138 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1139 MonoReflectionCtorBuilder *mb)
1141 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1143 rmb->ilgen = mb->ilgen;
1144 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1145 rmb->parameters = mb->parameters;
1146 rmb->generic_params = NULL;
1147 rmb->pinfo = mb->pinfo;
1148 rmb->attrs = mb->attrs;
1149 rmb->iattrs = mb->iattrs;
1150 rmb->call_conv = mb->call_conv;
1152 rmb->type = mb->type;
1153 rmb->name = mono_string_new (mono_domain_get (), name);
1154 rmb->table_idx = &mb->table_idx;
1155 rmb->init_locals = mb->init_locals;
1156 rmb->return_modreq = NULL;
1157 rmb->return_modopt = NULL;
1158 rmb->param_modreq = mb->param_modreq;
1159 rmb->param_modopt = mb->param_modopt;
1160 rmb->permissions = mb->permissions;
1161 rmb->mhandle = mb->mhandle;
1167 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1168 MonoReflectionDynamicMethod *mb)
1170 rmb->ilgen = mb->ilgen;
1171 rmb->rtype = mb->rtype;
1172 rmb->parameters = mb->parameters;
1173 rmb->generic_params = NULL;
1175 rmb->attrs = mb->attrs;
1177 rmb->call_conv = mb->call_conv;
1180 rmb->name = mb->name;
1181 rmb->table_idx = NULL;
1182 rmb->init_locals = mb->init_locals;
1183 rmb->return_modreq = NULL;
1184 rmb->return_modopt = NULL;
1185 rmb->param_modreq = NULL;
1186 rmb->param_modopt = NULL;
1187 rmb->permissions = NULL;
1188 rmb->mhandle = mb->mhandle;
1194 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1196 MonoDynamicTable *table;
1199 ReflectionMethodBuilder rmb;
1202 reflection_methodbuilder_from_method_builder (&rmb, mb);
1204 mono_image_basic_method (&rmb, assembly);
1206 if (mb->dll) { /* It's a P/Invoke method */
1208 int charset = mb->charset & 0xf;
1209 int lasterr = mb->charset & 0x40;
1210 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1212 alloc_table (table, table->rows);
1213 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1214 /* map CharSet values to on-disk values */
1216 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1217 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1218 name = mono_string_to_utf8 (mb->dllentry);
1219 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1221 name = mono_string_to_utf8 (mb->dll);
1222 moduleref = string_heap_insert (&assembly->sheap, name);
1224 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1225 table = &assembly->tables [MONO_TABLE_MODULEREF];
1227 alloc_table (table, table->rows);
1228 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1229 values [MONO_IMPLMAP_SCOPE] = table->rows;
1233 if (mb->override_method) {
1234 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1236 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1238 alloc_table (table, table->rows);
1239 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1240 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1241 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1242 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1243 switch (mono_metadata_token_table (tok)) {
1244 case MONO_TABLE_MEMBERREF:
1245 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1247 case MONO_TABLE_METHOD:
1248 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1251 g_assert_not_reached ();
1253 values [MONO_METHODIMPL_DECLARATION] = tok;
1256 if (mb->generic_params) {
1257 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1258 table->rows += mono_array_length (mb->generic_params);
1259 alloc_table (table, table->rows);
1260 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1261 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1263 mono_image_get_generic_param_info (
1264 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1271 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1273 ReflectionMethodBuilder rmb;
1275 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1277 mono_image_basic_method (&rmb, assembly);
1281 type_get_fully_qualified_name (MonoType *type) {
1282 char *name, *result;
1286 name = mono_type_get_name (type);
1287 klass = my_mono_class_from_mono_type (type);
1288 ta = klass->image->assembly;
1290 /* missing public key */
1291 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1292 name, ta->aname.name,
1293 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1294 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
1300 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1304 klass = my_mono_class_from_mono_type (type);
1305 ta = klass->image->assembly;
1306 if (ta == ass || klass->image == mono_defaults.corlib)
1307 return mono_type_get_name (type);
1309 return type_get_fully_qualified_name (type);
1313 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1315 char blob_size [64];
1316 char *b = blob_size;
1321 if (!assembly->save)
1324 p = buf = g_malloc (64);
1326 mono_metadata_encode_value (0x06, p, &p);
1327 /* encode custom attributes before the type */
1328 encode_type (assembly, type, p, &p);
1329 g_assert (p-buf < 64);
1330 mono_metadata_encode_value (p-buf, b, &b);
1331 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1337 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1339 char blob_size [64];
1340 char *b = blob_size;
1345 p = buf = g_malloc (64);
1347 mono_metadata_encode_value (0x06, p, &p);
1348 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1349 /* encode custom attributes before the type */
1350 encode_reflection_type (assembly, fb->type, p, &p);
1351 g_assert (p-buf < 64);
1352 mono_metadata_encode_value (p-buf, b, &b);
1353 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1359 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1360 char blob_size [64];
1361 char *b = blob_size;
1364 guint32 idx = 0, len = 0, dummy = 0;
1366 p = buf = g_malloc (64);
1368 *ret_type = MONO_TYPE_CLASS;
1370 box_val = (char*)&dummy;
1372 box_val = ((char*)val) + sizeof (MonoObject);
1373 *ret_type = val->vtable->klass->byval_arg.type;
1376 switch (*ret_type) {
1377 case MONO_TYPE_BOOLEAN:
1382 case MONO_TYPE_CHAR:
1397 case MONO_TYPE_VALUETYPE:
1398 if (val->vtable->klass->enumtype) {
1399 *ret_type = val->vtable->klass->enum_basetype->type;
1402 g_error ("we can't encode valuetypes");
1403 case MONO_TYPE_CLASS:
1405 case MONO_TYPE_STRING: {
1406 MonoString *str = (MonoString*)val;
1407 /* there is no signature */
1408 len = str->length * 2;
1409 mono_metadata_encode_value (len, b, &b);
1410 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1412 char *swapped = g_malloc (2 * mono_string_length (str));
1413 const char *p = (const char*)mono_string_chars (str);
1415 swap_with_size (swapped, p, 2, mono_string_length (str));
1416 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1420 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1427 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1430 /* there is no signature */
1431 mono_metadata_encode_value (len, b, &b);
1432 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1433 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1434 swap_with_size (blob_size, box_val, len, 1);
1435 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1437 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1445 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1446 char blob_size [64];
1447 char *b = blob_size;
1448 char *p, *buf, *str;
1449 guint32 idx, len, bufsize = 256;
1451 p = buf = g_malloc (bufsize);
1453 switch (minfo->type) {
1454 case MONO_NATIVE_BYVALTSTR:
1455 case MONO_NATIVE_BYVALARRAY:
1456 mono_metadata_encode_value (minfo->type, p, &p);
1457 mono_metadata_encode_value (minfo->count, p, &p);
1459 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1460 case MONO_NATIVE_CUSTOM:
1461 mono_metadata_encode_value (minfo->type, p, &p);
1463 str = mono_string_to_utf8 (minfo->guid);
1465 mono_metadata_encode_value (len, p, &p);
1466 memcpy (p, str, len);
1470 mono_metadata_encode_value (0, p, &p);
1472 if (minfo->marshaltype) {
1473 str = mono_string_to_utf8 (minfo->marshaltype);
1475 mono_metadata_encode_value (len, p, &p);
1476 if (p + len >= buf + bufsize) {
1479 buf = g_realloc (buf, bufsize);
1482 memcpy (p, str, len);
1486 mono_metadata_encode_value (0, p, &p);
1488 if (minfo->marshaltyperef) {
1489 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1491 mono_metadata_encode_value (len, p, &p);
1492 if (p + len >= buf + bufsize) {
1495 buf = g_realloc (buf, bufsize);
1498 memcpy (p, str, len);
1502 mono_metadata_encode_value (0, p, &p);
1504 if (minfo->mcookie) {
1505 str = mono_string_to_utf8 (minfo->mcookie);
1507 mono_metadata_encode_value (len, p, &p);
1508 if (p + len >= buf + bufsize) {
1511 buf = g_realloc (buf, bufsize);
1514 memcpy (p, str, len);
1518 mono_metadata_encode_value (0, p, &p);
1522 mono_metadata_encode_value (minfo->type, p, &p);
1526 mono_metadata_encode_value (len, b, &b);
1527 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1533 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1535 MonoDynamicTable *table;
1539 /* maybe this fixup should be done in the C# code */
1540 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1541 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1542 table = &assembly->tables [MONO_TABLE_FIELD];
1543 fb->table_idx = table->next_idx ++;
1544 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1545 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1546 name = mono_string_to_utf8 (fb->name);
1547 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1549 values [MONO_FIELD_FLAGS] = fb->attrs;
1550 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1552 if (fb->offset != -1) {
1553 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1555 alloc_table (table, table->rows);
1556 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1557 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1558 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1560 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1561 guint32 field_type = 0;
1562 table = &assembly->tables [MONO_TABLE_CONSTANT];
1564 alloc_table (table, table->rows);
1565 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1566 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1567 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1568 values [MONO_CONSTANT_TYPE] = field_type;
1569 values [MONO_CONSTANT_PADDING] = 0;
1571 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1573 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1575 alloc_table (table, table->rows);
1576 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1577 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1579 * We store it in the code section because it's simpler for now.
1582 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1584 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1585 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1587 if (fb->marshal_info) {
1588 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1590 alloc_table (table, table->rows);
1591 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1592 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1593 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1598 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1602 char *b = blob_size;
1603 guint32 nparams = 0;
1604 MonoReflectionMethodBuilder *mb = fb->get_method;
1605 MonoReflectionMethodBuilder *smb = fb->set_method;
1606 guint32 idx, i, size;
1608 if (mb && mb->parameters)
1609 nparams = mono_array_length (mb->parameters);
1610 if (!mb && smb && smb->parameters)
1611 nparams = mono_array_length (smb->parameters) - 1;
1612 size = 24 + nparams * 10;
1613 buf = p = g_malloc (size);
1616 mono_metadata_encode_value (nparams, p, &p);
1618 encode_reflection_type (assembly, mb->rtype, p, &p);
1619 for (i = 0; i < nparams; ++i) {
1620 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1621 encode_reflection_type (assembly, pt, p, &p);
1624 /* the property type is the last param */
1625 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1626 for (i = 0; i < nparams; ++i) {
1627 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1628 encode_reflection_type (assembly, pt, p, &p);
1632 g_assert (p - buf < size);
1633 mono_metadata_encode_value (p-buf, b, &b);
1634 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1640 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1642 MonoDynamicTable *table;
1645 guint num_methods = 0;
1649 * we need to set things in the following tables:
1650 * PROPERTYMAP (info already filled in _get_type_info ())
1651 * PROPERTY (rows already preallocated in _get_type_info ())
1652 * METHOD (method info already done with the generic method code)
1655 table = &assembly->tables [MONO_TABLE_PROPERTY];
1656 pb->table_idx = table->next_idx ++;
1657 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1658 name = mono_string_to_utf8 (pb->name);
1659 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1661 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1662 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1664 /* FIXME: we still don't handle 'other' methods */
1665 if (pb->get_method) num_methods ++;
1666 if (pb->set_method) num_methods ++;
1668 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1669 table->rows += num_methods;
1670 alloc_table (table, table->rows);
1672 if (pb->get_method) {
1673 semaidx = table->next_idx ++;
1674 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1675 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1676 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1677 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1679 if (pb->set_method) {
1680 semaidx = table->next_idx ++;
1681 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1682 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1683 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1684 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1689 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1691 MonoDynamicTable *table;
1694 guint num_methods = 0;
1698 * we need to set things in the following tables:
1699 * EVENTMAP (info already filled in _get_type_info ())
1700 * EVENT (rows already preallocated in _get_type_info ())
1701 * METHOD (method info already done with the generic method code)
1704 table = &assembly->tables [MONO_TABLE_EVENT];
1705 eb->table_idx = table->next_idx ++;
1706 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1707 name = mono_string_to_utf8 (eb->name);
1708 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1710 values [MONO_EVENT_FLAGS] = eb->attrs;
1711 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1714 * FIXME: we still don't handle 'other' methods
1716 if (eb->add_method) num_methods ++;
1717 if (eb->remove_method) num_methods ++;
1718 if (eb->raise_method) num_methods ++;
1720 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1721 table->rows += num_methods;
1722 alloc_table (table, table->rows);
1724 if (eb->add_method) {
1725 semaidx = table->next_idx ++;
1726 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1727 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1728 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1729 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1731 if (eb->remove_method) {
1732 semaidx = table->next_idx ++;
1733 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1734 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1735 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1736 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1738 if (eb->raise_method) {
1739 semaidx = table->next_idx ++;
1740 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1741 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1742 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1743 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1748 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1750 MonoDynamicTable *table;
1751 guint32 num_constraints, i;
1755 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1756 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1757 table->rows += num_constraints;
1758 alloc_table (table, table->rows);
1760 for (i = 0; i < num_constraints; i++) {
1761 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1763 table_idx = table->next_idx ++;
1764 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1766 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1767 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1772 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1774 MonoDynamicTable *table;
1775 MonoGenericParam *param;
1779 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1780 table_idx = table->next_idx ++;
1781 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1783 param = gparam->type.type->data.generic_param;
1785 values [MONO_GENERICPARAM_OWNER] = owner;
1786 values [MONO_GENERICPARAM_FLAGS] = param->flags;
1787 values [MONO_GENERICPARAM_NUMBER] = param->num;
1788 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1789 values [MONO_GENERICPARAM_KIND] = 0;
1790 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1792 if (gparam->constraints)
1793 encode_constraints (gparam, table_idx, assembly);
1797 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1799 MonoDynamicTable *table;
1802 guint32 cols [MONO_ASSEMBLY_SIZE];
1806 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1809 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1810 table = &assembly->tables [MONO_TABLE_MODULEREF];
1811 token = table->next_idx ++;
1813 alloc_table (table, table->rows);
1814 values = table->values + token * MONO_MODULEREF_SIZE;
1815 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1817 token <<= RESOLTION_SCOPE_BITS;
1818 token |= RESOLTION_SCOPE_MODULEREF;
1819 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1824 if (image->assembly->dynamic)
1826 memset (cols, 0, sizeof (cols));
1828 /* image->assembly->image is the manifest module */
1829 image = image->assembly->image;
1830 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1833 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1834 token = table->next_idx ++;
1836 alloc_table (table, table->rows);
1837 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1838 if (strcmp ("corlib", image->assembly_name) == 0)
1839 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1841 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1842 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1843 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1844 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1845 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1846 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1847 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1848 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1850 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1851 guchar pubtoken [9];
1853 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1854 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1857 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1858 * This is currently only a problem with references to System.Xml (see bug#27706),
1859 * but there may be other cases that makes this necessary. Note, we need to set
1860 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1861 * recognized by ms, yuck!
1862 * FIXME: need to add more assembly names, as needed.
1864 if (strcmp (image->assembly_name, "corlib") == 0 ||
1865 strcmp (image->assembly_name, "mscorlib") == 0 ||
1866 strcmp (image->assembly_name, "System") == 0 ||
1867 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1868 strcmp (image->assembly_name, "System.Xml") == 0 ||
1869 strcmp (image->assembly_name, "System.Data") == 0 ||
1870 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1871 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1872 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1873 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1874 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1875 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1876 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1877 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1878 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1879 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1880 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1881 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1882 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1883 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1884 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1885 strcmp (image->assembly_name, "System.Design") == 0 ||
1886 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1887 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1888 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1889 strcmp (image->assembly_name, "System.Management") == 0 ||
1890 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1891 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1892 strcmp (image->assembly_name, "System.Security") == 0 ||
1893 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1894 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1895 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1896 strcmp (image->assembly_name, "System.Web") == 0) {
1897 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1898 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1899 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1900 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1902 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1905 token <<= RESOLTION_SCOPE_BITS;
1906 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1907 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1912 create_typespec (MonoDynamicImage *assembly, MonoType *type)
1914 MonoDynamicTable *table;
1920 char *b = blob_size;
1922 switch (type->type) {
1923 case MONO_TYPE_FNPTR:
1925 case MONO_TYPE_SZARRAY:
1926 case MONO_TYPE_ARRAY:
1928 case MONO_TYPE_MVAR:
1929 case MONO_TYPE_GENERICINST:
1930 encode_type (assembly, type, p, &p);
1932 case MONO_TYPE_CLASS:
1933 case MONO_TYPE_VALUETYPE: {
1934 MonoClass *k = mono_class_from_mono_type (type);
1935 if (!k || !k->generic_inst)
1937 encode_generic_inst (assembly, k->generic_inst, p, &p);
1944 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1945 if (assembly->save) {
1946 g_assert (p-sig < 128);
1947 mono_metadata_encode_value (p-sig, b, &b);
1948 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1949 alloc_table (table, table->rows + 1);
1950 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1951 values [MONO_TYPESPEC_SIGNATURE] = token;
1954 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1955 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1961 * Despite the name, we handle also TypeSpec (with the above helper).
1964 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
1966 MonoDynamicTable *table;
1968 guint32 token, scope, enclosing;
1971 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1974 token = create_typespec (assembly, type);
1977 klass = my_mono_class_from_mono_type (type);
1979 klass = mono_class_from_mono_type (type);
1982 * If it's in the same module and not a generic type parameter:
1984 if ((klass->image == &assembly->image) &&
1985 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
1986 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1987 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1988 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1992 if (klass->nested_in) {
1993 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1994 /* get the typeref idx of the enclosing type */
1995 enclosing >>= TYPEDEFORREF_BITS;
1996 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1998 scope = resolution_scope_from_image (assembly, klass->image);
2000 table = &assembly->tables [MONO_TABLE_TYPEREF];
2001 if (assembly->save) {
2002 alloc_table (table, table->rows + 1);
2003 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2004 values [MONO_TYPEREF_SCOPE] = scope;
2005 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2006 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2008 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2009 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2011 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2016 * Insert a memberef row into the metadata: the token that point to the memberref
2017 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2018 * mono_image_get_fieldref_token()).
2019 * The sig param is an index to an already built signature.
2022 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2024 MonoDynamicTable *table;
2026 guint32 token, pclass;
2029 parent = mono_image_typedef_or_ref (assembly, type);
2030 switch (parent & TYPEDEFORREF_MASK) {
2031 case TYPEDEFORREF_TYPEREF:
2032 pclass = MEMBERREF_PARENT_TYPEREF;
2034 case TYPEDEFORREF_TYPESPEC:
2035 pclass = MEMBERREF_PARENT_TYPESPEC;
2037 case TYPEDEFORREF_TYPEDEF:
2038 pclass = MEMBERREF_PARENT_TYPEDEF;
2041 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2044 /* extract the index */
2045 parent >>= TYPEDEFORREF_BITS;
2047 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2049 if (assembly->save) {
2050 alloc_table (table, table->rows + 1);
2051 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2052 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2053 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2054 values [MONO_MEMBERREF_SIGNATURE] = sig;
2057 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2064 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2068 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2071 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2072 method->name, method_encode_signature (assembly, method->signature));
2073 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2078 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2081 ReflectionMethodBuilder rmb;
2083 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2087 reflection_methodbuilder_from_method_builder (&rmb, mb);
2089 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2090 mono_string_to_utf8 (rmb.name),
2091 method_builder_encode_signature (assembly, &rmb));
2092 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2097 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2100 ReflectionMethodBuilder rmb;
2102 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2106 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2108 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2109 mono_string_to_utf8 (rmb.name),
2110 method_builder_encode_signature (assembly, &rmb));
2111 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2116 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass)
2121 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
2124 field->parent = klass;
2125 type = field->generic_type ? field->generic_type : field->type;
2126 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
2127 field->name, fieldref_encode_signature (assembly, type));
2128 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
2133 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2138 guint32 nparams = gmethod->mtype_argc;
2139 guint32 size = 10 + nparams * 10;
2142 char *b = blob_size;
2144 if (!assembly->save)
2147 p = buf = g_malloc (size);
2149 * FIXME: vararg, explicit_this, differenc call_conv values...
2151 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2152 mono_metadata_encode_value (nparams, p, &p);
2154 for (i = 0; i < nparams; i++)
2155 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2158 g_assert (p - buf < size);
2159 mono_metadata_encode_value (p-buf, b, &b);
2160 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2166 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2168 MonoDynamicTable *table;
2170 guint32 token, mtoken = 0, sig;
2171 MonoGenericMethod *gmethod;
2172 MonoMethod *declaring;
2174 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2176 g_assert ((gmethod = method->signature->gen_method) != NULL);
2177 declaring = gmethod->generic_method;
2178 if (declaring->signature->gen_method)
2179 declaring = declaring->signature->gen_method->generic_method;
2180 sig = method_encode_signature (assembly, declaring->signature);
2181 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2182 declaring->name, sig);
2184 if (!gmethod->generic_method->signature->generic_param_count)
2187 switch (mono_metadata_token_table (mtoken)) {
2188 case MONO_TABLE_MEMBERREF:
2189 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2191 case MONO_TABLE_METHOD:
2192 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2195 g_assert_not_reached ();
2198 sig = encode_generic_method_sig (assembly, gmethod);
2200 if (assembly->save) {
2201 alloc_table (table, table->rows + 1);
2202 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2203 values [MONO_METHODSPEC_METHOD] = mtoken;
2204 values [MONO_METHODSPEC_SIGNATURE] = sig;
2207 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2214 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2216 MonoGenericMethod *gmethod;
2219 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2223 g_assert ((gmethod = m->signature->gen_method) != NULL);
2225 if (gmethod->generic_method->signature->generic_param_count)
2226 token = method_encode_methodspec (assembly, m);
2228 guint32 sig = method_encode_signature (assembly, gmethod->generic_method->signature);
2229 token = mono_image_get_memberref_token (
2230 assembly, &m->klass->byval_arg, gmethod->generic_method->name, sig);
2233 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2238 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2240 MonoDynamicTable *table;
2247 char *b = blob_size;
2250 g_assert (tb->generic_params);
2251 klass = mono_class_from_mono_type (tb->type.type);
2253 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2254 encode_type (assembly, &klass->byval_arg, p, &p);
2256 count = mono_array_length (tb->generic_params);
2257 mono_metadata_encode_value (count, p, &p);
2258 for (i = 0; i < count; i++) {
2259 MonoReflectionGenericParam *gparam;
2261 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2263 encode_type (assembly, gparam->type.type, p, &p);
2266 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2267 if (assembly->save) {
2268 g_assert (p-sig < 128);
2269 mono_metadata_encode_value (p-sig, b, &b);
2270 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2271 alloc_table (table, table->rows + 1);
2272 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2273 values [MONO_TYPESPEC_SIGNATURE] = token;
2276 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2277 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2283 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2285 MonoDynamicTable *table;
2288 guint32 token, pclass, parent, sig;
2291 klass = mono_class_from_mono_type (fb->typeb->type);
2292 name = mono_string_to_utf8 (fb->name);
2294 sig = fieldref_encode_signature (assembly, fb->type->type);
2296 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2297 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2299 pclass = MEMBERREF_PARENT_TYPESPEC;
2300 parent >>= TYPEDEFORREF_BITS;
2302 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2304 if (assembly->save) {
2305 alloc_table (table, table->rows + 1);
2306 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2307 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2308 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2309 values [MONO_MEMBERREF_SIGNATURE] = sig;
2312 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2319 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2327 char *b = blob_size;
2329 if (!assembly->save)
2333 g_assert (helper->type == 2);
2335 if (helper->arguments)
2336 nargs = mono_array_length (helper->arguments);
2340 size = 10 + (nargs * 10);
2342 p = buf = g_malloc (size);
2344 /* Encode calling convention */
2345 /* Change Any to Standard */
2346 if ((helper->call_conv & 0x03) == 0x03)
2347 helper->call_conv = 0x01;
2348 /* explicit_this implies has_this */
2349 if (helper->call_conv & 0x40)
2350 helper->call_conv &= 0x20;
2352 if (helper->call_conv == 0) /* Unmanaged */
2353 *p = helper->unmanaged_call_conv - 1;
2356 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2357 if (helper->call_conv & 0x02) /* varargs */
2362 mono_metadata_encode_value (nargs, p, &p);
2363 encode_reflection_type (assembly, helper->return_type, p, &p);
2364 for (i = 0; i < nargs; ++i) {
2365 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2366 encode_reflection_type (assembly, pt, p, &p);
2369 g_assert (p - buf < size);
2370 mono_metadata_encode_value (p-buf, b, &b);
2371 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2378 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2381 MonoDynamicTable *table;
2384 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2385 idx = table->next_idx ++;
2387 alloc_table (table, table->rows);
2388 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2390 values [MONO_STAND_ALONE_SIGNATURE] =
2391 mono_reflection_encode_sighelper (assembly, helper);
2397 reflection_cc_to_file (int call_conv) {
2398 switch (call_conv & 0x3) {
2400 case 1: return MONO_CALL_DEFAULT;
2401 case 2: return MONO_CALL_VARARG;
2403 g_assert_not_reached ();
2410 MonoMethodSignature *sig;
2416 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2421 MonoMethodSignature *sig;
2424 name = mono_string_to_utf8 (m->name);
2425 nparams = mono_array_length (m->parameters);
2426 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2428 sig->call_convention = reflection_cc_to_file (m->call_conv);
2429 sig->param_count = nparams;
2430 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2431 for (i = 0; i < nparams; ++i) {
2432 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2433 sig->params [i] = t->type;
2436 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2438 if (strcmp (name, am->name) == 0 &&
2439 mono_metadata_type_equal (am->parent, m->parent->type) &&
2440 mono_metadata_signature_equal (am->sig, sig)) {
2443 m->table_idx = am->token & 0xffffff;
2447 am = g_new0 (ArrayMethod, 1);
2450 am->parent = m->parent->type;
2451 am->token = mono_image_get_memberref_token (assembly, am->parent,
2452 name, method_encode_signature (assembly, sig));
2453 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2454 m->table_idx = am->token & 0xffffff;
2459 * Insert into the metadata tables all the info about the TypeBuilder tb.
2460 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2463 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2465 MonoDynamicTable *table;
2467 int i, is_object = 0, is_system = 0;
2470 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2471 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2472 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2473 n = mono_string_to_utf8 (tb->name);
2474 if (strcmp (n, "Object") == 0)
2476 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2478 n = mono_string_to_utf8 (tb->nspace);
2479 if (strcmp (n, "System") == 0)
2481 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2483 if (tb->parent && !(is_system && is_object) &&
2484 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2485 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2487 values [MONO_TYPEDEF_EXTENDS] = 0;
2488 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2489 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2492 * if we have explicitlayout or sequentiallayouts, output data in the
2493 * ClassLayout table.
2495 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2496 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2498 alloc_table (table, table->rows);
2499 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2500 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2501 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2502 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2505 /* handle interfaces */
2506 if (tb->interfaces) {
2507 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2509 table->rows += mono_array_length (tb->interfaces);
2510 alloc_table (table, table->rows);
2511 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2512 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2513 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2514 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2515 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2516 values += MONO_INTERFACEIMPL_SIZE;
2520 /* handle generic parameters */
2521 if (tb->generic_params) {
2522 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2523 table->rows += mono_array_length (tb->generic_params);
2524 alloc_table (table, table->rows);
2525 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2526 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2528 mono_image_get_generic_param_info (
2529 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2535 table = &assembly->tables [MONO_TABLE_FIELD];
2536 table->rows += tb->num_fields;
2537 alloc_table (table, table->rows);
2538 for (i = 0; i < tb->num_fields; ++i)
2539 mono_image_get_field_info (
2540 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2543 /* handle constructors */
2545 table = &assembly->tables [MONO_TABLE_METHOD];
2546 table->rows += mono_array_length (tb->ctors);
2547 alloc_table (table, table->rows);
2548 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2549 mono_image_get_ctor_info (domain,
2550 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2553 /* handle methods */
2555 table = &assembly->tables [MONO_TABLE_METHOD];
2556 table->rows += tb->num_methods;
2557 alloc_table (table, table->rows);
2558 for (i = 0; i < tb->num_methods; ++i)
2559 mono_image_get_method_info (
2560 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2563 /* Do the same with properties etc.. */
2564 if (tb->events && mono_array_length (tb->events)) {
2565 table = &assembly->tables [MONO_TABLE_EVENT];
2566 table->rows += mono_array_length (tb->events);
2567 alloc_table (table, table->rows);
2568 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2570 alloc_table (table, table->rows);
2571 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2572 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2573 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2574 for (i = 0; i < mono_array_length (tb->events); ++i)
2575 mono_image_get_event_info (
2576 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2578 if (tb->properties && mono_array_length (tb->properties)) {
2579 table = &assembly->tables [MONO_TABLE_PROPERTY];
2580 table->rows += mono_array_length (tb->properties);
2581 alloc_table (table, table->rows);
2582 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2584 alloc_table (table, table->rows);
2585 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2586 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2587 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2588 for (i = 0; i < mono_array_length (tb->properties); ++i)
2589 mono_image_get_property_info (
2590 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2593 mono_image_add_decl_security (assembly,
2594 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2598 MonoDynamicTable *ntable;
2600 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2601 ntable->rows += mono_array_length (tb->subtypes);
2602 alloc_table (ntable, ntable->rows);
2603 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2605 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2606 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2608 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2609 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2610 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2611 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2612 mono_string_to_utf8 (tb->name), tb->table_idx,
2613 ntable->next_idx, ntable->rows);*/
2614 values += MONO_NESTED_CLASS_SIZE;
2621 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2625 g_ptr_array_add (types, type);
2627 if (!type->subtypes)
2630 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2631 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2632 collect_types (types, subtype);
2637 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2638 MonoReflectionTypeBuilder **type2)
2640 if ((*type1)->table_idx < (*type2)->table_idx)
2643 if ((*type1)->table_idx > (*type2)->table_idx)
2650 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2655 for (i = 0; i < mono_array_length (pinfo); ++i) {
2656 MonoReflectionParamBuilder *pb;
2657 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2660 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2665 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2668 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2670 for (i = 0; i < tb->num_fields; ++i) {
2671 MonoReflectionFieldBuilder* fb;
2672 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2673 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2677 for (i = 0; i < mono_array_length (tb->events); ++i) {
2678 MonoReflectionEventBuilder* eb;
2679 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2680 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2683 if (tb->properties) {
2684 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2685 MonoReflectionPropertyBuilder* pb;
2686 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2687 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2691 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2692 MonoReflectionCtorBuilder* cb;
2693 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2694 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2695 params_add_cattrs (assembly, cb->pinfo);
2700 for (i = 0; i < tb->num_methods; ++i) {
2701 MonoReflectionMethodBuilder* mb;
2702 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2703 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2704 params_add_cattrs (assembly, mb->pinfo);
2709 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2710 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2715 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2718 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2720 /* no types in the module */
2724 for (i = 0; i < mb->num_types; ++i)
2725 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2729 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2730 MonoDynamicImage *assembly)
2732 MonoDynamicTable *table;
2736 char *b = blob_size;
2739 table = &assembly->tables [MONO_TABLE_FILE];
2741 alloc_table (table, table->rows);
2742 values = table->values + table->next_idx * MONO_FILE_SIZE;
2743 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2744 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2745 if (module->image->dynamic) {
2746 /* This depends on the fact that the main module is emitted last */
2747 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2748 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2752 path = g_strdup (module->image->name);
2754 mono_sha1_get_digest_from_file (path, hash);
2757 mono_metadata_encode_value (20, b, &b);
2758 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2759 mono_image_add_stream_data (&assembly->blob, hash, 20);
2764 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2766 MonoDynamicTable *table;
2770 table = &assembly->tables [MONO_TABLE_MODULE];
2771 mb->table_idx = table->next_idx ++;
2772 name = mono_string_to_utf8 (mb->module.name);
2773 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2775 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2778 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2779 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2780 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2784 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2785 guint32 module_index, guint32 parent_index,
2786 MonoDynamicImage *assembly)
2788 MonoDynamicTable *table;
2792 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2793 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2796 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2798 alloc_table (table, table->rows);
2799 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2801 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2802 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2803 if (klass->nested_in)
2804 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2806 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2807 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2808 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2810 res = table->next_idx;
2814 /* Emit nested types */
2815 if (klass->nested_classes) {
2818 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2819 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2826 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2827 guint32 module_index, guint32 parent_index,
2828 MonoDynamicImage *assembly)
2833 klass = mono_class_from_mono_type (tb->type.type);
2835 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
2837 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
2838 parent_index, assembly);
2842 * We need to do this ourselves since klass->nested_classes is not set up.
2845 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2846 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
2851 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
2852 guint32 module_index,
2853 MonoDynamicImage *assembly)
2855 MonoImage *image = module->image;
2859 t = &image->tables [MONO_TABLE_TYPEDEF];
2861 for (i = 0; i < t->rows; ++i) {
2862 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
2864 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
2865 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
2869 #define align_pointer(base,p)\
2871 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2873 (p) += 4 - (__diff & 3);\
2877 compare_semantics (const void *a, const void *b)
2879 const guint32 *a_values = a;
2880 const guint32 *b_values = b;
2881 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2884 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2888 compare_custom_attrs (const void *a, const void *b)
2890 const guint32 *a_values = a;
2891 const guint32 *b_values = b;
2893 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2897 compare_field_marshal (const void *a, const void *b)
2899 const guint32 *a_values = a;
2900 const guint32 *b_values = b;
2902 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2906 compare_nested (const void *a, const void *b)
2908 const guint32 *a_values = a;
2909 const guint32 *b_values = b;
2911 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2915 * build_compressed_metadata() fills in the blob of data that represents the
2916 * raw metadata as it will be saved in the PE file. The five streams are output
2917 * and the metadata tables are comnpressed from the guint32 array representation,
2918 * to the compressed on-disk format.
2921 build_compressed_metadata (MonoDynamicImage *assembly)
2923 MonoDynamicTable *table;
2925 guint64 valid_mask = 0;
2926 guint64 sorted_mask;
2927 guint32 heapt_size = 0;
2928 guint32 meta_size = 256; /* allow for header and other stuff */
2929 guint32 table_offset;
2930 guint32 ntables = 0;
2939 MonoDynamicStream *stream;
2942 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
2943 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2944 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
2945 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
2946 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
2948 /* tables that are sorted */
2949 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2950 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2951 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2952 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2953 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2954 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2956 /* Compute table sizes */
2957 /* the MonoImage has already been created in mono_image_basic_init() */
2958 meta = &assembly->image;
2960 /* Setup the info used by compute_sizes () */
2961 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2962 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2963 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2965 meta_size += assembly->blob.index;
2966 meta_size += assembly->guid.index;
2967 meta_size += assembly->sheap.index;
2968 meta_size += assembly->us.index;
2970 for (i=0; i < 64; ++i)
2971 meta->tables [i].rows = assembly->tables [i].rows;
2973 for (i = 0; i < 64; i++){
2974 if (meta->tables [i].rows == 0)
2976 valid_mask |= (guint64)1 << i;
2978 meta->tables [i].row_size = mono_metadata_compute_size (
2979 meta, i, &meta->tables [i].size_bitfield);
2980 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2982 heapt_size += 24; /* #~ header size */
2983 heapt_size += ntables * 4;
2984 meta_size += heapt_size;
2985 meta->raw_metadata = g_malloc0 (meta_size);
2986 p = meta->raw_metadata;
2987 /* the metadata signature */
2988 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2989 /* version numbers and 4 bytes reserved */
2990 int16val = (guint16*)p;
2991 *int16val++ = GUINT16_TO_LE (1);
2992 *int16val = GUINT16_TO_LE (1);
2994 /* version string */
2995 int32val = (guint32*)p;
2996 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
2998 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
2999 p += GUINT32_FROM_LE (*int32val);
3000 align_pointer (meta->raw_metadata, p);
3001 int16val = (guint16*)p;
3002 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3003 *int16val = GUINT16_TO_LE (5); /* number of streams */
3007 * write the stream info.
3009 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3010 table_offset += 3; table_offset &= ~3;
3012 assembly->tstream.index = heapt_size;
3013 for (i = 0; i < 5; ++i) {
3014 int32val = (guint32*)p;
3015 stream_desc [i].stream->offset = table_offset;
3016 *int32val++ = GUINT32_TO_LE (table_offset);
3017 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3018 table_offset += GUINT32_FROM_LE (*int32val);
3019 table_offset += 3; table_offset &= ~3;
3021 strcpy (p, stream_desc [i].name);
3022 p += strlen (stream_desc [i].name) + 1;
3023 align_pointer (meta->raw_metadata, p);
3026 * now copy the data, the table stream header and contents goes first.
3028 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3029 p = meta->raw_metadata + assembly->tstream.offset;
3030 int32val = (guint32*)p;
3031 *int32val = GUINT32_TO_LE (0); /* reserved */
3033 *p++ = 1; /* version */
3035 if (meta->idx_string_wide)
3037 if (meta->idx_guid_wide)
3039 if (meta->idx_blob_wide)
3042 *p++ = 0; /* reserved */
3043 int64val = (guint64*)p;
3044 *int64val++ = GUINT64_TO_LE (valid_mask);
3045 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3047 int32val = (guint32*)p;
3048 for (i = 0; i < 64; i++){
3049 if (meta->tables [i].rows == 0)
3051 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3053 p = (unsigned char*)int32val;
3055 /* sort the tables that still need sorting */
3056 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3058 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3059 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3061 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3062 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3064 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3065 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3067 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3069 /* compress the tables */
3070 for (i = 0; i < 64; i++){
3073 guint32 bitfield = meta->tables [i].size_bitfield;
3074 if (!meta->tables [i].rows)
3076 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3077 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3078 meta->tables [i].base = p;
3079 for (row = 1; row <= meta->tables [i].rows; ++row) {
3080 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3081 for (col = 0; col < assembly->tables [i].columns; ++col) {
3082 switch (mono_metadata_table_size (bitfield, col)) {
3084 *p++ = values [col];
3087 *p++ = values [col] & 0xff;
3088 *p++ = (values [col] >> 8) & 0xff;
3091 *p++ = values [col] & 0xff;
3092 *p++ = (values [col] >> 8) & 0xff;
3093 *p++ = (values [col] >> 16) & 0xff;
3094 *p++ = (values [col] >> 24) & 0xff;
3097 g_assert_not_reached ();
3101 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3104 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3105 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3106 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3107 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3108 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3110 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3114 * Some tables in metadata need to be sorted according to some criteria, but
3115 * when methods and fields are first created with reflection, they may be assigned a token
3116 * that doesn't correspond to the final token they will get assigned after the sorting.
3117 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3118 * with the reflection objects that represent them. Once all the tables are set up, the
3119 * reflection objects will contains the correct table index. fixup_method() will fixup the
3120 * tokens for the method with ILGenerator @ilgen.
3123 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3124 guint32 code_idx = GPOINTER_TO_UINT (value);
3125 MonoReflectionILTokenInfo *iltoken;
3126 MonoReflectionFieldBuilder *field;
3127 MonoReflectionCtorBuilder *ctor;
3128 MonoReflectionMethodBuilder *method;
3129 MonoReflectionTypeBuilder *tb;
3130 MonoReflectionArrayMethod *am;
3132 unsigned char *target;
3134 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3135 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3136 target = assembly->code.data + code_idx + iltoken->code_pos;
3137 switch (target [3]) {
3138 case MONO_TABLE_FIELD:
3139 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3140 field = (MonoReflectionFieldBuilder *)iltoken->member;
3141 idx = field->table_idx;
3142 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3143 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3144 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3146 g_assert_not_reached ();
3149 case MONO_TABLE_METHOD:
3150 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3151 method = (MonoReflectionMethodBuilder *)iltoken->member;
3152 idx = method->table_idx;
3153 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3154 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3155 idx = ctor->table_idx;
3156 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3157 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3158 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3159 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3161 g_assert_not_reached ();
3164 case MONO_TABLE_TYPEDEF:
3165 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3166 g_assert_not_reached ();
3167 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3168 idx = tb->table_idx;
3170 case MONO_TABLE_MEMBERREF:
3171 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3172 am = (MonoReflectionArrayMethod*)iltoken->member;
3173 idx = am->table_idx;
3174 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3175 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3176 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3177 g_assert (m->klass->generic_inst);
3179 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3181 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3182 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3183 g_assert (f->generic_type);
3186 g_assert_not_reached ();
3189 case MONO_TABLE_METHODSPEC:
3190 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3191 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3192 g_assert (m->signature->generic_param_count);
3195 g_assert_not_reached ();
3199 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3201 target [0] = idx & 0xff;
3202 target [1] = (idx >> 8) & 0xff;
3203 target [2] = (idx >> 16) & 0xff;
3210 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3211 * value is not known when the table is emitted.
3214 fixup_cattrs (MonoDynamicImage *assembly)
3216 MonoDynamicTable *table;
3218 guint32 type, i, idx, token;
3221 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3223 for (i = 0; i < table->rows; ++i) {
3224 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3226 type = values [MONO_CUSTOM_ATTR_TYPE];
3227 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3228 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3229 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3230 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3233 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3234 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3235 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3236 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3243 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3245 MonoDynamicTable *table;
3249 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3251 alloc_table (table, table->rows);
3252 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3253 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3254 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3255 name = mono_string_to_utf8 (rsrc->name);
3256 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3258 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3263 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3265 MonoDynamicTable *table;
3269 char *b = blob_size;
3271 guint32 idx, offset;
3273 if (rsrc->filename) {
3274 name = mono_string_to_utf8 (rsrc->filename);
3275 sname = g_path_get_basename (name);
3277 table = &assembly->tables [MONO_TABLE_FILE];
3279 alloc_table (table, table->rows);
3280 values = table->values + table->next_idx * MONO_FILE_SIZE;
3281 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3282 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3285 mono_sha1_get_digest_from_file (name, hash);
3286 mono_metadata_encode_value (20, b, &b);
3287 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3288 mono_image_add_stream_data (&assembly->blob, hash, 20);
3290 idx = table->next_idx++;
3292 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3295 offset = mono_array_length (rsrc->data);
3296 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3297 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3298 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3299 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3303 * The entry should be emitted into the MANIFESTRESOURCE table of
3304 * the main module, but that needs to reference the FILE table
3305 * which isn't emitted yet.
3312 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3316 set_version_from_string (MonoString *version, guint32 *values)
3318 gchar *ver, *p, *str;
3321 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3322 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3323 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3324 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3327 ver = str = mono_string_to_utf8 (version);
3328 for (i = 0; i < 4; ++i) {
3329 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3335 /* handle Revision and Build */
3345 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3349 char *b = blob_size;
3354 len = mono_array_length (pkey);
3355 mono_metadata_encode_value (len, b, &b);
3356 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3357 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3359 /* need to get the actual value from the key type... */
3360 assembly->strong_name_size = 128;
3361 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3367 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3369 MonoDynamicTable *table;
3370 MonoDynamicImage *assembly;
3371 MonoReflectionAssemblyBuilder *assemblyb;
3376 guint32 module_index;
3378 assemblyb = moduleb->assemblyb;
3379 assembly = moduleb->dynamic_image;
3380 domain = mono_object_domain (assemblyb);
3382 /* Emit ASSEMBLY table */
3383 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3384 alloc_table (table, 1);
3385 values = table->values + MONO_ASSEMBLY_SIZE;
3386 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3387 name = mono_string_to_utf8 (assemblyb->name);
3388 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3390 if (assemblyb->culture) {
3391 name = mono_string_to_utf8 (assemblyb->culture);
3392 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3395 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3397 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3398 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3399 set_version_from_string (assemblyb->version, values);
3401 /* Emit FILE + EXPORTED_TYPE table */
3403 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3405 MonoReflectionModuleBuilder *file_module =
3406 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3407 if (file_module != moduleb) {
3408 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3410 if (file_module->types) {
3411 for (j = 0; j < file_module->num_types; ++j) {
3412 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3413 mono_image_fill_export_table (domain, tb, module_index, 0,
3419 if (assemblyb->loaded_modules) {
3420 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3421 MonoReflectionModule *file_module =
3422 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3423 mono_image_fill_file_table (domain, file_module, assembly);
3425 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3429 /* Emit MANIFESTRESOURCE table */
3431 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3433 MonoReflectionModuleBuilder *file_module =
3434 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3435 /* The table for the main module is emitted later */
3436 if (file_module != moduleb) {
3438 if (file_module->resources) {
3439 int len = mono_array_length (file_module->resources);
3440 for (j = 0; j < len; ++j) {
3441 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3442 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3450 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3451 * for the modulebuilder @moduleb.
3452 * At the end of the process, method and field tokens are fixed up and the
3453 * on-disk compressed metadata representation is created.
3456 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3458 MonoDynamicTable *table;
3459 MonoDynamicImage *assembly;
3460 MonoReflectionAssemblyBuilder *assemblyb;
3465 assemblyb = moduleb->assemblyb;
3466 assembly = moduleb->dynamic_image;
3467 domain = mono_object_domain (assemblyb);
3469 if (assembly->text_rva)
3472 assembly->text_rva = START_TEXT_RVA;
3474 if (moduleb->is_main) {
3475 mono_image_emit_manifest (moduleb);
3478 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3479 table->rows = 1; /* .<Module> */
3481 alloc_table (table, table->rows);
3483 * Set the first entry.
3485 values = table->values + table->columns;
3486 values [MONO_TYPEDEF_FLAGS] = 0;
3487 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3488 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3489 values [MONO_TYPEDEF_EXTENDS] = 0;
3490 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3491 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3494 * handle global methods
3495 * FIXME: test what to do when global methods are defined in multiple modules.
3497 if (moduleb->global_methods) {
3498 table = &assembly->tables [MONO_TABLE_METHOD];
3499 table->rows += mono_array_length (moduleb->global_methods);
3500 alloc_table (table, table->rows);
3501 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3502 mono_image_get_method_info (
3503 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3505 if (moduleb->global_fields) {
3506 table = &assembly->tables [MONO_TABLE_FIELD];
3507 table->rows += mono_array_length (moduleb->global_fields);
3508 alloc_table (table, table->rows);
3509 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3510 mono_image_get_field_info (
3511 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3514 table = &assembly->tables [MONO_TABLE_MODULE];
3515 alloc_table (table, 1);
3516 mono_image_fill_module_table (domain, moduleb, assembly);
3520 /* Collect all types into a list sorted by their table_idx */
3521 GPtrArray *types = g_ptr_array_new ();
3524 for (i = 0; i < moduleb->num_types; ++i) {
3525 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3526 collect_types (types, type);
3529 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3530 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3531 table->rows += types->len;
3532 alloc_table (table, table->rows);
3534 for (i = 0; i < types->len; ++i) {
3535 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3536 mono_image_get_type_info (domain, type, assembly);
3538 g_ptr_array_free (types, TRUE);
3542 * table->rows is already set above and in mono_image_fill_module_table.
3544 /* add all the custom attributes at the end, once all the indexes are stable */
3545 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3547 module_add_cattrs (assembly, moduleb);
3550 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3551 fixup_cattrs (assembly);
3555 * mono_image_insert_string:
3556 * @module: module builder object
3559 * Insert @str into the user string stream of @module.
3562 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3564 MonoDynamicImage *assembly;
3569 MONO_ARCH_SAVE_REGS;
3571 if (!module->dynamic_image)
3572 mono_image_module_basic_init (module);
3574 assembly = module->dynamic_image;
3576 if (assembly->save) {
3577 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3578 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3579 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3581 char *swapped = g_malloc (2 * mono_string_length (str));
3582 const char *p = (const char*)mono_string_chars (str);
3584 swap_with_size (swapped, p, 2, mono_string_length (str));
3585 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3589 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3591 mono_image_add_stream_data (&assembly->us, "", 1);
3594 idx = assembly->us.index ++;
3596 mono_g_hash_table_insert (assembly->tokens,
3597 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3599 return MONO_TOKEN_STRING | idx;
3603 * mono_image_create_token:
3604 * @assembly: a dynamic assembly
3607 * Get a token to insert in the IL code stream for the given MemberInfo.
3608 * @obj can be one of:
3609 * ConstructorBuilder
3619 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3624 klass = obj->vtable->klass;
3625 if (strcmp (klass->name, "MethodBuilder") == 0) {
3626 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3628 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3629 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3631 token = mono_image_get_methodbuilder_token (assembly, mb);
3632 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3634 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3635 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3637 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3638 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3640 token = mono_image_get_ctorbuilder_token (assembly, mb);
3641 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3643 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3644 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3645 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3646 if (tb->generic_params) {
3647 token = mono_image_get_generic_field_token (assembly, fb);
3649 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3652 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3653 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3654 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3656 else if (strcmp (klass->name, "MonoType") == 0 ||
3657 strcmp (klass->name, "MonoGenericParam") == 0) {
3658 MonoReflectionType *tb = (MonoReflectionType *)obj;
3659 token = mono_metadata_token_from_dor (
3660 mono_image_typedef_or_ref (assembly, tb->type));
3662 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3663 MonoReflectionType *tb = (MonoReflectionType *)obj;
3664 token = mono_metadata_token_from_dor (
3665 mono_image_typedef_or_ref (assembly, tb->type));
3667 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3668 strcmp (klass->name, "MonoMethod") == 0) {
3669 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3670 if (m->method->signature->gen_method) {
3671 token = mono_image_get_methodspec_token (assembly, m->method);
3672 } else if (m->method->signature->generic_param_count) {
3673 g_assert_not_reached ();
3674 } else if ((m->method->klass->image == &assembly->image) &&
3675 !m->method->klass->generic_inst) {
3676 static guint32 method_table_idx = 0xffffff;
3678 * Each token should have a unique index, but the indexes are
3679 * assigned by managed code, so we don't know about them. An
3680 * easy solution is to count backwards...
3682 method_table_idx --;
3683 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3685 token = mono_image_get_methodref_token (assembly, m->method);
3686 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3688 else if (strcmp (klass->name, "MonoField") == 0) {
3689 MonoReflectionField *f = (MonoReflectionField *)obj;
3690 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3691 static guint32 field_table_idx = 0xffffff;
3693 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3695 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
3696 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3698 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3699 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3700 token = mono_image_get_array_token (assembly, m);
3702 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3703 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3704 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3707 g_error ("requested token for %s\n", klass->name);
3709 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3716 guint32 import_lookup_table;
3720 guint32 import_address_table_rva;
3728 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3730 static MonoDynamicImage*
3731 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3732 char *assembly_name, char *module_name)
3734 static const guchar entrycode [16] = {0xff, 0x25, 0};
3735 MonoDynamicImage *image;
3739 * We need to use the current ms version or the ms runtime it won't find
3740 * the support dlls. D'oh!
3741 * const char *version = "mono-" VERSION;
3743 const char *version = "v1.0.3705";
3746 image = GC_MALLOC (sizeof (MonoDynamicImage));
3748 image = g_new0 (MonoDynamicImage, 1);
3751 /* keep in sync with image.c */
3752 image->image.name = assembly_name;
3753 image->image.assembly_name = image->image.name; /* they may be different */
3754 image->image.module_name = module_name;
3755 image->image.version = g_strdup (version);
3756 image->image.dynamic = TRUE;
3758 image->image.references = g_new0 (MonoAssembly*, 1);
3759 image->image.references [0] = NULL;
3761 mono_image_init (&image->image);
3763 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3764 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3765 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3766 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3767 image->handleref = g_hash_table_new (NULL, NULL);
3768 image->tokens = mono_g_hash_table_new (NULL, NULL);
3769 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3770 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3772 string_heap_init (&image->sheap);
3773 mono_image_add_stream_data (&image->us, "", 1);
3774 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3775 /* import tables... */
3776 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3777 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3778 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3779 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3780 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3781 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3782 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3783 stream_data_align (&image->code);
3785 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3787 for (i=0; i < 64; ++i) {
3788 image->tables [i].next_idx = 1;
3789 image->tables [i].columns = table_sizes [i];
3792 image->image.assembly = (MonoAssembly*)assembly;
3793 image->run = assembly->run;
3794 image->save = assembly->save;
3800 * mono_image_basic_init:
3801 * @assembly: an assembly builder object
3803 * Create the MonoImage that represents the assembly builder and setup some
3804 * of the helper hash table and the basic metadata streams.
3807 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3809 MonoDynamicAssembly *assembly;
3810 MonoDynamicImage *image;
3812 MONO_ARCH_SAVE_REGS;
3814 if (assemblyb->dynamic_assembly)
3818 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3820 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3823 assembly->assembly.dynamic = TRUE;
3824 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3825 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3826 if (assemblyb->culture)
3827 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3829 assembly->assembly.aname.culture = g_strdup ("");
3831 assembly->run = assemblyb->access != 2;
3832 assembly->save = assemblyb->access != 1;
3834 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
3835 assembly->assembly.aname.name = image->image.name;
3836 assembly->assembly.image = &image->image;
3838 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
3839 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
3843 calc_section_size (MonoDynamicImage *assembly)
3847 /* alignment constraints */
3848 assembly->code.index += 3;
3849 assembly->code.index &= ~3;
3850 assembly->meta_size += 3;
3851 assembly->meta_size &= ~3;
3852 assembly->resources.index += 3;
3853 assembly->resources.index &= ~3;
3855 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3856 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3859 if (assembly->win32_res) {
3860 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
3862 assembly->sections [MONO_SECTION_RSRC].size = res_size;
3863 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
3867 assembly->sections [MONO_SECTION_RELOC].size = 12;
3868 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3878 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
3882 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
3884 ResTreeNode *t1 = (ResTreeNode*)a;
3885 ResTreeNode *t2 = (ResTreeNode*)b;
3887 return t1->id - t2->id;
3891 * resource_tree_create:
3893 * Organize the resources into a resource tree.
3895 static ResTreeNode *
3896 resource_tree_create (MonoArray *win32_resources)
3898 ResTreeNode *tree, *res_node, *type_node, *lang_node;
3902 tree = g_new0 (ResTreeNode, 1);
3904 for (i = 0; i < mono_array_length (win32_resources); ++i) {
3905 MonoReflectionWin32Resource *win32_res =
3906 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
3910 lang_node = g_new0 (ResTreeNode, 1);
3911 lang_node->id = win32_res->lang_id;
3912 lang_node->win32_res = win32_res;
3914 /* Create type node if neccesary */
3916 for (l = tree->children; l; l = l->next)
3917 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
3918 type_node = (ResTreeNode*)l->data;
3923 type_node = g_new0 (ResTreeNode, 1);
3924 type_node->id = win32_res->res_type;
3927 * The resource types have to be sorted otherwise
3928 * Windows Explorer can't display the version information.
3930 tree->children = g_slist_insert_sorted (tree->children, type_node,
3931 resource_tree_compare_by_id);
3934 /* Create res node if neccesary */
3936 for (l = type_node->children; l; l = l->next)
3937 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
3938 res_node = (ResTreeNode*)l->data;
3943 res_node = g_new0 (ResTreeNode, 1);
3944 res_node->id = win32_res->res_id;
3945 type_node->children = g_slist_append (type_node->children, res_node);
3948 res_node->children = g_slist_append (res_node->children, lang_node);
3955 * resource_tree_encode:
3957 * Encode the resource tree into the format used in the PE file.
3960 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
3963 MonoPEResourceDir dir;
3964 MonoPEResourceDirEntry dir_entry;
3965 MonoPEResourceDataEntry data_entry;
3969 * For the format of the resource directory, see the article
3970 * "An In-Depth Look into the Win32 Portable Executable File Format" by
3974 memset (&dir, 0, sizeof (dir));
3975 memset (&dir_entry, 0, sizeof (dir_entry));
3976 memset (&data_entry, 0, sizeof (data_entry));
3978 g_assert (sizeof (dir) == 16);
3979 g_assert (sizeof (dir_entry) == 8);
3980 g_assert (sizeof (data_entry) == 16);
3982 node->offset = p - begin;
3984 /* IMAGE_RESOURCE_DIRECTORY */
3985 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
3987 memcpy (p, &dir, sizeof (dir));
3990 /* Reserve space for entries */
3992 p += sizeof (dir_entry) * dir.res_id_entries;
3994 /* Write children */
3995 for (l = node->children; l; l = l->next) {
3996 ResTreeNode *child = (ResTreeNode*)l->data;
3998 if (child->win32_res) {
4000 child->offset = p - begin;
4002 /* IMAGE_RESOURCE_DATA_ENTRY */
4003 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4004 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4006 memcpy (p, &data_entry, sizeof (data_entry));
4007 p += sizeof (data_entry);
4009 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4010 p += data_entry.rde_size;
4013 resource_tree_encode (child, begin, p, &p);
4016 /* IMAGE_RESOURCE_ENTRY */
4017 for (l = node->children; l; l = l->next) {
4018 ResTreeNode *child = (ResTreeNode*)l->data;
4019 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4021 dir_entry.is_dir = child->win32_res ? 0 : 1;
4022 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4024 memcpy (entries, &dir_entry, sizeof (dir_entry));
4025 entries += sizeof (dir_entry);
4032 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4037 MonoReflectionWin32Resource *win32_res;
4040 if (!assemblyb->win32_resources)
4044 * Resources are stored in a three level tree inside the PE file.
4045 * - level one contains a node for each type of resource
4046 * - level two contains a node for each resource
4047 * - level three contains a node for each instance of a resource for a
4048 * specific language.
4051 tree = resource_tree_create (assemblyb->win32_resources);
4053 /* Estimate the size of the encoded tree */
4055 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4056 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4057 size += mono_array_length (win32_res->res_data);
4059 /* Directory structure */
4060 size += mono_array_length (assemblyb->win32_resources) * 256;
4061 p = buf = g_malloc (size);
4063 resource_tree_encode (tree, p, p, &p);
4065 g_assert (p - buf < size);
4067 assembly->win32_res = g_malloc (p - buf);
4068 assembly->win32_res_size = p - buf;
4069 memcpy (assembly->win32_res, buf, p - buf);
4075 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4077 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4080 p += sizeof (MonoPEResourceDir);
4081 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4082 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4083 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4084 if (dir_entry->is_dir)
4085 fixup_resource_directory (res_section, child, rva);
4087 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4088 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4091 p += sizeof (MonoPEResourceDirEntry);
4096 * mono_image_create_pefile:
4097 * @mb: a module builder object
4099 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4100 * assembly->pefile where it can be easily retrieved later in chunks.
4103 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4104 MonoMSDOSHeader *msdos;
4105 MonoDotNetHeader *header;
4106 MonoSectionTable *section;
4107 MonoCLIHeader *cli_header;
4108 guint32 size, image_size, virtual_base, text_offset;
4109 guint32 header_start, section_start, file_offset, virtual_offset;
4110 MonoDynamicImage *assembly;
4111 MonoReflectionAssemblyBuilder *assemblyb;
4112 MonoDynamicStream *pefile;
4114 guint32 *rva, value;
4117 static const unsigned char msheader[] = {
4118 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4119 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4122 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4123 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4124 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4125 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4128 assemblyb = mb->assemblyb;
4130 mono_image_basic_init (assemblyb);
4131 assembly = mb->dynamic_image;
4133 /* already created */
4134 if (assembly->pefile.index)
4137 mono_image_build_metadata (mb);
4139 if (mb->is_main && assemblyb->resources) {
4140 int len = mono_array_length (assemblyb->resources);
4141 for (i = 0; i < len; ++i)
4142 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4145 if (mb->resources) {
4146 int len = mono_array_length (mb->resources);
4147 for (i = 0; i < len; ++i)
4148 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4151 build_compressed_metadata (assembly);
4154 assembly_add_win32_resources (assembly, assemblyb);
4156 nsections = calc_section_size (assembly);
4158 pefile = &assembly->pefile;
4160 /* The DOS header and stub */
4161 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4162 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4164 /* the dotnet header */
4165 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4167 /* the section tables */
4168 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4170 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4171 virtual_offset = VIRT_ALIGN;
4174 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4175 if (!assembly->sections [i].size)
4178 file_offset += FILE_ALIGN - 1;
4179 file_offset &= ~(FILE_ALIGN - 1);
4180 virtual_offset += VIRT_ALIGN - 1;
4181 virtual_offset &= ~(VIRT_ALIGN - 1);
4183 assembly->sections [i].offset = file_offset;
4184 assembly->sections [i].rva = virtual_offset;
4186 file_offset += assembly->sections [i].size;
4187 virtual_offset += assembly->sections [i].size;
4188 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4191 file_offset += FILE_ALIGN - 1;
4192 file_offset &= ~(FILE_ALIGN - 1);
4193 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4195 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4197 /* back-patch info */
4198 msdos = (MonoMSDOSHeader*)pefile->data;
4199 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4200 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4201 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4203 header = (MonoDotNetHeader*)(pefile->data + header_start);
4204 header->pesig [0] = 'P';
4205 header->pesig [1] = 'E';
4207 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4208 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4209 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4210 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4211 if (assemblyb->pekind == 1) {
4213 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4216 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4219 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4221 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4222 header->pe.pe_major = 6;
4223 header->pe.pe_minor = 0;
4224 size = assembly->sections [MONO_SECTION_TEXT].size;
4225 size += FILE_ALIGN - 1;
4226 size &= ~(FILE_ALIGN - 1);
4227 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4228 size = assembly->sections [MONO_SECTION_RSRC].size;
4229 size += FILE_ALIGN - 1;
4230 size &= ~(FILE_ALIGN - 1);
4231 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4232 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4233 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4234 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4235 /* pe_rva_entry_point always at the beginning of the text section */
4236 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4238 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4239 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4240 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4241 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4242 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4243 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4244 size = section_start;
4245 size += FILE_ALIGN - 1;
4246 size &= ~(FILE_ALIGN - 1);
4247 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4249 size += VIRT_ALIGN - 1;
4250 size &= ~(VIRT_ALIGN - 1);
4251 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4254 // Translate the PEFileKind value to the value expected by the Windows loader
4257 short kind = assemblyb->pekind;
4260 // PEFileKinds.ConsoleApplication == 2
4261 // PEFileKinds.WindowApplication == 3
4264 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4265 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4271 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4273 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4274 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4275 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4276 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4277 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4278 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4280 /* fill data directory entries */
4282 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4283 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4285 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4286 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4288 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4289 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4290 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4291 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4292 /* patch imported function RVA name */
4293 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4294 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4296 /* the import table */
4297 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4298 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4299 /* patch imported dll RVA name and other entries in the dir */
4300 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4301 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4302 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4303 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4304 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4305 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4307 p = (assembly->code.data + assembly->ilt_offset);
4308 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4309 *p++ = (value) & 0xff;
4310 *p++ = (value >> 8) & (0xff);
4311 *p++ = (value >> 16) & (0xff);
4312 *p++ = (value >> 24) & (0xff);
4314 /* the CLI header info */
4315 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4316 cli_header->ch_size = GUINT32_FROM_LE (72);
4317 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4318 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4319 if (assemblyb->entry_point) {
4320 guint32 table_idx = 0;
4321 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4322 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4323 table_idx = methodb->table_idx;
4326 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4327 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4330 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4331 /* The embedded managed resources */
4332 text_offset = assembly->text_rva + assembly->code.index;
4333 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4334 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4335 text_offset += assembly->resources.index;
4336 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4337 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4338 text_offset += assembly->meta_size;
4339 if (assembly->strong_name_size) {
4340 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4341 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4342 text_offset += assembly->strong_name_size;
4345 /* write the section tables and section content */
4346 section = (MonoSectionTable*)(pefile->data + section_start);
4347 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4348 static const char *section_names [] = {
4349 ".text", ".rsrc", ".reloc"
4351 if (!assembly->sections [i].size)
4353 strcpy (section->st_name, section_names [i]);
4354 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4355 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4356 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4357 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4358 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4359 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4360 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4362 case MONO_SECTION_TEXT:
4363 /* patch entry point */
4364 p = (assembly->code.data + 2);
4365 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4366 *p++ = (value) & 0xff;
4367 *p++ = (value >> 8) & 0xff;
4368 *p++ = (value >> 16) & 0xff;
4369 *p++ = (value >> 24) & 0xff;
4371 text_offset = assembly->sections [i].offset;
4372 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4373 text_offset += assembly->code.index;
4374 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4375 text_offset += assembly->resources.index;
4376 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4377 text_offset += assembly->meta_size;
4378 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4380 g_free (assembly->image.raw_metadata);
4382 case MONO_SECTION_RELOC:
4383 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4384 *rva = GUINT32_FROM_LE (assembly->text_rva);
4386 *rva = GUINT32_FROM_LE (12);
4388 data16 = (guint16*)rva;
4390 * the entrypoint is always at the start of the text section
4391 * 3 is IMAGE_REL_BASED_HIGHLOW
4392 * 2 is patch_size_rva - text_rva
4394 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4396 *data16 = 0; /* terminate */
4398 case MONO_SECTION_RSRC:
4399 if (assembly->win32_res) {
4400 text_offset = assembly->sections [i].offset;
4402 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4403 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4405 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4409 g_assert_not_reached ();
4414 /* check that the file is properly padded */
4417 FILE *f = fopen ("mypetest.exe", "w");
4418 fwrite (pefile->data, pefile->index, 1, f);
4424 MonoReflectionModule *
4425 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4429 MonoImageOpenStatus status;
4430 MonoDynamicAssembly *assembly;
4432 name = mono_string_to_utf8 (fileName);
4434 image = mono_image_open (name, &status);
4437 if (status == MONO_IMAGE_ERROR_ERRNO)
4438 exc = mono_get_exception_file_not_found (fileName);
4440 exc = mono_get_exception_bad_image_format (name);
4442 mono_raise_exception (exc);
4447 assembly = ab->dynamic_assembly;
4448 image->assembly = (MonoAssembly*)assembly;
4450 mono_assembly_load_references (image, &status);
4452 mono_image_close (image);
4453 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4456 return mono_module_get_object (mono_domain_get (), image);
4460 * We need to return always the same object for MethodInfo, FieldInfo etc..
4461 * but we need to consider the reflected type.
4462 * type uses a different hash, since it uses custom hash/equal functions.
4467 MonoClass *refclass;
4471 reflected_equal (gconstpointer a, gconstpointer b) {
4472 const ReflectedEntry *ea = a;
4473 const ReflectedEntry *eb = b;
4475 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4479 reflected_hash (gconstpointer a) {
4480 const ReflectedEntry *ea = a;
4481 return GPOINTER_TO_UINT (ea->item);
4484 #define CHECK_OBJECT(t,p,k) \
4490 mono_domain_lock (domain); \
4491 if (!domain->refobject_hash) \
4492 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4493 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4494 mono_domain_unlock (domain); \
4500 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4502 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4505 #define CACHE_OBJECT(p,o,k) \
4507 ReflectedEntry *e = ALLOC_REFENTRY; \
4509 e->refclass = (k); \
4510 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4511 mono_domain_unlock (domain); \
4515 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4517 /* this is done only once */
4518 mono_domain_lock (domain);
4519 CACHE_OBJECT (assembly, res, NULL);
4523 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4525 /* this is done only once */
4526 mono_domain_lock (domain);
4527 CACHE_OBJECT (module, res, NULL);
4531 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4533 MonoDynamicImage *image = moduleb->dynamic_image;
4534 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4537 * FIXME: we already created an image in mono_image_basic_init (), but
4538 * we don't know which module it belongs to, since that is only
4539 * determined at assembly save time.
4541 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4542 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4544 moduleb->module.image = &image->image;
4545 moduleb->dynamic_image = image;
4546 register_module (mono_object_domain (moduleb), moduleb, image);
4551 * mono_assembly_get_object:
4552 * @domain: an app domain
4553 * @assembly: an assembly
4555 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4557 MonoReflectionAssembly*
4558 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4560 static MonoClass *System_Reflection_Assembly;
4561 MonoReflectionAssembly *res;
4563 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4564 if (!System_Reflection_Assembly)
4565 System_Reflection_Assembly = mono_class_from_name (
4566 mono_defaults.corlib, "System.Reflection", "Assembly");
4567 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4568 res->assembly = assembly;
4569 CACHE_OBJECT (assembly, res, NULL);
4575 MonoReflectionModule*
4576 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4578 static MonoClass *System_Reflection_Module;
4579 MonoReflectionModule *res;
4581 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4582 if (!System_Reflection_Module)
4583 System_Reflection_Module = mono_class_from_name (
4584 mono_defaults.corlib, "System.Reflection", "Module");
4585 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4588 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4590 res->fqname = mono_string_new (domain, image->name);
4591 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4592 res->scopename = mono_string_new (domain, image->module_name);
4594 mono_image_addref (image);
4596 CACHE_OBJECT (image, res, NULL);
4600 MonoReflectionModule*
4601 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4603 static MonoClass *System_Reflection_Module;
4604 MonoReflectionModule *res;
4605 MonoTableInfo *table;
4606 guint32 cols [MONO_FILE_SIZE];
4608 guint32 i, name_idx;
4611 if (!System_Reflection_Module)
4612 System_Reflection_Module = mono_class_from_name (
4613 mono_defaults.corlib, "System.Reflection", "Module");
4614 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4616 table = &image->tables [MONO_TABLE_FILE];
4617 g_assert (table_index < table->rows);
4618 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4621 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4622 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4624 // Check whenever the row has a corresponding row in the moduleref table
4625 table = &image->tables [MONO_TABLE_MODULEREF];
4626 for (i = 0; i < table->rows; ++i) {
4627 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4628 val = mono_metadata_string_heap (image, name_idx);
4629 if (strcmp (val, name) == 0)
4630 res->image = image->modules [i];
4633 res->fqname = mono_string_new (domain, name);
4634 res->name = mono_string_new (domain, name);
4635 res->scopename = mono_string_new (domain, name);
4636 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4642 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4644 if ((t1->type != t2->type) ||
4645 (t1->byref != t2->byref))
4649 case MONO_TYPE_VOID:
4650 case MONO_TYPE_BOOLEAN:
4651 case MONO_TYPE_CHAR:
4662 case MONO_TYPE_STRING:
4665 case MONO_TYPE_OBJECT:
4666 case MONO_TYPE_TYPEDBYREF:
4668 case MONO_TYPE_VALUETYPE:
4669 case MONO_TYPE_CLASS:
4670 case MONO_TYPE_SZARRAY:
4671 return t1->data.klass == t2->data.klass;
4673 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4674 case MONO_TYPE_ARRAY:
4675 if (t1->data.array->rank != t2->data.array->rank)
4677 return t1->data.array->eklass == t2->data.array->eklass;
4678 case MONO_TYPE_GENERICINST: {
4680 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4682 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4684 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4685 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4691 case MONO_TYPE_MVAR:
4692 return t1->data.generic_param == t2->data.generic_param;
4694 g_error ("implement type compare for %0x!", t1->type);
4702 mymono_metadata_type_hash (MonoType *t1)
4708 hash |= t1->byref << 6; /* do not collide with t1->type values */
4710 case MONO_TYPE_VALUETYPE:
4711 case MONO_TYPE_CLASS:
4712 case MONO_TYPE_SZARRAY:
4713 /* check if the distribution is good enough */
4714 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4716 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4721 static MonoReflectionGenericInst*
4722 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4724 static MonoClass *System_Reflection_MonoGenericInst;
4725 MonoReflectionGenericInst *res;
4726 MonoGenericInst *ginst;
4729 if (!System_Reflection_MonoGenericInst) {
4730 System_Reflection_MonoGenericInst = mono_class_from_name (
4731 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4732 g_assert (System_Reflection_MonoGenericInst);
4735 ginst = geninst->data.generic_inst;
4736 gklass = mono_class_from_mono_type (ginst->generic_type);
4738 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4740 res->type.type = geninst;
4741 if (gklass->wastypebuilder && gklass->reflection_info)
4742 res->generic_type = gklass->reflection_info;
4744 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4750 * mono_type_get_object:
4751 * @domain: an app domain
4754 * Return an System.MonoType object representing the type @type.
4757 mono_type_get_object (MonoDomain *domain, MonoType *type)
4759 MonoReflectionType *res;
4760 MonoClass *klass = mono_class_from_mono_type (type);
4762 mono_domain_lock (domain);
4763 if (!domain->type_hash)
4764 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4765 (GCompareFunc)mymono_metadata_type_equal);
4766 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4767 mono_domain_unlock (domain);
4770 if (type->type == MONO_TYPE_GENERICINST) {
4771 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4772 mono_g_hash_table_insert (domain->type_hash, type, res);
4773 mono_domain_unlock (domain);
4776 if (klass->reflection_info && !klass->wastypebuilder) {
4777 //g_assert_not_reached ();
4778 /* should this be considered an error condition? */
4780 mono_domain_unlock (domain);
4781 return klass->reflection_info;
4784 mono_class_init (klass);
4785 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4787 mono_g_hash_table_insert (domain->type_hash, type, res);
4788 mono_domain_unlock (domain);
4793 * mono_method_get_object:
4794 * @domain: an app domain
4796 * @refclass: the reflected type (can be NULL)
4798 * Return an System.Reflection.MonoMethod object representing the method @method.
4800 MonoReflectionMethod*
4801 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4804 * We use the same C representation for methods and constructors, but the type
4805 * name in C# is different.
4809 MonoReflectionMethod *ret;
4812 refclass = method->klass;
4814 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4815 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4816 cname = "MonoCMethod";
4818 cname = "MonoMethod";
4819 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4821 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4822 ret->method = method;
4823 ret->name = mono_string_new (domain, method->name);
4824 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4825 CACHE_OBJECT (method, ret, refclass);
4830 * mono_field_get_object:
4831 * @domain: an app domain
4835 * Return an System.Reflection.MonoField object representing the field @field
4838 MonoReflectionField*
4839 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
4841 MonoReflectionField *res;
4844 CHECK_OBJECT (MonoReflectionField *, field, klass);
4845 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
4846 res = (MonoReflectionField *)mono_object_new (domain, oklass);
4849 res->name = mono_string_new (domain, field->name);
4850 res->attrs = field->type->attrs;
4851 res->type = mono_type_get_object (domain, field->type);
4852 CACHE_OBJECT (field, res, klass);
4857 * mono_property_get_object:
4858 * @domain: an app domain
4860 * @property: a property
4862 * Return an System.Reflection.MonoProperty object representing the property @property
4865 MonoReflectionProperty*
4866 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
4868 MonoReflectionProperty *res;
4871 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
4872 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
4873 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
4875 res->property = property;
4876 CACHE_OBJECT (property, res, klass);
4881 * mono_event_get_object:
4882 * @domain: an app domain
4886 * Return an System.Reflection.MonoEvent object representing the event @event
4889 MonoReflectionEvent*
4890 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
4892 MonoReflectionEvent *res;
4895 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
4896 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
4897 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
4900 CACHE_OBJECT (event, res, klass);
4905 * mono_param_get_objects:
4906 * @domain: an app domain
4909 * Return an System.Reflection.ParameterInfo array object representing the parameters
4910 * in the method @method.
4913 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
4915 static MonoClass *System_Reflection_ParameterInfo;
4916 MonoArray *res = NULL;
4917 MonoReflectionMethod *member = NULL;
4918 MonoReflectionParameter *param = NULL;
4922 if (!System_Reflection_ParameterInfo)
4923 System_Reflection_ParameterInfo = mono_class_from_name (
4924 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
4926 if (!method->signature->param_count)
4927 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
4929 /* Note: the cache is based on the address of the signature into the method
4930 * since we already cache MethodInfos with the method as keys.
4932 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
4934 member = mono_method_get_object (domain, method, NULL);
4935 names = g_new (char *, method->signature->param_count);
4936 mono_method_get_param_names (method, (const char **) names);
4938 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
4939 for (i = 0; i < method->signature->param_count; ++i) {
4940 param = (MonoReflectionParameter *)mono_object_new (domain,
4941 System_Reflection_ParameterInfo);
4942 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
4943 param->DefaultValueImpl = NULL; /* FIXME */
4944 param->MemberImpl = (MonoObject*)member;
4945 param->NameImpl = mono_string_new (domain, names [i]);
4946 param->PositionImpl = i;
4947 param->AttrsImpl = method->signature->params [i]->attrs;
4948 mono_array_set (res, gpointer, i, param);
4951 CACHE_OBJECT (&(method->signature), res, NULL);
4956 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
4960 memset (assembly, 0, sizeof (MonoAssemblyName));
4962 assembly->culture = "";
4964 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
4967 while (*p == ' ' || *p == ',') {
4976 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
4978 assembly->major = strtoul (p, &s, 10);
4979 if (s == p || *s != '.')
4982 assembly->minor = strtoul (p, &s, 10);
4983 if (s == p || *s != '.')
4986 assembly->build = strtoul (p, &s, 10);
4987 if (s == p || *s != '.')
4990 assembly->revision = strtoul (p, &s, 10);
4993 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
4995 if (strncmp (p, "neutral", 7) == 0) {
4996 assembly->culture = "";
4999 assembly->culture = p;
5000 while (*p && *p != ',') {
5004 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5007 while (*s && isxdigit (*s)) {
5011 assembly->hash_len = s - p;
5012 if (!(s-p) || ((s-p) & 1))
5014 assembly->hash_value = s = p;
5015 while (*s && isxdigit (*s)) {
5017 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5020 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5025 while (*p && *p != ',')
5029 while (*p == ' ' || *p == ',') {
5043 * mono_reflection_parse_type:
5046 * Parse a type name as accepted by the GetType () method and output the info
5047 * extracted in the info structure.
5048 * the name param will be mangled, so, make a copy before passing it to this function.
5049 * The fields in info will be valid until the memory pointed to by name is valid.
5050 * Returns 0 on parse error.
5051 * See also mono_type_get_name () below.
5054 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5056 char *start, *p, *w, *last_point, *startn;
5057 int in_modifiers = 0;
5058 int isbyref = 0, rank;
5060 start = p = w = name;
5062 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5063 info->name = info->name_space = NULL;
5064 info->nested = NULL;
5065 info->modifiers = NULL;
5067 /* last_point separates the namespace from the name */
5073 *p = 0; /* NULL terminate the name */
5075 info->nested = g_list_append (info->nested, startn);
5076 /* we have parsed the nesting namespace + name */
5080 info->name_space = start;
5082 info->name = last_point + 1;
5084 info->name_space = (char *)"";
5110 info->name_space = start;
5112 info->name = last_point + 1;
5114 info->name_space = (char *)"";
5121 if (isbyref) /* only one level allowed by the spec */
5124 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5128 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5139 else if (*p != '*') /* '*' means unknown lower bound */
5145 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5157 return 0; /* missing assembly name */
5158 if (!assembly_name_to_aname (&info->assembly, p))
5165 if (info->assembly.name)
5168 *w = 0; /* terminate class name */
5169 if (!info->name || !*info->name)
5171 /* add other consistency checks */
5176 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5183 image = mono_defaults.corlib;
5186 klass = mono_class_from_name_case (image, info->name_space, info->name);
5188 klass = mono_class_from_name (image, info->name_space, info->name);
5191 for (mod = info->nested; mod; mod = mod->next) {
5194 mono_class_init (klass);
5195 nested = klass->nested_classes;
5198 klass = nested->data;
5200 if (g_strcasecmp (klass->name, mod->data) == 0)
5203 if (strcmp (klass->name, mod->data) == 0)
5207 nested = nested->next;
5214 mono_class_init (klass);
5215 for (mod = info->modifiers; mod; mod = mod->next) {
5216 modval = GPOINTER_TO_UINT (mod->data);
5217 if (!modval) { /* byref: must be last modifier */
5218 return &klass->this_arg;
5219 } else if (modval == -1) {
5220 klass = mono_ptr_class_get (&klass->byval_arg);
5221 } else { /* array rank */
5222 klass = mono_array_class_get (klass, modval);
5224 mono_class_init (klass);
5227 return &klass->byval_arg;
5231 * mono_reflection_get_type:
5232 * @image: a metadata context
5233 * @info: type description structure
5234 * @ignorecase: flag for case-insensitive string compares
5236 * Build a MonoType from the type description in @info.
5241 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5244 MonoReflectionAssembly *assembly;
5248 type = mono_reflection_get_type_internal (image, info, ignorecase);
5251 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5254 // Reconstruct the type name
5255 fullName = g_string_new ("");
5256 if (info->name_space && (info->name_space [0] != '\0'))
5257 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5259 g_string_printf (fullName, info->name);
5260 for (mod = info->nested; mod; mod = mod->next)
5261 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5264 mono_domain_try_type_resolve (
5265 mono_domain_get (), fullName->str, NULL);
5266 if (assembly && (!image || (assembly->assembly->image == image)))
5267 type = mono_reflection_get_type_internal (assembly->assembly->image,
5269 g_string_free (fullName, TRUE);
5274 * mono_reflection_type_from_name:
5276 * @image: a metadata context (can be NULL).
5278 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5279 * it defaults to get the type from @image or, if @image is NULL or loading
5280 * from it fails, uses corlib.
5284 mono_reflection_type_from_name (char *name, MonoImage *image)
5287 MonoTypeNameParse info;
5288 MonoAssembly *assembly;
5290 /*g_print ("requested type %s\n", str);*/
5291 if (!mono_reflection_parse_type (name, &info)) {
5292 g_list_free (info.modifiers);
5293 g_list_free (info.nested);
5297 if (info.assembly.name) {
5298 assembly = mono_assembly_loaded (&info.assembly);
5299 /* do we need to load if it's not already loaded? */
5301 g_list_free (info.modifiers);
5302 g_list_free (info.nested);
5306 image = assembly->image;
5307 } else if (image == NULL) {
5308 image = mono_defaults.corlib;
5311 type = mono_reflection_get_type (image, &info, FALSE);
5312 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5313 image = mono_defaults.corlib;
5314 type = mono_reflection_get_type (image, &info, FALSE);
5317 g_list_free (info.modifiers);
5318 g_list_free (info.nested);
5323 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5325 int slen, type = t->type;
5330 case MONO_TYPE_BOOLEAN: {
5331 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5336 case MONO_TYPE_CHAR:
5338 case MONO_TYPE_I2: {
5339 guint16 *val = g_malloc (sizeof (guint16));
5344 #if SIZEOF_VOID_P == 4
5350 case MONO_TYPE_I4: {
5351 guint32 *val = g_malloc (sizeof (guint32));
5356 #if SIZEOF_VOID_P == 8
5357 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5362 case MONO_TYPE_I8: {
5363 guint64 *val = g_malloc (sizeof (guint64));
5368 case MONO_TYPE_VALUETYPE:
5369 if (t->data.klass->enumtype) {
5370 type = t->data.klass->enum_basetype->type;
5373 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5376 case MONO_TYPE_STRING:
5377 if (*p == (char)0xFF) {
5381 slen = mono_metadata_decode_value (p, &p);
5383 return mono_string_new_len (mono_domain_get (), p, slen);
5384 case MONO_TYPE_CLASS: {
5387 if (*p == (char)0xFF) {
5392 slen = mono_metadata_decode_value (p, &p);
5393 n = g_memdup (p, slen + 1);
5395 t = mono_reflection_type_from_name (n, image);
5397 g_warning ("Cannot load type '%s'", n);
5401 return mono_type_get_object (mono_domain_get (), t);
5405 case MONO_TYPE_OBJECT: {
5408 MonoClass *subc = NULL;
5413 } else if (subt == 0x0E) {
5414 type = MONO_TYPE_STRING;
5416 } else if (subt == 0x55) {
5419 slen = mono_metadata_decode_value (p, &p);
5420 n = g_memdup (p, slen + 1);
5422 t = mono_reflection_type_from_name (n, image);
5424 g_warning ("Cannot load type '%s'", n);
5427 subc = mono_class_from_mono_type (t);
5428 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5429 MonoType simple_type = {{0}};
5430 simple_type.type = subt;
5431 subc = mono_class_from_mono_type (&simple_type);
5433 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5435 val = load_cattr_value (image, &subc->byval_arg, p, end);
5436 obj = mono_object_new (mono_domain_get (), subc);
5437 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5441 case MONO_TYPE_SZARRAY:
5444 guint32 i, alen, basetype;
5447 if (alen == 0xffffffff) {
5451 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5452 basetype = t->data.klass->byval_arg.type;
5457 case MONO_TYPE_BOOLEAN:
5458 for (i=0;i<alen;i++)
5460 MonoBoolean val=*p++;
5461 mono_array_set(arr,MonoBoolean,i,val);
5464 case MONO_TYPE_CHAR:
5467 for (i=0;i<alen;i++)
5469 guint16 val=read16(p);
5470 mono_array_set(arr,guint16,i,val);
5477 for (i=0;i<alen;i++)
5479 guint32 val=read32(p);
5480 mono_array_set(arr,guint32,i,val);
5487 for (i=0;i<alen;i++)
5489 guint64 val=read64(p);
5490 mono_array_set(arr,guint64,i,val);
5494 case MONO_TYPE_CLASS:
5495 case MONO_TYPE_STRING:
5496 for (i = 0; i < alen; i++) {
5497 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5498 mono_array_set (arr, gpointer, i, item);
5502 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5508 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5514 type_is_reference (MonoType *type)
5516 switch (type->type) {
5517 case MONO_TYPE_BOOLEAN:
5518 case MONO_TYPE_CHAR:
5531 case MONO_TYPE_VALUETYPE:
5539 free_param_data (MonoMethodSignature *sig, void **params) {
5541 for (i = 0; i < sig->param_count; ++i) {
5542 if (!type_is_reference (sig->params [i]))
5543 g_free (params [i]);
5548 * Find the method index in the metadata methodDef table.
5549 * Later put these three helper methods in metadata and export them.
5552 find_method_index (MonoMethod *method) {
5553 MonoClass *klass = method->klass;
5556 for (i = 0; i < klass->method.count; ++i) {
5557 if (method == klass->methods [i])
5558 return klass->method.first + 1 + i;
5564 * Find the field index in the metadata FieldDef table.
5567 find_field_index (MonoClass *klass, MonoClassField *field) {
5570 for (i = 0; i < klass->field.count; ++i) {
5571 if (field == &klass->fields [i])
5572 return klass->field.first + 1 + i;
5578 * Find the property index in the metadata Property table.
5581 find_property_index (MonoClass *klass, MonoProperty *property) {
5584 for (i = 0; i < klass->property.count; ++i) {
5585 if (property == &klass->properties [i])
5586 return klass->property.first + 1 + i;
5592 * Find the event index in the metadata Event table.
5595 find_event_index (MonoClass *klass, MonoEvent *event) {
5598 for (i = 0; i < klass->event.count; ++i) {
5599 if (event == &klass->events [i])
5600 return klass->event.first + 1 + i;
5606 create_custom_attr (MonoImage *image, MonoMethod *method,
5607 const char *data, guint32 len)
5609 const char *p = data;
5611 guint32 i, j, num_named;
5615 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5618 mono_class_init (method->klass);
5619 /*g_print ("got attr %s\n", method->klass->name);*/
5621 params = g_new (void*, method->signature->param_count);
5625 for (i = 0; i < method->signature->param_count; ++i) {
5626 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5630 attr = mono_object_new (mono_domain_get (), method->klass);
5631 mono_runtime_invoke (method, attr, params, NULL);
5632 free_param_data (method->signature, params);
5634 num_named = read16 (named);
5636 for (j = 0; j < num_named; j++) {
5638 char *name, named_type, data_type;
5639 named_type = *named++;
5640 data_type = *named++; /* type of data */
5641 if (data_type == 0x55) {
5644 type_len = mono_metadata_decode_blob_size (named, &named);
5645 type_name = g_malloc (type_len + 1);
5646 memcpy (type_name, named, type_len);
5647 type_name [type_len] = 0;
5649 /* FIXME: lookup the type and check type consistency */
5652 if (data_type == MONO_TYPE_SZARRAY)
5653 /* The spec does not mention this */
5655 name_len = mono_metadata_decode_blob_size (named, &named);
5656 name = g_malloc (name_len + 1);
5657 memcpy (name, named, name_len);
5658 name [name_len] = 0;
5660 if (named_type == 0x53) {
5661 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5662 void *val = load_cattr_value (image, field->type, named, &named);
5663 mono_field_set_value (attr, field, val);
5664 if (!type_is_reference (field->type))
5666 } else if (named_type == 0x54) {
5669 MonoType *prop_type;
5671 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5672 /* can we have more that 1 arg in a custom attr named property? */
5673 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5674 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5675 mono_property_set_value (prop, attr, pparams, NULL);
5676 if (!type_is_reference (prop_type))
5677 g_free (pparams [0]);
5686 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5693 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5694 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5695 for (i = 0; i < cinfo->num_attrs; ++i) {
5696 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5697 mono_array_set (result, gpointer, i, attr);
5703 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5705 guint32 mtoken, i, len;
5706 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5708 MonoCustomAttrInfo *ainfo;
5709 GList *tmp, *list = NULL;
5712 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5714 i = mono_metadata_custom_attrs_from_index (image, idx);
5718 while (i < ca->rows) {
5719 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5721 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5724 len = g_list_length (list);
5727 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5728 ainfo->num_attrs = len;
5729 ainfo->image = image;
5730 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5731 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5732 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5733 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5734 case CUSTOM_ATTR_TYPE_METHODDEF:
5735 mtoken |= MONO_TOKEN_METHOD_DEF;
5737 case CUSTOM_ATTR_TYPE_MEMBERREF:
5738 mtoken |= MONO_TOKEN_MEMBER_REF;
5741 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5744 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5745 if (!ainfo->attrs [i].ctor)
5746 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5747 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5748 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5749 ainfo->attrs [i].data = data;
5757 mono_custom_attrs_from_method (MonoMethod *method)
5759 MonoCustomAttrInfo *cinfo;
5762 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5764 idx = find_method_index (method);
5765 idx <<= CUSTOM_ATTR_BITS;
5766 idx |= CUSTOM_ATTR_METHODDEF;
5767 return mono_custom_attrs_from_index (method->klass->image, idx);
5771 mono_custom_attrs_from_class (MonoClass *klass)
5773 MonoCustomAttrInfo *cinfo;
5776 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5778 idx = mono_metadata_token_index (klass->type_token);
5779 idx <<= CUSTOM_ATTR_BITS;
5780 idx |= CUSTOM_ATTR_TYPEDEF;
5781 return mono_custom_attrs_from_index (klass->image, idx);
5785 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5787 MonoCustomAttrInfo *cinfo;
5790 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5792 idx = 1; /* there is only one assembly */
5793 idx <<= CUSTOM_ATTR_BITS;
5794 idx |= CUSTOM_ATTR_ASSEMBLY;
5795 return mono_custom_attrs_from_index (assembly->image, idx);
5798 static MonoCustomAttrInfo*
5799 mono_custom_attrs_from_module (MonoImage *image)
5801 MonoCustomAttrInfo *cinfo;
5804 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5806 idx = 1; /* there is only one module */
5807 idx <<= CUSTOM_ATTR_BITS;
5808 idx |= CUSTOM_ATTR_MODULE;
5809 return mono_custom_attrs_from_index (image, idx);
5813 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5815 MonoCustomAttrInfo *cinfo;
5818 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5820 idx = find_property_index (klass, property);
5821 idx <<= CUSTOM_ATTR_BITS;
5822 idx |= CUSTOM_ATTR_PROPERTY;
5823 return mono_custom_attrs_from_index (klass->image, idx);
5827 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
5829 MonoCustomAttrInfo *cinfo;
5832 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
5834 idx = find_event_index (klass, event);
5835 idx <<= CUSTOM_ATTR_BITS;
5836 idx |= CUSTOM_ATTR_EVENT;
5837 return mono_custom_attrs_from_index (klass->image, idx);
5841 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
5843 MonoCustomAttrInfo *cinfo;
5846 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5848 idx = find_field_index (klass, field);
5849 idx <<= CUSTOM_ATTR_BITS;
5850 idx |= CUSTOM_ATTR_FIELDDEF;
5851 return mono_custom_attrs_from_index (klass->image, idx);
5855 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
5858 guint32 i, idx, method_index;
5859 guint32 param_list, param_last, param_pos, found;
5861 MonoReflectionMethodAux *aux;
5863 if (method->klass->image->dynamic) {
5864 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5865 if (!aux || !aux->param_cattr)
5867 return aux->param_cattr [param];
5870 image = method->klass->image;
5871 method_index = find_method_index (method);
5872 ca = &image->tables [MONO_TABLE_METHOD];
5874 if (method->klass->generic_inst || method->klass->gen_params ||
5875 method->signature->generic_param_count) {
5876 // FIXME FIXME FIXME
5880 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
5881 if (method_index == ca->rows) {
5882 ca = &image->tables [MONO_TABLE_PARAM];
5883 param_last = ca->rows + 1;
5885 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
5886 ca = &image->tables [MONO_TABLE_PARAM];
5889 for (i = param_list; i < param_last; ++i) {
5890 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
5891 if (param_pos == param) {
5899 idx <<= CUSTOM_ATTR_BITS;
5900 idx |= CUSTOM_ATTR_PARAMDEF;
5901 return mono_custom_attrs_from_index (image, idx);
5905 * mono_reflection_get_custom_attrs:
5906 * @obj: a reflection object handle
5908 * Return an array with all the custom attributes defined of the
5909 * reflection handle @obj. The objects are fully build.
5912 mono_reflection_get_custom_attrs (MonoObject *obj)
5916 MonoCustomAttrInfo *cinfo = NULL;
5918 MONO_ARCH_SAVE_REGS;
5920 klass = obj->vtable->klass;
5921 /* FIXME: need to handle: Module */
5922 if (klass == mono_defaults.monotype_class) {
5923 MonoReflectionType *rtype = (MonoReflectionType*)obj;
5924 klass = mono_class_from_mono_type (rtype->type);
5925 cinfo = mono_custom_attrs_from_class (klass);
5926 } else if (strcmp ("Assembly", klass->name) == 0) {
5927 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
5928 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
5929 } else if (strcmp ("Module", klass->name) == 0) {
5930 MonoReflectionModule *module = (MonoReflectionModule*)obj;
5931 cinfo = mono_custom_attrs_from_module (module->image);
5932 } else if (strcmp ("MonoProperty", klass->name) == 0) {
5933 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
5934 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
5935 } else if (strcmp ("MonoEvent", klass->name) == 0) {
5936 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
5937 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
5938 } else if (strcmp ("MonoField", klass->name) == 0) {
5939 MonoReflectionField *rfield = (MonoReflectionField*)obj;
5940 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
5941 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
5942 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
5943 cinfo = mono_custom_attrs_from_method (rmethod->method);
5944 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
5945 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
5946 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
5947 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
5948 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
5949 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
5950 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
5951 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
5952 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5953 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
5954 } else { /* handle other types here... */
5955 g_error ("get custom attrs not yet supported for %s", klass->name);
5959 result = mono_custom_attrs_construct (cinfo);
5961 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5962 result = mono_array_new (mono_domain_get (), klass, 0);
5968 static MonoMethodSignature*
5969 parameters_to_signature (MonoArray *parameters) {
5970 MonoMethodSignature *sig;
5973 count = parameters? mono_array_length (parameters): 0;
5975 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
5976 sig->param_count = count;
5977 sig->sentinelpos = -1; /* FIXME */
5978 for (i = 0; i < count; ++i) {
5979 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
5980 sig->params [i] = pt->type;
5985 static MonoMethodSignature*
5986 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
5987 MonoMethodSignature *sig;
5989 sig = parameters_to_signature (ctor->parameters);
5990 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5991 sig->ret = &mono_defaults.void_class->byval_arg;
5995 static MonoMethodSignature*
5996 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
5997 MonoMethodSignature *sig;
5999 sig = parameters_to_signature (method->parameters);
6000 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6001 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6002 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6006 static MonoMethodSignature*
6007 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6008 MonoMethodSignature *sig;
6010 sig = parameters_to_signature (method->parameters);
6011 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6012 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6013 sig->generic_param_count = 0;
6018 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6020 MonoClass *klass = mono_object_class (prop);
6021 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6022 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6023 *name = mono_string_to_utf8 (pb->name);
6024 *type = pb->type->type;
6026 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6027 *name = g_strdup (p->property->name);
6028 if (p->property->get)
6029 *type = p->property->get->signature->ret;
6031 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6036 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6038 MonoClass *klass = mono_object_class (field);
6039 if (strcmp (klass->name, "FieldBuilder") == 0) {
6040 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6041 *name = mono_string_to_utf8 (fb->name);
6042 *type = fb->type->type;
6044 MonoReflectionField *f = (MonoReflectionField *)field;
6045 *name = g_strdup (f->field->name);
6046 *type = f->field->type;
6051 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6054 MonoTypeEnum simple_type;
6056 if ((p-buffer) + 10 >= *buflen) {
6059 newbuf = g_realloc (buffer, *buflen);
6060 p = newbuf + (p-buffer);
6063 argval = ((char*)arg + sizeof (MonoObject));
6064 simple_type = type->type;
6066 switch (simple_type) {
6067 case MONO_TYPE_BOOLEAN:
6072 case MONO_TYPE_CHAR:
6075 swap_with_size (p, argval, 2, 1);
6081 swap_with_size (p, argval, 4, 1);
6087 swap_with_size (p, argval, 8, 1);
6090 case MONO_TYPE_VALUETYPE:
6091 if (type->data.klass->enumtype) {
6092 simple_type = type->data.klass->enum_basetype->type;
6095 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6098 case MONO_TYPE_STRING: {
6105 str = mono_string_to_utf8 ((MonoString*)arg);
6106 slen = strlen (str);
6107 if ((p-buffer) + 10 + slen >= *buflen) {
6111 newbuf = g_realloc (buffer, *buflen);
6112 p = newbuf + (p-buffer);
6115 mono_metadata_encode_value (slen, p, &p);
6116 memcpy (p, str, slen);
6121 case MONO_TYPE_CLASS: {
6129 k = mono_object_class (arg);
6130 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6131 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6132 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6134 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6135 slen = strlen (str);
6136 if ((p-buffer) + 10 + slen >= *buflen) {
6140 newbuf = g_realloc (buffer, *buflen);
6141 p = newbuf + (p-buffer);
6144 mono_metadata_encode_value (slen, p, &p);
6145 memcpy (p, str, slen);
6150 case MONO_TYPE_SZARRAY: {
6155 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6158 len = mono_array_length ((MonoArray*)arg);
6160 *p++ = (len >> 8) & 0xff;
6161 *p++ = (len >> 16) & 0xff;
6162 *p++ = (len >> 24) & 0xff;
6164 *retbuffer = buffer;
6165 eclass = type->data.klass;
6166 for (i = 0; i < len; ++i) {
6167 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6171 /* it may be a boxed value or a Type */
6172 case MONO_TYPE_OBJECT: {
6173 MonoClass *klass = mono_object_class (arg);
6177 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6180 } else if (klass->enumtype) {
6182 } else if (klass == mono_defaults.string_class) {
6183 simple_type = MONO_TYPE_STRING;
6186 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6187 *p++ = simple_type = klass->byval_arg.type;
6190 g_error ("unhandled type in custom attr");
6192 str = type_get_qualified_name (klass->enum_basetype, NULL);
6193 slen = strlen (str);
6194 if ((p-buffer) + 10 + slen >= *buflen) {
6198 newbuf = g_realloc (buffer, *buflen);
6199 p = newbuf + (p-buffer);
6202 mono_metadata_encode_value (slen, p, &p);
6203 memcpy (p, str, slen);
6206 simple_type = klass->enum_basetype->type;
6210 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6213 *retbuffer = buffer;
6217 * mono_reflection_get_custom_attrs_blob:
6218 * @ctor: custom attribute constructor
6219 * @ctorArgs: arguments o the constructor
6225 * Creates the blob of data that needs to be saved in the metadata and that represents
6226 * the custom attributed described by @ctor, @ctorArgs etc.
6227 * Returns: a Byte array representing the blob of data.
6230 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6233 MonoMethodSignature *sig;
6238 MONO_ARCH_SAVE_REGS;
6240 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6241 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6243 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6245 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6247 p = buffer = g_malloc (buflen);
6248 /* write the prolog */
6251 for (i = 0; i < sig->param_count; ++i) {
6252 arg = mono_array_get (ctorArgs, MonoObject*, i);
6253 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6257 i += mono_array_length (properties);
6259 i += mono_array_length (fields);
6261 *p++ = (i >> 8) & 0xff;
6264 for (i = 0; i < mono_array_length (properties); ++i) {
6269 prop = mono_array_get (properties, gpointer, i);
6270 get_prop_name_and_type (prop, &pname, &ptype);
6271 *p++ = 0x54; /* PROPERTY signature */
6273 /* Preallocate a large enough buffer */
6274 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6275 char *str = type_get_qualified_name (ptype, NULL);
6281 len += strlen (pname);
6283 if ((p-buffer) + 20 + len >= buflen) {
6287 newbuf = g_realloc (buffer, buflen);
6288 p = newbuf + (p-buffer);
6292 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6293 char *str = type_get_qualified_name (ptype, NULL);
6294 int slen = strlen (str);
6298 * This seems to be optional...
6301 mono_metadata_encode_value (slen, p, &p);
6302 memcpy (p, str, slen);
6306 mono_metadata_encode_value (ptype->type, p, &p);
6307 if (ptype->type == MONO_TYPE_SZARRAY)
6308 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6310 len = strlen (pname);
6311 mono_metadata_encode_value (len, p, &p);
6312 memcpy (p, pname, len);
6314 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6321 for (i = 0; i < mono_array_length (fields); ++i) {
6326 field = mono_array_get (fields, gpointer, i);
6327 get_field_name_and_type (field, &fname, &ftype);
6328 *p++ = 0x53; /* FIELD signature */
6329 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6330 char *str = type_get_qualified_name (ftype, NULL);
6331 int slen = strlen (str);
6332 if ((p-buffer) + 10 + slen >= buflen) {
6336 newbuf = g_realloc (buffer, buflen);
6337 p = newbuf + (p-buffer);
6342 * This seems to be optional...
6345 mono_metadata_encode_value (slen, p, &p);
6346 memcpy (p, str, slen);
6350 mono_metadata_encode_value (ftype->type, p, &p);
6352 len = strlen (fname);
6353 mono_metadata_encode_value (len, p, &p);
6354 memcpy (p, fname, len);
6356 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6361 g_assert (p - buffer <= buflen);
6362 buflen = p - buffer;
6363 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6364 p = mono_array_addr (result, char, 0);
6365 memcpy (p, buffer, buflen);
6367 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6373 * mono_reflection_setup_internal_class:
6374 * @tb: a TypeBuilder object
6376 * Creates a MonoClass that represents the TypeBuilder.
6377 * This is a trick that lets us simplify a lot of reflection code
6378 * (and will allow us to support Build and Run assemblies easier).
6381 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6383 MonoClass *klass, *parent;
6385 MONO_ARCH_SAVE_REGS;
6387 klass = g_new0 (MonoClass, 1);
6389 klass->image = &tb->module->dynamic_image->image;
6392 /* check so we can compile corlib correctly */
6393 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6394 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6395 parent = tb->parent->type->data.klass;
6397 parent = my_mono_class_from_mono_type (tb->parent->type);
6401 klass->inited = 1; /* we lie to the runtime */
6402 klass->name = mono_string_to_utf8 (tb->name);
6403 klass->name_space = mono_string_to_utf8 (tb->nspace);
6404 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6405 klass->flags = tb->attrs;
6407 klass->element_class = klass;
6408 klass->reflection_info = tb; /* need to pin. */
6410 /* Put into cache so mono_class_get () will find it */
6411 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6414 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6415 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6419 mono_class_setup_parent (klass, parent);
6420 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6421 const char *old_n = klass->name;
6422 /* trick to get relative numbering right when compiling corlib */
6423 klass->name = "BuildingObject";
6424 mono_class_setup_parent (klass, mono_defaults.object_class);
6425 klass->name = old_n;
6427 mono_class_setup_mono_type (klass);
6429 mono_class_setup_supertypes (klass);
6432 * FIXME: handle interfaces.
6435 tb->type.type = &klass->byval_arg;
6437 if (tb->nesting_type) {
6438 g_assert (tb->nesting_type->type);
6439 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6442 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6446 * mono_reflection_setup_generic_class:
6447 * @tb: a TypeBuilder object
6449 * Setup the generic class after all generic parameters have been added.
6452 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6457 MONO_ARCH_SAVE_REGS;
6459 klass = my_mono_class_from_mono_type (tb->type.type);
6461 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6463 if (klass->gen_params || (count == 0))
6466 klass->num_gen_params = count;
6467 klass->gen_params = g_new0 (MonoGenericParam, count);
6469 for (i = 0; i < count; i++) {
6470 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6471 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6474 ensure_runtime_vtable (klass);
6478 * mono_reflection_create_internal_class:
6479 * @tb: a TypeBuilder object
6481 * Actually create the MonoClass that is associated with the TypeBuilder.
6484 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6488 MONO_ARCH_SAVE_REGS;
6490 klass = my_mono_class_from_mono_type (tb->type.type);
6492 if (klass->enumtype && klass->enum_basetype == NULL) {
6493 MonoReflectionFieldBuilder *fb;
6495 g_assert (tb->fields != NULL);
6496 g_assert (mono_array_length (tb->fields) >= 1);
6498 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6500 klass->enum_basetype = fb->type->type;
6501 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6502 if (!klass->element_class)
6503 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6504 klass->instance_size = klass->element_class->instance_size;
6505 klass->size_inited = 1;
6507 * this is almost safe to do with enums and it's needed to be able
6508 * to create objects of the enum type (for use in SetConstant).
6510 /* FIXME: Does this mean enums can't have method overrides ? */
6511 mono_class_setup_vtable (klass, NULL, 0);
6515 static MonoMarshalSpec*
6516 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6517 MonoReflectionMarshal *minfo)
6519 MonoMarshalSpec *res;
6521 res = g_new0 (MonoMarshalSpec, 1);
6522 res->native = minfo->type;
6524 switch (minfo->type) {
6525 case MONO_NATIVE_LPARRAY:
6526 res->data.array_data.elem_type = minfo->eltype;
6527 res->data.array_data.param_num = 0; /* Not yet */
6528 res->data.array_data.num_elem = minfo->count;
6531 case MONO_NATIVE_BYVALTSTR:
6532 case MONO_NATIVE_BYVALARRAY:
6533 res->data.array_data.num_elem = minfo->count;
6536 case MONO_NATIVE_CUSTOM:
6537 if (minfo->marshaltyperef)
6538 res->data.custom_data.custom_name =
6539 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6541 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6552 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6553 ReflectionMethodBuilder *rmb,
6554 MonoMethodSignature *sig)
6557 MonoMethodNormal *pm;
6558 MonoMarshalSpec **specs;
6559 MonoReflectionMethodAux *method_aux;
6562 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6563 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6564 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6567 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6569 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6571 pm = (MonoMethodNormal*)m;
6574 m->flags = rmb->attrs;
6575 m->iflags = rmb->iattrs;
6576 m->name = mono_string_to_utf8 (rmb->name);
6580 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6582 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6583 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6586 m->signature->pinvoke = 1;
6587 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6589 m->signature->pinvoke = 1;
6591 } else if (!m->klass->dummy &&
6592 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6593 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6594 MonoMethodHeader *header;
6596 gint32 max_stack, i;
6597 gint32 num_locals = 0;
6598 gint32 num_clauses = 0;
6602 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6603 code_size = rmb->ilgen->code_len;
6604 max_stack = rmb->ilgen->max_stack;
6605 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6606 if (rmb->ilgen->ex_handlers)
6607 num_clauses = method_count_clauses (rmb->ilgen);
6610 code = mono_array_addr (rmb->code, guint8, 0);
6611 code_size = mono_array_length (rmb->code);
6612 /* we probably need to run a verifier on the code... */
6622 header = g_malloc0 (sizeof (MonoMethodHeader) +
6623 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6624 header->code_size = code_size;
6625 header->code = g_malloc (code_size);
6626 memcpy ((char*)header->code, code, code_size);
6627 header->max_stack = max_stack;
6628 header->init_locals = rmb->init_locals;
6629 header->num_locals = num_locals;
6631 for (i = 0; i < num_locals; ++i) {
6632 MonoReflectionLocalBuilder *lb =
6633 mono_array_get (rmb->ilgen->locals,
6634 MonoReflectionLocalBuilder*, i);
6636 header->locals [i] = g_new0 (MonoType, 1);
6637 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6640 header->num_clauses = num_clauses;
6642 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6647 if (rmb->generic_params) {
6648 int count = mono_array_length (rmb->generic_params);
6649 header->gen_params = g_new0 (MonoGenericParam, count);
6650 for (i = 0; i < count; i++) {
6651 MonoReflectionGenericParam *gp =
6652 mono_array_get (rmb->generic_params,
6653 MonoReflectionGenericParam*, i);
6655 header->gen_params [i] = *gp->type.type->data.generic_param;
6659 pm->header = header;
6663 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6666 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6668 for (i = 0; i < rmb->nrefs; ++i)
6669 mw->data = g_list_append (mw->data, rmb->refs [i]);
6674 /* Parameter names */
6677 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6678 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6679 for (i = 0; i <= m->signature->param_count; ++i) {
6680 MonoReflectionParamBuilder *pb;
6681 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6683 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6685 if (!method_aux->param_cattr)
6686 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6687 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6693 /* Parameter marshalling */
6696 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6697 MonoReflectionParamBuilder *pb;
6698 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6699 if (pb->marshal_info) {
6701 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6702 specs [pb->position] =
6703 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6707 if (specs != NULL) {
6709 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6710 method_aux->param_marshall = specs;
6713 if (klass->image->dynamic && method_aux)
6714 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6720 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6722 ReflectionMethodBuilder rmb;
6723 MonoMethodSignature *sig;
6725 sig = ctor_builder_to_signature (mb);
6727 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6729 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6730 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6732 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6733 /* ilgen is no longer needed */
6741 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6743 ReflectionMethodBuilder rmb;
6744 MonoMethodSignature *sig;
6746 sig = method_builder_to_signature (mb);
6748 reflection_methodbuilder_from_method_builder (&rmb, mb);
6750 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6751 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6753 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6754 /* ilgen is no longer needed */
6760 static MonoClassField*
6761 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6763 MonoClassField *field;
6770 field = g_new0 (MonoClassField, 1);
6772 field->name = mono_string_to_utf8 (fb->name);
6774 /* FIXME: handle type modifiers */
6775 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6776 field->type->attrs = fb->attrs;
6778 field->type = fb->type->type;
6780 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6781 field->data = mono_array_addr (fb->rva_data, char, 0);
6782 if (fb->offset != -1)
6783 field->offset = fb->offset;
6784 field->parent = klass;
6786 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6788 if (fb->def_value) {
6789 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6790 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6791 field->def_value = g_new0 (MonoConstant, 1);
6792 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6793 /* Copy the data from the blob since it might get realloc-ed */
6794 p = assembly->blob.data + idx;
6795 len = mono_metadata_decode_blob_size (p, &p2);
6797 field->def_value->value = g_malloc (len);
6798 memcpy (field->def_value->value, p, len);
6805 bind_nested_generic_parameters (MonoReflectionTypeBuilder *ntype, int type_argc,
6806 MonoType **types, MonoType *geninst)
6811 ntype_argc = ntype->generic_params ? mono_array_length (ntype->generic_params) : 0;
6813 if (ntype_argc > type_argc) {
6814 ntypes = g_new0 (MonoType *, ntype_argc);
6816 for (j = 0; j < type_argc; j++)
6817 ntypes [j] = types [j];
6819 for (j = type_argc; j < ntype_argc; j++) {
6820 MonoReflectionGenericParam *ngparam;
6821 MonoType *pt = g_new0 (MonoType, 1);
6823 ngparam = mono_array_get (ntype->generic_params, gpointer, j);
6825 pt->type = MONO_TYPE_VAR;
6826 pt->data.generic_param = ngparam->type.type->data.generic_param;
6833 return mono_reflection_bind_generic_parameters ((MonoReflectionType *) ntype, ntype_argc, ntypes, geninst);
6837 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
6838 MonoType **types, MonoType *nested_in)
6840 MonoClass *klass, *pklass = NULL;
6841 MonoReflectionTypeBuilder *tb = NULL;
6842 MonoGenericInst *ginst;
6843 MonoReflectionType *parent = NULL;
6848 klass = mono_class_from_mono_type (type->type);
6849 if (!klass->gen_params && !klass->generic_inst &&
6850 !(klass->nested_in && klass->nested_in->gen_params))
6853 mono_loader_lock ();
6855 domain = mono_object_domain (type);
6857 ginst = g_new0 (MonoGenericInst, 1);
6858 ginst->is_dynamic = 1;
6860 if (!klass->generic_inst) {
6861 ginst->type_argc = type_argc;
6862 ginst->type_argv = types;
6864 for (i = 0; i < ginst->type_argc; ++i) {
6865 if (!ginst->is_open)
6866 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
6869 ginst->generic_type = &klass->byval_arg;
6871 MonoGenericInst *kginst = klass->generic_inst;
6873 ginst->type_argc = kginst->type_argc;
6874 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6876 for (i = 0; i < ginst->type_argc; i++) {
6877 MonoType *t = kginst->type_argv [i];
6879 if (t->type == MONO_TYPE_VAR)
6880 t = types [t->data.generic_param->num];
6882 if (!ginst->is_open)
6883 ginst->is_open = mono_class_is_open_constructed_type (t);
6885 ginst->type_argv [i] = t;
6888 ginst->generic_type = kginst->generic_type;
6891 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
6894 mono_loader_unlock ();
6898 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
6899 tb = (MonoReflectionTypeBuilder *) type;
6902 parent = tb->parent;
6903 pklass = mono_class_from_mono_type (parent->type);
6906 pklass = klass->parent;
6908 parent = mono_type_get_object (domain, &pklass->byval_arg);
6911 geninst = g_new0 (MonoType, 1);
6912 geninst->type = MONO_TYPE_GENERICINST;
6913 geninst->data.generic_inst = ginst;
6915 if (pklass && pklass->generic_inst)
6916 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types, NULL);
6919 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
6921 icount = klass->interface_count;
6922 ginst->ifaces = g_new0 (MonoType *, icount);
6924 for (i = 0; i < icount; i++) {
6925 MonoReflectionType *itype;
6928 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
6930 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
6931 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types, NULL);
6932 if (!ginst->ifaces [i])
6933 ginst->ifaces [i] = itype->type;
6936 ginst->nested_in = nested_in;
6939 int ncount = tb->subtypes ? mono_array_length (tb->subtypes) : 0;
6940 for (i = 0; i < ncount; i++) {
6941 MonoReflectionTypeBuilder *ntype = mono_array_get (tb->subtypes, gpointer, i);
6942 MonoType *nested = bind_nested_generic_parameters (ntype, type_argc, types, geninst);
6944 ginst->nested = g_list_prepend (ginst->nested, nested);
6948 mono_class_create_generic (ginst);
6950 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
6952 mono_loader_unlock ();
6957 MonoReflectionMethod*
6958 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
6960 MonoMethod *method, *inflated;
6961 MonoReflectionMethodBuilder *mb = NULL;
6962 MonoGenericMethod *gmethod;
6965 MONO_ARCH_SAVE_REGS;
6966 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
6967 MonoReflectionTypeBuilder *tb;
6970 mb = (MonoReflectionMethodBuilder *) rmethod;
6971 tb = (MonoReflectionTypeBuilder *) mb->type;
6972 klass = mono_class_from_mono_type (tb->type.type);
6974 method = methodbuilder_to_mono_method (klass, mb);
6976 method = rmethod->method;
6978 count = method->signature->generic_param_count;
6979 if (count != mono_array_length (types))
6982 gmethod = g_new0 (MonoGenericMethod, 1);
6983 gmethod->generic_method = method;
6984 gmethod->mtype_argc = count;
6985 gmethod->mtype_argv = g_new0 (MonoType *, count);
6986 for (i = 0; i < count; i++) {
6987 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6988 gmethod->mtype_argv [i] = garg->type;
6991 gmethod->generic_inst = method->klass->generic_inst;
6993 inflated = mono_class_inflate_generic_method (method, gmethod, NULL);
6995 return mono_method_get_object (
6996 mono_object_domain (rmethod), inflated, NULL);
7000 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7002 MonoGenericMethod *gmethod;
7003 MonoGenericInst *ginst;
7005 ginst = type->type.type->data.generic_inst;
7007 gmethod = g_new0 (MonoGenericMethod, 1);
7008 gmethod->generic_method = method;
7009 gmethod->reflection_info = obj;
7010 gmethod->generic_inst = ginst;
7012 return mono_class_inflate_generic_method (method, gmethod, ginst->klass);
7016 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7021 klass = mono_class_from_mono_type (type->type.type);
7023 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7024 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7025 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7026 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7027 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7028 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7029 method = ((MonoReflectionMethod *) obj)->method;
7031 g_assert_not_reached ();
7033 return inflate_mono_method (type, method, obj);
7037 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7038 MonoArray *methods, MonoArray *ctors,
7039 MonoArray *fields, MonoArray *properties)
7041 MonoGenericInst *ginst;
7042 MonoDynamicGenericInst *dginst;
7043 MonoClass *klass, *gklass, *pklass;
7046 MONO_ARCH_SAVE_REGS;
7048 klass = mono_class_from_mono_type (type->type.type);
7049 ginst = type->type.type->data.generic_inst;
7051 if (ginst->initialized)
7054 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7056 gklass = mono_class_from_mono_type (ginst->generic_type);
7057 mono_class_init (gklass);
7060 pklass = mono_class_from_mono_type (ginst->parent);
7062 pklass = gklass->parent;
7064 mono_class_setup_parent (klass, pklass);
7066 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7067 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7068 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7069 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7071 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7072 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7073 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7074 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7076 for (i = 0; i < dginst->count_methods; i++) {
7077 MonoObject *obj = mono_array_get (methods, gpointer, i);
7079 dginst->methods [i] = inflate_method (type, obj);
7082 for (i = 0; i < dginst->count_ctors; i++) {
7083 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7085 dginst->ctors [i] = inflate_method (type, obj);
7088 for (i = 0; i < dginst->count_fields; i++) {
7089 MonoObject *obj = mono_array_get (fields, gpointer, i);
7090 MonoClassField *field;
7092 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7093 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7094 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7095 field = ((MonoReflectionField *) obj)->field;
7097 g_assert_not_reached ();
7099 dginst->fields [i] = *field;
7100 dginst->fields [i].generic_type = field->type;
7101 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst, NULL);
7104 for (i = 0; i < dginst->count_properties; i++) {
7105 MonoObject *obj = mono_array_get (properties, gpointer, i);
7106 MonoProperty *property = &dginst->properties [i];
7108 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7109 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7111 property->parent = klass;
7112 property->attrs = pb->attrs;
7113 property->name = mono_string_to_utf8 (pb->name);
7115 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7117 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7118 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7119 *property = *((MonoReflectionProperty *) obj)->property;
7122 property->get = inflate_mono_method (type, property->get, NULL);
7124 property->set = inflate_mono_method (type, property->set, NULL);
7126 g_assert_not_reached ();
7129 ginst->initialized = TRUE;
7133 ensure_runtime_vtable (MonoClass *klass)
7135 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7136 int i, num, j, onum;
7137 MonoMethod **overrides;
7139 if (!tb || klass->wastypebuilder)
7142 ensure_runtime_vtable (klass->parent);
7144 num = tb->ctors? mono_array_length (tb->ctors): 0;
7145 num += tb->num_methods;
7146 klass->method.count = num;
7147 klass->methods = g_new (MonoMethod*, num);
7148 num = tb->ctors? mono_array_length (tb->ctors): 0;
7149 for (i = 0; i < num; ++i)
7150 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7151 num = tb->num_methods;
7153 for (i = 0; i < num; ++i)
7154 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7156 klass->wastypebuilder = TRUE;
7157 if (tb->interfaces) {
7158 klass->interface_count = mono_array_length (tb->interfaces);
7159 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7160 for (i = 0; i < klass->interface_count; ++i) {
7161 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7162 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7166 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7167 for (i = 0; i < klass->method.count; ++i)
7168 klass->methods [i]->slot = i;
7173 for (i = 0; i < tb->num_methods; ++i) {
7174 MonoReflectionMethodBuilder *mb =
7175 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7176 if (mb->override_method)
7181 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7185 for (i = 0; i < tb->num_methods; ++i) {
7186 MonoReflectionMethodBuilder *mb =
7187 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7188 if (mb->override_method) {
7189 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7190 overrides [onum * 2] =
7191 mb->override_method->method;
7192 overrides [onum * 2 + 1] =
7195 g_assert (mb->mhandle);
7202 mono_class_setup_vtable (klass, overrides, onum);
7206 typebuilder_setup_fields (MonoClass *klass)
7208 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7209 MonoReflectionFieldBuilder *fb;
7210 MonoClassField *field;
7215 klass->field.count = tb->num_fields;
7216 klass->field.first = 0;
7217 klass->field.last = klass->field.count;
7219 if (!klass->field.count)
7222 klass->fields = g_new0 (MonoClassField, klass->field.count);
7224 for (i = 0; i < klass->field.count; ++i) {
7225 fb = mono_array_get (tb->fields, gpointer, i);
7226 field = &klass->fields [i];
7227 field->name = mono_string_to_utf8 (fb->name);
7229 /* FIXME: handle type modifiers */
7230 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7231 field->type->attrs = fb->attrs;
7233 field->type = fb->type->type;
7235 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7236 field->data = mono_array_addr (fb->rva_data, char, 0);
7237 if (fb->offset != -1)
7238 field->offset = fb->offset;
7239 field->parent = klass;
7241 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7243 if (fb->def_value) {
7244 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7245 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7246 field->def_value = g_new0 (MonoConstant, 1);
7247 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7248 /* Copy the data from the blob since it might get realloc-ed */
7249 p = assembly->blob.data + idx;
7250 len = mono_metadata_decode_blob_size (p, &p2);
7252 field->def_value->value = g_malloc (len);
7253 memcpy (field->def_value->value, p, len);
7256 mono_class_layout_fields (klass);
7260 typebuilder_setup_properties (MonoClass *klass)
7262 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7263 MonoReflectionPropertyBuilder *pb;
7266 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7267 klass->property.first = 0;
7268 klass->property.last = klass->property.count;
7270 klass->properties = g_new0 (MonoProperty, klass->property.count);
7271 for (i = 0; i < klass->property.count; ++i) {
7272 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7273 klass->properties [i].parent = klass;
7274 klass->properties [i].attrs = pb->attrs;
7275 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7277 klass->properties [i].get = pb->get_method->mhandle;
7279 klass->properties [i].set = pb->set_method->mhandle;
7284 typebuilder_setup_events (MonoClass *klass)
7286 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7287 MonoReflectionEventBuilder *eb;
7290 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7291 klass->event.first = 0;
7292 klass->event.last = klass->event.count;
7294 klass->events = g_new0 (MonoEvent, klass->event.count);
7295 for (i = 0; i < klass->event.count; ++i) {
7296 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7297 klass->events [i].parent = klass;
7298 klass->events [i].attrs = eb->attrs;
7299 klass->events [i].name = mono_string_to_utf8 (eb->name);
7301 klass->events [i].add = eb->add_method->mhandle;
7302 if (eb->remove_method)
7303 klass->events [i].remove = eb->remove_method->mhandle;
7304 if (eb->raise_method)
7305 klass->events [i].raise = eb->raise_method->mhandle;
7307 if (eb->other_methods) {
7308 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7309 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7310 MonoReflectionMethodBuilder *mb =
7311 mono_array_get (eb->other_methods,
7312 MonoReflectionMethodBuilder*, j);
7313 klass->events [i].other [j] = mb->mhandle;
7320 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7323 MonoReflectionType* res;
7325 MONO_ARCH_SAVE_REGS;
7327 klass = my_mono_class_from_mono_type (tb->type.type);
7329 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7332 * Fields to set in klass:
7333 * the various flags: delegate/unicode/contextbound etc.
7336 klass->flags = tb->attrs;
7338 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7339 /* No need to fully construct the type */
7340 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7342 /* enums are done right away */
7343 if (!klass->enumtype)
7344 ensure_runtime_vtable (klass);
7346 /* fields and object layout */
7347 if (klass->parent) {
7348 if (!klass->parent->size_inited)
7349 mono_class_init (klass->parent);
7350 klass->instance_size += klass->parent->instance_size;
7351 klass->class_size += klass->parent->class_size;
7352 klass->min_align = klass->parent->min_align;
7354 klass->instance_size = sizeof (MonoObject);
7355 klass->min_align = 1;
7358 /* FIXME: handle packing_size and instance_size */
7359 typebuilder_setup_fields (klass);
7361 typebuilder_setup_properties (klass);
7363 typebuilder_setup_events (klass);
7365 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7366 /* with enums res == tb: need to fix that. */
7367 if (!klass->enumtype)
7368 g_assert (res != (MonoReflectionType*)tb);
7372 MonoReflectionGenericParam *
7373 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7375 static MonoClass *System_Reflection_MonoGenericParam;
7377 MonoGenericParam *param;
7378 MonoReflectionGenericParam *res;
7381 if (!System_Reflection_MonoGenericParam) {
7382 System_Reflection_MonoGenericParam = mono_class_from_name (
7383 mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7384 g_assert (System_Reflection_MonoGenericParam);
7387 param = g_new0 (MonoGenericParam, 1);
7390 tb = (MonoReflectionTypeBuilder *) mb->type;
7392 domain = mono_object_domain (tb);
7393 image = (MonoImage*)tb->module->dynamic_image;
7395 param->method = NULL;
7396 param->name = mono_string_to_utf8 (name);
7399 res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7400 res->type.type = g_new0 (MonoType, 1);
7401 res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7402 res->type.type->data.generic_param = param;
7404 res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7412 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7414 MonoGenericParam *param;
7415 MonoReflectionMethodBuilder *mb = NULL;
7416 MonoReflectionTypeBuilder *tb;
7420 param = gparam->type.type->data.generic_param;
7421 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7422 param->constraints = g_new0 (MonoClass *, count + 1);
7423 for (i = 0; i < count; i++) {
7424 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7426 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7429 if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7430 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7431 tb = (MonoReflectionTypeBuilder *) mb->type;
7433 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7435 image = (MonoImage*)tb->module->dynamic_image;
7437 param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7439 gparam->initialized = TRUE;
7443 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7445 MonoDynamicImage *assembly = sig->module->dynamic_image;
7446 guint32 na = mono_array_length (sig->arguments);
7451 MONO_ARCH_SAVE_REGS;
7453 p = buf = g_malloc (10 + na * 10);
7455 mono_metadata_encode_value (0x07, p, &p);
7456 mono_metadata_encode_value (na, p, &p);
7457 for (i = 0; i < na; ++i) {
7458 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7459 encode_reflection_type (assembly, type, p, &p);
7463 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7464 p = mono_array_addr (result, char, 0);
7465 memcpy (p, buf, buflen);
7472 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7474 MonoDynamicImage *assembly = sig->module->dynamic_image;
7475 guint32 na = mono_array_length (sig->arguments);
7480 MONO_ARCH_SAVE_REGS;
7482 p = buf = g_malloc (10 + na * 10);
7484 mono_metadata_encode_value (0x06, p, &p);
7485 for (i = 0; i < na; ++i) {
7486 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7487 encode_reflection_type (assembly, type, p, &p);
7491 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7492 p = mono_array_addr (result, char, 0);
7493 memcpy (p, buf, buflen);
7500 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7502 ReflectionMethodBuilder rmb;
7503 MonoMethodSignature *sig;
7506 sig = dynamic_method_to_signature (mb);
7508 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7511 * Resolve references.
7513 rmb.nrefs = mb->nrefs;
7514 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7515 for (i = 0; i < mb->nrefs; ++i) {
7516 gpointer ref = resolve_object (mb->module->image,
7517 mono_array_get (mb->refs, MonoObject*, i));
7520 mono_raise_exception (mono_get_exception_type_load (NULL));
7527 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7531 /* ilgen is no longer needed */
7536 * mono_reflection_lookup_dynamic_token:
7538 * Finish the Builder object pointed to by TOKEN and return the corresponding
7539 * runtime structure.
7542 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7544 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7547 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7550 return resolve_object (image, obj);
7554 resolve_object (MonoImage *image, MonoObject *obj)
7556 gpointer result = NULL;
7558 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7559 result = mono_string_intern ((MonoString*)obj);
7562 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7563 MonoReflectionType *tb = (MonoReflectionType*)obj;
7564 result = mono_class_from_mono_type (tb->type);
7567 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7568 result = ((MonoReflectionMethod*)obj)->method;
7571 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7572 result = ((MonoReflectionMethod*)obj)->method;
7575 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7576 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7577 result = mb->mhandle;
7579 /* Type is not yet created */
7580 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7582 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7585 * Hopefully this has been filled in by calling CreateType() on the
7589 * TODO: This won't work if the application finishes another
7590 * TypeBuilder instance instead of this one.
7592 result = mb->mhandle;
7595 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7596 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7598 result = cb->mhandle;
7600 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7602 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7603 result = cb->mhandle;
7606 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7607 result = ((MonoReflectionField*)obj)->field;
7610 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7611 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7612 result = fb->handle;
7615 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7617 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7618 result = fb->handle;
7621 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7622 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7625 klass = tb->type.type->data.klass;
7626 if (klass->wastypebuilder) {
7627 /* Already created */
7631 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7632 result = tb->type.type->data.klass;
7636 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7637 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7638 MonoMethodSignature *sig;
7641 if (helper->arguments)
7642 nargs = mono_array_length (helper->arguments);
7646 sig = mono_metadata_signature_alloc (image, nargs);
7647 sig->explicit_this = helper->call_conv & 64;
7648 sig->hasthis = helper->call_conv & 32;
7650 if (helper->call_conv == 0) /* unmanaged */
7651 sig->call_convention = helper->unmanaged_call_conv - 1;
7653 if (helper->call_conv & 0x02)
7654 sig->call_convention = MONO_CALL_VARARG;
7656 sig->call_convention = MONO_CALL_DEFAULT;
7658 sig->param_count = nargs;
7659 /* TODO: Copy type ? */
7660 sig->ret = helper->return_type->type;
7661 for (i = 0; i < nargs; ++i) {
7662 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7663 sig->params [i] = rt->type;
7669 g_print (obj->vtable->klass->name);
7670 g_assert_not_reached ();