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);
142 alloc_table (MonoDynamicTable *table, guint nrows)
145 g_assert (table->columns);
146 if (nrows + 1 >= table->alloc_rows) {
147 while (nrows + 1 >= table->alloc_rows)
148 if (table->alloc_rows == 0)
149 table->alloc_rows = 16;
151 table->alloc_rows *= 2;
154 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
156 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
161 make_room_in_stream (MonoDynamicStream *stream, int size)
163 while (stream->alloc_size <= size) {
164 if (stream->alloc_size < 4096)
165 stream->alloc_size = 4096;
167 stream->alloc_size *= 2;
170 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
172 stream->data = ALLOC_ATOMIC (stream->alloc_size);
176 string_heap_insert (MonoDynamicStream *sh, const char *str)
180 gpointer oldkey, oldval;
182 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
183 return GPOINTER_TO_UINT (oldval);
185 len = strlen (str) + 1;
187 if (idx + len > sh->alloc_size)
188 make_room_in_stream (sh, idx + len);
191 * We strdup the string even if we already copy them in sh->data
192 * so that the string pointers in the hash remain valid even if
193 * we need to realloc sh->data. We may want to avoid that later.
195 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
196 memcpy (sh->data + idx, str, len);
202 string_heap_init (MonoDynamicStream *sh)
205 sh->alloc_size = 4096;
206 sh->data = ALLOC_ATOMIC (4096);
207 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
208 string_heap_insert (sh, "");
211 #if 0 /* never used */
213 string_heap_free (MonoDynamicStream *sh)
215 FREE_ATOMIC (sh->data);
216 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
217 g_hash_table_destroy (sh->hash);
222 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
225 if (stream->alloc_size < stream->index + len)
226 make_room_in_stream (stream, stream->index + len);
227 memcpy (stream->data + stream->index, data, len);
229 stream->index += len;
231 * align index? Not without adding an additional param that controls it since
232 * we may store a blob value in pieces.
238 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
241 if (stream->alloc_size < stream->index + len)
242 make_room_in_stream (stream, stream->index + len);
243 memset (stream->data + stream->index, 0, len);
245 stream->index += len;
250 stream_data_align (MonoDynamicStream *stream)
253 guint32 count = stream->index % 4;
255 /* we assume the stream data will be aligned */
257 mono_image_add_stream_data (stream, buf, 4 - count);
261 mono_blob_entry_hash (const char* str)
265 len = mono_metadata_decode_blob_size (str, &str);
269 for (str += 1; str < end; str++)
270 h = (h << 5) - h + *str;
278 mono_blob_entry_equal (const char *str1, const char *str2) {
282 len = mono_metadata_decode_blob_size (str1, &end1);
283 len2 = mono_metadata_decode_blob_size (str2, &end2);
286 return memcmp (end1, end2, len) == 0;
290 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
294 gpointer oldkey, oldval;
296 copy = ALLOC_ATOMIC (s1+s2);
297 memcpy (copy, b1, s1);
298 memcpy (copy + s1, b2, s2);
299 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
301 idx = GPOINTER_TO_UINT (oldval);
303 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
304 mono_image_add_stream_data (&assembly->blob, b2, s2);
305 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
311 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
312 * dest may be misaligned.
315 swap_with_size (char *dest, const char* val, int len, int nelem) {
316 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
319 for (elem = 0; elem < nelem; ++elem) {
345 g_assert_not_reached ();
351 memcpy (dest, val, len * nelem);
356 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
360 guint32 idx = 0, len;
362 len = str->length * 2;
363 mono_metadata_encode_value (len, b, &b);
364 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
366 char *swapped = g_malloc (2 * mono_string_length (str));
367 const char *p = (const char*)mono_string_chars (str);
369 swap_with_size (swapped, p, 2, mono_string_length (str));
370 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
374 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
379 /* modified version needed to handle building corlib */
381 my_mono_class_from_mono_type (MonoType *type) {
382 switch (type->type) {
383 case MONO_TYPE_ARRAY:
385 case MONO_TYPE_SZARRAY:
386 case MONO_TYPE_GENERICINST:
387 return mono_class_from_mono_type (type);
390 g_assert (type->data.generic_param->pklass);
391 return type->data.generic_param->pklass;
393 /* should be always valid when we reach this case... */
394 return type->data.klass;
399 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
402 g_assert_not_reached ();
407 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
411 case MONO_TYPE_BOOLEAN:
425 case MONO_TYPE_STRING:
426 case MONO_TYPE_OBJECT:
427 case MONO_TYPE_TYPEDBYREF:
428 mono_metadata_encode_value (type->type, p, &p);
431 mono_metadata_encode_value (type->type, p, &p);
432 encode_type (assembly, type->data.type, p, &p);
434 case MONO_TYPE_SZARRAY:
435 mono_metadata_encode_value (type->type, p, &p);
436 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
439 case MONO_TYPE_VALUETYPE:
440 case MONO_TYPE_CLASS: {
441 MonoClass *k = mono_class_from_mono_type (type);
442 mono_metadata_encode_value (type->type, p, &p);
444 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
445 * otherwise two typerefs could point to the same type, leading to
446 * verification errors.
448 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
452 case MONO_TYPE_ARRAY:
453 mono_metadata_encode_value (type->type, p, &p);
454 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
455 mono_metadata_encode_value (type->data.array->rank, p, &p);
456 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
457 mono_metadata_encode_value (0, p, &p);
459 case MONO_TYPE_GENERICINST: {
461 mono_metadata_encode_value (type->type, p, &p);
462 encode_type (assembly, type->data.generic_inst->generic_type, p, &p);
463 mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p);
464 for (i = 0; i < type->data.generic_inst->type_argc; ++i) {
465 encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p);
471 mono_metadata_encode_value (type->type, p, &p);
472 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
476 g_error ("need to encode type %x", type->type);
482 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
485 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
489 encode_type (assembly, type->type, p, endbuf);
493 g_assert_not_reached ();
498 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
503 for (i = 0; i < mono_array_length (modreq); ++i) {
504 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
505 *p = MONO_TYPE_CMOD_REQD;
507 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
511 for (i = 0; i < mono_array_length (modopt); ++i) {
512 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
513 *p = MONO_TYPE_CMOD_OPT;
515 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
522 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
527 guint32 nparams = sig->param_count;
528 guint32 size = 10 + nparams * 10;
536 p = buf = g_malloc (size);
538 * FIXME: vararg, explicit_this, differenc call_conv values...
540 *p = sig->call_convention;
542 *p |= 0x20; /* hasthis */
543 if (sig->generic_param_count)
544 *p |= 0x10; /* generic */
546 if (sig->generic_param_count)
547 mono_metadata_encode_value (sig->generic_param_count, p, &p);
548 mono_metadata_encode_value (nparams, p, &p);
549 encode_type (assembly, sig->ret, p, &p);
550 for (i = 0; i < nparams; ++i)
551 encode_type (assembly, sig->params [i], p, &p);
553 g_assert (p - buf < size);
554 mono_metadata_encode_value (p-buf, b, &b);
555 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
561 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
564 * FIXME: reuse code from method_encode_signature().
569 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
570 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
571 guint32 size = 21 + nparams * 20;
576 p = buf = g_malloc (size);
577 /* LAMESPEC: all the call conv spec is foobared */
578 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
579 if (mb->call_conv & 2)
580 *p |= 0x5; /* vararg */
581 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
582 *p |= 0x20; /* hasthis */
584 *p |= 0x10; /* generic */
587 mono_metadata_encode_value (ngparams, p, &p);
588 mono_metadata_encode_value (nparams, p, &p);
589 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
590 encode_reflection_type (assembly, mb->rtype, p, &p);
591 for (i = 0; i < nparams; ++i) {
592 MonoArray *modreq = NULL;
593 MonoArray *modopt = NULL;
594 MonoReflectionType *pt;
596 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
597 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
598 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
599 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
600 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
601 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
602 encode_reflection_type (assembly, pt, p, &p);
605 g_assert (p - buf < size);
606 mono_metadata_encode_value (p-buf, b, &b);
607 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
613 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
615 MonoDynamicTable *table;
618 guint32 idx, sig_idx, size;
619 guint nl = mono_array_length (ilgen->locals);
626 p = buf = g_malloc (size);
627 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
628 idx = table->next_idx ++;
630 alloc_table (table, table->rows);
631 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
633 mono_metadata_encode_value (0x07, p, &p);
634 mono_metadata_encode_value (nl, p, &p);
635 for (i = 0; i < nl; ++i) {
636 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
637 encode_reflection_type (assembly, lb->type, p, &p);
639 g_assert (p - buf < size);
640 mono_metadata_encode_value (p-buf, b, &b);
641 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
644 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
650 method_count_clauses (MonoReflectionILGen *ilgen)
652 guint32 num_clauses = 0;
655 MonoILExceptionInfo *ex_info;
656 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
657 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
658 if (ex_info->handlers)
659 num_clauses += mono_array_length (ex_info->handlers);
667 static MonoExceptionClause*
668 method_encode_clauses (MonoDynamicImage *assembly,
669 MonoReflectionILGen *ilgen, guint32 num_clauses)
671 MonoExceptionClause *clauses;
672 MonoExceptionClause *clause;
673 MonoILExceptionInfo *ex_info;
674 MonoILExceptionBlock *ex_block;
675 guint32 finally_start;
676 int i, j, clause_index;;
678 clauses = g_new0 (MonoExceptionClause, num_clauses);
681 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
682 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
683 finally_start = ex_info->start + ex_info->len;
684 g_assert (ex_info->handlers);
685 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
686 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
687 clause = &(clauses [clause_index]);
689 clause->flags = ex_block->type;
690 clause->try_offset = ex_info->start;
692 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
693 clause->try_len = finally_start - ex_info->start;
695 clause->try_len = ex_info->len;
696 clause->handler_offset = ex_block->start;
697 clause->handler_len = ex_block->len;
698 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
699 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
700 if (ex_block->extype) {
701 mono_g_hash_table_insert (assembly->tokens,
702 GUINT_TO_POINTER (clause->token_or_filter),
705 finally_start = ex_block->start + ex_block->len;
715 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
721 gint32 num_locals = 0;
722 gint32 num_exception = 0;
725 char fat_header [12];
728 guint32 local_sig = 0;
729 guint32 header_size = 12;
732 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
733 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
734 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
735 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
739 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
741 code = mb->ilgen->code;
742 code_size = mb->ilgen->code_len;
743 max_stack = mb->ilgen->max_stack;
744 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
745 if (mb->ilgen->ex_handlers)
746 num_exception = method_count_clauses (mb->ilgen);
750 mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
752 code_size = mono_array_length (code);
753 max_stack = 8; /* we probably need to run a verifier on the code... */
756 /* check for exceptions, maxstack, locals */
757 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
759 if (code_size < 64 && !(code_size & 1)) {
760 flags = (code_size << 2) | 0x2;
761 } else if (code_size < 32 && (code_size & 1)) {
762 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
766 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
767 /* add to the fixup todo list */
768 if (mb->ilgen && mb->ilgen->num_token_fixups)
769 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
770 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
771 return assembly->text_rva + idx;
775 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
777 * FIXME: need to set also the header size in fat_flags.
778 * (and more sects and init locals flags)
782 fat_flags |= METHOD_HEADER_MORE_SECTS;
784 fat_flags |= METHOD_HEADER_INIT_LOCALS;
785 fat_header [0] = fat_flags;
786 fat_header [1] = (header_size / 4 ) << 4;
787 shortp = (guint16*)(fat_header + 2);
788 *shortp = GUINT16_TO_LE (max_stack);
789 intp = (guint32*)(fat_header + 4);
790 *intp = GUINT32_TO_LE (code_size);
791 intp = (guint32*)(fat_header + 8);
792 *intp = GUINT32_TO_LE (local_sig);
793 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
794 /* add to the fixup todo list */
795 if (mb->ilgen && mb->ilgen->num_token_fixups)
796 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
798 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
800 unsigned char sheader [4];
801 MonoExceptionClause clause;
802 MonoILExceptionInfo * ex_info;
803 MonoILExceptionBlock * ex_block;
806 stream_data_align (&assembly->code);
807 /* always use fat format for now */
808 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
809 num_exception *= sizeof (MonoExceptionClause);
810 num_exception += 4; /* include the size of the header */
811 sheader [1] = num_exception & 0xff;
812 sheader [2] = (num_exception >> 8) & 0xff;
813 sheader [3] = (num_exception >> 16) & 0xff;
814 mono_image_add_stream_data (&assembly->code, sheader, 4);
815 /* fat header, so we are already aligned */
817 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
818 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
819 if (ex_info->handlers) {
820 int finally_start = ex_info->start + ex_info->len;
821 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
822 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
823 clause.flags = GUINT32_TO_LE (ex_block->type);
824 clause.try_offset = GUINT32_TO_LE (ex_info->start);
825 /* need fault, too, probably */
826 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
827 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
829 clause.try_len = GUINT32_TO_LE (ex_info->len);
830 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
831 clause.handler_len = GUINT32_TO_LE (ex_block->len);
832 finally_start = ex_block->start + ex_block->len;
833 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
834 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
835 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
836 /*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",
837 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);*/
838 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
841 g_error ("No clauses for ex info block %d", i);
845 return assembly->text_rva + idx;
849 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
852 MonoDynamicTable *table;
855 table = &assembly->tables [table_idx];
857 g_assert (col < table->columns);
859 values = table->values + table->columns;
860 for (i = 1; i <= table->rows; ++i) {
861 if (values [col] == token)
863 values += table->columns;
868 static GHashTable *dynamic_custom_attrs = NULL;
870 static MonoCustomAttrInfo*
871 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
874 MonoCustomAttrInfo *ainfo;
875 MonoReflectionCustomAttr *cattr;
879 /* FIXME: check in assembly the Run flag is set */
881 count = mono_array_length (cattrs);
883 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
885 ainfo->image = image;
886 ainfo->num_attrs = count;
887 for (i = 0; i < count; ++i) {
888 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
889 ainfo->attrs [i].ctor = cattr->ctor->method;
890 /* FIXME: might want to memdup the data here */
891 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
892 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
899 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
901 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
906 if (!dynamic_custom_attrs)
907 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
909 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
913 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
915 /* they are cached, so we don't free them */
916 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
922 * idx is the table index of the object
923 * type is one of CUSTOM_ATTR_*
926 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
928 MonoDynamicTable *table;
929 MonoReflectionCustomAttr *cattr;
931 guint32 count, i, token;
935 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
938 count = mono_array_length (cattrs);
939 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
940 table->rows += count;
941 alloc_table (table, table->rows);
942 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
943 idx <<= CUSTOM_ATTR_BITS;
945 for (i = 0; i < count; ++i) {
946 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
947 values [MONO_CUSTOM_ATTR_PARENT] = idx;
948 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
949 type = mono_metadata_token_index (token);
950 type <<= CUSTOM_ATTR_TYPE_BITS;
951 switch (mono_metadata_token_table (token)) {
952 case MONO_TABLE_METHOD:
953 type |= CUSTOM_ATTR_TYPE_METHODDEF;
955 case MONO_TABLE_MEMBERREF:
956 type |= CUSTOM_ATTR_TYPE_MEMBERREF;
959 g_warning ("got wrong token in custom attr");
962 values [MONO_CUSTOM_ATTR_TYPE] = type;
964 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
965 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
966 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
967 values += MONO_CUSTOM_ATTR_SIZE;
973 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
974 MonoArray *permissions)
976 MonoDynamicTable *table;
978 guint32 count, i, idx;
979 MonoReflectionPermissionSet *perm;
984 count = mono_array_length (permissions);
985 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
986 table->rows += count;
987 alloc_table (table, table->rows);
989 for (i = 0; i < mono_array_length (permissions); ++i) {
990 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
992 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
994 idx = mono_metadata_token_index (parent_token);
995 idx <<= HAS_DECL_SECURITY_BITS;
996 switch (mono_metadata_token_table (parent_token)) {
997 case MONO_TABLE_TYPEDEF:
998 idx |= HAS_DECL_SECURITY_TYPEDEF;
1000 case MONO_TABLE_METHOD:
1001 idx |= HAS_DECL_SECURITY_METHODDEF;
1003 case MONO_TABLE_ASSEMBLY:
1004 idx |= HAS_DECL_SECURITY_ASSEMBLY;
1007 g_assert_not_reached ();
1010 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1011 values [MONO_DECL_SECURITY_PARENT] = idx;
1012 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1019 * Fill in the MethodDef and ParamDef tables for a method.
1020 * This is used for both normal methods and constructors.
1023 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1025 MonoDynamicTable *table;
1030 /* room in this table is already allocated */
1031 table = &assembly->tables [MONO_TABLE_METHOD];
1032 *mb->table_idx = table->next_idx ++;
1033 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1034 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1035 name = mono_string_to_utf8 (mb->name);
1036 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1038 values [MONO_METHOD_FLAGS] = mb->attrs;
1039 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1040 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1041 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1043 table = &assembly->tables [MONO_TABLE_PARAM];
1044 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1046 mono_image_add_decl_security (assembly,
1047 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1051 MonoDynamicTable *mtable;
1054 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1055 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1058 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1059 if (mono_array_get (mb->pinfo, gpointer, i))
1062 table->rows += count;
1063 alloc_table (table, table->rows);
1064 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1065 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1066 MonoReflectionParamBuilder *pb;
1067 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1068 values [MONO_PARAM_FLAGS] = pb->attrs;
1069 values [MONO_PARAM_SEQUENCE] = i;
1070 if (pb->name != NULL) {
1071 name = mono_string_to_utf8 (pb->name);
1072 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1076 values [MONO_PARAM_NAME] = 0;
1077 values += MONO_PARAM_SIZE;
1078 if (pb->marshal_info) {
1080 alloc_table (mtable, mtable->rows);
1081 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1082 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1083 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1085 pb->table_idx = table->next_idx++;
1092 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1093 MonoReflectionMethodBuilder *mb)
1095 rmb->ilgen = mb->ilgen;
1096 rmb->rtype = mb->rtype;
1097 rmb->parameters = mb->parameters;
1098 rmb->generic_params = mb->generic_params;
1099 rmb->pinfo = mb->pinfo;
1100 rmb->attrs = mb->attrs;
1101 rmb->iattrs = mb->iattrs;
1102 rmb->call_conv = mb->call_conv;
1103 rmb->code = mb->code;
1104 rmb->type = mb->type;
1105 rmb->name = mb->name;
1106 rmb->table_idx = &mb->table_idx;
1107 rmb->init_locals = mb->init_locals;
1108 rmb->return_modreq = mb->return_modreq;
1109 rmb->return_modopt = mb->return_modopt;
1110 rmb->param_modreq = mb->param_modreq;
1111 rmb->param_modopt = mb->param_modopt;
1112 rmb->permissions = mb->permissions;
1113 rmb->mhandle = mb->mhandle;
1119 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1120 MonoReflectionCtorBuilder *mb)
1122 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1124 rmb->ilgen = mb->ilgen;
1125 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1126 rmb->parameters = mb->parameters;
1127 rmb->generic_params = NULL;
1128 rmb->pinfo = mb->pinfo;
1129 rmb->attrs = mb->attrs;
1130 rmb->iattrs = mb->iattrs;
1131 rmb->call_conv = mb->call_conv;
1133 rmb->type = mb->type;
1134 rmb->name = mono_string_new (mono_domain_get (), name);
1135 rmb->table_idx = &mb->table_idx;
1136 rmb->init_locals = mb->init_locals;
1137 rmb->return_modreq = NULL;
1138 rmb->return_modopt = NULL;
1139 rmb->param_modreq = mb->param_modreq;
1140 rmb->param_modopt = mb->param_modopt;
1141 rmb->permissions = mb->permissions;
1142 rmb->mhandle = mb->mhandle;
1148 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1149 MonoReflectionDynamicMethod *mb)
1151 rmb->ilgen = mb->ilgen;
1152 rmb->rtype = mb->rtype;
1153 rmb->parameters = mb->parameters;
1154 rmb->generic_params = NULL;
1156 rmb->attrs = mb->attrs;
1158 rmb->call_conv = mb->call_conv;
1161 rmb->name = mb->name;
1162 rmb->table_idx = NULL;
1163 rmb->init_locals = mb->init_locals;
1164 rmb->return_modreq = NULL;
1165 rmb->return_modopt = NULL;
1166 rmb->param_modreq = NULL;
1167 rmb->param_modopt = NULL;
1168 rmb->permissions = NULL;
1169 rmb->mhandle = mb->mhandle;
1175 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1177 MonoDynamicTable *table;
1180 ReflectionMethodBuilder rmb;
1183 reflection_methodbuilder_from_method_builder (&rmb, mb);
1185 mono_image_basic_method (&rmb, assembly);
1187 if (mb->dll) { /* It's a P/Invoke method */
1189 int charset = mb->charset & 0xf;
1190 int lasterr = mb->charset & 0x40;
1191 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1193 alloc_table (table, table->rows);
1194 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1195 /* map CharSet values to on-disk values */
1197 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1198 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1199 name = mono_string_to_utf8 (mb->dllentry);
1200 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1202 name = mono_string_to_utf8 (mb->dll);
1203 moduleref = string_heap_insert (&assembly->sheap, name);
1205 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1206 table = &assembly->tables [MONO_TABLE_MODULEREF];
1208 alloc_table (table, table->rows);
1209 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1210 values [MONO_IMPLMAP_SCOPE] = table->rows;
1214 if (mb->override_method) {
1215 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1217 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1219 alloc_table (table, table->rows);
1220 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1221 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1222 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1223 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1224 switch (mono_metadata_token_table (tok)) {
1225 case MONO_TABLE_MEMBERREF:
1226 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1228 case MONO_TABLE_METHOD:
1229 tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1232 g_assert_not_reached ();
1234 values [MONO_METHODIMPL_DECLARATION] = tok;
1237 if (mb->generic_params) {
1238 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1239 table->rows += mono_array_length (mb->generic_params);
1240 alloc_table (table, table->rows);
1241 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1242 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1244 mono_image_get_generic_param_info (
1245 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1252 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1254 ReflectionMethodBuilder rmb;
1256 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1258 mono_image_basic_method (&rmb, assembly);
1262 type_get_fully_qualified_name (MonoType *type) {
1263 char *name, *result;
1267 name = mono_type_get_name (type);
1268 klass = my_mono_class_from_mono_type (type);
1269 ta = klass->image->assembly;
1271 /* missing public key */
1272 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1273 name, ta->aname.name,
1274 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1275 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
1281 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1285 klass = my_mono_class_from_mono_type (type);
1286 ta = klass->image->assembly;
1287 if (ta == ass || klass->image == mono_defaults.corlib)
1288 return mono_type_get_name (type);
1290 return type_get_fully_qualified_name (type);
1294 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1296 char blob_size [64];
1297 char *b = blob_size;
1302 if (!assembly->save)
1305 p = buf = g_malloc (64);
1307 mono_metadata_encode_value (0x06, p, &p);
1308 /* encode custom attributes before the type */
1309 encode_type (assembly, type, p, &p);
1310 g_assert (p-buf < 64);
1311 mono_metadata_encode_value (p-buf, b, &b);
1312 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1318 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1320 char blob_size [64];
1321 char *b = blob_size;
1326 p = buf = g_malloc (64);
1328 mono_metadata_encode_value (0x06, p, &p);
1329 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1330 /* encode custom attributes before the type */
1331 encode_reflection_type (assembly, fb->type, p, &p);
1332 g_assert (p-buf < 64);
1333 mono_metadata_encode_value (p-buf, b, &b);
1334 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1340 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1341 char blob_size [64];
1342 char *b = blob_size;
1345 guint32 idx = 0, len = 0, dummy = 0;
1347 p = buf = g_malloc (64);
1349 *ret_type = MONO_TYPE_CLASS;
1351 box_val = (char*)&dummy;
1353 box_val = ((char*)val) + sizeof (MonoObject);
1354 *ret_type = val->vtable->klass->byval_arg.type;
1357 switch (*ret_type) {
1358 case MONO_TYPE_BOOLEAN:
1363 case MONO_TYPE_CHAR:
1378 case MONO_TYPE_VALUETYPE:
1379 if (val->vtable->klass->enumtype) {
1380 *ret_type = val->vtable->klass->enum_basetype->type;
1383 g_error ("we can't encode valuetypes");
1384 case MONO_TYPE_CLASS:
1386 case MONO_TYPE_STRING: {
1387 MonoString *str = (MonoString*)val;
1388 /* there is no signature */
1389 len = str->length * 2;
1390 mono_metadata_encode_value (len, b, &b);
1391 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1393 char *swapped = g_malloc (2 * mono_string_length (str));
1394 const char *p = (const char*)mono_string_chars (str);
1396 swap_with_size (swapped, p, 2, mono_string_length (str));
1397 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1401 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1408 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1411 /* there is no signature */
1412 mono_metadata_encode_value (len, b, &b);
1413 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1414 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1415 swap_with_size (blob_size, box_val, len, 1);
1416 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1418 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1426 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1427 char blob_size [64];
1428 char *b = blob_size;
1429 char *p, *buf, *str;
1430 guint32 idx, len, bufsize = 256;
1432 p = buf = g_malloc (bufsize);
1434 switch (minfo->type) {
1435 case MONO_NATIVE_BYVALTSTR:
1436 case MONO_NATIVE_BYVALARRAY:
1437 mono_metadata_encode_value (minfo->type, p, &p);
1438 mono_metadata_encode_value (minfo->count, p, &p);
1440 /* FIXME: handle ARRAY and other unmanaged types that need extra info */
1441 case MONO_NATIVE_CUSTOM:
1442 mono_metadata_encode_value (minfo->type, p, &p);
1444 str = mono_string_to_utf8 (minfo->guid);
1446 mono_metadata_encode_value (len, p, &p);
1447 memcpy (p, str, len);
1451 mono_metadata_encode_value (0, p, &p);
1453 if (minfo->marshaltype) {
1454 str = mono_string_to_utf8 (minfo->marshaltype);
1456 mono_metadata_encode_value (len, p, &p);
1457 if (p + len >= buf + bufsize) {
1460 buf = g_realloc (buf, bufsize);
1463 memcpy (p, str, len);
1467 mono_metadata_encode_value (0, p, &p);
1469 if (minfo->marshaltyperef) {
1470 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1472 mono_metadata_encode_value (len, p, &p);
1473 if (p + len >= buf + bufsize) {
1476 buf = g_realloc (buf, bufsize);
1479 memcpy (p, str, len);
1483 mono_metadata_encode_value (0, p, &p);
1485 if (minfo->mcookie) {
1486 str = mono_string_to_utf8 (minfo->mcookie);
1488 mono_metadata_encode_value (len, p, &p);
1489 if (p + len >= buf + bufsize) {
1492 buf = g_realloc (buf, bufsize);
1495 memcpy (p, str, len);
1499 mono_metadata_encode_value (0, p, &p);
1503 mono_metadata_encode_value (minfo->type, p, &p);
1507 mono_metadata_encode_value (len, b, &b);
1508 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1514 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1516 MonoDynamicTable *table;
1520 /* maybe this fixup should be done in the C# code */
1521 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1522 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1523 table = &assembly->tables [MONO_TABLE_FIELD];
1524 fb->table_idx = table->next_idx ++;
1525 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1526 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1527 name = mono_string_to_utf8 (fb->name);
1528 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1530 values [MONO_FIELD_FLAGS] = fb->attrs;
1531 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1533 if (fb->offset != -1) {
1534 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1536 alloc_table (table, table->rows);
1537 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1538 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1539 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1541 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1542 guint32 field_type = 0;
1543 table = &assembly->tables [MONO_TABLE_CONSTANT];
1545 alloc_table (table, table->rows);
1546 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1547 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
1548 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1549 values [MONO_CONSTANT_TYPE] = field_type;
1550 values [MONO_CONSTANT_PADDING] = 0;
1552 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1554 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1556 alloc_table (table, table->rows);
1557 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1558 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1560 * We store it in the code section because it's simpler for now.
1563 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1565 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1566 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1568 if (fb->marshal_info) {
1569 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1571 alloc_table (table, table->rows);
1572 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1573 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_FIELDSREF;
1574 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1579 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1583 char *b = blob_size;
1584 guint32 nparams = 0;
1585 MonoReflectionMethodBuilder *mb = fb->get_method;
1586 MonoReflectionMethodBuilder *smb = fb->set_method;
1587 guint32 idx, i, size;
1589 if (mb && mb->parameters)
1590 nparams = mono_array_length (mb->parameters);
1591 if (!mb && smb && smb->parameters)
1592 nparams = mono_array_length (smb->parameters) - 1;
1593 size = 24 + nparams * 10;
1594 buf = p = g_malloc (size);
1597 mono_metadata_encode_value (nparams, p, &p);
1599 encode_reflection_type (assembly, mb->rtype, p, &p);
1600 for (i = 0; i < nparams; ++i) {
1601 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1602 encode_reflection_type (assembly, pt, p, &p);
1605 /* the property type is the last param */
1606 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1607 for (i = 0; i < nparams; ++i) {
1608 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1609 encode_reflection_type (assembly, pt, p, &p);
1613 g_assert (p - buf < size);
1614 mono_metadata_encode_value (p-buf, b, &b);
1615 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1621 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1623 MonoDynamicTable *table;
1626 guint num_methods = 0;
1630 * we need to set things in the following tables:
1631 * PROPERTYMAP (info already filled in _get_type_info ())
1632 * PROPERTY (rows already preallocated in _get_type_info ())
1633 * METHOD (method info already done with the generic method code)
1636 table = &assembly->tables [MONO_TABLE_PROPERTY];
1637 pb->table_idx = table->next_idx ++;
1638 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1639 name = mono_string_to_utf8 (pb->name);
1640 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1642 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1643 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1645 /* FIXME: we still don't handle 'other' methods */
1646 if (pb->get_method) num_methods ++;
1647 if (pb->set_method) num_methods ++;
1649 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1650 table->rows += num_methods;
1651 alloc_table (table, table->rows);
1653 if (pb->get_method) {
1654 semaidx = table->next_idx ++;
1655 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1656 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1657 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1658 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1660 if (pb->set_method) {
1661 semaidx = table->next_idx ++;
1662 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1663 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1664 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1665 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
1670 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1672 MonoDynamicTable *table;
1675 guint num_methods = 0;
1679 * we need to set things in the following tables:
1680 * EVENTMAP (info already filled in _get_type_info ())
1681 * EVENT (rows already preallocated in _get_type_info ())
1682 * METHOD (method info already done with the generic method code)
1685 table = &assembly->tables [MONO_TABLE_EVENT];
1686 eb->table_idx = table->next_idx ++;
1687 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1688 name = mono_string_to_utf8 (eb->name);
1689 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1691 values [MONO_EVENT_FLAGS] = eb->attrs;
1692 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1695 * FIXME: we still don't handle 'other' methods
1697 if (eb->add_method) num_methods ++;
1698 if (eb->remove_method) num_methods ++;
1699 if (eb->raise_method) num_methods ++;
1701 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1702 table->rows += num_methods;
1703 alloc_table (table, table->rows);
1705 if (eb->add_method) {
1706 semaidx = table->next_idx ++;
1707 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1708 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1709 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1710 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1712 if (eb->remove_method) {
1713 semaidx = table->next_idx ++;
1714 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1715 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1716 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1717 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1719 if (eb->raise_method) {
1720 semaidx = table->next_idx ++;
1721 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1722 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1723 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1724 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1729 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1731 MonoDynamicTable *table;
1732 guint32 num_constraints, i;
1736 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1737 num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
1738 table->rows += num_constraints;
1739 alloc_table (table, table->rows);
1741 for (i = 0; i < num_constraints; i++) {
1742 MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
1744 table_idx = table->next_idx ++;
1745 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1747 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1748 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
1753 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1755 MonoDynamicTable *table;
1756 MonoGenericParam *param;
1760 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1761 table_idx = table->next_idx ++;
1762 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
1764 param = gparam->type.type->data.generic_param;
1766 values [MONO_GENERICPARAM_OWNER] = owner;
1767 values [MONO_GENERICPARAM_FLAGS] = param->flags;
1768 values [MONO_GENERICPARAM_NUMBER] = param->num;
1769 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
1770 values [MONO_GENERICPARAM_KIND] = 0;
1771 values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
1773 if (gparam->constraints)
1774 encode_constraints (gparam, table_idx, assembly);
1778 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
1780 MonoDynamicTable *table;
1783 guint32 cols [MONO_ASSEMBLY_SIZE];
1787 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1790 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
1791 table = &assembly->tables [MONO_TABLE_MODULEREF];
1792 token = table->next_idx ++;
1794 alloc_table (table, table->rows);
1795 values = table->values + token * MONO_MODULEREF_SIZE;
1796 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
1798 token <<= RESOLTION_SCOPE_BITS;
1799 token |= RESOLTION_SCOPE_MODULEREF;
1800 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1805 if (image->assembly->dynamic)
1807 memset (cols, 0, sizeof (cols));
1809 /* image->assembly->image is the manifest module */
1810 image = image->assembly->image;
1811 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1814 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1815 token = table->next_idx ++;
1817 alloc_table (table, table->rows);
1818 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1819 if (strcmp ("corlib", image->assembly_name) == 0)
1820 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1822 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1823 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1824 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1825 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1826 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1827 values [MONO_ASSEMBLYREF_FLAGS] = 0;
1828 values [MONO_ASSEMBLYREF_CULTURE] = 0;
1829 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1831 if ((pubkey = mono_image_get_public_key (image, &publen))) {
1832 guchar pubtoken [9];
1834 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
1835 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
1838 * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
1839 * This is currently only a problem with references to System.Xml (see bug#27706),
1840 * but there may be other cases that makes this necessary. Note, we need to set
1841 * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken
1842 * recognized by ms, yuck!
1843 * FIXME: need to add more assembly names, as needed.
1845 if (strcmp (image->assembly_name, "corlib") == 0 ||
1846 strcmp (image->assembly_name, "mscorlib") == 0 ||
1847 strcmp (image->assembly_name, "System") == 0 ||
1848 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
1849 strcmp (image->assembly_name, "System.Xml") == 0 ||
1850 strcmp (image->assembly_name, "System.Data") == 0 ||
1851 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
1852 static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
1853 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1854 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1855 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1856 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
1857 strcmp (image->assembly_name, "cscompmgd") == 0 ||
1858 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1859 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
1860 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
1861 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
1862 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
1863 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
1864 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
1865 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
1866 strcmp (image->assembly_name, "System.Design") == 0 ||
1867 strcmp (image->assembly_name, "System.Drawing") == 0 ||
1868 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
1869 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
1870 strcmp (image->assembly_name, "System.Management") == 0 ||
1871 strcmp (image->assembly_name, "System.Messaging") == 0 ||
1872 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
1873 strcmp (image->assembly_name, "System.Security") == 0 ||
1874 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
1875 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
1876 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
1877 strcmp (image->assembly_name, "System.Web") == 0) {
1878 static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
1879 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
1880 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
1881 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
1883 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1886 token <<= RESOLTION_SCOPE_BITS;
1887 token |= RESOLTION_SCOPE_ASSEMBLYREF;
1888 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1893 create_typespec (MonoDynamicImage *assembly, MonoType *type)
1895 MonoDynamicTable *table;
1901 char *b = blob_size;
1903 switch (type->type) {
1904 case MONO_TYPE_FNPTR:
1906 case MONO_TYPE_SZARRAY:
1907 case MONO_TYPE_ARRAY:
1909 case MONO_TYPE_MVAR:
1910 case MONO_TYPE_GENERICINST:
1911 encode_type (assembly, type, p, &p);
1913 case MONO_TYPE_CLASS:
1914 case MONO_TYPE_VALUETYPE: {
1915 MonoClass *k = mono_class_from_mono_type (type);
1916 if (!k || !k->generic_inst)
1918 encode_type (assembly, k->generic_inst, p, &p);
1925 table = &assembly->tables [MONO_TABLE_TYPESPEC];
1926 if (assembly->save) {
1927 g_assert (p-sig < 128);
1928 mono_metadata_encode_value (p-sig, b, &b);
1929 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
1930 alloc_table (table, table->rows + 1);
1931 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1932 values [MONO_TYPESPEC_SIGNATURE] = token;
1935 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1936 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1942 * Despite the name, we handle also TypeSpec (with the above helper).
1945 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
1947 MonoDynamicTable *table;
1949 guint32 token, scope, enclosing;
1952 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1955 token = create_typespec (assembly, type);
1958 klass = my_mono_class_from_mono_type (type);
1960 klass = mono_class_from_mono_type (type);
1963 * If it's in the same module and not a generic type parameter:
1965 if ((klass->image == &assembly->image) &&
1966 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
1967 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1968 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1969 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1973 if (klass->nested_in) {
1974 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
1975 /* get the typeref idx of the enclosing type */
1976 enclosing >>= TYPEDEFORREF_BITS;
1977 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
1979 scope = resolution_scope_from_image (assembly, klass->image);
1981 table = &assembly->tables [MONO_TABLE_TYPEREF];
1982 if (assembly->save) {
1983 alloc_table (table, table->rows + 1);
1984 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1985 values [MONO_TYPEREF_SCOPE] = scope;
1986 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1987 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1989 token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1990 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1992 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
1997 * Insert a memberef row into the metadata: the token that point to the memberref
1998 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1999 * mono_image_get_fieldref_token()).
2000 * The sig param is an index to an already built signature.
2003 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2005 MonoDynamicTable *table;
2007 guint32 token, pclass;
2010 parent = mono_image_typedef_or_ref (assembly, type);
2011 switch (parent & TYPEDEFORREF_MASK) {
2012 case TYPEDEFORREF_TYPEREF:
2013 pclass = MEMBERREF_PARENT_TYPEREF;
2015 case TYPEDEFORREF_TYPESPEC:
2016 pclass = MEMBERREF_PARENT_TYPESPEC;
2018 case TYPEDEFORREF_TYPEDEF:
2019 pclass = MEMBERREF_PARENT_TYPEDEF;
2022 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2025 /* extract the index */
2026 parent >>= TYPEDEFORREF_BITS;
2028 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2030 if (assembly->save) {
2031 alloc_table (table, table->rows + 1);
2032 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2033 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2034 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2035 values [MONO_MEMBERREF_SIGNATURE] = sig;
2038 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2045 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2049 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2052 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2053 method->name, method_encode_signature (assembly, method->signature));
2054 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2059 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2062 ReflectionMethodBuilder rmb;
2064 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2068 reflection_methodbuilder_from_method_builder (&rmb, mb);
2070 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2071 mono_string_to_utf8 (rmb.name),
2072 method_builder_encode_signature (assembly, &rmb));
2073 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2078 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2081 ReflectionMethodBuilder rmb;
2083 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2087 reflection_methodbuilder_from_ctor_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_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass)
2101 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
2104 field->parent = klass;
2105 token = mono_image_get_memberref_token (assembly, &klass->byval_arg,
2106 field->name, fieldref_encode_signature (assembly, field->type));
2107 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
2112 field_encode_inflated_field (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
2118 klass = field->rfield.klass;
2119 name = field->rfield.field->name;
2120 sig = fieldref_encode_signature (assembly, field->declaring->type);
2121 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2127 mono_image_get_inflated_field_token (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
2131 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field->rfield.field));
2134 token = field_encode_inflated_field (assembly, field);
2135 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
2140 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst)
2145 guint32 nparams = ginst->mtype_argc;
2146 guint32 size = 10 + nparams * 10;
2149 char *b = blob_size;
2151 if (!assembly->save)
2154 p = buf = g_malloc (size);
2156 * FIXME: vararg, explicit_this, differenc call_conv values...
2158 mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2159 mono_metadata_encode_value (nparams, p, &p);
2161 for (i = 0; i < nparams; i++)
2162 encode_type (assembly, ginst->mtype_argv [i], p, &p);
2165 g_assert (p - buf < size);
2166 mono_metadata_encode_value (p-buf, b, &b);
2167 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2173 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method, MonoGenericInst *ginst)
2175 MonoDynamicTable *table;
2177 guint32 token, mtoken = 0, sig;
2180 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2183 k = ginst->klass ? ginst->klass : method->klass;
2185 sig = method_encode_signature (assembly, method->signature);
2186 mtoken = mono_image_get_memberref_token (assembly, &k->byval_arg, method->name, sig);
2188 if (!method->signature->generic_param_count)
2191 switch (mono_metadata_token_table (mtoken)) {
2192 case MONO_TABLE_MEMBERREF:
2193 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2195 case MONO_TABLE_METHOD:
2196 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2199 g_assert_not_reached ();
2202 sig = encode_generic_method_sig (assembly, ginst);
2204 if (assembly->save) {
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2207 values [MONO_METHODSPEC_METHOD] = mtoken;
2208 values [MONO_METHODSPEC_SIGNATURE] = sig;
2211 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2218 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoReflectionInflatedMethod *m)
2222 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m->rmethod.method));
2225 if (m->declaring->method->signature->generic_param_count)
2226 token = method_encode_methodspec (assembly, m->declaring->method, m->ginst);
2231 g_assert (m->ginst);
2232 k = m->ginst->klass ? m->ginst->klass : m->ginst->generic_method->klass;
2234 sig = method_encode_signature (assembly, m->ginst->generic_method->signature);
2235 token = mono_image_get_memberref_token (
2236 assembly, &k->byval_arg, m->ginst->generic_method->name, sig);
2239 g_hash_table_insert (assembly->handleref, m->rmethod.method, GUINT_TO_POINTER(token));
2244 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2246 MonoDynamicTable *table;
2253 char *b = blob_size;
2256 g_assert (tb->generic_params);
2257 klass = mono_class_from_mono_type (tb->type.type);
2259 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2260 encode_type (assembly, &klass->byval_arg, p, &p);
2262 count = mono_array_length (tb->generic_params);
2263 mono_metadata_encode_value (count, p, &p);
2264 for (i = 0; i < count; i++) {
2265 MonoReflectionGenericParam *gparam;
2267 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2269 encode_type (assembly, gparam->type.type, p, &p);
2272 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2273 if (assembly->save) {
2274 g_assert (p-sig < 128);
2275 mono_metadata_encode_value (p-sig, b, &b);
2276 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2277 alloc_table (table, table->rows + 1);
2278 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2279 values [MONO_TYPESPEC_SIGNATURE] = token;
2282 token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2283 g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2289 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2291 MonoDynamicTable *table;
2294 guint32 token, pclass, parent, sig;
2297 klass = mono_class_from_mono_type (fb->typeb->type);
2298 name = mono_string_to_utf8 (fb->name);
2300 sig = fieldref_encode_signature (assembly, fb->type->type);
2302 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2303 g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2305 pclass = MEMBERREF_PARENT_TYPESPEC;
2306 parent >>= TYPEDEFORREF_BITS;
2308 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2310 if (assembly->save) {
2311 alloc_table (table, table->rows + 1);
2312 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2313 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2314 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2315 values [MONO_MEMBERREF_SIGNATURE] = sig;
2318 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2325 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2333 char *b = blob_size;
2335 if (!assembly->save)
2339 g_assert (helper->type == 2);
2341 if (helper->arguments)
2342 nargs = mono_array_length (helper->arguments);
2346 size = 10 + (nargs * 10);
2348 p = buf = g_malloc (size);
2350 /* Encode calling convention */
2351 /* Change Any to Standard */
2352 if ((helper->call_conv & 0x03) == 0x03)
2353 helper->call_conv = 0x01;
2354 /* explicit_this implies has_this */
2355 if (helper->call_conv & 0x40)
2356 helper->call_conv &= 0x20;
2358 if (helper->call_conv == 0) /* Unmanaged */
2359 *p = helper->unmanaged_call_conv - 1;
2362 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2363 if (helper->call_conv & 0x02) /* varargs */
2368 mono_metadata_encode_value (nargs, p, &p);
2369 encode_reflection_type (assembly, helper->return_type, p, &p);
2370 for (i = 0; i < nargs; ++i) {
2371 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2372 encode_reflection_type (assembly, pt, p, &p);
2375 g_assert (p - buf < size);
2376 mono_metadata_encode_value (p-buf, b, &b);
2377 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2384 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2387 MonoDynamicTable *table;
2390 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2391 idx = table->next_idx ++;
2393 alloc_table (table, table->rows);
2394 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2396 values [MONO_STAND_ALONE_SIGNATURE] =
2397 mono_reflection_encode_sighelper (assembly, helper);
2403 reflection_cc_to_file (int call_conv) {
2404 switch (call_conv & 0x3) {
2406 case 1: return MONO_CALL_DEFAULT;
2407 case 2: return MONO_CALL_VARARG;
2409 g_assert_not_reached ();
2416 MonoMethodSignature *sig;
2422 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2427 MonoMethodSignature *sig;
2430 name = mono_string_to_utf8 (m->name);
2431 nparams = mono_array_length (m->parameters);
2432 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2434 sig->call_convention = reflection_cc_to_file (m->call_conv);
2435 sig->param_count = nparams;
2436 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2437 for (i = 0; i < nparams; ++i) {
2438 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2439 sig->params [i] = t->type;
2442 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2444 if (strcmp (name, am->name) == 0 &&
2445 mono_metadata_type_equal (am->parent, m->parent->type) &&
2446 mono_metadata_signature_equal (am->sig, sig)) {
2449 m->table_idx = am->token & 0xffffff;
2453 am = g_new0 (ArrayMethod, 1);
2456 am->parent = m->parent->type;
2457 am->token = mono_image_get_memberref_token (assembly, am->parent,
2458 name, method_encode_signature (assembly, sig));
2459 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2460 m->table_idx = am->token & 0xffffff;
2465 * Insert into the metadata tables all the info about the TypeBuilder tb.
2466 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2469 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2471 MonoDynamicTable *table;
2473 int i, is_object = 0, is_system = 0;
2476 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2477 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2478 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2479 n = mono_string_to_utf8 (tb->name);
2480 if (strcmp (n, "Object") == 0)
2482 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2484 n = mono_string_to_utf8 (tb->nspace);
2485 if (strcmp (n, "System") == 0)
2487 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2489 if (tb->parent && !(is_system && is_object) &&
2490 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2491 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2493 values [MONO_TYPEDEF_EXTENDS] = 0;
2494 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2495 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2498 * if we have explicitlayout or sequentiallayouts, output data in the
2499 * ClassLayout table.
2501 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2502 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2504 alloc_table (table, table->rows);
2505 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2506 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2507 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2508 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2511 /* handle interfaces */
2512 if (tb->interfaces) {
2513 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2515 table->rows += mono_array_length (tb->interfaces);
2516 alloc_table (table, table->rows);
2517 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2518 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2519 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2520 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2521 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2522 values += MONO_INTERFACEIMPL_SIZE;
2526 /* handle generic parameters */
2527 if (tb->generic_params) {
2528 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2529 table->rows += mono_array_length (tb->generic_params);
2530 alloc_table (table, table->rows);
2531 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2532 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2534 mono_image_get_generic_param_info (
2535 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2541 table = &assembly->tables [MONO_TABLE_FIELD];
2542 table->rows += tb->num_fields;
2543 alloc_table (table, table->rows);
2544 for (i = 0; i < tb->num_fields; ++i)
2545 mono_image_get_field_info (
2546 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2549 /* handle constructors */
2551 table = &assembly->tables [MONO_TABLE_METHOD];
2552 table->rows += mono_array_length (tb->ctors);
2553 alloc_table (table, table->rows);
2554 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2555 mono_image_get_ctor_info (domain,
2556 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2559 /* handle methods */
2561 table = &assembly->tables [MONO_TABLE_METHOD];
2562 table->rows += tb->num_methods;
2563 alloc_table (table, table->rows);
2564 for (i = 0; i < tb->num_methods; ++i)
2565 mono_image_get_method_info (
2566 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2569 /* Do the same with properties etc.. */
2570 if (tb->events && mono_array_length (tb->events)) {
2571 table = &assembly->tables [MONO_TABLE_EVENT];
2572 table->rows += mono_array_length (tb->events);
2573 alloc_table (table, table->rows);
2574 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2576 alloc_table (table, table->rows);
2577 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2578 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2579 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2580 for (i = 0; i < mono_array_length (tb->events); ++i)
2581 mono_image_get_event_info (
2582 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2584 if (tb->properties && mono_array_length (tb->properties)) {
2585 table = &assembly->tables [MONO_TABLE_PROPERTY];
2586 table->rows += mono_array_length (tb->properties);
2587 alloc_table (table, table->rows);
2588 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2590 alloc_table (table, table->rows);
2591 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2592 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2593 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2594 for (i = 0; i < mono_array_length (tb->properties); ++i)
2595 mono_image_get_property_info (
2596 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2599 mono_image_add_decl_security (assembly,
2600 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2604 MonoDynamicTable *ntable;
2606 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2607 ntable->rows += mono_array_length (tb->subtypes);
2608 alloc_table (ntable, ntable->rows);
2609 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2611 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2612 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2614 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2615 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2616 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2617 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2618 mono_string_to_utf8 (tb->name), tb->table_idx,
2619 ntable->next_idx, ntable->rows);*/
2620 values += MONO_NESTED_CLASS_SIZE;
2627 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2631 g_ptr_array_add (types, type);
2633 if (!type->subtypes)
2636 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2637 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2638 collect_types (types, subtype);
2643 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2644 MonoReflectionTypeBuilder **type2)
2646 if ((*type1)->table_idx < (*type2)->table_idx)
2649 if ((*type1)->table_idx > (*type2)->table_idx)
2656 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2661 for (i = 0; i < mono_array_length (pinfo); ++i) {
2662 MonoReflectionParamBuilder *pb;
2663 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2666 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2671 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2674 mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2676 for (i = 0; i < tb->num_fields; ++i) {
2677 MonoReflectionFieldBuilder* fb;
2678 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2679 mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2683 for (i = 0; i < mono_array_length (tb->events); ++i) {
2684 MonoReflectionEventBuilder* eb;
2685 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2686 mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2689 if (tb->properties) {
2690 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2691 MonoReflectionPropertyBuilder* pb;
2692 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2693 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2697 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2698 MonoReflectionCtorBuilder* cb;
2699 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2700 mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2701 params_add_cattrs (assembly, cb->pinfo);
2706 for (i = 0; i < tb->num_methods; ++i) {
2707 MonoReflectionMethodBuilder* mb;
2708 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2709 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2710 params_add_cattrs (assembly, mb->pinfo);
2715 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2716 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2721 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2724 mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2726 /* no types in the module */
2730 for (i = 0; i < mb->num_types; ++i)
2731 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2735 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2736 MonoDynamicImage *assembly)
2738 MonoDynamicTable *table;
2742 char *b = blob_size;
2745 table = &assembly->tables [MONO_TABLE_FILE];
2747 alloc_table (table, table->rows);
2748 values = table->values + table->next_idx * MONO_FILE_SIZE;
2749 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2750 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2751 if (module->image->dynamic) {
2752 /* This depends on the fact that the main module is emitted last */
2753 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2754 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2758 path = g_strdup (module->image->name);
2760 mono_sha1_get_digest_from_file (path, hash);
2763 mono_metadata_encode_value (20, b, &b);
2764 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2765 mono_image_add_stream_data (&assembly->blob, hash, 20);
2770 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2772 MonoDynamicTable *table;
2776 table = &assembly->tables [MONO_TABLE_MODULE];
2777 mb->table_idx = table->next_idx ++;
2778 name = mono_string_to_utf8 (mb->module.name);
2779 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2781 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2784 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2785 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2786 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2790 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2791 guint32 module_index, guint32 parent_index,
2792 MonoDynamicImage *assembly)
2794 MonoDynamicTable *table;
2798 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2799 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2802 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2804 alloc_table (table, table->rows);
2805 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2807 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2808 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2809 if (klass->nested_in)
2810 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2812 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2813 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2814 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2816 res = table->next_idx;
2820 /* Emit nested types */
2821 if (klass->nested_classes) {
2824 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2825 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2832 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2833 guint32 module_index, guint32 parent_index,
2834 MonoDynamicImage *assembly)
2839 klass = mono_class_from_mono_type (tb->type.type);
2841 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
2843 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
2844 parent_index, assembly);
2848 * We need to do this ourselves since klass->nested_classes is not set up.
2851 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2852 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
2857 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
2858 guint32 module_index,
2859 MonoDynamicImage *assembly)
2861 MonoImage *image = module->image;
2865 t = &image->tables [MONO_TABLE_TYPEDEF];
2867 for (i = 0; i < t->rows; ++i) {
2868 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
2870 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
2871 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
2875 #define align_pointer(base,p)\
2877 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
2879 (p) += 4 - (__diff & 3);\
2883 compare_semantics (const void *a, const void *b)
2885 const guint32 *a_values = a;
2886 const guint32 *b_values = b;
2887 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
2890 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
2894 compare_custom_attrs (const void *a, const void *b)
2896 const guint32 *a_values = a;
2897 const guint32 *b_values = b;
2899 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
2903 compare_field_marshal (const void *a, const void *b)
2905 const guint32 *a_values = a;
2906 const guint32 *b_values = b;
2908 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
2912 compare_nested (const void *a, const void *b)
2914 const guint32 *a_values = a;
2915 const guint32 *b_values = b;
2917 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
2921 * build_compressed_metadata() fills in the blob of data that represents the
2922 * raw metadata as it will be saved in the PE file. The five streams are output
2923 * and the metadata tables are comnpressed from the guint32 array representation,
2924 * to the compressed on-disk format.
2927 build_compressed_metadata (MonoDynamicImage *assembly)
2929 MonoDynamicTable *table;
2931 guint64 valid_mask = 0;
2932 guint64 sorted_mask;
2933 guint32 heapt_size = 0;
2934 guint32 meta_size = 256; /* allow for header and other stuff */
2935 guint32 table_offset;
2936 guint32 ntables = 0;
2945 MonoDynamicStream *stream;
2948 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
2949 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
2950 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
2951 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
2952 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
2954 /* tables that are sorted */
2955 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
2956 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
2957 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
2958 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
2959 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
2960 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
2962 /* Compute table sizes */
2963 /* the MonoImage has already been created in mono_image_basic_init() */
2964 meta = &assembly->image;
2966 /* Setup the info used by compute_sizes () */
2967 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
2968 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
2969 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
2971 meta_size += assembly->blob.index;
2972 meta_size += assembly->guid.index;
2973 meta_size += assembly->sheap.index;
2974 meta_size += assembly->us.index;
2976 for (i=0; i < 64; ++i)
2977 meta->tables [i].rows = assembly->tables [i].rows;
2979 for (i = 0; i < 64; i++){
2980 if (meta->tables [i].rows == 0)
2982 valid_mask |= (guint64)1 << i;
2984 meta->tables [i].row_size = mono_metadata_compute_size (
2985 meta, i, &meta->tables [i].size_bitfield);
2986 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
2988 heapt_size += 24; /* #~ header size */
2989 heapt_size += ntables * 4;
2990 meta_size += heapt_size;
2991 meta->raw_metadata = g_malloc0 (meta_size);
2992 p = meta->raw_metadata;
2993 /* the metadata signature */
2994 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
2995 /* version numbers and 4 bytes reserved */
2996 int16val = (guint16*)p;
2997 *int16val++ = GUINT16_TO_LE (1);
2998 *int16val = GUINT16_TO_LE (1);
3000 /* version string */
3001 int32val = (guint32*)p;
3002 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3004 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3005 p += GUINT32_FROM_LE (*int32val);
3006 align_pointer (meta->raw_metadata, p);
3007 int16val = (guint16*)p;
3008 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3009 *int16val = GUINT16_TO_LE (5); /* number of streams */
3013 * write the stream info.
3015 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3016 table_offset += 3; table_offset &= ~3;
3018 assembly->tstream.index = heapt_size;
3019 for (i = 0; i < 5; ++i) {
3020 int32val = (guint32*)p;
3021 stream_desc [i].stream->offset = table_offset;
3022 *int32val++ = GUINT32_TO_LE (table_offset);
3023 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3024 table_offset += GUINT32_FROM_LE (*int32val);
3025 table_offset += 3; table_offset &= ~3;
3027 strcpy (p, stream_desc [i].name);
3028 p += strlen (stream_desc [i].name) + 1;
3029 align_pointer (meta->raw_metadata, p);
3032 * now copy the data, the table stream header and contents goes first.
3034 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3035 p = meta->raw_metadata + assembly->tstream.offset;
3036 int32val = (guint32*)p;
3037 *int32val = GUINT32_TO_LE (0); /* reserved */
3039 *p++ = 1; /* version */
3041 if (meta->idx_string_wide)
3043 if (meta->idx_guid_wide)
3045 if (meta->idx_blob_wide)
3048 *p++ = 0; /* reserved */
3049 int64val = (guint64*)p;
3050 *int64val++ = GUINT64_TO_LE (valid_mask);
3051 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3053 int32val = (guint32*)p;
3054 for (i = 0; i < 64; i++){
3055 if (meta->tables [i].rows == 0)
3057 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3059 p = (unsigned char*)int32val;
3061 /* sort the tables that still need sorting */
3062 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3064 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3065 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3067 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3068 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3070 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3071 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3073 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3075 /* compress the tables */
3076 for (i = 0; i < 64; i++){
3079 guint32 bitfield = meta->tables [i].size_bitfield;
3080 if (!meta->tables [i].rows)
3082 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3083 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3084 meta->tables [i].base = p;
3085 for (row = 1; row <= meta->tables [i].rows; ++row) {
3086 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3087 for (col = 0; col < assembly->tables [i].columns; ++col) {
3088 switch (mono_metadata_table_size (bitfield, col)) {
3090 *p++ = values [col];
3093 *p++ = values [col] & 0xff;
3094 *p++ = (values [col] >> 8) & 0xff;
3097 *p++ = values [col] & 0xff;
3098 *p++ = (values [col] >> 8) & 0xff;
3099 *p++ = (values [col] >> 16) & 0xff;
3100 *p++ = (values [col] >> 24) & 0xff;
3103 g_assert_not_reached ();
3107 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3110 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3111 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3112 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3113 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3114 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3116 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3120 * Some tables in metadata need to be sorted according to some criteria, but
3121 * when methods and fields are first created with reflection, they may be assigned a token
3122 * that doesn't correspond to the final token they will get assigned after the sorting.
3123 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3124 * with the reflection objects that represent them. Once all the tables are set up, the
3125 * reflection objects will contains the correct table index. fixup_method() will fixup the
3126 * tokens for the method with ILGenerator @ilgen.
3129 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3130 guint32 code_idx = GPOINTER_TO_UINT (value);
3131 MonoReflectionILTokenInfo *iltoken;
3132 MonoReflectionFieldBuilder *field;
3133 MonoReflectionCtorBuilder *ctor;
3134 MonoReflectionMethodBuilder *method;
3135 MonoReflectionTypeBuilder *tb;
3136 MonoReflectionArrayMethod *am;
3138 unsigned char *target;
3140 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3141 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3142 target = assembly->code.data + code_idx + iltoken->code_pos;
3143 switch (target [3]) {
3144 case MONO_TABLE_FIELD:
3145 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3146 field = (MonoReflectionFieldBuilder *)iltoken->member;
3147 idx = field->table_idx;
3148 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3149 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3150 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3152 g_assert_not_reached ();
3155 case MONO_TABLE_METHOD:
3156 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3157 method = (MonoReflectionMethodBuilder *)iltoken->member;
3158 idx = method->table_idx;
3159 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3160 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3161 idx = ctor->table_idx;
3162 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3163 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3164 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3165 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3167 g_assert_not_reached ();
3170 case MONO_TABLE_TYPEDEF:
3171 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3172 g_assert_not_reached ();
3173 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3174 idx = tb->table_idx;
3176 case MONO_TABLE_MEMBERREF:
3177 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3178 am = (MonoReflectionArrayMethod*)iltoken->member;
3179 idx = am->table_idx;
3180 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3181 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3182 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3183 g_assert (m->klass->generic_inst);
3185 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
3186 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor") ||
3187 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedField")) {
3189 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3192 g_assert_not_reached ();
3195 case MONO_TABLE_METHODSPEC:
3196 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3197 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3198 g_assert (m->signature->generic_param_count);
3200 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
3201 !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor")) {
3204 g_assert_not_reached ();
3208 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3210 target [0] = idx & 0xff;
3211 target [1] = (idx >> 8) & 0xff;
3212 target [2] = (idx >> 16) & 0xff;
3219 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3220 * value is not known when the table is emitted.
3223 fixup_cattrs (MonoDynamicImage *assembly)
3225 MonoDynamicTable *table;
3227 guint32 type, i, idx, token;
3230 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3232 for (i = 0; i < table->rows; ++i) {
3233 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3235 type = values [MONO_CUSTOM_ATTR_TYPE];
3236 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3237 idx = type >> CUSTOM_ATTR_TYPE_BITS;
3238 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3239 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3242 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3243 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3244 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3245 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3252 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3254 MonoDynamicTable *table;
3258 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3260 alloc_table (table, table->rows);
3261 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3262 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3263 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3264 name = mono_string_to_utf8 (rsrc->name);
3265 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3267 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3272 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3274 MonoDynamicTable *table;
3278 char *b = blob_size;
3280 guint32 idx, offset;
3282 if (rsrc->filename) {
3283 name = mono_string_to_utf8 (rsrc->filename);
3284 sname = g_path_get_basename (name);
3286 table = &assembly->tables [MONO_TABLE_FILE];
3288 alloc_table (table, table->rows);
3289 values = table->values + table->next_idx * MONO_FILE_SIZE;
3290 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3291 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3294 mono_sha1_get_digest_from_file (name, hash);
3295 mono_metadata_encode_value (20, b, &b);
3296 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3297 mono_image_add_stream_data (&assembly->blob, hash, 20);
3299 idx = table->next_idx++;
3301 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3304 offset = mono_array_length (rsrc->data);
3305 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3306 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3307 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3308 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3312 * The entry should be emitted into the MANIFESTRESOURCE table of
3313 * the main module, but that needs to reference the FILE table
3314 * which isn't emitted yet.
3321 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3325 set_version_from_string (MonoString *version, guint32 *values)
3327 gchar *ver, *p, *str;
3330 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3331 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3332 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3333 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3336 ver = str = mono_string_to_utf8 (version);
3337 for (i = 0; i < 4; ++i) {
3338 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3344 /* handle Revision and Build */
3354 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3358 char *b = blob_size;
3363 len = mono_array_length (pkey);
3364 mono_metadata_encode_value (len, b, &b);
3365 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3366 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3368 /* need to get the actual value from the key type... */
3369 assembly->strong_name_size = 128;
3370 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3376 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3378 MonoDynamicTable *table;
3379 MonoDynamicImage *assembly;
3380 MonoReflectionAssemblyBuilder *assemblyb;
3385 guint32 module_index;
3387 assemblyb = moduleb->assemblyb;
3388 assembly = moduleb->dynamic_image;
3389 domain = mono_object_domain (assemblyb);
3391 /* Emit ASSEMBLY table */
3392 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3393 alloc_table (table, 1);
3394 values = table->values + MONO_ASSEMBLY_SIZE;
3395 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3396 name = mono_string_to_utf8 (assemblyb->name);
3397 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3399 if (assemblyb->culture) {
3400 name = mono_string_to_utf8 (assemblyb->culture);
3401 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3404 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3406 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3407 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3408 set_version_from_string (assemblyb->version, values);
3410 /* Emit FILE + EXPORTED_TYPE table */
3412 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3414 MonoReflectionModuleBuilder *file_module =
3415 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3416 if (file_module != moduleb) {
3417 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3419 if (file_module->types) {
3420 for (j = 0; j < file_module->num_types; ++j) {
3421 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3422 mono_image_fill_export_table (domain, tb, module_index, 0,
3428 if (assemblyb->loaded_modules) {
3429 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3430 MonoReflectionModule *file_module =
3431 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3432 mono_image_fill_file_table (domain, file_module, assembly);
3434 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3438 /* Emit MANIFESTRESOURCE table */
3440 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3442 MonoReflectionModuleBuilder *file_module =
3443 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3444 /* The table for the main module is emitted later */
3445 if (file_module != moduleb) {
3447 if (file_module->resources) {
3448 int len = mono_array_length (file_module->resources);
3449 for (j = 0; j < len; ++j) {
3450 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3451 assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3459 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3460 * for the modulebuilder @moduleb.
3461 * At the end of the process, method and field tokens are fixed up and the
3462 * on-disk compressed metadata representation is created.
3465 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3467 MonoDynamicTable *table;
3468 MonoDynamicImage *assembly;
3469 MonoReflectionAssemblyBuilder *assemblyb;
3474 assemblyb = moduleb->assemblyb;
3475 assembly = moduleb->dynamic_image;
3476 domain = mono_object_domain (assemblyb);
3478 if (assembly->text_rva)
3481 assembly->text_rva = START_TEXT_RVA;
3483 if (moduleb->is_main) {
3484 mono_image_emit_manifest (moduleb);
3487 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3488 table->rows = 1; /* .<Module> */
3490 alloc_table (table, table->rows);
3492 * Set the first entry.
3494 values = table->values + table->columns;
3495 values [MONO_TYPEDEF_FLAGS] = 0;
3496 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3497 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3498 values [MONO_TYPEDEF_EXTENDS] = 0;
3499 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3500 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3503 * handle global methods
3504 * FIXME: test what to do when global methods are defined in multiple modules.
3506 if (moduleb->global_methods) {
3507 table = &assembly->tables [MONO_TABLE_METHOD];
3508 table->rows += mono_array_length (moduleb->global_methods);
3509 alloc_table (table, table->rows);
3510 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3511 mono_image_get_method_info (
3512 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3514 if (moduleb->global_fields) {
3515 table = &assembly->tables [MONO_TABLE_FIELD];
3516 table->rows += mono_array_length (moduleb->global_fields);
3517 alloc_table (table, table->rows);
3518 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3519 mono_image_get_field_info (
3520 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3523 table = &assembly->tables [MONO_TABLE_MODULE];
3524 alloc_table (table, 1);
3525 mono_image_fill_module_table (domain, moduleb, assembly);
3529 /* Collect all types into a list sorted by their table_idx */
3530 GPtrArray *types = g_ptr_array_new ();
3533 for (i = 0; i < moduleb->num_types; ++i) {
3534 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3535 collect_types (types, type);
3538 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3539 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3540 table->rows += types->len;
3541 alloc_table (table, table->rows);
3543 for (i = 0; i < types->len; ++i) {
3544 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3545 mono_image_get_type_info (domain, type, assembly);
3547 g_ptr_array_free (types, TRUE);
3551 * table->rows is already set above and in mono_image_fill_module_table.
3553 /* add all the custom attributes at the end, once all the indexes are stable */
3554 mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3556 module_add_cattrs (assembly, moduleb);
3559 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3560 fixup_cattrs (assembly);
3564 * mono_image_insert_string:
3565 * @module: module builder object
3568 * Insert @str into the user string stream of @module.
3571 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3573 MonoDynamicImage *assembly;
3578 MONO_ARCH_SAVE_REGS;
3580 if (!module->dynamic_image)
3581 mono_image_module_basic_init (module);
3583 assembly = module->dynamic_image;
3585 if (assembly->save) {
3586 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3587 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3588 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3590 char *swapped = g_malloc (2 * mono_string_length (str));
3591 const char *p = (const char*)mono_string_chars (str);
3593 swap_with_size (swapped, p, 2, mono_string_length (str));
3594 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3598 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3600 mono_image_add_stream_data (&assembly->us, "", 1);
3603 idx = assembly->us.index ++;
3605 mono_g_hash_table_insert (assembly->tokens,
3606 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3608 return MONO_TOKEN_STRING | idx;
3612 * mono_image_create_token:
3613 * @assembly: a dynamic assembly
3616 * Get a token to insert in the IL code stream for the given MemberInfo.
3617 * @obj can be one of:
3618 * ConstructorBuilder
3628 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3633 klass = obj->vtable->klass;
3634 if (strcmp (klass->name, "MethodBuilder") == 0) {
3635 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3637 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3638 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3640 token = mono_image_get_methodbuilder_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, "ConstructorBuilder") == 0) {
3644 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3646 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3647 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3649 token = mono_image_get_ctorbuilder_token (assembly, mb);
3650 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3652 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3653 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3654 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3655 if (tb->generic_params) {
3656 token = mono_image_get_generic_field_token (assembly, fb);
3658 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3661 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3662 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3663 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3665 else if (strcmp (klass->name, "MonoType") == 0 ||
3666 strcmp (klass->name, "MonoGenericParam") == 0) {
3667 MonoReflectionType *tb = (MonoReflectionType *)obj;
3668 token = mono_metadata_token_from_dor (
3669 mono_image_typedef_or_ref (assembly, tb->type));
3671 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3672 strcmp (klass->name, "MonoMethod") == 0) {
3673 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3674 if (m->method->signature->generic_param_count) {
3675 g_assert_not_reached ();
3676 } else if ((m->method->klass->image == &assembly->image) &&
3677 !m->method->klass->generic_inst) {
3678 static guint32 method_table_idx = 0xffffff;
3680 * Each token should have a unique index, but the indexes are
3681 * assigned by managed code, so we don't know about them. An
3682 * easy solution is to count backwards...
3684 method_table_idx --;
3685 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3687 token = mono_image_get_methodref_token (assembly, m->method);
3688 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3690 else if (strcmp (klass->name, "MonoInflatedMethod") == 0 ||
3691 strcmp (klass->name, "MonoInflatedCtor") == 0) {
3692 MonoReflectionInflatedMethod *m = (MonoReflectionInflatedMethod *)obj;
3693 token = mono_image_get_methodspec_token (assembly, m);
3695 else if (strcmp (klass->name, "MonoInflatedField") == 0) {
3696 MonoReflectionInflatedField *f = (MonoReflectionInflatedField *)obj;
3697 token = mono_image_get_inflated_field_token (assembly, f);
3699 else if (strcmp (klass->name, "MonoField") == 0) {
3700 MonoReflectionField *f = (MonoReflectionField *)obj;
3701 if (f->klass->image == &assembly->image) {
3702 static guint32 field_table_idx = 0xffffff;
3704 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3706 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
3707 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3709 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3710 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3711 token = mono_image_get_array_token (assembly, m);
3713 else if (strcmp (klass->name, "SignatureHelper") == 0) {
3714 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3715 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3718 g_error ("requested token for %s\n", klass->name);
3720 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3727 guint32 import_lookup_table;
3731 guint32 import_address_table_rva;
3739 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3741 static MonoDynamicImage*
3742 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
3743 char *assembly_name, char *module_name)
3745 static const guchar entrycode [16] = {0xff, 0x25, 0};
3746 MonoDynamicImage *image;
3750 * We need to use the current ms version or the ms runtime it won't find
3751 * the support dlls. D'oh!
3752 * const char *version = "mono-" VERSION;
3754 const char *version = "v1.0.3705";
3757 image = GC_MALLOC (sizeof (MonoDynamicImage));
3759 image = g_new0 (MonoDynamicImage, 1);
3762 /* keep in sync with image.c */
3763 image->image.name = assembly_name;
3764 image->image.assembly_name = image->image.name; /* they may be different */
3765 image->image.module_name = module_name;
3766 image->image.version = g_strdup (version);
3767 image->image.dynamic = TRUE;
3769 image->image.references = g_new0 (MonoAssembly*, 1);
3770 image->image.references [0] = NULL;
3772 mono_image_init (&image->image);
3774 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3775 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3776 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3777 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3778 image->handleref = g_hash_table_new (NULL, NULL);
3779 image->tokens = mono_g_hash_table_new (NULL, NULL);
3780 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3781 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3783 string_heap_init (&image->sheap);
3784 mono_image_add_stream_data (&image->us, "", 1);
3785 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3786 /* import tables... */
3787 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3788 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3789 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3790 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3791 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3792 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3793 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3794 stream_data_align (&image->code);
3796 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3798 for (i=0; i < 64; ++i) {
3799 image->tables [i].next_idx = 1;
3800 image->tables [i].columns = table_sizes [i];
3803 image->image.assembly = (MonoAssembly*)assembly;
3804 image->run = assembly->run;
3805 image->save = assembly->save;
3811 * mono_image_basic_init:
3812 * @assembly: an assembly builder object
3814 * Create the MonoImage that represents the assembly builder and setup some
3815 * of the helper hash table and the basic metadata streams.
3818 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3820 MonoDynamicAssembly *assembly;
3821 MonoDynamicImage *image;
3823 MONO_ARCH_SAVE_REGS;
3825 if (assemblyb->dynamic_assembly)
3829 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3831 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3834 assembly->assembly.dynamic = TRUE;
3835 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3836 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3837 if (assemblyb->culture)
3838 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3840 assembly->assembly.aname.culture = g_strdup ("");
3842 assembly->run = assemblyb->access != 2;
3843 assembly->save = assemblyb->access != 1;
3845 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
3846 assembly->assembly.aname.name = image->image.name;
3847 assembly->assembly.image = &image->image;
3849 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
3850 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
3854 calc_section_size (MonoDynamicImage *assembly)
3858 /* alignment constraints */
3859 assembly->code.index += 3;
3860 assembly->code.index &= ~3;
3861 assembly->meta_size += 3;
3862 assembly->meta_size &= ~3;
3863 assembly->resources.index += 3;
3864 assembly->resources.index &= ~3;
3866 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
3867 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
3870 if (assembly->win32_res) {
3871 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
3873 assembly->sections [MONO_SECTION_RSRC].size = res_size;
3874 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
3878 assembly->sections [MONO_SECTION_RELOC].size = 12;
3879 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
3889 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
3893 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
3895 ResTreeNode *t1 = (ResTreeNode*)a;
3896 ResTreeNode *t2 = (ResTreeNode*)b;
3898 return t1->id - t2->id;
3902 * resource_tree_create:
3904 * Organize the resources into a resource tree.
3906 static ResTreeNode *
3907 resource_tree_create (MonoArray *win32_resources)
3909 ResTreeNode *tree, *res_node, *type_node, *lang_node;
3913 tree = g_new0 (ResTreeNode, 1);
3915 for (i = 0; i < mono_array_length (win32_resources); ++i) {
3916 MonoReflectionWin32Resource *win32_res =
3917 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
3921 lang_node = g_new0 (ResTreeNode, 1);
3922 lang_node->id = win32_res->lang_id;
3923 lang_node->win32_res = win32_res;
3925 /* Create type node if neccesary */
3927 for (l = tree->children; l; l = l->next)
3928 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
3929 type_node = (ResTreeNode*)l->data;
3934 type_node = g_new0 (ResTreeNode, 1);
3935 type_node->id = win32_res->res_type;
3938 * The resource types have to be sorted otherwise
3939 * Windows Explorer can't display the version information.
3941 tree->children = g_slist_insert_sorted (tree->children, type_node,
3942 resource_tree_compare_by_id);
3945 /* Create res node if neccesary */
3947 for (l = type_node->children; l; l = l->next)
3948 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
3949 res_node = (ResTreeNode*)l->data;
3954 res_node = g_new0 (ResTreeNode, 1);
3955 res_node->id = win32_res->res_id;
3956 type_node->children = g_slist_append (type_node->children, res_node);
3959 res_node->children = g_slist_append (res_node->children, lang_node);
3966 * resource_tree_encode:
3968 * Encode the resource tree into the format used in the PE file.
3971 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
3974 MonoPEResourceDir dir;
3975 MonoPEResourceDirEntry dir_entry;
3976 MonoPEResourceDataEntry data_entry;
3980 * For the format of the resource directory, see the article
3981 * "An In-Depth Look into the Win32 Portable Executable File Format" by
3985 memset (&dir, 0, sizeof (dir));
3986 memset (&dir_entry, 0, sizeof (dir_entry));
3987 memset (&data_entry, 0, sizeof (data_entry));
3989 g_assert (sizeof (dir) == 16);
3990 g_assert (sizeof (dir_entry) == 8);
3991 g_assert (sizeof (data_entry) == 16);
3993 node->offset = p - begin;
3995 /* IMAGE_RESOURCE_DIRECTORY */
3996 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
3998 memcpy (p, &dir, sizeof (dir));
4001 /* Reserve space for entries */
4003 p += sizeof (dir_entry) * dir.res_id_entries;
4005 /* Write children */
4006 for (l = node->children; l; l = l->next) {
4007 ResTreeNode *child = (ResTreeNode*)l->data;
4009 if (child->win32_res) {
4011 child->offset = p - begin;
4013 /* IMAGE_RESOURCE_DATA_ENTRY */
4014 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4015 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4017 memcpy (p, &data_entry, sizeof (data_entry));
4018 p += sizeof (data_entry);
4020 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4021 p += data_entry.rde_size;
4024 resource_tree_encode (child, begin, p, &p);
4027 /* IMAGE_RESOURCE_ENTRY */
4028 for (l = node->children; l; l = l->next) {
4029 ResTreeNode *child = (ResTreeNode*)l->data;
4030 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4032 dir_entry.is_dir = child->win32_res ? 0 : 1;
4033 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4035 memcpy (entries, &dir_entry, sizeof (dir_entry));
4036 entries += sizeof (dir_entry);
4043 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4048 MonoReflectionWin32Resource *win32_res;
4051 if (!assemblyb->win32_resources)
4055 * Resources are stored in a three level tree inside the PE file.
4056 * - level one contains a node for each type of resource
4057 * - level two contains a node for each resource
4058 * - level three contains a node for each instance of a resource for a
4059 * specific language.
4062 tree = resource_tree_create (assemblyb->win32_resources);
4064 /* Estimate the size of the encoded tree */
4066 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4067 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4068 size += mono_array_length (win32_res->res_data);
4070 /* Directory structure */
4071 size += mono_array_length (assemblyb->win32_resources) * 256;
4072 p = buf = g_malloc (size);
4074 resource_tree_encode (tree, p, p, &p);
4076 g_assert (p - buf < size);
4078 assembly->win32_res = g_malloc (p - buf);
4079 assembly->win32_res_size = p - buf;
4080 memcpy (assembly->win32_res, buf, p - buf);
4086 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4088 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4091 p += sizeof (MonoPEResourceDir);
4092 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4093 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4094 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4095 if (dir_entry->is_dir)
4096 fixup_resource_directory (res_section, child, rva);
4098 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4099 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4102 p += sizeof (MonoPEResourceDirEntry);
4107 * mono_image_create_pefile:
4108 * @mb: a module builder object
4110 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4111 * assembly->pefile where it can be easily retrieved later in chunks.
4114 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4115 MonoMSDOSHeader *msdos;
4116 MonoDotNetHeader *header;
4117 MonoSectionTable *section;
4118 MonoCLIHeader *cli_header;
4119 guint32 size, image_size, virtual_base, text_offset;
4120 guint32 header_start, section_start, file_offset, virtual_offset;
4121 MonoDynamicImage *assembly;
4122 MonoReflectionAssemblyBuilder *assemblyb;
4123 MonoDynamicStream *pefile;
4125 guint32 *rva, value;
4128 static const unsigned char msheader[] = {
4129 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4130 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4133 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4134 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4135 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4136 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4139 assemblyb = mb->assemblyb;
4141 mono_image_basic_init (assemblyb);
4142 assembly = mb->dynamic_image;
4144 /* already created */
4145 if (assembly->pefile.index)
4148 mono_image_build_metadata (mb);
4150 if (mb->is_main && assemblyb->resources) {
4151 int len = mono_array_length (assemblyb->resources);
4152 for (i = 0; i < len; ++i)
4153 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4156 if (mb->resources) {
4157 int len = mono_array_length (mb->resources);
4158 for (i = 0; i < len; ++i)
4159 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4162 build_compressed_metadata (assembly);
4165 assembly_add_win32_resources (assembly, assemblyb);
4167 nsections = calc_section_size (assembly);
4169 pefile = &assembly->pefile;
4171 /* The DOS header and stub */
4172 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4173 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4175 /* the dotnet header */
4176 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4178 /* the section tables */
4179 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4181 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4182 virtual_offset = VIRT_ALIGN;
4185 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4186 if (!assembly->sections [i].size)
4189 file_offset += FILE_ALIGN - 1;
4190 file_offset &= ~(FILE_ALIGN - 1);
4191 virtual_offset += VIRT_ALIGN - 1;
4192 virtual_offset &= ~(VIRT_ALIGN - 1);
4194 assembly->sections [i].offset = file_offset;
4195 assembly->sections [i].rva = virtual_offset;
4197 file_offset += assembly->sections [i].size;
4198 virtual_offset += assembly->sections [i].size;
4199 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4202 file_offset += FILE_ALIGN - 1;
4203 file_offset &= ~(FILE_ALIGN - 1);
4204 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4206 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4208 /* back-patch info */
4209 msdos = (MonoMSDOSHeader*)pefile->data;
4210 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4211 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4212 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4214 header = (MonoDotNetHeader*)(pefile->data + header_start);
4215 header->pesig [0] = 'P';
4216 header->pesig [1] = 'E';
4218 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4219 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4220 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4221 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4222 if (assemblyb->pekind == 1) {
4224 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4227 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4230 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4232 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4233 header->pe.pe_major = 6;
4234 header->pe.pe_minor = 0;
4235 size = assembly->sections [MONO_SECTION_TEXT].size;
4236 size += FILE_ALIGN - 1;
4237 size &= ~(FILE_ALIGN - 1);
4238 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4239 size = assembly->sections [MONO_SECTION_RSRC].size;
4240 size += FILE_ALIGN - 1;
4241 size &= ~(FILE_ALIGN - 1);
4242 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4243 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4244 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4245 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4246 /* pe_rva_entry_point always at the beginning of the text section */
4247 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4249 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4250 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4251 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4252 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4253 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4254 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4255 size = section_start;
4256 size += FILE_ALIGN - 1;
4257 size &= ~(FILE_ALIGN - 1);
4258 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4260 size += VIRT_ALIGN - 1;
4261 size &= ~(VIRT_ALIGN - 1);
4262 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4265 // Translate the PEFileKind value to the value expected by the Windows loader
4268 short kind = assemblyb->pekind;
4271 // PEFileKinds.ConsoleApplication == 2
4272 // PEFileKinds.WindowApplication == 3
4275 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4276 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4282 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4284 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4285 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4286 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4287 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4288 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4289 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4291 /* fill data directory entries */
4293 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4294 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4296 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4297 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4299 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4300 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4301 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4302 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4303 /* patch imported function RVA name */
4304 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4305 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4307 /* the import table */
4308 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4309 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4310 /* patch imported dll RVA name and other entries in the dir */
4311 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4312 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4313 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4314 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4315 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4316 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4318 p = (assembly->code.data + assembly->ilt_offset);
4319 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4320 *p++ = (value) & 0xff;
4321 *p++ = (value >> 8) & (0xff);
4322 *p++ = (value >> 16) & (0xff);
4323 *p++ = (value >> 24) & (0xff);
4325 /* the CLI header info */
4326 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4327 cli_header->ch_size = GUINT32_FROM_LE (72);
4328 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4329 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4330 if (assemblyb->entry_point) {
4331 guint32 table_idx = 0;
4332 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4333 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4334 table_idx = methodb->table_idx;
4337 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4338 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4341 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4342 /* The embedded managed resources */
4343 text_offset = assembly->text_rva + assembly->code.index;
4344 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4345 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4346 text_offset += assembly->resources.index;
4347 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4348 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4349 text_offset += assembly->meta_size;
4350 if (assembly->strong_name_size) {
4351 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4352 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4353 text_offset += assembly->strong_name_size;
4356 /* write the section tables and section content */
4357 section = (MonoSectionTable*)(pefile->data + section_start);
4358 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4359 static const char *section_names [] = {
4360 ".text", ".rsrc", ".reloc"
4362 if (!assembly->sections [i].size)
4364 strcpy (section->st_name, section_names [i]);
4365 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4366 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4367 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4368 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4369 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4370 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4371 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4373 case MONO_SECTION_TEXT:
4374 /* patch entry point */
4375 p = (assembly->code.data + 2);
4376 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4377 *p++ = (value) & 0xff;
4378 *p++ = (value >> 8) & 0xff;
4379 *p++ = (value >> 16) & 0xff;
4380 *p++ = (value >> 24) & 0xff;
4382 text_offset = assembly->sections [i].offset;
4383 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4384 text_offset += assembly->code.index;
4385 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4386 text_offset += assembly->resources.index;
4387 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4388 text_offset += assembly->meta_size;
4389 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4391 g_free (assembly->image.raw_metadata);
4393 case MONO_SECTION_RELOC:
4394 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4395 *rva = GUINT32_FROM_LE (assembly->text_rva);
4397 *rva = GUINT32_FROM_LE (12);
4399 data16 = (guint16*)rva;
4401 * the entrypoint is always at the start of the text section
4402 * 3 is IMAGE_REL_BASED_HIGHLOW
4403 * 2 is patch_size_rva - text_rva
4405 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4407 *data16 = 0; /* terminate */
4409 case MONO_SECTION_RSRC:
4410 if (assembly->win32_res) {
4411 text_offset = assembly->sections [i].offset;
4413 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4414 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4416 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4420 g_assert_not_reached ();
4425 /* check that the file is properly padded */
4428 FILE *f = fopen ("mypetest.exe", "w");
4429 fwrite (pefile->data, pefile->index, 1, f);
4435 MonoReflectionModule *
4436 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4440 MonoImageOpenStatus status;
4441 MonoDynamicAssembly *assembly;
4443 name = mono_string_to_utf8 (fileName);
4445 image = mono_image_open (name, &status);
4448 if (status == MONO_IMAGE_ERROR_ERRNO)
4449 exc = mono_get_exception_file_not_found (fileName);
4451 exc = mono_get_exception_bad_image_format (name);
4453 mono_raise_exception (exc);
4458 assembly = ab->dynamic_assembly;
4459 image->assembly = (MonoAssembly*)assembly;
4461 mono_assembly_load_references (image, &status);
4463 mono_image_close (image);
4464 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4467 return mono_module_get_object (mono_domain_get (), image);
4471 * We need to return always the same object for MethodInfo, FieldInfo etc..
4472 * but we need to consider the reflected type.
4473 * type uses a different hash, since it uses custom hash/equal functions.
4478 MonoClass *refclass;
4482 reflected_equal (gconstpointer a, gconstpointer b) {
4483 const ReflectedEntry *ea = a;
4484 const ReflectedEntry *eb = b;
4486 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4490 reflected_hash (gconstpointer a) {
4491 const ReflectedEntry *ea = a;
4492 return GPOINTER_TO_UINT (ea->item);
4495 #define CHECK_OBJECT(t,p,k) \
4501 mono_domain_lock (domain); \
4502 if (!domain->refobject_hash) \
4503 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4504 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4505 mono_domain_unlock (domain); \
4511 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4513 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4516 #define CACHE_OBJECT(p,o,k) \
4518 ReflectedEntry *e = ALLOC_REFENTRY; \
4520 e->refclass = (k); \
4521 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4522 mono_domain_unlock (domain); \
4526 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4528 /* this is done only once */
4529 mono_domain_lock (domain);
4530 CACHE_OBJECT (assembly, res, NULL);
4534 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4536 /* this is done only once */
4537 mono_domain_lock (domain);
4538 CACHE_OBJECT (module, res, NULL);
4542 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4544 MonoDynamicImage *image = moduleb->dynamic_image;
4545 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4548 * FIXME: we already created an image in mono_image_basic_init (), but
4549 * we don't know which module it belongs to, since that is only
4550 * determined at assembly save time.
4552 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4553 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4555 moduleb->module.image = &image->image;
4556 moduleb->dynamic_image = image;
4557 register_module (mono_object_domain (moduleb), moduleb, image);
4562 * mono_assembly_get_object:
4563 * @domain: an app domain
4564 * @assembly: an assembly
4566 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4568 MonoReflectionAssembly*
4569 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4571 static MonoClass *System_Reflection_Assembly;
4572 MonoReflectionAssembly *res;
4574 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4575 if (!System_Reflection_Assembly)
4576 System_Reflection_Assembly = mono_class_from_name (
4577 mono_defaults.corlib, "System.Reflection", "Assembly");
4578 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4579 res->assembly = assembly;
4580 CACHE_OBJECT (assembly, res, NULL);
4586 MonoReflectionModule*
4587 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4589 static MonoClass *System_Reflection_Module;
4590 MonoReflectionModule *res;
4592 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4593 if (!System_Reflection_Module)
4594 System_Reflection_Module = mono_class_from_name (
4595 mono_defaults.corlib, "System.Reflection", "Module");
4596 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4599 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4601 res->fqname = mono_string_new (domain, image->name);
4602 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4603 res->scopename = mono_string_new (domain, image->module_name);
4605 mono_image_addref (image);
4607 CACHE_OBJECT (image, res, NULL);
4611 MonoReflectionModule*
4612 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4614 static MonoClass *System_Reflection_Module;
4615 MonoReflectionModule *res;
4616 MonoTableInfo *table;
4617 guint32 cols [MONO_FILE_SIZE];
4619 guint32 i, name_idx;
4622 if (!System_Reflection_Module)
4623 System_Reflection_Module = mono_class_from_name (
4624 mono_defaults.corlib, "System.Reflection", "Module");
4625 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4627 table = &image->tables [MONO_TABLE_FILE];
4628 g_assert (table_index < table->rows);
4629 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4632 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4633 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4635 // Check whenever the row has a corresponding row in the moduleref table
4636 table = &image->tables [MONO_TABLE_MODULEREF];
4637 for (i = 0; i < table->rows; ++i) {
4638 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4639 val = mono_metadata_string_heap (image, name_idx);
4640 if (strcmp (val, name) == 0)
4641 res->image = image->modules [i];
4644 res->fqname = mono_string_new (domain, name);
4645 res->name = mono_string_new (domain, name);
4646 res->scopename = mono_string_new (domain, name);
4647 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4653 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4655 if ((t1->type != t2->type) ||
4656 (t1->byref != t2->byref))
4660 case MONO_TYPE_VOID:
4661 case MONO_TYPE_BOOLEAN:
4662 case MONO_TYPE_CHAR:
4673 case MONO_TYPE_STRING:
4676 case MONO_TYPE_OBJECT:
4677 case MONO_TYPE_TYPEDBYREF:
4679 case MONO_TYPE_VALUETYPE:
4680 case MONO_TYPE_CLASS:
4681 case MONO_TYPE_SZARRAY:
4682 return t1->data.klass == t2->data.klass;
4684 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4685 case MONO_TYPE_ARRAY:
4686 if (t1->data.array->rank != t2->data.array->rank)
4688 return t1->data.array->eklass == t2->data.array->eklass;
4689 case MONO_TYPE_GENERICINST: {
4691 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4693 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4695 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4696 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4702 case MONO_TYPE_MVAR:
4703 return t1->data.generic_param == t2->data.generic_param;
4705 g_error ("implement type compare for %0x!", t1->type);
4713 mymono_metadata_type_hash (MonoType *t1)
4719 hash |= t1->byref << 6; /* do not collide with t1->type values */
4721 case MONO_TYPE_VALUETYPE:
4722 case MONO_TYPE_CLASS:
4723 case MONO_TYPE_SZARRAY:
4724 /* check if the distribution is good enough */
4725 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4727 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4733 * mono_type_get_object:
4734 * @domain: an app domain
4737 * Return an System.MonoType object representing the type @type.
4740 mono_type_get_object (MonoDomain *domain, MonoType *type)
4742 MonoReflectionType *res;
4743 MonoClass *klass = mono_class_from_mono_type (type);
4745 mono_domain_lock (domain);
4746 if (!domain->type_hash)
4747 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
4748 (GCompareFunc)mymono_metadata_type_equal);
4749 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4750 mono_domain_unlock (domain);
4753 if (klass->reflection_info && !klass->wastypebuilder) {
4754 //g_assert_not_reached ();
4755 /* should this be considered an error condition? */
4757 mono_domain_unlock (domain);
4758 return klass->reflection_info;
4761 mono_class_init (klass);
4762 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4764 mono_g_hash_table_insert (domain->type_hash, type, res);
4765 mono_domain_unlock (domain);
4770 * mono_method_get_object:
4771 * @domain: an app domain
4773 * @refclass: the reflected type (can be NULL)
4775 * Return an System.Reflection.MonoMethod object representing the method @method.
4777 MonoReflectionMethod*
4778 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4781 * We use the same C representation for methods and constructors, but the type
4782 * name in C# is different.
4786 MonoReflectionMethod *ret;
4789 refclass = method->klass;
4791 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4792 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4793 cname = "MonoCMethod";
4795 cname = "MonoMethod";
4796 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4798 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4799 ret->method = method;
4800 ret->name = mono_string_new (domain, method->name);
4801 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4802 CACHE_OBJECT (method, ret, refclass);
4807 * mono_field_get_object:
4808 * @domain: an app domain
4812 * Return an System.Reflection.MonoField object representing the field @field
4815 MonoReflectionField*
4816 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
4818 MonoReflectionField *res;
4821 CHECK_OBJECT (MonoReflectionField *, field, klass);
4822 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
4823 res = (MonoReflectionField *)mono_object_new (domain, oklass);
4826 res->name = mono_string_new (domain, field->name);
4827 res->attrs = field->type->attrs;
4828 res->type = mono_type_get_object (domain, field->type);
4829 CACHE_OBJECT (field, res, klass);
4834 * mono_property_get_object:
4835 * @domain: an app domain
4837 * @property: a property
4839 * Return an System.Reflection.MonoProperty object representing the property @property
4842 MonoReflectionProperty*
4843 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
4845 MonoReflectionProperty *res;
4848 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
4849 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
4850 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
4852 res->property = property;
4853 CACHE_OBJECT (property, res, klass);
4858 * mono_event_get_object:
4859 * @domain: an app domain
4863 * Return an System.Reflection.MonoEvent object representing the event @event
4866 MonoReflectionEvent*
4867 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
4869 MonoReflectionEvent *res;
4872 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
4873 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
4874 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
4877 CACHE_OBJECT (event, res, klass);
4882 * mono_param_get_objects:
4883 * @domain: an app domain
4886 * Return an System.Reflection.ParameterInfo array object representing the parameters
4887 * in the method @method.
4890 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
4892 static MonoClass *System_Reflection_ParameterInfo;
4893 MonoArray *res = NULL;
4894 MonoReflectionMethod *member = NULL;
4895 MonoReflectionParameter *param = NULL;
4899 if (!System_Reflection_ParameterInfo)
4900 System_Reflection_ParameterInfo = mono_class_from_name (
4901 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
4903 if (!method->signature->param_count)
4904 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
4906 /* Note: the cache is based on the address of the signature into the method
4907 * since we already cache MethodInfos with the method as keys.
4909 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
4911 member = mono_method_get_object (domain, method, NULL);
4912 names = g_new (char *, method->signature->param_count);
4913 mono_method_get_param_names (method, (const char **) names);
4915 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
4916 for (i = 0; i < method->signature->param_count; ++i) {
4917 param = (MonoReflectionParameter *)mono_object_new (domain,
4918 System_Reflection_ParameterInfo);
4919 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
4920 param->DefaultValueImpl = NULL; /* FIXME */
4921 param->MemberImpl = (MonoObject*)member;
4922 param->NameImpl = mono_string_new (domain, names [i]);
4923 param->PositionImpl = i;
4924 param->AttrsImpl = method->signature->params [i]->attrs;
4925 mono_array_set (res, gpointer, i, param);
4928 CACHE_OBJECT (&(method->signature), res, NULL);
4933 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
4937 memset (assembly, 0, sizeof (MonoAssemblyName));
4939 assembly->culture = "";
4941 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
4944 while (*p == ' ' || *p == ',') {
4953 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
4955 assembly->major = strtoul (p, &s, 10);
4956 if (s == p || *s != '.')
4959 assembly->minor = strtoul (p, &s, 10);
4960 if (s == p || *s != '.')
4963 assembly->build = strtoul (p, &s, 10);
4964 if (s == p || *s != '.')
4967 assembly->revision = strtoul (p, &s, 10);
4970 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
4972 if (strncmp (p, "neutral", 7) == 0) {
4973 assembly->culture = "";
4976 assembly->culture = p;
4977 while (*p && *p != ',') {
4981 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
4984 while (*s && isxdigit (*s)) {
4988 assembly->hash_len = s - p;
4989 if (!(s-p) || ((s-p) & 1))
4991 assembly->hash_value = s = p;
4992 while (*s && isxdigit (*s)) {
4994 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
4997 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5002 while (*p && *p != ',')
5006 while (*p == ' ' || *p == ',') {
5020 * mono_reflection_parse_type:
5023 * Parse a type name as accepted by the GetType () method and output the info
5024 * extracted in the info structure.
5025 * the name param will be mangled, so, make a copy before passing it to this function.
5026 * The fields in info will be valid until the memory pointed to by name is valid.
5027 * Returns 0 on parse error.
5028 * See also mono_type_get_name () below.
5031 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5033 char *start, *p, *w, *last_point, *startn;
5034 int in_modifiers = 0;
5035 int isbyref = 0, rank;
5037 start = p = w = name;
5039 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5040 info->name = info->name_space = NULL;
5041 info->nested = NULL;
5042 info->modifiers = NULL;
5044 /* last_point separates the namespace from the name */
5050 *p = 0; /* NULL terminate the name */
5052 info->nested = g_list_append (info->nested, startn);
5053 /* we have parsed the nesting namespace + name */
5057 info->name_space = start;
5059 info->name = last_point + 1;
5061 info->name_space = (char *)"";
5087 info->name_space = start;
5089 info->name = last_point + 1;
5091 info->name_space = (char *)"";
5098 if (isbyref) /* only one level allowed by the spec */
5101 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5105 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5116 else if (*p != '*') /* '*' means unknown lower bound */
5122 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5134 return 0; /* missing assembly name */
5135 if (!assembly_name_to_aname (&info->assembly, p))
5142 if (info->assembly.name)
5145 *w = 0; /* terminate class name */
5146 if (!info->name || !*info->name)
5148 /* add other consistency checks */
5153 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5160 image = mono_defaults.corlib;
5163 klass = mono_class_from_name_case (image, info->name_space, info->name);
5165 klass = mono_class_from_name (image, info->name_space, info->name);
5168 for (mod = info->nested; mod; mod = mod->next) {
5171 mono_class_init (klass);
5172 nested = klass->nested_classes;
5175 klass = nested->data;
5177 if (g_strcasecmp (klass->name, mod->data) == 0)
5180 if (strcmp (klass->name, mod->data) == 0)
5184 nested = nested->next;
5191 mono_class_init (klass);
5192 for (mod = info->modifiers; mod; mod = mod->next) {
5193 modval = GPOINTER_TO_UINT (mod->data);
5194 if (!modval) { /* byref: must be last modifier */
5195 return &klass->this_arg;
5196 } else if (modval == -1) {
5197 klass = mono_ptr_class_get (&klass->byval_arg);
5198 } else { /* array rank */
5199 klass = mono_array_class_get (klass, modval);
5201 mono_class_init (klass);
5204 return &klass->byval_arg;
5208 * mono_reflection_get_type:
5209 * @image: a metadata context
5210 * @info: type description structure
5211 * @ignorecase: flag for case-insensitive string compares
5213 * Build a MonoType from the type description in @info.
5218 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5221 MonoReflectionAssembly *assembly;
5225 type = mono_reflection_get_type_internal (image, info, ignorecase);
5228 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5231 // Reconstruct the type name
5232 fullName = g_string_new ("");
5233 if (info->name_space && (info->name_space [0] != '\0'))
5234 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5236 g_string_printf (fullName, info->name);
5237 for (mod = info->nested; mod; mod = mod->next)
5238 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5241 mono_domain_try_type_resolve (
5242 mono_domain_get (), fullName->str, NULL);
5243 if (assembly && (!image || (assembly->assembly->image == image)))
5244 type = mono_reflection_get_type_internal (assembly->assembly->image,
5246 g_string_free (fullName, TRUE);
5251 * mono_reflection_type_from_name:
5253 * @image: a metadata context (can be NULL).
5255 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5256 * it defaults to get the type from @image or, if @image is NULL or loading
5257 * from it fails, uses corlib.
5261 mono_reflection_type_from_name (char *name, MonoImage *image)
5264 MonoTypeNameParse info;
5265 MonoAssembly *assembly;
5267 /*g_print ("requested type %s\n", str);*/
5268 if (!mono_reflection_parse_type (name, &info)) {
5269 g_list_free (info.modifiers);
5270 g_list_free (info.nested);
5274 if (info.assembly.name) {
5275 assembly = mono_assembly_loaded (&info.assembly);
5276 /* do we need to load if it's not already loaded? */
5278 g_list_free (info.modifiers);
5279 g_list_free (info.nested);
5283 image = assembly->image;
5284 } else if (image == NULL) {
5285 image = mono_defaults.corlib;
5288 type = mono_reflection_get_type (image, &info, FALSE);
5289 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5290 image = mono_defaults.corlib;
5291 type = mono_reflection_get_type (image, &info, FALSE);
5294 g_list_free (info.modifiers);
5295 g_list_free (info.nested);
5300 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5302 int slen, type = t->type;
5307 case MONO_TYPE_BOOLEAN: {
5308 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5313 case MONO_TYPE_CHAR:
5315 case MONO_TYPE_I2: {
5316 guint16 *val = g_malloc (sizeof (guint16));
5321 #if SIZEOF_VOID_P == 4
5327 case MONO_TYPE_I4: {
5328 guint32 *val = g_malloc (sizeof (guint32));
5333 #if SIZEOF_VOID_P == 8
5334 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5339 case MONO_TYPE_I8: {
5340 guint64 *val = g_malloc (sizeof (guint64));
5345 case MONO_TYPE_VALUETYPE:
5346 if (t->data.klass->enumtype) {
5347 type = t->data.klass->enum_basetype->type;
5350 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5353 case MONO_TYPE_STRING:
5354 if (*p == (char)0xFF) {
5358 slen = mono_metadata_decode_value (p, &p);
5360 return mono_string_new_len (mono_domain_get (), p, slen);
5361 case MONO_TYPE_CLASS: {
5364 if (*p == (char)0xFF) {
5369 slen = mono_metadata_decode_value (p, &p);
5370 n = g_memdup (p, slen + 1);
5372 t = mono_reflection_type_from_name (n, image);
5374 g_warning ("Cannot load type '%s'", n);
5378 return mono_type_get_object (mono_domain_get (), t);
5382 case MONO_TYPE_OBJECT: {
5385 MonoClass *subc = NULL;
5390 } else if (subt == 0x0E) {
5391 type = MONO_TYPE_STRING;
5393 } else if (subt == 0x55) {
5396 slen = mono_metadata_decode_value (p, &p);
5397 n = g_memdup (p, slen + 1);
5399 t = mono_reflection_type_from_name (n, image);
5401 g_warning ("Cannot load type '%s'", n);
5404 subc = mono_class_from_mono_type (t);
5405 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5406 MonoType simple_type = {{0}};
5407 simple_type.type = subt;
5408 subc = mono_class_from_mono_type (&simple_type);
5410 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5412 val = load_cattr_value (image, &subc->byval_arg, p, end);
5413 obj = mono_object_new (mono_domain_get (), subc);
5414 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5418 case MONO_TYPE_SZARRAY:
5421 guint32 i, alen, basetype;
5424 if (alen == 0xffffffff) {
5428 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5429 basetype = t->data.klass->byval_arg.type;
5434 case MONO_TYPE_BOOLEAN:
5435 for (i=0;i<alen;i++)
5437 MonoBoolean val=*p++;
5438 mono_array_set(arr,MonoBoolean,i,val);
5441 case MONO_TYPE_CHAR:
5444 for (i=0;i<alen;i++)
5446 guint16 val=read16(p);
5447 mono_array_set(arr,guint16,i,val);
5454 for (i=0;i<alen;i++)
5456 guint32 val=read32(p);
5457 mono_array_set(arr,guint32,i,val);
5464 for (i=0;i<alen;i++)
5466 guint64 val=read64(p);
5467 mono_array_set(arr,guint64,i,val);
5471 case MONO_TYPE_CLASS:
5472 case MONO_TYPE_STRING:
5473 for (i = 0; i < alen; i++) {
5474 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5475 mono_array_set (arr, gpointer, i, item);
5479 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5485 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5491 type_is_reference (MonoType *type)
5493 switch (type->type) {
5494 case MONO_TYPE_BOOLEAN:
5495 case MONO_TYPE_CHAR:
5508 case MONO_TYPE_VALUETYPE:
5516 free_param_data (MonoMethodSignature *sig, void **params) {
5518 for (i = 0; i < sig->param_count; ++i) {
5519 if (!type_is_reference (sig->params [i]))
5520 g_free (params [i]);
5525 * Find the method index in the metadata methodDef table.
5526 * Later put these three helper methods in metadata and export them.
5529 find_method_index (MonoMethod *method) {
5530 MonoClass *klass = method->klass;
5533 for (i = 0; i < klass->method.count; ++i) {
5534 if (method == klass->methods [i])
5535 return klass->method.first + 1 + i;
5541 * Find the field index in the metadata FieldDef table.
5544 find_field_index (MonoClass *klass, MonoClassField *field) {
5547 for (i = 0; i < klass->field.count; ++i) {
5548 if (field == &klass->fields [i])
5549 return klass->field.first + 1 + i;
5555 * Find the property index in the metadata Property table.
5558 find_property_index (MonoClass *klass, MonoProperty *property) {
5561 for (i = 0; i < klass->property.count; ++i) {
5562 if (property == &klass->properties [i])
5563 return klass->property.first + 1 + i;
5569 * Find the event index in the metadata Event table.
5572 find_event_index (MonoClass *klass, MonoEvent *event) {
5575 for (i = 0; i < klass->event.count; ++i) {
5576 if (event == &klass->events [i])
5577 return klass->event.first + 1 + i;
5583 create_custom_attr (MonoImage *image, MonoMethod *method,
5584 const char *data, guint32 len)
5586 const char *p = data;
5588 guint32 i, j, num_named;
5592 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5595 mono_class_init (method->klass);
5596 /*g_print ("got attr %s\n", method->klass->name);*/
5598 params = g_new (void*, method->signature->param_count);
5602 for (i = 0; i < method->signature->param_count; ++i) {
5603 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5607 attr = mono_object_new (mono_domain_get (), method->klass);
5608 mono_runtime_invoke (method, attr, params, NULL);
5609 free_param_data (method->signature, params);
5611 num_named = read16 (named);
5613 for (j = 0; j < num_named; j++) {
5615 char *name, named_type, data_type;
5616 named_type = *named++;
5617 data_type = *named++; /* type of data */
5618 if (data_type == 0x55) {
5621 type_len = mono_metadata_decode_blob_size (named, &named);
5622 type_name = g_malloc (type_len + 1);
5623 memcpy (type_name, named, type_len);
5624 type_name [type_len] = 0;
5626 /* FIXME: lookup the type and check type consistency */
5629 if (data_type == MONO_TYPE_SZARRAY)
5630 /* The spec does not mention this */
5632 name_len = mono_metadata_decode_blob_size (named, &named);
5633 name = g_malloc (name_len + 1);
5634 memcpy (name, named, name_len);
5635 name [name_len] = 0;
5637 if (named_type == 0x53) {
5638 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5639 void *val = load_cattr_value (image, field->type, named, &named);
5640 mono_field_set_value (attr, field, val);
5641 if (!type_is_reference (field->type))
5643 } else if (named_type == 0x54) {
5646 MonoType *prop_type;
5648 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5649 /* can we have more that 1 arg in a custom attr named property? */
5650 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5651 pparams [0] = load_cattr_value (image, prop_type, named, &named);
5652 mono_property_set_value (prop, attr, pparams, NULL);
5653 if (!type_is_reference (prop_type))
5654 g_free (pparams [0]);
5663 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5670 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5671 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5672 for (i = 0; i < cinfo->num_attrs; ++i) {
5673 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5674 mono_array_set (result, gpointer, i, attr);
5680 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5682 guint32 mtoken, i, len;
5683 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5685 MonoCustomAttrInfo *ainfo;
5686 GList *tmp, *list = NULL;
5689 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5691 i = mono_metadata_custom_attrs_from_index (image, idx);
5695 while (i < ca->rows) {
5696 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5698 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5701 len = g_list_length (list);
5704 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5705 ainfo->num_attrs = len;
5706 ainfo->image = image;
5707 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5708 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5709 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5710 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5711 case CUSTOM_ATTR_TYPE_METHODDEF:
5712 mtoken |= MONO_TOKEN_METHOD_DEF;
5714 case CUSTOM_ATTR_TYPE_MEMBERREF:
5715 mtoken |= MONO_TOKEN_MEMBER_REF;
5718 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5721 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5722 if (!ainfo->attrs [i].ctor)
5723 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5724 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5725 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5726 ainfo->attrs [i].data = data;
5734 mono_custom_attrs_from_method (MonoMethod *method)
5736 MonoCustomAttrInfo *cinfo;
5739 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5741 idx = find_method_index (method);
5742 idx <<= CUSTOM_ATTR_BITS;
5743 idx |= CUSTOM_ATTR_METHODDEF;
5744 return mono_custom_attrs_from_index (method->klass->image, idx);
5748 mono_custom_attrs_from_class (MonoClass *klass)
5750 MonoCustomAttrInfo *cinfo;
5753 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5755 idx = mono_metadata_token_index (klass->type_token);
5756 idx <<= CUSTOM_ATTR_BITS;
5757 idx |= CUSTOM_ATTR_TYPEDEF;
5758 return mono_custom_attrs_from_index (klass->image, idx);
5762 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5764 MonoCustomAttrInfo *cinfo;
5767 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5769 idx = 1; /* there is only one assembly */
5770 idx <<= CUSTOM_ATTR_BITS;
5771 idx |= CUSTOM_ATTR_ASSEMBLY;
5772 return mono_custom_attrs_from_index (assembly->image, idx);
5775 static MonoCustomAttrInfo*
5776 mono_custom_attrs_from_module (MonoImage *image)
5778 MonoCustomAttrInfo *cinfo;
5781 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5783 idx = 1; /* there is only one module */
5784 idx <<= CUSTOM_ATTR_BITS;
5785 idx |= CUSTOM_ATTR_MODULE;
5786 return mono_custom_attrs_from_index (image, idx);
5790 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5792 MonoCustomAttrInfo *cinfo;
5795 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5797 idx = find_property_index (klass, property);
5798 idx <<= CUSTOM_ATTR_BITS;
5799 idx |= CUSTOM_ATTR_PROPERTY;
5800 return mono_custom_attrs_from_index (klass->image, idx);
5804 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
5806 MonoCustomAttrInfo *cinfo;
5809 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
5811 idx = find_event_index (klass, event);
5812 idx <<= CUSTOM_ATTR_BITS;
5813 idx |= CUSTOM_ATTR_EVENT;
5814 return mono_custom_attrs_from_index (klass->image, idx);
5818 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
5820 MonoCustomAttrInfo *cinfo;
5823 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5825 idx = find_field_index (klass, field);
5826 idx <<= CUSTOM_ATTR_BITS;
5827 idx |= CUSTOM_ATTR_FIELDDEF;
5828 return mono_custom_attrs_from_index (klass->image, idx);
5832 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
5835 guint32 i, idx, method_index;
5836 guint32 param_list, param_last, param_pos, found;
5839 /* FIXME: handle dynamic custom attrs for parameters */
5840 /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
5842 image = method->klass->image;
5843 method_index = find_method_index (method);
5844 ca = &image->tables [MONO_TABLE_METHOD];
5846 if (method->klass->generic_inst || method->klass->gen_params ||
5847 method->signature->generic_param_count) {
5848 // FIXME FIXME FIXME
5852 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
5853 if (method_index == ca->rows) {
5854 ca = &image->tables [MONO_TABLE_PARAM];
5855 param_last = ca->rows + 1;
5857 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
5858 ca = &image->tables [MONO_TABLE_PARAM];
5861 for (i = param_list; i < param_last; ++i) {
5862 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
5863 if (param_pos == param) {
5871 idx <<= CUSTOM_ATTR_BITS;
5872 idx |= CUSTOM_ATTR_PARAMDEF;
5873 return mono_custom_attrs_from_index (image, idx);
5877 * mono_reflection_get_custom_attrs:
5878 * @obj: a reflection object handle
5880 * Return an array with all the custom attributes defined of the
5881 * reflection handle @obj. The objects are fully build.
5884 mono_reflection_get_custom_attrs (MonoObject *obj)
5888 MonoCustomAttrInfo *cinfo = NULL;
5890 MONO_ARCH_SAVE_REGS;
5892 klass = obj->vtable->klass;
5893 /* FIXME: need to handle: Module */
5894 if (klass == mono_defaults.monotype_class) {
5895 MonoReflectionType *rtype = (MonoReflectionType*)obj;
5896 klass = mono_class_from_mono_type (rtype->type);
5897 cinfo = mono_custom_attrs_from_class (klass);
5898 } else if (strcmp ("Assembly", klass->name) == 0) {
5899 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
5900 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
5901 } else if (strcmp ("Module", klass->name) == 0) {
5902 MonoReflectionModule *module = (MonoReflectionModule*)obj;
5903 cinfo = mono_custom_attrs_from_module (module->image);
5904 } else if (strcmp ("MonoProperty", klass->name) == 0) {
5905 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
5906 cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
5907 } else if (strcmp ("MonoEvent", klass->name) == 0) {
5908 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
5909 cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
5910 } else if (strcmp ("MonoField", klass->name) == 0) {
5911 MonoReflectionField *rfield = (MonoReflectionField*)obj;
5912 cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
5913 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
5914 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
5915 cinfo = mono_custom_attrs_from_method (rmethod->method);
5916 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
5917 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
5918 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
5919 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
5920 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
5921 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
5922 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
5923 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
5924 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
5925 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
5926 } else { /* handle other types here... */
5927 g_error ("get custom attrs not yet supported for %s", klass->name);
5931 result = mono_custom_attrs_construct (cinfo);
5933 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5934 result = mono_array_new (mono_domain_get (), klass, 0);
5940 static MonoMethodSignature*
5941 parameters_to_signature (MonoArray *parameters) {
5942 MonoMethodSignature *sig;
5945 count = parameters? mono_array_length (parameters): 0;
5947 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
5948 sig->param_count = count;
5949 sig->sentinelpos = -1; /* FIXME */
5950 for (i = 0; i < count; ++i) {
5951 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
5952 sig->params [i] = pt->type;
5957 static MonoMethodSignature*
5958 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
5959 MonoMethodSignature *sig;
5961 sig = parameters_to_signature (ctor->parameters);
5962 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5963 sig->ret = &mono_defaults.void_class->byval_arg;
5967 static MonoMethodSignature*
5968 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
5969 MonoMethodSignature *sig;
5971 sig = parameters_to_signature (method->parameters);
5972 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5973 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
5974 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
5978 static MonoMethodSignature*
5979 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
5980 MonoMethodSignature *sig;
5982 sig = parameters_to_signature (method->parameters);
5983 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
5984 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
5985 sig->generic_param_count = 0;
5990 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
5992 MonoClass *klass = mono_object_class (prop);
5993 if (strcmp (klass->name, "PropertyBuilder") == 0) {
5994 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
5995 *name = mono_string_to_utf8 (pb->name);
5996 *type = pb->type->type;
5998 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
5999 *name = g_strdup (p->property->name);
6000 if (p->property->get)
6001 *type = p->property->get->signature->ret;
6003 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6008 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6010 MonoClass *klass = mono_object_class (field);
6011 if (strcmp (klass->name, "FieldBuilder") == 0) {
6012 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6013 *name = mono_string_to_utf8 (fb->name);
6014 *type = fb->type->type;
6016 MonoReflectionField *f = (MonoReflectionField *)field;
6017 *name = g_strdup (f->field->name);
6018 *type = f->field->type;
6023 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6026 MonoTypeEnum simple_type;
6028 if ((p-buffer) + 10 >= *buflen) {
6031 newbuf = g_realloc (buffer, *buflen);
6032 p = newbuf + (p-buffer);
6035 argval = ((char*)arg + sizeof (MonoObject));
6036 simple_type = type->type;
6038 switch (simple_type) {
6039 case MONO_TYPE_BOOLEAN:
6044 case MONO_TYPE_CHAR:
6047 swap_with_size (p, argval, 2, 1);
6053 swap_with_size (p, argval, 4, 1);
6059 swap_with_size (p, argval, 8, 1);
6062 case MONO_TYPE_VALUETYPE:
6063 if (type->data.klass->enumtype) {
6064 simple_type = type->data.klass->enum_basetype->type;
6067 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6070 case MONO_TYPE_STRING: {
6077 str = mono_string_to_utf8 ((MonoString*)arg);
6078 slen = strlen (str);
6079 if ((p-buffer) + 10 + slen >= *buflen) {
6083 newbuf = g_realloc (buffer, *buflen);
6084 p = newbuf + (p-buffer);
6087 mono_metadata_encode_value (slen, p, &p);
6088 memcpy (p, str, slen);
6093 case MONO_TYPE_CLASS: {
6101 k = mono_object_class (arg);
6102 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6103 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6104 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6106 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6107 slen = strlen (str);
6108 if ((p-buffer) + 10 + slen >= *buflen) {
6112 newbuf = g_realloc (buffer, *buflen);
6113 p = newbuf + (p-buffer);
6116 mono_metadata_encode_value (slen, p, &p);
6117 memcpy (p, str, slen);
6122 case MONO_TYPE_SZARRAY: {
6127 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6130 len = mono_array_length ((MonoArray*)arg);
6132 *p++ = (len >> 8) & 0xff;
6133 *p++ = (len >> 16) & 0xff;
6134 *p++ = (len >> 24) & 0xff;
6136 *retbuffer = buffer;
6137 eclass = type->data.klass;
6138 for (i = 0; i < len; ++i) {
6139 encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6143 /* it may be a boxed value or a Type */
6144 case MONO_TYPE_OBJECT: {
6145 MonoClass *klass = mono_object_class (arg);
6149 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6152 } else if (klass->enumtype) {
6154 } else if (klass == mono_defaults.string_class) {
6155 simple_type = MONO_TYPE_STRING;
6158 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6159 *p++ = simple_type = klass->byval_arg.type;
6162 g_error ("unhandled type in custom attr");
6164 str = type_get_qualified_name (klass->enum_basetype, NULL);
6165 slen = strlen (str);
6166 if ((p-buffer) + 10 + slen >= *buflen) {
6170 newbuf = g_realloc (buffer, *buflen);
6171 p = newbuf + (p-buffer);
6174 mono_metadata_encode_value (slen, p, &p);
6175 memcpy (p, str, slen);
6178 simple_type = klass->enum_basetype->type;
6182 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6185 *retbuffer = buffer;
6189 * mono_reflection_get_custom_attrs_blob:
6190 * @ctor: custom attribute constructor
6191 * @ctorArgs: arguments o the constructor
6197 * Creates the blob of data that needs to be saved in the metadata and that represents
6198 * the custom attributed described by @ctor, @ctorArgs etc.
6199 * Returns: a Byte array representing the blob of data.
6202 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6205 MonoMethodSignature *sig;
6210 MONO_ARCH_SAVE_REGS;
6212 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6213 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6215 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6217 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6219 p = buffer = g_malloc (buflen);
6220 /* write the prolog */
6223 for (i = 0; i < sig->param_count; ++i) {
6224 arg = mono_array_get (ctorArgs, MonoObject*, i);
6225 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6229 i += mono_array_length (properties);
6231 i += mono_array_length (fields);
6233 *p++ = (i >> 8) & 0xff;
6236 for (i = 0; i < mono_array_length (properties); ++i) {
6241 prop = mono_array_get (properties, gpointer, i);
6242 get_prop_name_and_type (prop, &pname, &ptype);
6243 *p++ = 0x54; /* PROPERTY signature */
6245 /* Preallocate a large enough buffer */
6246 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6247 char *str = type_get_qualified_name (ptype, NULL);
6253 len += strlen (pname);
6255 if ((p-buffer) + 20 + len >= buflen) {
6259 newbuf = g_realloc (buffer, buflen);
6260 p = newbuf + (p-buffer);
6264 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6265 char *str = type_get_qualified_name (ptype, NULL);
6266 int slen = strlen (str);
6270 * This seems to be optional...
6273 mono_metadata_encode_value (slen, p, &p);
6274 memcpy (p, str, slen);
6278 mono_metadata_encode_value (ptype->type, p, &p);
6279 if (ptype->type == MONO_TYPE_SZARRAY)
6280 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6282 len = strlen (pname);
6283 mono_metadata_encode_value (len, p, &p);
6284 memcpy (p, pname, len);
6286 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6293 for (i = 0; i < mono_array_length (fields); ++i) {
6298 field = mono_array_get (fields, gpointer, i);
6299 get_field_name_and_type (field, &fname, &ftype);
6300 *p++ = 0x53; /* FIELD signature */
6301 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6302 char *str = type_get_qualified_name (ftype, NULL);
6303 int slen = strlen (str);
6304 if ((p-buffer) + 10 + slen >= buflen) {
6308 newbuf = g_realloc (buffer, buflen);
6309 p = newbuf + (p-buffer);
6314 * This seems to be optional...
6317 mono_metadata_encode_value (slen, p, &p);
6318 memcpy (p, str, slen);
6322 mono_metadata_encode_value (ftype->type, p, &p);
6324 len = strlen (fname);
6325 mono_metadata_encode_value (len, p, &p);
6326 memcpy (p, fname, len);
6328 encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6333 g_assert (p - buffer <= buflen);
6334 buflen = p - buffer;
6335 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6336 p = mono_array_addr (result, char, 0);
6337 memcpy (p, buffer, buflen);
6339 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6345 * mono_reflection_setup_internal_class:
6346 * @tb: a TypeBuilder object
6348 * Creates a MonoClass that represents the TypeBuilder.
6349 * This is a trick that lets us simplify a lot of reflection code
6350 * (and will allow us to support Build and Run assemblies easier).
6353 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6355 MonoClass *klass, *parent;
6357 MONO_ARCH_SAVE_REGS;
6359 klass = g_new0 (MonoClass, 1);
6361 klass->image = &tb->module->dynamic_image->image;
6364 /* check so we can compile corlib correctly */
6365 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6366 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6367 parent = tb->parent->type->data.klass;
6369 parent = my_mono_class_from_mono_type (tb->parent->type);
6373 klass->inited = 1; /* we lie to the runtime */
6374 klass->name = mono_string_to_utf8 (tb->name);
6375 klass->name_space = mono_string_to_utf8 (tb->nspace);
6376 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6377 klass->flags = tb->attrs;
6379 klass->element_class = klass;
6380 klass->reflection_info = tb; /* need to pin. */
6382 /* Put into cache so mono_class_get () will find it */
6383 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6386 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6387 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6391 mono_class_setup_parent (klass, parent);
6392 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6393 const char *old_n = klass->name;
6394 /* trick to get relative numbering right when compiling corlib */
6395 klass->name = "BuildingObject";
6396 mono_class_setup_parent (klass, mono_defaults.object_class);
6397 klass->name = old_n;
6399 mono_class_setup_mono_type (klass);
6401 mono_class_setup_supertypes (klass);
6404 * FIXME: handle interfaces.
6407 tb->type.type = &klass->byval_arg;
6409 if (tb->nesting_type) {
6410 g_assert (tb->nesting_type->type);
6411 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6414 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6418 * mono_reflection_setup_generic_class:
6419 * @tb: a TypeBuilder object
6421 * Setup the generic class after all generic parameters have been added.
6424 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6429 MONO_ARCH_SAVE_REGS;
6431 klass = my_mono_class_from_mono_type (tb->type.type);
6433 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6435 if (klass->gen_params || (count == 0))
6438 klass->num_gen_params = count;
6439 klass->gen_params = g_new0 (MonoGenericParam, count);
6441 for (i = 0; i < count; i++) {
6442 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6443 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6446 ensure_runtime_vtable (klass);
6450 * mono_reflection_create_internal_class:
6451 * @tb: a TypeBuilder object
6453 * Actually create the MonoClass that is associated with the TypeBuilder.
6456 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6460 MONO_ARCH_SAVE_REGS;
6462 klass = my_mono_class_from_mono_type (tb->type.type);
6464 if (klass->enumtype && klass->enum_basetype == NULL) {
6465 MonoReflectionFieldBuilder *fb;
6467 g_assert (tb->fields != NULL);
6468 g_assert (mono_array_length (tb->fields) >= 1);
6470 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6472 klass->enum_basetype = fb->type->type;
6473 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6474 if (!klass->element_class)
6475 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6476 klass->instance_size = klass->element_class->instance_size;
6477 klass->size_inited = 1;
6479 * this is almost safe to do with enums and it's needed to be able
6480 * to create objects of the enum type (for use in SetConstant).
6482 /* FIXME: Does this mean enums can't have method overrides ? */
6483 mono_class_setup_vtable (klass, NULL, 0);
6487 static MonoMarshalSpec*
6488 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6489 MonoReflectionMarshal *minfo)
6491 MonoMarshalSpec *res;
6493 res = g_new0 (MonoMarshalSpec, 1);
6494 res->native = minfo->type;
6496 switch (minfo->type) {
6497 case MONO_NATIVE_LPARRAY:
6498 res->data.array_data.elem_type = minfo->eltype;
6499 res->data.array_data.param_num = 0; /* Not yet */
6500 res->data.array_data.num_elem = minfo->count;
6503 case MONO_NATIVE_BYVALTSTR:
6504 case MONO_NATIVE_BYVALARRAY:
6505 res->data.array_data.num_elem = minfo->count;
6508 case MONO_NATIVE_CUSTOM:
6509 if (minfo->marshaltyperef)
6510 res->data.custom_data.custom_name =
6511 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6513 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6524 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6525 ReflectionMethodBuilder *rmb,
6526 MonoMethodSignature *sig)
6529 MonoMethodNormal *pm;
6530 MonoMarshalSpec **specs;
6531 MonoReflectionMethodAux *method_aux;
6534 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6535 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6536 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6539 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6541 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6543 pm = (MonoMethodNormal*)m;
6546 m->flags = rmb->attrs;
6547 m->iflags = rmb->iattrs;
6548 m->name = mono_string_to_utf8 (rmb->name);
6552 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6554 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6555 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6558 m->signature->pinvoke = 1;
6559 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6561 m->signature->pinvoke = 1;
6563 } else if (!m->klass->dummy &&
6564 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6565 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6566 MonoMethodHeader *header;
6568 gint32 max_stack, i;
6569 gint32 num_locals = 0;
6570 gint32 num_clauses = 0;
6574 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6575 code_size = rmb->ilgen->code_len;
6576 max_stack = rmb->ilgen->max_stack;
6577 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6578 if (rmb->ilgen->ex_handlers)
6579 num_clauses = method_count_clauses (rmb->ilgen);
6582 code = mono_array_addr (rmb->code, guint8, 0);
6583 code_size = mono_array_length (rmb->code);
6584 /* we probably need to run a verifier on the code... */
6594 header = g_malloc0 (sizeof (MonoMethodHeader) +
6595 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6596 header->code_size = code_size;
6597 header->code = g_malloc (code_size);
6598 memcpy ((char*)header->code, code, code_size);
6599 header->max_stack = max_stack;
6600 header->init_locals = rmb->init_locals;
6601 header->num_locals = num_locals;
6603 for (i = 0; i < num_locals; ++i) {
6604 MonoReflectionLocalBuilder *lb =
6605 mono_array_get (rmb->ilgen->locals,
6606 MonoReflectionLocalBuilder*, i);
6608 header->locals [i] = g_new0 (MonoType, 1);
6609 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6612 header->num_clauses = num_clauses;
6614 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6619 if (rmb->generic_params) {
6620 int count = mono_array_length (rmb->generic_params);
6621 header->gen_params = g_new0 (MonoGenericParam, count);
6622 for (i = 0; i < count; i++) {
6623 MonoReflectionGenericParam *gp =
6624 mono_array_get (rmb->generic_params,
6625 MonoReflectionGenericParam*, i);
6627 header->gen_params [i] = *gp->type.type->data.generic_param;
6631 pm->header = header;
6635 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6638 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6640 for (i = 0; i < rmb->nrefs; ++i)
6641 mw->data = g_list_append (mw->data, rmb->refs [i]);
6646 /* Parameter names */
6647 if (rmb->parameters) {
6649 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6650 method_aux->param_names = g_new0 (char *, m->signature->param_count);
6651 for (i = 0; i < m->signature->param_count; ++i) {
6652 MonoReflectionParamBuilder *pb;
6653 if ((pb = mono_array_get (rmb->parameters, MonoReflectionParamBuilder*, i))) {
6655 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6660 /* Parameter marshalling */
6663 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6664 MonoReflectionParamBuilder *pb;
6665 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6666 if (pb->marshal_info) {
6668 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6669 specs [pb->position] =
6670 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6674 if (specs != NULL) {
6676 method_aux = g_new0 (MonoReflectionMethodAux, 1);
6677 method_aux->param_marshall = specs;
6680 if (klass->image->dynamic && method_aux)
6681 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6687 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6689 ReflectionMethodBuilder rmb;
6690 MonoMethodSignature *sig;
6692 sig = ctor_builder_to_signature (mb);
6694 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6696 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6697 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6699 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6700 /* ilgen is no longer needed */
6708 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6710 ReflectionMethodBuilder rmb;
6711 MonoMethodSignature *sig;
6713 sig = method_builder_to_signature (mb);
6715 reflection_methodbuilder_from_method_builder (&rmb, mb);
6717 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6718 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6720 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6721 /* ilgen is no longer needed */
6727 static MonoClassField*
6728 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6730 MonoClassField *field;
6737 field = g_new0 (MonoClassField, 1);
6739 field->name = mono_string_to_utf8 (fb->name);
6741 /* FIXME: handle type modifiers */
6742 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6743 field->type->attrs = fb->attrs;
6745 field->type = fb->type->type;
6747 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6748 field->data = mono_array_addr (fb->rva_data, char, 0);
6749 if (fb->offset != -1)
6750 field->offset = fb->offset;
6751 field->parent = klass;
6753 mono_save_custom_attrs (klass->image, field, fb->cattrs);
6755 if (fb->def_value) {
6756 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6757 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6758 field->def_value = g_new0 (MonoConstant, 1);
6759 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6760 /* Copy the data from the blob since it might get realloc-ed */
6761 p = assembly->blob.data + idx;
6762 len = mono_metadata_decode_blob_size (p, &p2);
6764 field->def_value->value = g_malloc (len);
6765 memcpy (field->def_value->value, p, len);
6771 static MonoReflectionInflatedMethod*
6772 inflated_method_get_object (MonoDomain *domain, MonoMethod *method, MonoReflectionMethod *declaring,
6773 MonoGenericInst *ginst)
6776 MonoClass *klass, *refclass;
6777 MonoReflectionInflatedMethod *ret;
6779 refclass = method->klass;
6781 CHECK_OBJECT (MonoReflectionInflatedMethod *, method, refclass);
6782 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
6783 cname = "MonoInflatedCtor";
6785 cname = "MonoInflatedMethod";
6786 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
6789 ret = (MonoReflectionInflatedMethod*)mono_object_new (domain, klass);
6790 ret->rmethod.method = method;
6791 ret->rmethod.name = mono_string_new (domain, method->name);
6792 ret->rmethod.reftype = mono_type_get_object (domain, &refclass->byval_arg);
6793 ret->declaring = declaring;
6795 CACHE_OBJECT (method, ret, refclass);
6799 MonoReflectionGenericInst*
6800 mono_reflection_bind_generic_parameters (MonoReflectionType *type, MonoArray *types)
6802 static MonoClass *System_Reflection_MonoGenericInst;
6805 MonoGenericInst *ginst;
6806 MonoArray *ifaces = NULL;
6807 MonoReflectionType *ptype = NULL;
6808 MonoClass *klass, *iklass, *pklass = NULL;
6809 MonoReflectionGenericInst *res, *parent = NULL;
6810 MonoReflectionTypeBuilder *tb = NULL;
6813 domain = mono_object_domain (type);
6815 klass = mono_class_from_mono_type (type->type);
6816 if (!klass->gen_params && !klass->generic_inst)
6819 if (!System_Reflection_MonoGenericInst) {
6820 System_Reflection_MonoGenericInst = mono_class_from_name (
6821 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
6822 g_assert (System_Reflection_MonoGenericInst);
6825 if (klass->wastypebuilder && klass->reflection_info) {
6826 tb = klass->reflection_info;
6830 pklass = mono_class_from_mono_type (ptype->type);
6832 pklass = klass->parent;
6834 ptype = mono_type_get_object (domain, &pklass->byval_arg);
6837 if (pklass && pklass->generic_inst)
6838 parent = mono_reflection_bind_generic_parameters (ptype, types);
6842 pklass = mono_defaults.object_class;
6844 icount = klass->interface_count;
6845 ifaces = mono_array_new (domain, System_Reflection_MonoGenericInst, icount);
6847 for (i = 0; i < icount; i++) {
6848 MonoReflectionGenericInst *iface;
6849 MonoReflectionType *itype;
6852 itype = mono_array_get (tb->interfaces, gpointer, i);
6854 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
6855 iface = mono_reflection_bind_generic_parameters (itype, types);
6857 mono_array_set (ifaces, gpointer, i, iface);
6861 geninst = g_new0 (MonoType, 1);
6862 geninst->type = MONO_TYPE_GENERICINST;
6863 geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1);
6865 if (klass->gen_params) {
6866 ginst->type_argc = mono_array_length (types);
6867 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6869 for (i = 0; i < ginst->type_argc; ++i) {
6870 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6872 ginst->type_argv [i] = garg->type;
6874 if (!ginst->is_open)
6875 ginst->is_open = mono_class_is_open_constructed_type (garg->type);
6878 ginst->generic_type = &klass->byval_arg;
6880 MonoGenericInst *kginst = klass->generic_inst->data.generic_inst;
6882 ginst->type_argc = kginst->type_argc;
6883 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
6885 for (i = 0; i < ginst->type_argc; i++) {
6886 MonoType *t = kginst->type_argv [i];
6888 if (t->type == MONO_TYPE_VAR) {
6889 int num = t->data.generic_param->num;
6890 MonoReflectionType *garg = mono_array_get (types, gpointer, num);
6895 if (!ginst->is_open)
6896 ginst->is_open = mono_class_is_open_constructed_type (t);
6898 ginst->type_argv [i] = t;
6901 ginst->generic_type = kginst->generic_type;
6904 iklass = mono_class_from_generic (geninst, FALSE);
6906 mono_class_setup_parent (iklass, parent ? parent->klass : pklass);
6907 mono_class_setup_mono_type (iklass);
6909 res = (MonoReflectionGenericInst *)mono_object_new (domain, System_Reflection_MonoGenericInst);
6911 res->type.type = iklass->generic_inst;
6912 res->klass = iklass;
6913 res->parent = parent;
6914 res->generic_type = type;
6915 res->interfaces = ifaces;
6920 MonoReflectionInflatedMethod*
6921 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
6923 MonoMethod *method, *inflated;
6924 MonoReflectionMethodBuilder *mb = NULL;
6925 MonoReflectionMethod *declaring;
6926 MonoGenericInst *ginst;
6929 MONO_ARCH_SAVE_REGS;
6930 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
6931 MonoReflectionTypeBuilder *tb;
6934 mb = (MonoReflectionMethodBuilder *) rmethod;
6935 tb = (MonoReflectionTypeBuilder *) mb->type;
6936 klass = mono_class_from_mono_type (tb->type.type);
6938 method = methodbuilder_to_mono_method (klass, mb);
6939 declaring = rmethod;
6940 } else if (!strcmp (rmethod->object.vtable->klass->name, "MonoInflatedMethod") ||
6941 !strcmp (rmethod->object.vtable->klass->name, "MonoInflatedCtor")) {
6942 method = ((MonoReflectionInflatedMethod *) rmethod)->rmethod.method;
6943 declaring = ((MonoReflectionInflatedMethod *) rmethod)->declaring;
6945 method = rmethod->method;
6946 declaring = rmethod;
6949 count = method->signature->generic_param_count;
6950 if (count != mono_array_length (types))
6953 ginst = g_new0 (MonoGenericInst, 1);
6954 ginst->generic_method = method;
6955 ginst->mtype_argc = count;
6956 ginst->mtype_argv = g_new0 (MonoType *, count);
6957 for (i = 0; i < count; i++) {
6958 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
6959 ginst->mtype_argv [i] = garg->type;
6962 if (method->klass->generic_inst) {
6963 MonoGenericInst *kginst = method->klass->generic_inst->data.generic_inst;
6965 ginst->type_argc = kginst->type_argc;
6966 ginst->type_argv = kginst->type_argv;
6969 inflated = mono_class_inflate_generic_method (method, ginst);
6971 return inflated_method_get_object (
6972 mono_object_domain (rmethod), inflated, declaring, ginst);
6975 MonoReflectionInflatedMethod*
6976 mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type,
6977 MonoReflectionGenericInst *reflected_type,
6980 MonoGenericInst *ginst, *type_ginst;
6981 MonoMethod *method = NULL, *inflated;
6982 MonoReflectionInflatedMethod *res;
6983 MonoReflectionMethod *declaring;
6986 MONO_ARCH_SAVE_REGS;
6988 klass = mono_class_from_mono_type (reflected_type->type.type);
6989 type_ginst = reflected_type->type.type->data.generic_inst;
6991 if (!strcmp (obj->vtable->klass->name, "MethodBuilder")) {
6992 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
6993 declaring = (MonoReflectionMethod *) obj;
6994 } else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
6995 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
6996 declaring = (MonoReflectionMethod *) obj;
6997 } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
6998 !strcmp (obj->vtable->klass->name, "MonoCMethod")) {
6999 method = ((MonoReflectionMethod *) obj)->method;
7000 declaring = (MonoReflectionMethod *) obj;
7001 } else if (!strcmp (obj->vtable->klass->name, "MonoInflatedMethod") ||
7002 !strcmp (obj->vtable->klass->name, "MonoInflatedCtor")) {
7003 method = ((MonoReflectionInflatedMethod *) obj)->rmethod.method;
7004 declaring = ((MonoReflectionInflatedMethod *) obj)->declaring;
7006 g_assert_not_reached ();
7008 ginst = g_new0 (MonoGenericInst, 1);
7009 ginst->generic_method = method;
7010 ginst->generic_type = reflected_type->type.type;
7011 ginst->type_argc = type_ginst->type_argc;
7012 ginst->type_argv = type_ginst->type_argv;
7013 ginst->is_open = type_ginst->is_open;
7015 ginst->klass = mono_class_from_generic (ginst->generic_type, FALSE);
7017 inflated = mono_class_inflate_generic_method (method, ginst);
7019 res = inflated_method_get_object (
7020 mono_object_domain (reflected_type), inflated, declaring, ginst);
7022 res->declaring_type = declaring_type;
7023 res->reflected_type = reflected_type;
7028 MonoReflectionInflatedField*
7029 mono_reflection_inflate_field (MonoReflectionGenericInst *declaring_type,
7030 MonoReflectionGenericInst *reflected_type,
7033 static MonoClass *System_Reflection_MonoInflatedField;
7034 MonoGenericInst *ginst, *type_ginst;
7035 MonoClassField *field = NULL, *inflated;
7036 MonoReflectionInflatedField *res;
7040 MONO_ARCH_SAVE_REGS;
7042 if (!System_Reflection_MonoInflatedField) {
7043 System_Reflection_MonoInflatedField = mono_class_from_name (
7044 mono_defaults.corlib, "System.Reflection", "MonoInflatedField");
7045 g_assert (System_Reflection_MonoInflatedField);
7048 klass = mono_class_from_mono_type (reflected_type->type.type);
7049 type_ginst = reflected_type->type.type->data.generic_inst;
7051 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
7052 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7053 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7054 field = ((MonoReflectionField *) obj)->field;
7056 g_assert_not_reached ();
7058 ginst = g_new0 (MonoGenericInst, 1);
7059 ginst->generic_type = reflected_type->type.type;
7060 ginst->type_argc = type_ginst->type_argc;
7061 ginst->type_argv = type_ginst->type_argv;
7063 inflated = g_new0 (MonoClassField, 1);
7065 inflated->type = mono_class_inflate_generic_type (field->type, ginst);
7067 domain = mono_object_domain (obj);
7069 res = (MonoReflectionInflatedField *)mono_object_new (domain, System_Reflection_MonoInflatedField);
7070 res->declaring = field;
7071 res->declaring_type = declaring_type;
7072 res->reflected_type = reflected_type;
7073 res->rfield.klass = klass;
7074 res->rfield.field = inflated;
7075 res->rfield.name = mono_string_new (domain, inflated->name);
7076 res->rfield.attrs = inflated->type->attrs;
7077 res->rfield.type = mono_type_get_object (domain, inflated->type);
7078 CACHE_OBJECT (inflated, res, field->parent);
7083 ensure_runtime_vtable (MonoClass *klass)
7085 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7086 int i, num, j, onum;
7087 MonoMethod **overrides;
7089 if (!tb || klass->wastypebuilder)
7092 ensure_runtime_vtable (klass->parent);
7094 num = tb->ctors? mono_array_length (tb->ctors): 0;
7095 num += tb->num_methods;
7096 klass->method.count = num;
7097 klass->methods = g_new (MonoMethod*, num);
7098 num = tb->ctors? mono_array_length (tb->ctors): 0;
7099 for (i = 0; i < num; ++i)
7100 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7101 num = tb->num_methods;
7103 for (i = 0; i < num; ++i)
7104 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7106 klass->wastypebuilder = TRUE;
7107 if (tb->interfaces) {
7108 klass->interface_count = mono_array_length (tb->interfaces);
7109 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7110 for (i = 0; i < klass->interface_count; ++i) {
7111 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7112 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7116 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7117 for (i = 0; i < klass->method.count; ++i)
7118 klass->methods [i]->slot = i;
7123 for (i = 0; i < tb->num_methods; ++i) {
7124 MonoReflectionMethodBuilder *mb =
7125 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7126 if (mb->override_method)
7131 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7135 for (i = 0; i < tb->num_methods; ++i) {
7136 MonoReflectionMethodBuilder *mb =
7137 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7138 if (mb->override_method) {
7139 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7140 overrides [onum * 2] =
7141 mb->override_method->method;
7142 overrides [onum * 2 + 1] =
7145 g_assert (mb->mhandle);
7152 mono_class_setup_vtable (klass, overrides, onum);
7156 typebuilder_setup_fields (MonoClass *klass)
7158 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7159 MonoReflectionFieldBuilder *fb;
7160 MonoClassField *field;
7165 klass->field.count = tb->num_fields;
7166 klass->field.first = 0;
7167 klass->field.last = klass->field.count;
7169 if (!klass->field.count)
7172 klass->fields = g_new0 (MonoClassField, klass->field.count);
7174 for (i = 0; i < klass->field.count; ++i) {
7175 fb = mono_array_get (tb->fields, gpointer, i);
7176 field = &klass->fields [i];
7177 field->name = mono_string_to_utf8 (fb->name);
7179 /* FIXME: handle type modifiers */
7180 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7181 field->type->attrs = fb->attrs;
7183 field->type = fb->type->type;
7185 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7186 field->data = mono_array_addr (fb->rva_data, char, 0);
7187 if (fb->offset != -1)
7188 field->offset = fb->offset;
7189 field->parent = klass;
7191 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7193 if (fb->def_value) {
7194 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7195 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7196 field->def_value = g_new0 (MonoConstant, 1);
7197 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7198 /* Copy the data from the blob since it might get realloc-ed */
7199 p = assembly->blob.data + idx;
7200 len = mono_metadata_decode_blob_size (p, &p2);
7202 field->def_value->value = g_malloc (len);
7203 memcpy (field->def_value->value, p, len);
7206 mono_class_layout_fields (klass);
7210 typebuilder_setup_properties (MonoClass *klass)
7212 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7213 MonoReflectionPropertyBuilder *pb;
7216 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7217 klass->property.first = 0;
7218 klass->property.last = klass->property.count;
7220 klass->properties = g_new0 (MonoProperty, klass->property.count);
7221 for (i = 0; i < klass->property.count; ++i) {
7222 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7223 klass->properties [i].attrs = pb->attrs;
7224 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7226 klass->properties [i].get = pb->get_method->mhandle;
7228 klass->properties [i].set = pb->set_method->mhandle;
7233 typebuilder_setup_events (MonoClass *klass)
7235 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7236 MonoReflectionEventBuilder *eb;
7239 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7240 klass->event.first = 0;
7241 klass->event.last = klass->event.count;
7243 klass->events = g_new0 (MonoEvent, klass->event.count);
7244 for (i = 0; i < klass->event.count; ++i) {
7245 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7246 klass->events [i].attrs = eb->attrs;
7247 klass->events [i].name = mono_string_to_utf8 (eb->name);
7249 klass->events [i].add = eb->add_method->mhandle;
7250 if (eb->remove_method)
7251 klass->events [i].remove = eb->remove_method->mhandle;
7252 if (eb->raise_method)
7253 klass->events [i].raise = eb->raise_method->mhandle;
7255 if (eb->other_methods) {
7256 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7257 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7258 MonoReflectionMethodBuilder *mb =
7259 mono_array_get (eb->other_methods,
7260 MonoReflectionMethodBuilder*, j);
7261 klass->events [i].other [j] = mb->mhandle;
7268 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7271 MonoReflectionType* res;
7273 MONO_ARCH_SAVE_REGS;
7275 klass = my_mono_class_from_mono_type (tb->type.type);
7277 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7280 * Fields to set in klass:
7281 * the various flags: delegate/unicode/contextbound etc.
7284 klass->flags = tb->attrs;
7286 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7287 /* No need to fully construct the type */
7288 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7290 /* enums are done right away */
7291 if (!klass->enumtype)
7292 ensure_runtime_vtable (klass);
7294 /* fields and object layout */
7295 if (klass->parent) {
7296 if (!klass->parent->size_inited)
7297 mono_class_init (klass->parent);
7298 klass->instance_size += klass->parent->instance_size;
7299 klass->class_size += klass->parent->class_size;
7300 klass->min_align = klass->parent->min_align;
7302 klass->instance_size = sizeof (MonoObject);
7303 klass->min_align = 1;
7306 /* FIXME: handle packing_size and instance_size */
7307 typebuilder_setup_fields (klass);
7309 typebuilder_setup_properties (klass);
7311 typebuilder_setup_events (klass);
7313 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7314 /* with enums res == tb: need to fix that. */
7315 if (!klass->enumtype)
7316 g_assert (res != (MonoReflectionType*)tb);
7320 MonoReflectionGenericParam *
7321 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7323 static MonoClass *System_Reflection_MonoGenericParam;
7325 MonoGenericParam *param;
7326 MonoReflectionGenericParam *res;
7329 if (!System_Reflection_MonoGenericParam) {
7330 System_Reflection_MonoGenericParam = mono_class_from_name (
7331 mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7332 g_assert (System_Reflection_MonoGenericParam);
7335 param = g_new0 (MonoGenericParam, 1);
7338 tb = (MonoReflectionTypeBuilder *) mb->type;
7340 domain = mono_object_domain (tb);
7341 image = (MonoImage*)tb->module->dynamic_image;
7343 param->method = NULL;
7344 param->name = mono_string_to_utf8 (name);
7347 res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7348 res->type.type = g_new0 (MonoType, 1);
7349 res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7350 res->type.type->data.generic_param = param;
7352 res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7360 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7362 MonoGenericParam *param;
7363 MonoReflectionMethodBuilder *mb = NULL;
7364 MonoReflectionTypeBuilder *tb;
7368 param = gparam->type.type->data.generic_param;
7369 count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7370 param->constraints = g_new0 (MonoClass *, count + 1);
7371 for (i = 0; i < count; i++) {
7372 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7374 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7377 if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7378 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7379 tb = (MonoReflectionTypeBuilder *) mb->type;
7381 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7383 image = (MonoImage*)tb->module->dynamic_image;
7385 param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7387 gparam->initialized = TRUE;
7391 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7393 MonoDynamicImage *assembly = sig->module->dynamic_image;
7394 guint32 na = mono_array_length (sig->arguments);
7399 MONO_ARCH_SAVE_REGS;
7401 p = buf = g_malloc (10 + na * 10);
7403 mono_metadata_encode_value (0x07, p, &p);
7404 mono_metadata_encode_value (na, p, &p);
7405 for (i = 0; i < na; ++i) {
7406 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7407 encode_reflection_type (assembly, type, p, &p);
7411 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7412 p = mono_array_addr (result, char, 0);
7413 memcpy (p, buf, buflen);
7420 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7422 MonoDynamicImage *assembly = sig->module->dynamic_image;
7423 guint32 na = mono_array_length (sig->arguments);
7428 MONO_ARCH_SAVE_REGS;
7430 p = buf = g_malloc (10 + na * 10);
7432 mono_metadata_encode_value (0x06, p, &p);
7433 for (i = 0; i < na; ++i) {
7434 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7435 encode_reflection_type (assembly, type, p, &p);
7439 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7440 p = mono_array_addr (result, char, 0);
7441 memcpy (p, buf, buflen);
7448 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7450 ReflectionMethodBuilder rmb;
7451 MonoMethodSignature *sig;
7454 sig = dynamic_method_to_signature (mb);
7456 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7459 * Resolve references.
7461 rmb.nrefs = mb->nrefs;
7462 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7463 for (i = 0; i < mb->nrefs; ++i) {
7464 gpointer ref = resolve_object (mb->module->image,
7465 mono_array_get (mb->refs, MonoObject*, i));
7468 mono_raise_exception (mono_get_exception_type_load (NULL));
7475 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7479 /* ilgen is no longer needed */
7484 * mono_reflection_lookup_dynamic_token:
7486 * Finish the Builder object pointed to by TOKEN and return the corresponding
7487 * runtime structure.
7490 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7492 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7495 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7498 return resolve_object (image, obj);
7502 resolve_object (MonoImage *image, MonoObject *obj)
7504 gpointer result = NULL;
7506 if (strcmp (obj->vtable->klass->name, "String") == 0) {
7507 result = mono_string_intern ((MonoString*)obj);
7510 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7511 MonoReflectionType *tb = (MonoReflectionType*)obj;
7512 result = mono_class_from_mono_type (tb->type);
7515 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7516 result = ((MonoReflectionMethod*)obj)->method;
7519 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7520 result = ((MonoReflectionMethod*)obj)->method;
7523 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7524 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7525 result = mb->mhandle;
7527 /* Type is not yet created */
7528 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7530 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7533 * Hopefully this has been filled in by calling CreateType() on the
7537 * TODO: This won't work if the application finishes another
7538 * TypeBuilder instance instead of this one.
7540 result = mb->mhandle;
7543 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7544 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7546 result = cb->mhandle;
7548 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7550 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7551 result = cb->mhandle;
7554 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7555 result = ((MonoReflectionField*)obj)->field;
7558 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7559 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7560 result = fb->handle;
7563 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7565 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7566 result = fb->handle;
7569 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7570 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7573 klass = tb->type.type->data.klass;
7574 if (klass->wastypebuilder) {
7575 /* Already created */
7579 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7580 result = tb->type.type->data.klass;
7584 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7585 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7586 MonoMethodSignature *sig;
7589 if (helper->arguments)
7590 nargs = mono_array_length (helper->arguments);
7594 sig = mono_metadata_signature_alloc (image, nargs);
7595 sig->explicit_this = helper->call_conv & 64;
7596 sig->hasthis = helper->call_conv & 32;
7598 if (helper->call_conv == 0) /* unmanaged */
7599 sig->call_convention = helper->unmanaged_call_conv - 1;
7601 if (helper->call_conv & 0x02)
7602 sig->call_convention = MONO_CALL_VARARG;
7604 sig->call_convention = MONO_CALL_DEFAULT;
7606 sig->param_count = nargs;
7607 /* TODO: Copy type ? */
7608 sig->ret = helper->return_type->type;
7609 for (i = 0; i < nargs; ++i) {
7610 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7611 sig->params [i] = rt->type;
7617 g_print (obj->vtable->klass->name);
7618 g_assert_not_reached ();