2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
33 #include <mono/os/gc_wrapper.h>
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA 0x00002000
42 MonoReflectionILGen *ilgen;
43 MonoReflectionType *rtype;
44 MonoArray *parameters;
45 MonoArray *generic_params;
51 guint32 *table_idx; /* note: it's a pointer */
55 MonoBoolean init_locals;
56 MonoArray *return_modreq;
57 MonoArray *return_modopt;
58 MonoArray *param_modreq;
59 MonoArray *param_modopt;
60 MonoArray *permissions;
64 } ReflectionMethodBuilder;
66 const unsigned char table_sizes [64] = {
76 MONO_INTERFACEIMPL_SIZE,
77 MONO_MEMBERREF_SIZE, /* 0x0A */
79 MONO_CUSTOM_ATTR_SIZE,
80 MONO_FIELD_MARSHAL_SIZE,
81 MONO_DECL_SECURITY_SIZE,
82 MONO_CLASS_LAYOUT_SIZE,
83 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
84 MONO_STAND_ALONE_SIGNATURE_SIZE,
88 MONO_PROPERTY_MAP_SIZE,
91 MONO_METHOD_SEMA_SIZE,
93 MONO_MODULEREF_SIZE, /* 0x1A */
99 MONO_ASSEMBLY_SIZE, /* 0x20 */
100 MONO_ASSEMBLY_PROCESSOR_SIZE,
101 MONO_ASSEMBLYOS_SIZE,
102 MONO_ASSEMBLYREF_SIZE,
103 MONO_ASSEMBLYREFPROC_SIZE,
104 MONO_ASSEMBLYREFOS_SIZE,
108 MONO_NESTED_CLASS_SIZE,
110 MONO_GENERICPARAM_SIZE, /* 0x2A */
111 MONO_METHODSPEC_SIZE,
112 MONO_GENPARCONSTRAINT_SIZE,
118 * These macros can be used to allocate long living atomic data so it won't be
119 * tracked by the garbage collector. We use libgc because it's apparently faster
123 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
124 #define FREE_ATOMIC(ptr)
125 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
127 #define ALLOC_ATOMIC(size) g_malloc (size)
128 #define FREE_ATOMIC(ptr) g_free (ptr)
129 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
132 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
133 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
134 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
135 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
136 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
137 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
138 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
139 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
140 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
141 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
142 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
143 static void ensure_runtime_vtable (MonoClass *klass);
144 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
145 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
146 static guint32 type_get_signature_size (MonoType *type);
150 alloc_table (MonoDynamicTable *table, guint nrows)
153 g_assert (table->columns);
154 if (nrows + 1 >= table->alloc_rows) {
155 while (nrows + 1 >= table->alloc_rows)
156 if (table->alloc_rows == 0)
157 table->alloc_rows = 16;
159 table->alloc_rows *= 2;
162 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
164 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
169 make_room_in_stream (MonoDynamicStream *stream, int size)
171 while (stream->alloc_size <= size) {
172 if (stream->alloc_size < 4096)
173 stream->alloc_size = 4096;
175 stream->alloc_size *= 2;
178 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
180 stream->data = ALLOC_ATOMIC (stream->alloc_size);
184 string_heap_insert (MonoDynamicStream *sh, const char *str)
188 gpointer oldkey, oldval;
190 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
191 return GPOINTER_TO_UINT (oldval);
193 len = strlen (str) + 1;
195 if (idx + len > sh->alloc_size)
196 make_room_in_stream (sh, idx + len);
199 * We strdup the string even if we already copy them in sh->data
200 * so that the string pointers in the hash remain valid even if
201 * we need to realloc sh->data. We may want to avoid that later.
203 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
204 memcpy (sh->data + idx, str, len);
210 string_heap_init (MonoDynamicStream *sh)
213 sh->alloc_size = 4096;
214 sh->data = ALLOC_ATOMIC (4096);
215 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
216 string_heap_insert (sh, "");
219 #if 0 /* never used */
221 string_heap_free (MonoDynamicStream *sh)
223 FREE_ATOMIC (sh->data);
224 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
225 g_hash_table_destroy (sh->hash);
230 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
233 if (stream->alloc_size < stream->index + len)
234 make_room_in_stream (stream, stream->index + len);
235 memcpy (stream->data + stream->index, data, len);
237 stream->index += len;
239 * align index? Not without adding an additional param that controls it since
240 * we may store a blob value in pieces.
246 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
249 if (stream->alloc_size < stream->index + len)
250 make_room_in_stream (stream, stream->index + len);
251 memset (stream->data + stream->index, 0, len);
253 stream->index += len;
258 stream_data_align (MonoDynamicStream *stream)
261 guint32 count = stream->index % 4;
263 /* we assume the stream data will be aligned */
265 mono_image_add_stream_data (stream, buf, 4 - count);
269 mono_blob_entry_hash (const char* str)
273 len = mono_metadata_decode_blob_size (str, &str);
277 for (str += 1; str < end; str++)
278 h = (h << 5) - h + *str;
286 mono_blob_entry_equal (const char *str1, const char *str2) {
290 len = mono_metadata_decode_blob_size (str1, &end1);
291 len2 = mono_metadata_decode_blob_size (str2, &end2);
294 return memcmp (end1, end2, len) == 0;
298 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
302 gpointer oldkey, oldval;
304 copy = ALLOC_ATOMIC (s1+s2);
305 memcpy (copy, b1, s1);
306 memcpy (copy + s1, b2, s2);
307 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
309 idx = GPOINTER_TO_UINT (oldval);
311 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
312 mono_image_add_stream_data (&assembly->blob, b2, s2);
313 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
319 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
320 * dest may be misaligned.
323 swap_with_size (char *dest, const char* val, int len, int nelem) {
324 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
327 for (elem = 0; elem < nelem; ++elem) {
353 g_assert_not_reached ();
359 memcpy (dest, val, len * nelem);
364 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
368 guint32 idx = 0, len;
370 len = str->length * 2;
371 mono_metadata_encode_value (len, b, &b);
372 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
374 char *swapped = g_malloc (2 * mono_string_length (str));
375 const char *p = (const char*)mono_string_chars (str);
377 swap_with_size (swapped, p, 2, mono_string_length (str));
378 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
382 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
387 /* modified version needed to handle building corlib */
389 my_mono_class_from_mono_type (MonoType *type) {
390 switch (type->type) {
391 case MONO_TYPE_ARRAY:
393 case MONO_TYPE_SZARRAY:
394 case MONO_TYPE_GENERICINST:
395 return mono_class_from_mono_type (type);
398 g_assert (type->data.generic_param->pklass);
399 return type->data.generic_param->pklass;
401 /* should be always valid when we reach this case... */
402 return type->data.klass;
407 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
412 g_assert_not_reached ();
416 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
417 encode_type (assembly, ginst->generic_type, p, &p);
418 mono_metadata_encode_value (ginst->type_argc, p, &p);
419 for (i = 0; i < ginst->type_argc; ++i)
420 encode_type (assembly, ginst->type_argv [i], p, &p);
426 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
429 g_assert_not_reached ();
434 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
438 case MONO_TYPE_BOOLEAN:
452 case MONO_TYPE_STRING:
453 case MONO_TYPE_OBJECT:
454 case MONO_TYPE_TYPEDBYREF:
455 mono_metadata_encode_value (type->type, p, &p);
458 mono_metadata_encode_value (type->type, p, &p);
459 encode_type (assembly, type->data.type, p, &p);
461 case MONO_TYPE_SZARRAY:
462 mono_metadata_encode_value (type->type, p, &p);
463 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
466 case MONO_TYPE_VALUETYPE:
467 case MONO_TYPE_CLASS: {
468 MonoClass *k = mono_class_from_mono_type (type);
469 mono_metadata_encode_value (type->type, p, &p);
471 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
472 * otherwise two typerefs could point to the same type, leading to
473 * verification errors.
475 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
479 case MONO_TYPE_ARRAY:
480 mono_metadata_encode_value (type->type, p, &p);
481 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
482 mono_metadata_encode_value (type->data.array->rank, p, &p);
483 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
484 mono_metadata_encode_value (0, p, &p);
486 case MONO_TYPE_GENERICINST:
487 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
491 mono_metadata_encode_value (type->type, p, &p);
492 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
496 g_error ("need to encode type %x", type->type);
502 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
505 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
509 encode_type (assembly, type->type, p, endbuf);
513 g_assert_not_reached ();
518 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
523 for (i = 0; i < mono_array_length (modreq); ++i) {
524 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
525 *p = MONO_TYPE_CMOD_REQD;
527 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
531 for (i = 0; i < mono_array_length (modopt); ++i) {
532 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
533 *p = MONO_TYPE_CMOD_OPT;
535 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
542 generic_inst_get_signature_size (MonoGenericInst *ginst)
548 g_assert_not_reached ();
551 size += 1 + type_get_signature_size (ginst->generic_type);
553 for (i = 0; i < ginst->type_argc; ++i)
554 size += type_get_signature_size (ginst->type_argv [i]);
560 type_get_signature_size (MonoType *type)
565 g_assert_not_reached ();
573 case MONO_TYPE_BOOLEAN:
587 case MONO_TYPE_STRING:
588 case MONO_TYPE_OBJECT:
589 case MONO_TYPE_TYPEDBYREF:
592 return size + 1 + type_get_signature_size (type->data.type);
593 case MONO_TYPE_SZARRAY:
594 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
596 case MONO_TYPE_VALUETYPE:
597 case MONO_TYPE_CLASS:
600 case MONO_TYPE_ARRAY:
601 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
602 case MONO_TYPE_GENERICINST:
603 return size + generic_inst_get_signature_size (type->data.generic_inst);
609 g_error ("need to encode type %x", type->type);
615 method_get_signature_size (MonoMethodSignature *sig)
620 size = type_get_signature_size (sig->ret);
621 for (i = 0; i < sig->param_count; i++)
622 size += type_get_signature_size (sig->params [i]);
624 if (sig->generic_param_count)
626 if (sig->sentinelpos >= 0)
633 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
638 guint32 nparams = sig->param_count;
639 guint32 size = 11 + method_get_signature_size (sig);
647 p = buf = g_malloc (size);
649 * FIXME: vararg, explicit_this, differenc call_conv values...
651 *p = sig->call_convention;
653 *p |= 0x20; /* hasthis */
654 if (sig->generic_param_count)
655 *p |= 0x10; /* generic */
657 if (sig->generic_param_count)
658 mono_metadata_encode_value (sig->generic_param_count, p, &p);
659 mono_metadata_encode_value (nparams, p, &p);
660 encode_type (assembly, sig->ret, p, &p);
661 for (i = 0; i < nparams; ++i) {
662 if (i == sig->sentinelpos)
663 *p++ = MONO_TYPE_SENTINEL;
664 encode_type (assembly, sig->params [i], p, &p);
667 g_assert (p - buf < size);
668 mono_metadata_encode_value (p-buf, b, &b);
669 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
675 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
678 * FIXME: reuse code from method_encode_signature().
683 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
684 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
685 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
686 guint32 size = 21 + nparams * 20 + notypes * 20;
691 p = buf = g_malloc (size);
692 /* LAMESPEC: all the call conv spec is foobared */
693 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
694 if (mb->call_conv & 2)
695 *p |= 0x5; /* vararg */
696 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
697 *p |= 0x20; /* hasthis */
699 *p |= 0x10; /* generic */
702 mono_metadata_encode_value (ngparams, p, &p);
703 mono_metadata_encode_value (nparams + notypes, p, &p);
704 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
705 encode_reflection_type (assembly, mb->rtype, p, &p);
706 for (i = 0; i < nparams; ++i) {
707 MonoArray *modreq = NULL;
708 MonoArray *modopt = NULL;
709 MonoReflectionType *pt;
711 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
712 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
713 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
714 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
715 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
716 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
717 encode_reflection_type (assembly, pt, p, &p);
720 *p++ = MONO_TYPE_SENTINEL;
721 for (i = 0; i < notypes; ++i) {
722 MonoReflectionType *pt;
724 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
725 encode_reflection_type (assembly, pt, p, &p);
729 g_assert (p - buf < size);
730 mono_metadata_encode_value (p-buf, b, &b);
731 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
737 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
739 MonoDynamicTable *table;
742 guint32 idx, sig_idx, size;
743 guint nl = mono_array_length (ilgen->locals);
750 p = buf = g_malloc (size);
751 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
752 idx = table->next_idx ++;
754 alloc_table (table, table->rows);
755 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
757 mono_metadata_encode_value (0x07, p, &p);
758 mono_metadata_encode_value (nl, p, &p);
759 for (i = 0; i < nl; ++i) {
760 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
763 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
765 encode_reflection_type (assembly, lb->type, p, &p);
767 g_assert (p - buf < size);
768 mono_metadata_encode_value (p-buf, b, &b);
769 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
772 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
778 method_count_clauses (MonoReflectionILGen *ilgen)
780 guint32 num_clauses = 0;
783 MonoILExceptionInfo *ex_info;
784 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
785 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
786 if (ex_info->handlers)
787 num_clauses += mono_array_length (ex_info->handlers);
795 static MonoExceptionClause*
796 method_encode_clauses (MonoDynamicImage *assembly,
797 MonoReflectionILGen *ilgen, guint32 num_clauses)
799 MonoExceptionClause *clauses;
800 MonoExceptionClause *clause;
801 MonoILExceptionInfo *ex_info;
802 MonoILExceptionBlock *ex_block;
803 guint32 finally_start;
804 int i, j, clause_index;;
806 clauses = g_new0 (MonoExceptionClause, num_clauses);
809 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
810 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
811 finally_start = ex_info->start + ex_info->len;
812 g_assert (ex_info->handlers);
813 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
814 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
815 clause = &(clauses [clause_index]);
817 clause->flags = ex_block->type;
818 clause->try_offset = ex_info->start;
820 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
821 clause->try_len = finally_start - ex_info->start;
823 clause->try_len = ex_info->len;
824 clause->handler_offset = ex_block->start;
825 clause->handler_len = ex_block->len;
826 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
827 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
828 if (ex_block->extype) {
829 mono_g_hash_table_insert (assembly->tokens,
830 GUINT_TO_POINTER (clause->token_or_filter),
833 finally_start = ex_block->start + ex_block->len;
843 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
849 gint32 num_locals = 0;
850 gint32 num_exception = 0;
853 char fat_header [12];
856 guint32 local_sig = 0;
857 guint32 header_size = 12;
860 if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
861 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
862 (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
863 (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
867 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
869 code = mb->ilgen->code;
870 code_size = mb->ilgen->code_len;
871 max_stack = mb->ilgen->max_stack;
872 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
873 if (mb->ilgen->ex_handlers)
874 num_exception = method_count_clauses (mb->ilgen);
878 char *name = mono_string_to_utf8 (mb->name);
879 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
880 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
883 mono_raise_exception (exception);
886 code_size = mono_array_length (code);
887 max_stack = 8; /* we probably need to run a verifier on the code... */
890 /* check for exceptions, maxstack, locals */
891 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
893 if (code_size < 64 && !(code_size & 1)) {
894 flags = (code_size << 2) | 0x2;
895 } else if (code_size < 32 && (code_size & 1)) {
896 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
900 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
901 /* add to the fixup todo list */
902 if (mb->ilgen && mb->ilgen->num_token_fixups)
903 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
904 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
905 return assembly->text_rva + idx;
909 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
911 * FIXME: need to set also the header size in fat_flags.
912 * (and more sects and init locals flags)
916 fat_flags |= METHOD_HEADER_MORE_SECTS;
918 fat_flags |= METHOD_HEADER_INIT_LOCALS;
919 fat_header [0] = fat_flags;
920 fat_header [1] = (header_size / 4 ) << 4;
921 shortp = (guint16*)(fat_header + 2);
922 *shortp = GUINT16_TO_LE (max_stack);
923 intp = (guint32*)(fat_header + 4);
924 *intp = GUINT32_TO_LE (code_size);
925 intp = (guint32*)(fat_header + 8);
926 *intp = GUINT32_TO_LE (local_sig);
927 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
928 /* add to the fixup todo list */
929 if (mb->ilgen && mb->ilgen->num_token_fixups)
930 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
932 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
934 unsigned char sheader [4];
935 MonoExceptionClause clause;
936 MonoILExceptionInfo * ex_info;
937 MonoILExceptionBlock * ex_block;
940 stream_data_align (&assembly->code);
941 /* always use fat format for now */
942 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
943 num_exception *= sizeof (MonoExceptionClause);
944 num_exception += 4; /* include the size of the header */
945 sheader [1] = num_exception & 0xff;
946 sheader [2] = (num_exception >> 8) & 0xff;
947 sheader [3] = (num_exception >> 16) & 0xff;
948 mono_image_add_stream_data (&assembly->code, sheader, 4);
949 /* fat header, so we are already aligned */
951 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
952 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
953 if (ex_info->handlers) {
954 int finally_start = ex_info->start + ex_info->len;
955 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
956 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
957 clause.flags = GUINT32_TO_LE (ex_block->type);
958 clause.try_offset = GUINT32_TO_LE (ex_info->start);
959 /* need fault, too, probably */
960 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
961 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
963 clause.try_len = GUINT32_TO_LE (ex_info->len);
964 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
965 clause.handler_len = GUINT32_TO_LE (ex_block->len);
966 finally_start = ex_block->start + ex_block->len;
967 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
968 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
969 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
970 /*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",
971 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);*/
972 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
975 g_error ("No clauses for ex info block %d", i);
979 return assembly->text_rva + idx;
983 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
986 MonoDynamicTable *table;
989 table = &assembly->tables [table_idx];
991 g_assert (col < table->columns);
993 values = table->values + table->columns;
994 for (i = 1; i <= table->rows; ++i) {
995 if (values [col] == token)
997 values += table->columns;
1002 static GHashTable *dynamic_custom_attrs = NULL;
1004 static MonoCustomAttrInfo*
1005 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1008 MonoCustomAttrInfo *ainfo;
1009 MonoReflectionCustomAttr *cattr;
1013 /* FIXME: check in assembly the Run flag is set */
1015 count = mono_array_length (cattrs);
1017 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1019 ainfo->image = image;
1020 ainfo->num_attrs = count;
1021 for (i = 0; i < count; ++i) {
1022 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1023 ainfo->attrs [i].ctor = cattr->ctor->method;
1024 /* FIXME: might want to memdup the data here */
1025 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1026 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1033 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1035 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1040 if (!dynamic_custom_attrs)
1041 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1043 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1044 ainfo->cached = TRUE;
1048 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1050 /* they are cached, so we don't free them */
1051 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1057 * idx is the table index of the object
1058 * type is one of MONO_CUSTOM_ATTR_*
1061 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1063 MonoDynamicTable *table;
1064 MonoReflectionCustomAttr *cattr;
1066 guint32 count, i, token;
1068 char *p = blob_size;
1070 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1073 count = mono_array_length (cattrs);
1074 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1075 table->rows += count;
1076 alloc_table (table, table->rows);
1077 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1078 idx <<= MONO_CUSTOM_ATTR_BITS;
1080 for (i = 0; i < count; ++i) {
1081 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1082 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1083 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1084 type = mono_metadata_token_index (token);
1085 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1086 switch (mono_metadata_token_table (token)) {
1087 case MONO_TABLE_METHOD:
1088 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1090 case MONO_TABLE_MEMBERREF:
1091 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1094 g_warning ("got wrong token in custom attr");
1097 values [MONO_CUSTOM_ATTR_TYPE] = type;
1099 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1100 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1101 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1102 values += MONO_CUSTOM_ATTR_SIZE;
1108 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1109 MonoArray *permissions)
1111 MonoDynamicTable *table;
1113 guint32 count, i, idx;
1114 MonoReflectionPermissionSet *perm;
1119 count = mono_array_length (permissions);
1120 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1121 table->rows += count;
1122 alloc_table (table, table->rows);
1124 for (i = 0; i < mono_array_length (permissions); ++i) {
1125 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1127 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1129 idx = mono_metadata_token_index (parent_token);
1130 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1131 switch (mono_metadata_token_table (parent_token)) {
1132 case MONO_TABLE_TYPEDEF:
1133 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1135 case MONO_TABLE_METHOD:
1136 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1138 case MONO_TABLE_ASSEMBLY:
1139 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1142 g_assert_not_reached ();
1145 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1146 values [MONO_DECL_SECURITY_PARENT] = idx;
1147 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1154 * Fill in the MethodDef and ParamDef tables for a method.
1155 * This is used for both normal methods and constructors.
1158 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1160 MonoDynamicTable *table;
1165 /* room in this table is already allocated */
1166 table = &assembly->tables [MONO_TABLE_METHOD];
1167 *mb->table_idx = table->next_idx ++;
1168 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1169 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1170 name = mono_string_to_utf8 (mb->name);
1171 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1173 values [MONO_METHOD_FLAGS] = mb->attrs;
1174 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1175 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1176 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1178 table = &assembly->tables [MONO_TABLE_PARAM];
1179 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1181 mono_image_add_decl_security (assembly,
1182 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1186 MonoDynamicTable *mtable;
1189 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1190 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1193 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1194 if (mono_array_get (mb->pinfo, gpointer, i))
1197 table->rows += count;
1198 alloc_table (table, table->rows);
1199 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1200 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1201 MonoReflectionParamBuilder *pb;
1202 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1203 values [MONO_PARAM_FLAGS] = pb->attrs;
1204 values [MONO_PARAM_SEQUENCE] = i;
1205 if (pb->name != NULL) {
1206 name = mono_string_to_utf8 (pb->name);
1207 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1210 values [MONO_PARAM_NAME] = 0;
1212 values += MONO_PARAM_SIZE;
1213 if (pb->marshal_info) {
1215 alloc_table (mtable, mtable->rows);
1216 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1217 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1218 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1220 pb->table_idx = table->next_idx++;
1221 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1222 guint32 field_type = 0;
1223 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1225 alloc_table (mtable, mtable->rows);
1226 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1227 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1228 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1229 mvalues [MONO_CONSTANT_TYPE] = field_type;
1230 mvalues [MONO_CONSTANT_PADDING] = 0;
1238 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1239 MonoReflectionMethodBuilder *mb)
1241 rmb->ilgen = mb->ilgen;
1242 rmb->rtype = mb->rtype;
1243 rmb->parameters = mb->parameters;
1244 rmb->generic_params = mb->generic_params;
1245 rmb->opt_types = NULL;
1246 rmb->pinfo = mb->pinfo;
1247 rmb->attrs = mb->attrs;
1248 rmb->iattrs = mb->iattrs;
1249 rmb->call_conv = mb->call_conv;
1250 rmb->code = mb->code;
1251 rmb->type = mb->type;
1252 rmb->name = mb->name;
1253 rmb->table_idx = &mb->table_idx;
1254 rmb->init_locals = mb->init_locals;
1255 rmb->return_modreq = mb->return_modreq;
1256 rmb->return_modopt = mb->return_modopt;
1257 rmb->param_modreq = mb->param_modreq;
1258 rmb->param_modopt = mb->param_modopt;
1259 rmb->permissions = mb->permissions;
1260 rmb->mhandle = mb->mhandle;
1266 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1267 MonoReflectionCtorBuilder *mb)
1269 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1271 rmb->ilgen = mb->ilgen;
1272 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1273 rmb->parameters = mb->parameters;
1274 rmb->generic_params = NULL;
1275 rmb->opt_types = NULL;
1276 rmb->pinfo = mb->pinfo;
1277 rmb->attrs = mb->attrs;
1278 rmb->iattrs = mb->iattrs;
1279 rmb->call_conv = mb->call_conv;
1281 rmb->type = mb->type;
1282 rmb->name = mono_string_new (mono_domain_get (), name);
1283 rmb->table_idx = &mb->table_idx;
1284 rmb->init_locals = mb->init_locals;
1285 rmb->return_modreq = NULL;
1286 rmb->return_modopt = NULL;
1287 rmb->param_modreq = mb->param_modreq;
1288 rmb->param_modopt = mb->param_modopt;
1289 rmb->permissions = mb->permissions;
1290 rmb->mhandle = mb->mhandle;
1296 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1297 MonoReflectionDynamicMethod *mb)
1299 rmb->ilgen = mb->ilgen;
1300 rmb->rtype = mb->rtype;
1301 rmb->parameters = mb->parameters;
1302 rmb->generic_params = NULL;
1303 rmb->opt_types = NULL;
1305 rmb->attrs = mb->attrs;
1307 rmb->call_conv = mb->call_conv;
1310 rmb->name = mb->name;
1311 rmb->table_idx = NULL;
1312 rmb->init_locals = mb->init_locals;
1313 rmb->return_modreq = NULL;
1314 rmb->return_modopt = NULL;
1315 rmb->param_modreq = NULL;
1316 rmb->param_modopt = NULL;
1317 rmb->permissions = NULL;
1318 rmb->mhandle = mb->mhandle;
1324 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1326 MonoDynamicTable *table;
1329 ReflectionMethodBuilder rmb;
1332 reflection_methodbuilder_from_method_builder (&rmb, mb);
1334 mono_image_basic_method (&rmb, assembly);
1336 if (mb->dll) { /* It's a P/Invoke method */
1338 int charset = mb->charset & 0xf;
1339 int lasterr = mb->charset & 0x40;
1340 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1342 alloc_table (table, table->rows);
1343 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1344 /* map CharSet values to on-disk values */
1346 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1347 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1348 name = mono_string_to_utf8 (mb->dllentry);
1349 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1351 name = mono_string_to_utf8 (mb->dll);
1352 moduleref = string_heap_insert (&assembly->sheap, name);
1354 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1355 table = &assembly->tables [MONO_TABLE_MODULEREF];
1357 alloc_table (table, table->rows);
1358 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1359 values [MONO_IMPLMAP_SCOPE] = table->rows;
1363 if (mb->override_method) {
1364 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1366 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1368 alloc_table (table, table->rows);
1369 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1370 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1371 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1372 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1373 switch (mono_metadata_token_table (tok)) {
1374 case MONO_TABLE_MEMBERREF:
1375 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1377 case MONO_TABLE_METHOD:
1378 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1381 g_assert_not_reached ();
1383 values [MONO_METHODIMPL_DECLARATION] = tok;
1386 if (mb->generic_params) {
1387 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1388 table->rows += mono_array_length (mb->generic_params);
1389 alloc_table (table, table->rows);
1390 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1391 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1393 mono_image_get_generic_param_info (
1394 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1401 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1403 ReflectionMethodBuilder rmb;
1405 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1407 mono_image_basic_method (&rmb, assembly);
1411 type_get_fully_qualified_name (MonoType *type) {
1412 char *name, *result;
1416 name = mono_type_get_name (type);
1417 klass = my_mono_class_from_mono_type (type);
1418 ta = klass->image->assembly;
1420 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1421 name, ta->aname.name,
1422 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1423 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1424 ta->aname.public_key_token [0] ? ta->aname.public_key_token : "null");
1430 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1434 klass = my_mono_class_from_mono_type (type);
1435 ta = klass->image->assembly;
1436 if (ta == ass || klass->image == mono_defaults.corlib)
1437 return mono_type_get_name (type);
1439 return type_get_fully_qualified_name (type);
1443 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1445 char blob_size [64];
1446 char *b = blob_size;
1451 if (!assembly->save)
1454 p = buf = g_malloc (64);
1456 mono_metadata_encode_value (0x06, p, &p);
1457 /* encode custom attributes before the type */
1458 encode_type (assembly, type, p, &p);
1459 g_assert (p-buf < 64);
1460 mono_metadata_encode_value (p-buf, b, &b);
1461 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1467 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1469 char blob_size [64];
1470 char *b = blob_size;
1475 p = buf = g_malloc (64);
1477 mono_metadata_encode_value (0x06, p, &p);
1478 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1479 /* encode custom attributes before the type */
1480 encode_reflection_type (assembly, fb->type, p, &p);
1481 g_assert (p-buf < 64);
1482 mono_metadata_encode_value (p-buf, b, &b);
1483 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1489 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1490 char blob_size [64];
1491 char *b = blob_size;
1494 guint32 idx = 0, len = 0, dummy = 0;
1496 p = buf = g_malloc (64);
1498 *ret_type = MONO_TYPE_CLASS;
1500 box_val = (char*)&dummy;
1502 box_val = ((char*)val) + sizeof (MonoObject);
1503 *ret_type = val->vtable->klass->byval_arg.type;
1506 switch (*ret_type) {
1507 case MONO_TYPE_BOOLEAN:
1512 case MONO_TYPE_CHAR:
1527 case MONO_TYPE_VALUETYPE:
1528 if (val->vtable->klass->enumtype) {
1529 *ret_type = val->vtable->klass->enum_basetype->type;
1532 g_error ("we can't encode valuetypes");
1533 case MONO_TYPE_CLASS:
1535 case MONO_TYPE_STRING: {
1536 MonoString *str = (MonoString*)val;
1537 /* there is no signature */
1538 len = str->length * 2;
1539 mono_metadata_encode_value (len, b, &b);
1540 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1542 char *swapped = g_malloc (2 * mono_string_length (str));
1543 const char *p = (const char*)mono_string_chars (str);
1545 swap_with_size (swapped, p, 2, mono_string_length (str));
1546 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1550 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1557 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1560 /* there is no signature */
1561 mono_metadata_encode_value (len, b, &b);
1562 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1563 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1564 swap_with_size (blob_size, box_val, len, 1);
1565 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1567 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1575 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1576 char blob_size [64];
1577 char *b = blob_size;
1578 char *p, *buf, *str;
1579 guint32 idx, len, bufsize = 256;
1581 p = buf = g_malloc (bufsize);
1583 switch (minfo->type) {
1584 case MONO_NATIVE_BYVALTSTR:
1585 case MONO_NATIVE_BYVALARRAY:
1586 mono_metadata_encode_value (minfo->type, p, &p);
1587 mono_metadata_encode_value (minfo->count, p, &p);
1589 case MONO_NATIVE_LPARRAY:
1590 mono_metadata_encode_value (minfo->type, p, &p);
1591 if (minfo->eltype || (minfo->count > 0)) {
1592 mono_metadata_encode_value (minfo->eltype, p, &p);
1593 if (minfo->count > 0) {
1594 mono_metadata_encode_value (0, p, &p);
1595 mono_metadata_encode_value (minfo->count, p, &p);
1599 case MONO_NATIVE_CUSTOM:
1600 mono_metadata_encode_value (minfo->type, p, &p);
1602 str = mono_string_to_utf8 (minfo->guid);
1604 mono_metadata_encode_value (len, p, &p);
1605 memcpy (p, str, len);
1609 mono_metadata_encode_value (0, p, &p);
1611 if (minfo->marshaltype) {
1612 str = mono_string_to_utf8 (minfo->marshaltype);
1614 mono_metadata_encode_value (len, p, &p);
1615 if (p + len >= buf + bufsize) {
1618 buf = g_realloc (buf, bufsize);
1621 memcpy (p, str, len);
1625 mono_metadata_encode_value (0, p, &p);
1627 if (minfo->marshaltyperef) {
1628 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1630 mono_metadata_encode_value (len, p, &p);
1631 if (p + len >= buf + bufsize) {
1634 buf = g_realloc (buf, bufsize);
1637 memcpy (p, str, len);
1641 mono_metadata_encode_value (0, p, &p);
1643 if (minfo->mcookie) {
1644 str = mono_string_to_utf8 (minfo->mcookie);
1646 mono_metadata_encode_value (len, p, &p);
1647 if (p + len >= buf + bufsize) {
1650 buf = g_realloc (buf, bufsize);
1653 memcpy (p, str, len);
1657 mono_metadata_encode_value (0, p, &p);
1661 mono_metadata_encode_value (minfo->type, p, &p);
1665 mono_metadata_encode_value (len, b, &b);
1666 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1672 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1674 MonoDynamicTable *table;
1678 /* maybe this fixup should be done in the C# code */
1679 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1680 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1681 table = &assembly->tables [MONO_TABLE_FIELD];
1682 fb->table_idx = table->next_idx ++;
1683 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1684 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1685 name = mono_string_to_utf8 (fb->name);
1686 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1688 values [MONO_FIELD_FLAGS] = fb->attrs;
1689 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1691 if (fb->offset != -1) {
1692 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1694 alloc_table (table, table->rows);
1695 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1696 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1697 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1699 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1700 guint32 field_type = 0;
1701 table = &assembly->tables [MONO_TABLE_CONSTANT];
1703 alloc_table (table, table->rows);
1704 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1705 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1706 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1707 values [MONO_CONSTANT_TYPE] = field_type;
1708 values [MONO_CONSTANT_PADDING] = 0;
1710 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1712 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1714 alloc_table (table, table->rows);
1715 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1716 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1718 * We store it in the code section because it's simpler for now.
1721 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1723 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1724 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1726 if (fb->marshal_info) {
1727 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1729 alloc_table (table, table->rows);
1730 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1731 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1732 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1737 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1741 char *b = blob_size;
1742 guint32 nparams = 0;
1743 MonoReflectionMethodBuilder *mb = fb->get_method;
1744 MonoReflectionMethodBuilder *smb = fb->set_method;
1745 guint32 idx, i, size;
1747 if (mb && mb->parameters)
1748 nparams = mono_array_length (mb->parameters);
1749 if (!mb && smb && smb->parameters)
1750 nparams = mono_array_length (smb->parameters) - 1;
1751 size = 24 + nparams * 10;
1752 buf = p = g_malloc (size);
1755 mono_metadata_encode_value (nparams, p, &p);
1757 encode_reflection_type (assembly, mb->rtype, p, &p);
1758 for (i = 0; i < nparams; ++i) {
1759 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1760 encode_reflection_type (assembly, pt, p, &p);
1763 /* the property type is the last param */
1764 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1765 for (i = 0; i < nparams; ++i) {
1766 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1767 encode_reflection_type (assembly, pt, p, &p);
1771 g_assert (p - buf < size);
1772 mono_metadata_encode_value (p-buf, b, &b);
1773 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1779 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1781 MonoDynamicTable *table;
1784 guint num_methods = 0;
1788 * we need to set things in the following tables:
1789 * PROPERTYMAP (info already filled in _get_type_info ())
1790 * PROPERTY (rows already preallocated in _get_type_info ())
1791 * METHOD (method info already done with the generic method code)
1794 table = &assembly->tables [MONO_TABLE_PROPERTY];
1795 pb->table_idx = table->next_idx ++;
1796 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1797 name = mono_string_to_utf8 (pb->name);
1798 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1800 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1801 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1803 /* FIXME: we still don't handle 'other' methods */
1804 if (pb->get_method) num_methods ++;
1805 if (pb->set_method) num_methods ++;
1807 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1808 table->rows += num_methods;
1809 alloc_table (table, table->rows);
1811 if (pb->get_method) {
1812 semaidx = table->next_idx ++;
1813 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1814 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1815 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1816 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1818 if (pb->set_method) {
1819 semaidx = table->next_idx ++;
1820 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1821 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1822 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1823 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1828 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1830 MonoDynamicTable *table;
1833 guint num_methods = 0;
1837 * we need to set things in the following tables:
1838 * EVENTMAP (info already filled in _get_type_info ())
1839 * EVENT (rows already preallocated in _get_type_info ())
1840 * METHOD (method info already done with the generic method code)
1843 table = &assembly->tables [MONO_TABLE_EVENT];
1844 eb->table_idx = table->next_idx ++;
1845 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1846 name = mono_string_to_utf8 (eb->name);
1847 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1849 values [MONO_EVENT_FLAGS] = eb->attrs;
1850 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1853 * FIXME: we still don't handle 'other' methods
1855 if (eb->add_method) num_methods ++;
1856 if (eb->remove_method) num_methods ++;
1857 if (eb->raise_method) num_methods ++;
1859 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1860 table->rows += num_methods;
1861 alloc_table (table, table->rows);
1863 if (eb->add_method) {
1864 semaidx = table->next_idx ++;
1865 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1866 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1867 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1868 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1870 if (eb->remove_method) {
1871 semaidx = table->next_idx ++;
1872 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1873 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1874 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1875 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1877 if (eb->raise_method) {
1878 semaidx = table->next_idx ++;
1879 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1880 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1881 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1882 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1887 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1889 static MonoClass *NewConstraintAttr;
1890 static MonoMethod *NewConstraintAttr_ctor;
1891 MonoDynamicTable *table;
1893 guint32 token, type;
1894 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1897 if (!NewConstraintAttr)
1898 NewConstraintAttr = mono_class_from_name (
1899 mono_defaults.corlib, "System.Runtime.CompilerServices",
1900 "NewConstraintAttribute");
1901 g_assert (NewConstraintAttr);
1903 if (!NewConstraintAttr_ctor) {
1906 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1907 MonoMethod *m = NewConstraintAttr->methods [i];
1909 if (strcmp (m->name, ".ctor"))
1912 NewConstraintAttr_ctor = m;
1916 g_assert (NewConstraintAttr_ctor);
1919 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1921 alloc_table (table, table->rows);
1923 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1924 owner <<= MONO_CUSTOM_ATTR_BITS;
1925 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1926 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1928 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1930 type = mono_metadata_token_index (token);
1931 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1932 switch (mono_metadata_token_table (token)) {
1933 case MONO_TABLE_METHOD:
1934 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1936 case MONO_TABLE_MEMBERREF:
1937 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1940 g_warning ("got wrong token in custom attr");
1943 values [MONO_CUSTOM_ATTR_TYPE] = type;
1945 buf = p = g_malloc (1);
1946 mono_metadata_encode_value (4, p, &p);
1947 g_assert (p-buf == 1);
1949 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1951 values += MONO_CUSTOM_ATTR_SIZE;
1956 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1958 MonoDynamicTable *table;
1959 guint32 num_constraints, i;
1963 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1964 num_constraints = gparam->iface_constraints ?
1965 mono_array_length (gparam->iface_constraints) : 0;
1966 table->rows += num_constraints;
1967 if (gparam->base_type)
1969 alloc_table (table, table->rows);
1971 if (gparam->base_type) {
1972 table_idx = table->next_idx ++;
1973 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1975 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1976 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1977 assembly, gparam->base_type->type);
1980 for (i = 0; i < num_constraints; i++) {
1981 MonoReflectionType *constraint = mono_array_get (
1982 gparam->iface_constraints, gpointer, i);
1984 table_idx = table->next_idx ++;
1985 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
1987 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
1988 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
1989 assembly, constraint->type);
1992 if (gparam->has_ctor_constraint)
1993 encode_new_constraint (assembly, owner);
1997 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1999 MonoDynamicTable *table;
2000 MonoGenericParam *param;
2004 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2005 table_idx = table->next_idx ++;
2006 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2008 param = gparam->type.type->data.generic_param;
2010 values [MONO_GENERICPARAM_OWNER] = owner;
2011 if (gparam->has_value_type)
2012 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2013 else if (gparam->has_reference_type)
2014 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2016 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2017 values [MONO_GENERICPARAM_NUMBER] = param->num;
2018 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2019 values [MONO_GENERICPARAM_KIND] = 0;
2021 encode_constraints (gparam, table_idx, assembly);
2025 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2027 MonoDynamicTable *table;
2030 guint32 cols [MONO_ASSEMBLY_SIZE];
2034 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2037 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2038 table = &assembly->tables [MONO_TABLE_MODULEREF];
2039 token = table->next_idx ++;
2041 alloc_table (table, table->rows);
2042 values = table->values + token * MONO_MODULEREF_SIZE;
2043 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2045 token <<= MONO_RESOLTION_SCOPE_BITS;
2046 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2047 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2052 if (image->assembly->dynamic)
2054 memset (cols, 0, sizeof (cols));
2056 /* image->assembly->image is the manifest module */
2057 image = image->assembly->image;
2058 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2061 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2062 token = table->next_idx ++;
2064 alloc_table (table, table->rows);
2065 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2066 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2067 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2068 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2069 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2070 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2071 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2072 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2073 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2075 if (strcmp ("", image->assembly->aname.culture)) {
2076 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2077 image->assembly->aname.culture);
2080 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2081 guchar pubtoken [9];
2083 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2084 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2086 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2088 token <<= MONO_RESOLTION_SCOPE_BITS;
2089 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2090 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2095 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2097 MonoDynamicTable *table;
2103 char *b = blob_size;
2105 switch (type->type) {
2106 case MONO_TYPE_FNPTR:
2108 case MONO_TYPE_SZARRAY:
2109 case MONO_TYPE_ARRAY:
2111 case MONO_TYPE_MVAR:
2112 case MONO_TYPE_GENERICINST:
2113 encode_type (assembly, type, p, &p);
2115 case MONO_TYPE_CLASS:
2116 case MONO_TYPE_VALUETYPE: {
2117 MonoClass *k = mono_class_from_mono_type (type);
2118 if (!k || !k->generic_inst)
2120 encode_generic_inst (assembly, k->generic_inst, p, &p);
2127 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2128 if (assembly->save) {
2129 g_assert (p-sig < 128);
2130 mono_metadata_encode_value (p-sig, b, &b);
2131 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2132 alloc_table (table, table->rows + 1);
2133 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2134 values [MONO_TYPESPEC_SIGNATURE] = token;
2137 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2138 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2144 * Despite the name, we handle also TypeSpec (with the above helper).
2147 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2149 MonoDynamicTable *table;
2151 guint32 token, scope, enclosing;
2154 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2157 token = create_typespec (assembly, type);
2160 klass = my_mono_class_from_mono_type (type);
2162 klass = mono_class_from_mono_type (type);
2165 * If it's in the same module and not a generic type parameter:
2167 if ((klass->image == &assembly->image) &&
2168 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2169 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2170 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2171 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2175 if (klass->nested_in) {
2176 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2177 /* get the typeref idx of the enclosing type */
2178 enclosing >>= MONO_TYPEDEFORREF_BITS;
2179 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2181 scope = resolution_scope_from_image (assembly, klass->image);
2183 table = &assembly->tables [MONO_TABLE_TYPEREF];
2184 if (assembly->save) {
2185 alloc_table (table, table->rows + 1);
2186 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2187 values [MONO_TYPEREF_SCOPE] = scope;
2188 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2189 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2191 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2192 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2194 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2199 * Insert a memberef row into the metadata: the token that point to the memberref
2200 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2201 * mono_image_get_fieldref_token()).
2202 * The sig param is an index to an already built signature.
2205 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2207 MonoDynamicTable *table;
2209 guint32 token, pclass;
2212 parent = mono_image_typedef_or_ref (assembly, type);
2213 switch (parent & MONO_TYPEDEFORREF_MASK) {
2214 case MONO_TYPEDEFORREF_TYPEREF:
2215 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2217 case MONO_TYPEDEFORREF_TYPESPEC:
2218 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2220 case MONO_TYPEDEFORREF_TYPEDEF:
2221 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2224 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2227 /* extract the index */
2228 parent >>= MONO_TYPEDEFORREF_BITS;
2230 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2232 if (assembly->save) {
2233 alloc_table (table, table->rows + 1);
2234 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2235 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2236 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2237 values [MONO_MEMBERREF_SIGNATURE] = sig;
2240 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2247 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2251 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2254 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2255 method->name, method_encode_signature (assembly, method->signature));
2256 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2261 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2262 const gchar *name, guint32 sig)
2264 MonoDynamicTable *table;
2265 guint32 parent, token;
2268 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2270 if (assembly->save) {
2271 alloc_table (table, table->rows + 1);
2272 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2273 values [MONO_MEMBERREF_CLASS] = original;
2274 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2275 values [MONO_MEMBERREF_SIGNATURE] = sig;
2278 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2285 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2288 ReflectionMethodBuilder rmb;
2290 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2294 reflection_methodbuilder_from_method_builder (&rmb, mb);
2296 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2297 mono_string_to_utf8 (rmb.name),
2298 method_builder_encode_signature (assembly, &rmb));
2299 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2304 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2307 ReflectionMethodBuilder rmb;
2309 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2313 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2315 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2316 mono_string_to_utf8 (rmb.name),
2317 method_builder_encode_signature (assembly, &rmb));
2318 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2323 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2328 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2331 g_assert (f->field->parent);
2332 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2333 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2334 f->field->name, fieldref_encode_signature (assembly, type));
2335 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2340 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2345 guint32 nparams = gmethod->mtype_argc;
2346 guint32 size = 10 + nparams * 10;
2349 char *b = blob_size;
2351 if (!assembly->save)
2354 p = buf = g_malloc (size);
2356 * FIXME: vararg, explicit_this, differenc call_conv values...
2358 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2359 mono_metadata_encode_value (nparams, p, &p);
2361 for (i = 0; i < nparams; i++)
2362 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2365 g_assert (p - buf < size);
2366 mono_metadata_encode_value (p-buf, b, &b);
2367 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2373 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2375 MonoDynamicTable *table;
2377 guint32 token, mtoken = 0, sig;
2378 MonoMethodInflated *imethod;
2379 MonoMethod *declaring;
2381 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2383 g_assert (method->signature->is_inflated);
2384 imethod = (MonoMethodInflated *) method;
2385 declaring = imethod->declaring;
2387 sig = method_encode_signature (assembly, declaring->signature);
2388 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2389 declaring->name, sig);
2391 if (!declaring->signature->generic_param_count)
2394 switch (mono_metadata_token_table (mtoken)) {
2395 case MONO_TABLE_MEMBERREF:
2396 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2398 case MONO_TABLE_METHOD:
2399 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2402 g_assert_not_reached ();
2405 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2407 if (assembly->save) {
2408 alloc_table (table, table->rows + 1);
2409 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2410 values [MONO_METHODSPEC_METHOD] = mtoken;
2411 values [MONO_METHODSPEC_SIGNATURE] = sig;
2414 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2421 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2423 MonoMethodInflated *imethod;
2426 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2430 g_assert (m->signature->is_inflated);
2431 imethod = (MonoMethodInflated *) m;
2433 if (imethod->declaring->signature->generic_param_count)
2434 token = method_encode_methodspec (assembly, m);
2436 guint32 sig = method_encode_signature (
2437 assembly, imethod->declaring->signature);
2438 token = mono_image_get_memberref_token (
2439 assembly, &m->klass->byval_arg, m->name, sig);
2442 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2447 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2449 MonoDynamicTable *table;
2456 char *b = blob_size;
2460 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2461 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2462 * Because of this, we must not insert it into the `typeref' hash table.
2465 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2469 g_assert (tb->generic_params);
2470 klass = mono_class_from_mono_type (tb->type.type);
2472 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2473 encode_type (assembly, &klass->byval_arg, p, &p);
2475 count = mono_array_length (tb->generic_params);
2476 mono_metadata_encode_value (count, p, &p);
2477 for (i = 0; i < count; i++) {
2478 MonoReflectionGenericParam *gparam;
2480 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2482 encode_type (assembly, gparam->type.type, p, &p);
2485 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2486 if (assembly->save) {
2487 g_assert (p-sig < 128);
2488 mono_metadata_encode_value (p-sig, b, &b);
2489 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2490 alloc_table (table, table->rows + 1);
2491 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2492 values [MONO_TYPESPEC_SIGNATURE] = token;
2495 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2496 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2502 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2504 MonoDynamicTable *table;
2507 guint32 token, pclass, parent, sig;
2510 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2514 klass = mono_class_from_mono_type (fb->typeb->type);
2515 name = mono_string_to_utf8 (fb->name);
2517 sig = fieldref_encode_signature (assembly, fb->type->type);
2519 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2520 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2522 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2523 parent >>= MONO_TYPEDEFORREF_BITS;
2525 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2527 if (assembly->save) {
2528 alloc_table (table, table->rows + 1);
2529 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2530 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2531 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2532 values [MONO_MEMBERREF_SIGNATURE] = sig;
2535 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2537 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2542 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2550 char *b = blob_size;
2552 if (!assembly->save)
2556 g_assert (helper->type == 2);
2558 if (helper->arguments)
2559 nargs = mono_array_length (helper->arguments);
2563 size = 10 + (nargs * 10);
2565 p = buf = g_malloc (size);
2567 /* Encode calling convention */
2568 /* Change Any to Standard */
2569 if ((helper->call_conv & 0x03) == 0x03)
2570 helper->call_conv = 0x01;
2571 /* explicit_this implies has_this */
2572 if (helper->call_conv & 0x40)
2573 helper->call_conv &= 0x20;
2575 if (helper->call_conv == 0) /* Unmanaged */
2576 *p = helper->unmanaged_call_conv - 1;
2579 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2580 if (helper->call_conv & 0x02) /* varargs */
2585 mono_metadata_encode_value (nargs, p, &p);
2586 encode_reflection_type (assembly, helper->return_type, p, &p);
2587 for (i = 0; i < nargs; ++i) {
2588 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2589 encode_reflection_type (assembly, pt, p, &p);
2592 g_assert (p - buf < size);
2593 mono_metadata_encode_value (p-buf, b, &b);
2594 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2601 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2604 MonoDynamicTable *table;
2607 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2608 idx = table->next_idx ++;
2610 alloc_table (table, table->rows);
2611 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2613 values [MONO_STAND_ALONE_SIGNATURE] =
2614 mono_reflection_encode_sighelper (assembly, helper);
2620 reflection_cc_to_file (int call_conv) {
2621 switch (call_conv & 0x3) {
2623 case 1: return MONO_CALL_DEFAULT;
2624 case 2: return MONO_CALL_VARARG;
2626 g_assert_not_reached ();
2633 MonoMethodSignature *sig;
2639 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2644 MonoMethodSignature *sig;
2647 name = mono_string_to_utf8 (m->name);
2648 nparams = mono_array_length (m->parameters);
2649 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2651 sig->sentinelpos = -1;
2652 sig->call_convention = reflection_cc_to_file (m->call_conv);
2653 sig->param_count = nparams;
2654 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2655 for (i = 0; i < nparams; ++i) {
2656 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2657 sig->params [i] = t->type;
2660 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2662 if (strcmp (name, am->name) == 0 &&
2663 mono_metadata_type_equal (am->parent, m->parent->type) &&
2664 mono_metadata_signature_equal (am->sig, sig)) {
2667 m->table_idx = am->token & 0xffffff;
2671 am = g_new0 (ArrayMethod, 1);
2674 am->parent = m->parent->type;
2675 am->token = mono_image_get_memberref_token (assembly, am->parent,
2676 name, method_encode_signature (assembly, sig));
2677 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2678 m->table_idx = am->token & 0xffffff;
2683 * Insert into the metadata tables all the info about the TypeBuilder tb.
2684 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2687 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2689 MonoDynamicTable *table;
2691 int i, is_object = 0, is_system = 0;
2694 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2695 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2696 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2697 n = mono_string_to_utf8 (tb->name);
2698 if (strcmp (n, "Object") == 0)
2700 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2702 n = mono_string_to_utf8 (tb->nspace);
2703 if (strcmp (n, "System") == 0)
2705 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2707 if (tb->parent && !(is_system && is_object) &&
2708 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2709 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2711 values [MONO_TYPEDEF_EXTENDS] = 0;
2712 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2713 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2716 * if we have explicitlayout or sequentiallayouts, output data in the
2717 * ClassLayout table.
2719 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2720 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2722 alloc_table (table, table->rows);
2723 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2724 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2725 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2726 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2729 /* handle interfaces */
2730 if (tb->interfaces) {
2731 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2733 table->rows += mono_array_length (tb->interfaces);
2734 alloc_table (table, table->rows);
2735 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2736 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2737 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2738 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2739 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2740 values += MONO_INTERFACEIMPL_SIZE;
2744 /* handle generic parameters */
2745 if (tb->generic_params) {
2746 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2747 table->rows += mono_array_length (tb->generic_params);
2748 alloc_table (table, table->rows);
2749 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2750 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2752 mono_image_get_generic_param_info (
2753 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2759 table = &assembly->tables [MONO_TABLE_FIELD];
2760 table->rows += tb->num_fields;
2761 alloc_table (table, table->rows);
2762 for (i = 0; i < tb->num_fields; ++i)
2763 mono_image_get_field_info (
2764 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2767 /* handle constructors */
2769 table = &assembly->tables [MONO_TABLE_METHOD];
2770 table->rows += mono_array_length (tb->ctors);
2771 alloc_table (table, table->rows);
2772 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2773 mono_image_get_ctor_info (domain,
2774 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2777 /* handle methods */
2779 table = &assembly->tables [MONO_TABLE_METHOD];
2780 table->rows += tb->num_methods;
2781 alloc_table (table, table->rows);
2782 for (i = 0; i < tb->num_methods; ++i)
2783 mono_image_get_method_info (
2784 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2787 /* Do the same with properties etc.. */
2788 if (tb->events && mono_array_length (tb->events)) {
2789 table = &assembly->tables [MONO_TABLE_EVENT];
2790 table->rows += mono_array_length (tb->events);
2791 alloc_table (table, table->rows);
2792 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2794 alloc_table (table, table->rows);
2795 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2796 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2797 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2798 for (i = 0; i < mono_array_length (tb->events); ++i)
2799 mono_image_get_event_info (
2800 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2802 if (tb->properties && mono_array_length (tb->properties)) {
2803 table = &assembly->tables [MONO_TABLE_PROPERTY];
2804 table->rows += mono_array_length (tb->properties);
2805 alloc_table (table, table->rows);
2806 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2808 alloc_table (table, table->rows);
2809 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2810 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2811 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2812 for (i = 0; i < mono_array_length (tb->properties); ++i)
2813 mono_image_get_property_info (
2814 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2817 mono_image_add_decl_security (assembly,
2818 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2822 MonoDynamicTable *ntable;
2824 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2825 ntable->rows += mono_array_length (tb->subtypes);
2826 alloc_table (ntable, ntable->rows);
2827 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2829 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2830 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2832 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2833 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2834 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2835 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2836 mono_string_to_utf8 (tb->name), tb->table_idx,
2837 ntable->next_idx, ntable->rows);*/
2838 values += MONO_NESTED_CLASS_SIZE;
2845 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2849 g_ptr_array_add (types, type);
2851 if (!type->subtypes)
2854 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2855 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2856 collect_types (types, subtype);
2861 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2862 MonoReflectionTypeBuilder **type2)
2864 if ((*type1)->table_idx < (*type2)->table_idx)
2867 if ((*type1)->table_idx > (*type2)->table_idx)
2874 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2879 for (i = 0; i < mono_array_length (pinfo); ++i) {
2880 MonoReflectionParamBuilder *pb;
2881 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2884 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2889 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2892 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2894 for (i = 0; i < tb->num_fields; ++i) {
2895 MonoReflectionFieldBuilder* fb;
2896 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2897 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2901 for (i = 0; i < mono_array_length (tb->events); ++i) {
2902 MonoReflectionEventBuilder* eb;
2903 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2904 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2907 if (tb->properties) {
2908 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2909 MonoReflectionPropertyBuilder* pb;
2910 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2911 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2915 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2916 MonoReflectionCtorBuilder* cb;
2917 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2918 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2919 params_add_cattrs (assembly, cb->pinfo);
2924 for (i = 0; i < tb->num_methods; ++i) {
2925 MonoReflectionMethodBuilder* mb;
2926 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2927 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2928 params_add_cattrs (assembly, mb->pinfo);
2933 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2934 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2939 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2942 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2944 /* no types in the module */
2948 for (i = 0; i < mb->num_types; ++i)
2949 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2953 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2954 MonoDynamicImage *assembly)
2956 MonoDynamicTable *table;
2960 char *b = blob_size;
2963 table = &assembly->tables [MONO_TABLE_FILE];
2965 alloc_table (table, table->rows);
2966 values = table->values + table->next_idx * MONO_FILE_SIZE;
2967 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2968 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2969 if (module->image->dynamic) {
2970 /* This depends on the fact that the main module is emitted last */
2971 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2972 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2976 path = g_strdup (module->image->name);
2978 mono_sha1_get_digest_from_file (path, hash);
2981 mono_metadata_encode_value (20, b, &b);
2982 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2983 mono_image_add_stream_data (&assembly->blob, hash, 20);
2988 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2990 MonoDynamicTable *table;
2994 table = &assembly->tables [MONO_TABLE_MODULE];
2995 mb->table_idx = table->next_idx ++;
2996 name = mono_string_to_utf8 (mb->module.name);
2997 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2999 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3002 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3003 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3004 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3008 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3009 guint32 module_index, guint32 parent_index,
3010 MonoDynamicImage *assembly)
3012 MonoDynamicTable *table;
3016 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3017 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3020 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3022 alloc_table (table, table->rows);
3023 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3025 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3026 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3027 if (klass->nested_in)
3028 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3030 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3031 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3032 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3034 res = table->next_idx;
3038 /* Emit nested types */
3039 if (klass->nested_classes) {
3042 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3043 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3050 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3051 guint32 module_index, guint32 parent_index,
3052 MonoDynamicImage *assembly)
3057 klass = mono_class_from_mono_type (tb->type.type);
3059 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3061 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3062 parent_index, assembly);
3066 * We need to do this ourselves since klass->nested_classes is not set up.
3069 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3070 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3075 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3076 guint32 module_index,
3077 MonoDynamicImage *assembly)
3079 MonoImage *image = module->image;
3083 t = &image->tables [MONO_TABLE_TYPEDEF];
3085 for (i = 0; i < t->rows; ++i) {
3086 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3088 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3089 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3093 #define align_pointer(base,p)\
3095 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3097 (p) += 4 - (__diff & 3);\
3101 compare_semantics (const void *a, const void *b)
3103 const guint32 *a_values = a;
3104 const guint32 *b_values = b;
3105 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3108 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3112 compare_custom_attrs (const void *a, const void *b)
3114 const guint32 *a_values = a;
3115 const guint32 *b_values = b;
3117 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3121 compare_field_marshal (const void *a, const void *b)
3123 const guint32 *a_values = a;
3124 const guint32 *b_values = b;
3126 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3130 compare_nested (const void *a, const void *b)
3132 const guint32 *a_values = a;
3133 const guint32 *b_values = b;
3135 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3139 pad_heap (MonoDynamicStream *sh)
3141 if (sh->index & 3) {
3142 int sz = 4 - (sh->index & 3);
3143 memset (sh->data + sh->index, 0, sz);
3149 * build_compressed_metadata() fills in the blob of data that represents the
3150 * raw metadata as it will be saved in the PE file. The five streams are output
3151 * and the metadata tables are comnpressed from the guint32 array representation,
3152 * to the compressed on-disk format.
3155 build_compressed_metadata (MonoDynamicImage *assembly)
3157 MonoDynamicTable *table;
3159 guint64 valid_mask = 0;
3160 guint64 sorted_mask;
3161 guint32 heapt_size = 0;
3162 guint32 meta_size = 256; /* allow for header and other stuff */
3163 guint32 table_offset;
3164 guint32 ntables = 0;
3173 MonoDynamicStream *stream;
3176 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3177 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3178 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3179 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3180 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3182 /* tables that are sorted */
3183 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3184 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3185 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3186 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3187 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3188 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3190 /* Compute table sizes */
3191 /* the MonoImage has already been created in mono_image_basic_init() */
3192 meta = &assembly->image;
3194 /* sizes should be multiple of 4 */
3195 pad_heap (&assembly->blob);
3196 pad_heap (&assembly->guid);
3197 pad_heap (&assembly->sheap);
3198 pad_heap (&assembly->us);
3200 /* Setup the info used by compute_sizes () */
3201 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3202 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3203 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3205 meta_size += assembly->blob.index;
3206 meta_size += assembly->guid.index;
3207 meta_size += assembly->sheap.index;
3208 meta_size += assembly->us.index;
3210 for (i=0; i < 64; ++i)
3211 meta->tables [i].rows = assembly->tables [i].rows;
3213 for (i = 0; i < 64; i++){
3214 if (meta->tables [i].rows == 0)
3216 valid_mask |= (guint64)1 << i;
3218 meta->tables [i].row_size = mono_metadata_compute_size (
3219 meta, i, &meta->tables [i].size_bitfield);
3220 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3222 heapt_size += 24; /* #~ header size */
3223 heapt_size += ntables * 4;
3224 /* make multiple of 4 */
3227 meta_size += heapt_size;
3228 meta->raw_metadata = g_malloc0 (meta_size);
3229 p = meta->raw_metadata;
3230 /* the metadata signature */
3231 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3232 /* version numbers and 4 bytes reserved */
3233 int16val = (guint16*)p;
3234 *int16val++ = GUINT16_TO_LE (1);
3235 *int16val = GUINT16_TO_LE (1);
3237 /* version string */
3238 int32val = (guint32*)p;
3239 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3241 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3242 p += GUINT32_FROM_LE (*int32val);
3243 align_pointer (meta->raw_metadata, p);
3244 int16val = (guint16*)p;
3245 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3246 *int16val = GUINT16_TO_LE (5); /* number of streams */
3250 * write the stream info.
3252 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3253 table_offset += 3; table_offset &= ~3;
3255 assembly->tstream.index = heapt_size;
3256 for (i = 0; i < 5; ++i) {
3257 int32val = (guint32*)p;
3258 stream_desc [i].stream->offset = table_offset;
3259 *int32val++ = GUINT32_TO_LE (table_offset);
3260 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3261 table_offset += GUINT32_FROM_LE (*int32val);
3262 table_offset += 3; table_offset &= ~3;
3264 strcpy (p, stream_desc [i].name);
3265 p += strlen (stream_desc [i].name) + 1;
3266 align_pointer (meta->raw_metadata, p);
3269 * now copy the data, the table stream header and contents goes first.
3271 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3272 p = meta->raw_metadata + assembly->tstream.offset;
3273 int32val = (guint32*)p;
3274 *int32val = GUINT32_TO_LE (0); /* reserved */
3277 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3278 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3279 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3280 *p++ = 1; /* version */
3283 *p++ = 1; /* version */
3287 if (meta->idx_string_wide)
3289 if (meta->idx_guid_wide)
3291 if (meta->idx_blob_wide)
3294 *p++ = 0; /* reserved */
3295 int64val = (guint64*)p;
3296 *int64val++ = GUINT64_TO_LE (valid_mask);
3297 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3299 int32val = (guint32*)p;
3300 for (i = 0; i < 64; i++){
3301 if (meta->tables [i].rows == 0)
3303 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3305 p = (unsigned char*)int32val;
3307 /* sort the tables that still need sorting */
3308 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3310 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3311 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3313 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3314 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3316 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3317 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3319 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3321 /* compress the tables */
3322 for (i = 0; i < 64; i++){
3325 guint32 bitfield = meta->tables [i].size_bitfield;
3326 if (!meta->tables [i].rows)
3328 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3329 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3330 meta->tables [i].base = p;
3331 for (row = 1; row <= meta->tables [i].rows; ++row) {
3332 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3333 for (col = 0; col < assembly->tables [i].columns; ++col) {
3334 switch (mono_metadata_table_size (bitfield, col)) {
3336 *p++ = values [col];
3339 *p++ = values [col] & 0xff;
3340 *p++ = (values [col] >> 8) & 0xff;
3343 *p++ = values [col] & 0xff;
3344 *p++ = (values [col] >> 8) & 0xff;
3345 *p++ = (values [col] >> 16) & 0xff;
3346 *p++ = (values [col] >> 24) & 0xff;
3349 g_assert_not_reached ();
3353 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3356 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3357 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3358 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3359 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3360 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3362 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3366 * Some tables in metadata need to be sorted according to some criteria, but
3367 * when methods and fields are first created with reflection, they may be assigned a token
3368 * that doesn't correspond to the final token they will get assigned after the sorting.
3369 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3370 * with the reflection objects that represent them. Once all the tables are set up, the
3371 * reflection objects will contains the correct table index. fixup_method() will fixup the
3372 * tokens for the method with ILGenerator @ilgen.
3375 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3376 guint32 code_idx = GPOINTER_TO_UINT (value);
3377 MonoReflectionILTokenInfo *iltoken;
3378 MonoReflectionFieldBuilder *field;
3379 MonoReflectionCtorBuilder *ctor;
3380 MonoReflectionMethodBuilder *method;
3381 MonoReflectionTypeBuilder *tb;
3382 MonoReflectionArrayMethod *am;
3384 unsigned char *target;
3386 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3387 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3388 target = assembly->code.data + code_idx + iltoken->code_pos;
3389 switch (target [3]) {
3390 case MONO_TABLE_FIELD:
3391 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3392 field = (MonoReflectionFieldBuilder *)iltoken->member;
3393 idx = field->table_idx;
3394 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3395 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3396 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3398 g_assert_not_reached ();
3401 case MONO_TABLE_METHOD:
3402 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3403 method = (MonoReflectionMethodBuilder *)iltoken->member;
3404 idx = method->table_idx;
3405 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3406 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3407 idx = ctor->table_idx;
3408 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3409 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3410 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3411 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3413 g_assert_not_reached ();
3416 case MONO_TABLE_TYPEDEF:
3417 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3418 g_assert_not_reached ();
3419 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3420 idx = tb->table_idx;
3422 case MONO_TABLE_MEMBERREF:
3423 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3424 am = (MonoReflectionArrayMethod*)iltoken->member;
3425 idx = am->table_idx;
3426 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3427 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3428 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3429 g_assert (m->klass->generic_inst);
3431 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3433 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3434 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3435 g_assert (f->generic_info);
3437 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3440 g_assert_not_reached ();
3443 case MONO_TABLE_METHODSPEC:
3444 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3445 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3446 g_assert (m->signature->generic_param_count);
3449 g_assert_not_reached ();
3453 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3455 target [0] = idx & 0xff;
3456 target [1] = (idx >> 8) & 0xff;
3457 target [2] = (idx >> 16) & 0xff;
3464 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3465 * value is not known when the table is emitted.
3468 fixup_cattrs (MonoDynamicImage *assembly)
3470 MonoDynamicTable *table;
3472 guint32 type, i, idx, token;
3475 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3477 for (i = 0; i < table->rows; ++i) {
3478 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3480 type = values [MONO_CUSTOM_ATTR_TYPE];
3481 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3482 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3483 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3484 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3487 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3488 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3489 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3490 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3497 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3499 MonoDynamicTable *table;
3503 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3505 alloc_table (table, table->rows);
3506 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3507 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3508 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3509 name = mono_string_to_utf8 (rsrc->name);
3510 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3512 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3517 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3519 MonoDynamicTable *table;
3523 char *b = blob_size;
3525 guint32 idx, offset;
3527 if (rsrc->filename) {
3528 name = mono_string_to_utf8 (rsrc->filename);
3529 sname = g_path_get_basename (name);
3531 table = &assembly->tables [MONO_TABLE_FILE];
3533 alloc_table (table, table->rows);
3534 values = table->values + table->next_idx * MONO_FILE_SIZE;
3535 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3536 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3539 mono_sha1_get_digest_from_file (name, hash);
3540 mono_metadata_encode_value (20, b, &b);
3541 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3542 mono_image_add_stream_data (&assembly->blob, hash, 20);
3544 idx = table->next_idx++;
3546 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3549 offset = mono_array_length (rsrc->data);
3550 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3551 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3552 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3553 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3557 * The entry should be emitted into the MANIFESTRESOURCE table of
3558 * the main module, but that needs to reference the FILE table
3559 * which isn't emitted yet.
3566 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3570 set_version_from_string (MonoString *version, guint32 *values)
3572 gchar *ver, *p, *str;
3575 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3576 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3577 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3578 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3581 ver = str = mono_string_to_utf8 (version);
3582 for (i = 0; i < 4; ++i) {
3583 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3589 /* handle Revision and Build */
3599 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3603 char *b = blob_size;
3608 len = mono_array_length (pkey);
3609 mono_metadata_encode_value (len, b, &b);
3610 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3611 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3613 /* need to get the actual value from the key type... */
3614 assembly->strong_name_size = 128;
3615 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3621 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3623 MonoDynamicTable *table;
3624 MonoDynamicImage *assembly;
3625 MonoReflectionAssemblyBuilder *assemblyb;
3630 guint32 module_index;
3632 assemblyb = moduleb->assemblyb;
3633 assembly = moduleb->dynamic_image;
3634 domain = mono_object_domain (assemblyb);
3636 /* Emit ASSEMBLY table */
3637 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3638 alloc_table (table, 1);
3639 values = table->values + MONO_ASSEMBLY_SIZE;
3640 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3641 name = mono_string_to_utf8 (assemblyb->name);
3642 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3644 if (assemblyb->culture) {
3645 name = mono_string_to_utf8 (assemblyb->culture);
3646 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3649 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3651 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3652 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3653 set_version_from_string (assemblyb->version, values);
3655 /* Emit FILE + EXPORTED_TYPE table */
3657 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3659 MonoReflectionModuleBuilder *file_module =
3660 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3661 if (file_module != moduleb) {
3662 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3664 if (file_module->types) {
3665 for (j = 0; j < file_module->num_types; ++j) {
3666 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3667 mono_image_fill_export_table (domain, tb, module_index, 0,
3673 if (assemblyb->loaded_modules) {
3674 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3675 MonoReflectionModule *file_module =
3676 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3677 mono_image_fill_file_table (domain, file_module, assembly);
3679 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3683 /* Emit MANIFESTRESOURCE table */
3685 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3687 MonoReflectionModuleBuilder *file_module =
3688 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3689 /* The table for the main module is emitted later */
3690 if (file_module != moduleb) {
3692 if (file_module->resources) {
3693 int len = mono_array_length (file_module->resources);
3694 for (j = 0; j < len; ++j) {
3695 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3696 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3704 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3705 * for the modulebuilder @moduleb.
3706 * At the end of the process, method and field tokens are fixed up and the
3707 * on-disk compressed metadata representation is created.
3710 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3712 MonoDynamicTable *table;
3713 MonoDynamicImage *assembly;
3714 MonoReflectionAssemblyBuilder *assemblyb;
3719 assemblyb = moduleb->assemblyb;
3720 assembly = moduleb->dynamic_image;
3721 domain = mono_object_domain (assemblyb);
3723 if (assembly->text_rva)
3726 assembly->text_rva = START_TEXT_RVA;
3728 if (moduleb->is_main) {
3729 mono_image_emit_manifest (moduleb);
3732 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3733 table->rows = 1; /* .<Module> */
3735 alloc_table (table, table->rows);
3737 * Set the first entry.
3739 values = table->values + table->columns;
3740 values [MONO_TYPEDEF_FLAGS] = 0;
3741 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3742 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3743 values [MONO_TYPEDEF_EXTENDS] = 0;
3744 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3745 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3748 * handle global methods
3749 * FIXME: test what to do when global methods are defined in multiple modules.
3751 if (moduleb->global_methods) {
3752 table = &assembly->tables [MONO_TABLE_METHOD];
3753 table->rows += mono_array_length (moduleb->global_methods);
3754 alloc_table (table, table->rows);
3755 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3756 mono_image_get_method_info (
3757 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3759 if (moduleb->global_fields) {
3760 table = &assembly->tables [MONO_TABLE_FIELD];
3761 table->rows += mono_array_length (moduleb->global_fields);
3762 alloc_table (table, table->rows);
3763 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3764 mono_image_get_field_info (
3765 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3768 table = &assembly->tables [MONO_TABLE_MODULE];
3769 alloc_table (table, 1);
3770 mono_image_fill_module_table (domain, moduleb, assembly);
3774 /* Collect all types into a list sorted by their table_idx */
3775 GPtrArray *types = g_ptr_array_new ();
3778 for (i = 0; i < moduleb->num_types; ++i) {
3779 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3780 collect_types (types, type);
3783 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3784 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3785 table->rows += types->len;
3786 alloc_table (table, table->rows);
3788 for (i = 0; i < types->len; ++i) {
3789 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3790 mono_image_get_type_info (domain, type, assembly);
3792 g_ptr_array_free (types, TRUE);
3796 * table->rows is already set above and in mono_image_fill_module_table.
3798 /* add all the custom attributes at the end, once all the indexes are stable */
3799 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3801 module_add_cattrs (assembly, moduleb);
3804 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3805 fixup_cattrs (assembly);
3809 * mono_image_insert_string:
3810 * @module: module builder object
3813 * Insert @str into the user string stream of @module.
3816 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3818 MonoDynamicImage *assembly;
3823 MONO_ARCH_SAVE_REGS;
3825 if (!module->dynamic_image)
3826 mono_image_module_basic_init (module);
3828 assembly = module->dynamic_image;
3830 if (assembly->save) {
3831 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3832 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3833 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3835 char *swapped = g_malloc (2 * mono_string_length (str));
3836 const char *p = (const char*)mono_string_chars (str);
3838 swap_with_size (swapped, p, 2, mono_string_length (str));
3839 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3843 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3845 mono_image_add_stream_data (&assembly->us, "", 1);
3848 idx = assembly->us.index ++;
3850 mono_g_hash_table_insert (assembly->tokens,
3851 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3853 return MONO_TOKEN_STRING | idx;
3857 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3858 MonoArray *opt_param_types)
3863 klass = obj->vtable->klass;
3864 if (strcmp (klass->name, "MonoMethod") == 0) {
3865 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3866 MonoMethodSignature *sig, *old;
3867 guint32 sig_token, parent;
3870 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3872 nargs = mono_array_length (opt_param_types);
3873 old = method->signature;
3874 sig = mono_metadata_signature_alloc (
3875 &assembly->image, old->param_count + nargs);
3877 sig->hasthis = old->hasthis;
3878 sig->explicit_this = old->explicit_this;
3879 sig->call_convention = old->call_convention;
3880 sig->generic_param_count = old->generic_param_count;
3881 sig->param_count = old->param_count + nargs;
3882 sig->sentinelpos = old->param_count;
3883 sig->ret = old->ret;
3885 for (i = 0; i < old->param_count; i++)
3886 sig->params [i] = old->params [i];
3888 for (i = 0; i < nargs; i++) {
3889 MonoReflectionType *rt = mono_array_get (
3890 opt_param_types, MonoReflectionType *, i);
3891 sig->params [old->param_count + i] = rt->type;
3894 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3895 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3896 parent >>= MONO_TYPEDEFORREF_BITS;
3898 parent <<= MONO_MEMBERREF_PARENT_BITS;
3899 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3901 sig_token = method_encode_signature (assembly, sig);
3902 token = mono_image_get_varargs_method_token (
3903 assembly, parent, method->name, sig_token);
3904 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3905 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3906 ReflectionMethodBuilder rmb;
3907 guint32 parent, sig;
3909 reflection_methodbuilder_from_method_builder (&rmb, mb);
3910 rmb.opt_types = opt_param_types;
3912 sig = method_builder_encode_signature (assembly, &rmb);
3914 parent = mono_image_create_token (assembly, obj);
3915 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3917 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3918 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3920 token = mono_image_get_varargs_method_token (
3921 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3923 g_error ("requested method token for %s\n", klass->name);
3929 * mono_image_create_token:
3930 * @assembly: a dynamic assembly
3933 * Get a token to insert in the IL code stream for the given MemberInfo.
3934 * @obj can be one of:
3935 * ConstructorBuilder
3945 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3950 klass = obj->vtable->klass;
3951 if (strcmp (klass->name, "MethodBuilder") == 0) {
3952 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3954 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3955 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3957 token = mono_image_get_methodbuilder_token (assembly, mb);
3958 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3960 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3961 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3963 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3964 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3966 token = mono_image_get_ctorbuilder_token (assembly, mb);
3967 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3969 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3970 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3971 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3972 if (tb->generic_params) {
3973 token = mono_image_get_generic_field_token (assembly, fb);
3975 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3978 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3979 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3980 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3982 else if (strcmp (klass->name, "MonoType") == 0 ||
3983 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3984 MonoReflectionType *tb = (MonoReflectionType *)obj;
3985 token = mono_metadata_token_from_dor (
3986 mono_image_typedef_or_ref (assembly, tb->type));
3988 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3989 MonoReflectionType *tb = (MonoReflectionType *)obj;
3990 token = mono_metadata_token_from_dor (
3991 mono_image_typedef_or_ref (assembly, tb->type));
3993 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3994 strcmp (klass->name, "MonoMethod") == 0) {
3995 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3996 if (m->method->signature->is_inflated) {
3997 token = mono_image_get_methodspec_token (assembly, m->method);
3998 } else if (m->method->signature->generic_param_count) {
3999 g_assert_not_reached ();
4000 } else if ((m->method->klass->image == &assembly->image) &&
4001 !m->method->klass->generic_inst) {
4002 static guint32 method_table_idx = 0xffffff;
4003 if (m->method->klass->wastypebuilder) {
4004 /* we use the same token as the one that was assigned
4005 * to the Methodbuilder.
4006 * FIXME: do the equivalent for Fields.
4008 token = m->method->token;
4011 * Each token should have a unique index, but the indexes are
4012 * assigned by managed code, so we don't know about them. An
4013 * easy solution is to count backwards...
4015 method_table_idx --;
4016 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4019 token = mono_image_get_methodref_token (assembly, m->method);
4020 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4022 else if (strcmp (klass->name, "MonoField") == 0) {
4023 MonoReflectionField *f = (MonoReflectionField *)obj;
4024 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4025 static guint32 field_table_idx = 0xffffff;
4027 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4029 token = mono_image_get_fieldref_token (assembly, f);
4030 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4032 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4033 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4034 token = mono_image_get_array_token (assembly, m);
4036 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4037 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4038 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4041 g_error ("requested token for %s\n", klass->name);
4043 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4050 guint32 import_lookup_table;
4054 guint32 import_address_table_rva;
4062 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4064 static MonoDynamicImage*
4065 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4066 char *assembly_name, char *module_name)
4068 static const guchar entrycode [16] = {0xff, 0x25, 0};
4069 MonoDynamicImage *image;
4073 * We need to use the current ms version or the ms runtime it won't find
4074 * the support dlls. D'oh!
4075 * const char *version = "mono-" VERSION;
4078 * To make binaries default to the .Net 1.0 version
4079 * const char *version = "v1.0.3705";
4081 const char *version = "v1.1.4322";
4084 image = GC_MALLOC (sizeof (MonoDynamicImage));
4086 image = g_new0 (MonoDynamicImage, 1);
4089 /* keep in sync with image.c */
4090 image->image.name = assembly_name;
4091 image->image.assembly_name = image->image.name; /* they may be different */
4092 image->image.module_name = module_name;
4093 image->image.version = g_strdup (version);
4094 image->image.dynamic = TRUE;
4096 image->image.references = g_new0 (MonoAssembly*, 1);
4097 image->image.references [0] = NULL;
4099 mono_image_init (&image->image);
4101 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4102 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4103 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4104 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4105 image->handleref = g_hash_table_new (NULL, NULL);
4106 image->tokens = mono_g_hash_table_new (NULL, NULL);
4107 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4108 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4109 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4111 string_heap_init (&image->sheap);
4112 mono_image_add_stream_data (&image->us, "", 1);
4113 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4114 /* import tables... */
4115 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4116 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4117 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4118 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4119 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4120 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4121 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4122 stream_data_align (&image->code);
4124 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4126 for (i=0; i < 64; ++i) {
4127 image->tables [i].next_idx = 1;
4128 image->tables [i].columns = table_sizes [i];
4131 image->image.assembly = (MonoAssembly*)assembly;
4132 image->run = assembly->run;
4133 image->save = assembly->save;
4139 * mono_image_basic_init:
4140 * @assembly: an assembly builder object
4142 * Create the MonoImage that represents the assembly builder and setup some
4143 * of the helper hash table and the basic metadata streams.
4146 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4148 MonoDynamicAssembly *assembly;
4149 MonoDynamicImage *image;
4151 MONO_ARCH_SAVE_REGS;
4153 if (assemblyb->dynamic_assembly)
4157 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4159 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4162 assembly->assembly.dynamic = TRUE;
4163 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4164 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4165 if (assemblyb->culture)
4166 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4168 assembly->assembly.aname.culture = g_strdup ("");
4170 assembly->run = assemblyb->access != 2;
4171 assembly->save = assemblyb->access != 1;
4173 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4174 assembly->assembly.aname.name = image->image.name;
4175 assembly->assembly.image = &image->image;
4177 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4178 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4182 calc_section_size (MonoDynamicImage *assembly)
4186 /* alignment constraints */
4187 assembly->code.index += 3;
4188 assembly->code.index &= ~3;
4189 assembly->meta_size += 3;
4190 assembly->meta_size &= ~3;
4191 assembly->resources.index += 3;
4192 assembly->resources.index &= ~3;
4194 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4195 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4198 if (assembly->win32_res) {
4199 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4201 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4202 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4206 assembly->sections [MONO_SECTION_RELOC].size = 12;
4207 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4217 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4221 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4223 ResTreeNode *t1 = (ResTreeNode*)a;
4224 ResTreeNode *t2 = (ResTreeNode*)b;
4226 return t1->id - t2->id;
4230 * resource_tree_create:
4232 * Organize the resources into a resource tree.
4234 static ResTreeNode *
4235 resource_tree_create (MonoArray *win32_resources)
4237 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4241 tree = g_new0 (ResTreeNode, 1);
4243 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4244 MonoReflectionWin32Resource *win32_res =
4245 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4249 lang_node = g_new0 (ResTreeNode, 1);
4250 lang_node->id = win32_res->lang_id;
4251 lang_node->win32_res = win32_res;
4253 /* Create type node if neccesary */
4255 for (l = tree->children; l; l = l->next)
4256 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4257 type_node = (ResTreeNode*)l->data;
4262 type_node = g_new0 (ResTreeNode, 1);
4263 type_node->id = win32_res->res_type;
4266 * The resource types have to be sorted otherwise
4267 * Windows Explorer can't display the version information.
4269 tree->children = g_slist_insert_sorted (tree->children, type_node,
4270 resource_tree_compare_by_id);
4273 /* Create res node if neccesary */
4275 for (l = type_node->children; l; l = l->next)
4276 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4277 res_node = (ResTreeNode*)l->data;
4282 res_node = g_new0 (ResTreeNode, 1);
4283 res_node->id = win32_res->res_id;
4284 type_node->children = g_slist_append (type_node->children, res_node);
4287 res_node->children = g_slist_append (res_node->children, lang_node);
4294 * resource_tree_encode:
4296 * Encode the resource tree into the format used in the PE file.
4299 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4302 MonoPEResourceDir dir;
4303 MonoPEResourceDirEntry dir_entry;
4304 MonoPEResourceDataEntry data_entry;
4308 * For the format of the resource directory, see the article
4309 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4313 memset (&dir, 0, sizeof (dir));
4314 memset (&dir_entry, 0, sizeof (dir_entry));
4315 memset (&data_entry, 0, sizeof (data_entry));
4317 g_assert (sizeof (dir) == 16);
4318 g_assert (sizeof (dir_entry) == 8);
4319 g_assert (sizeof (data_entry) == 16);
4321 node->offset = p - begin;
4323 /* IMAGE_RESOURCE_DIRECTORY */
4324 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4326 memcpy (p, &dir, sizeof (dir));
4329 /* Reserve space for entries */
4331 p += sizeof (dir_entry) * dir.res_id_entries;
4333 /* Write children */
4334 for (l = node->children; l; l = l->next) {
4335 ResTreeNode *child = (ResTreeNode*)l->data;
4337 if (child->win32_res) {
4339 child->offset = p - begin;
4341 /* IMAGE_RESOURCE_DATA_ENTRY */
4342 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4343 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4345 memcpy (p, &data_entry, sizeof (data_entry));
4346 p += sizeof (data_entry);
4348 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4349 p += data_entry.rde_size;
4352 resource_tree_encode (child, begin, p, &p);
4355 /* IMAGE_RESOURCE_ENTRY */
4356 for (l = node->children; l; l = l->next) {
4357 ResTreeNode *child = (ResTreeNode*)l->data;
4358 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4360 dir_entry.is_dir = child->win32_res ? 0 : 1;
4361 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4363 memcpy (entries, &dir_entry, sizeof (dir_entry));
4364 entries += sizeof (dir_entry);
4371 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4376 MonoReflectionWin32Resource *win32_res;
4379 if (!assemblyb->win32_resources)
4383 * Resources are stored in a three level tree inside the PE file.
4384 * - level one contains a node for each type of resource
4385 * - level two contains a node for each resource
4386 * - level three contains a node for each instance of a resource for a
4387 * specific language.
4390 tree = resource_tree_create (assemblyb->win32_resources);
4392 /* Estimate the size of the encoded tree */
4394 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4395 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4396 size += mono_array_length (win32_res->res_data);
4398 /* Directory structure */
4399 size += mono_array_length (assemblyb->win32_resources) * 256;
4400 p = buf = g_malloc (size);
4402 resource_tree_encode (tree, p, p, &p);
4404 g_assert (p - buf < size);
4406 assembly->win32_res = g_malloc (p - buf);
4407 assembly->win32_res_size = p - buf;
4408 memcpy (assembly->win32_res, buf, p - buf);
4414 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4416 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4419 p += sizeof (MonoPEResourceDir);
4420 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4421 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4422 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4423 if (dir_entry->is_dir)
4424 fixup_resource_directory (res_section, child, rva);
4426 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4427 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4430 p += sizeof (MonoPEResourceDirEntry);
4435 * mono_image_create_pefile:
4436 * @mb: a module builder object
4438 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4439 * assembly->pefile where it can be easily retrieved later in chunks.
4442 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4443 MonoMSDOSHeader *msdos;
4444 MonoDotNetHeader *header;
4445 MonoSectionTable *section;
4446 MonoCLIHeader *cli_header;
4447 guint32 size, image_size, virtual_base, text_offset;
4448 guint32 header_start, section_start, file_offset, virtual_offset;
4449 MonoDynamicImage *assembly;
4450 MonoReflectionAssemblyBuilder *assemblyb;
4451 MonoDynamicStream *pefile;
4453 guint32 *rva, value;
4456 static const unsigned char msheader[] = {
4457 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4458 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4461 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4462 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4463 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4464 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4467 assemblyb = mb->assemblyb;
4469 mono_image_basic_init (assemblyb);
4470 assembly = mb->dynamic_image;
4472 /* already created */
4473 if (assembly->pefile.index)
4476 mono_image_build_metadata (mb);
4478 if (mb->is_main && assemblyb->resources) {
4479 int len = mono_array_length (assemblyb->resources);
4480 for (i = 0; i < len; ++i)
4481 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4484 if (mb->resources) {
4485 int len = mono_array_length (mb->resources);
4486 for (i = 0; i < len; ++i)
4487 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4490 build_compressed_metadata (assembly);
4493 assembly_add_win32_resources (assembly, assemblyb);
4495 nsections = calc_section_size (assembly);
4497 pefile = &assembly->pefile;
4499 /* The DOS header and stub */
4500 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4501 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4503 /* the dotnet header */
4504 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4506 /* the section tables */
4507 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4509 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4510 virtual_offset = VIRT_ALIGN;
4513 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4514 if (!assembly->sections [i].size)
4517 file_offset += FILE_ALIGN - 1;
4518 file_offset &= ~(FILE_ALIGN - 1);
4519 virtual_offset += VIRT_ALIGN - 1;
4520 virtual_offset &= ~(VIRT_ALIGN - 1);
4522 assembly->sections [i].offset = file_offset;
4523 assembly->sections [i].rva = virtual_offset;
4525 file_offset += assembly->sections [i].size;
4526 virtual_offset += assembly->sections [i].size;
4527 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4530 file_offset += FILE_ALIGN - 1;
4531 file_offset &= ~(FILE_ALIGN - 1);
4532 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4534 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4536 /* back-patch info */
4537 msdos = (MonoMSDOSHeader*)pefile->data;
4538 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4539 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4540 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4542 header = (MonoDotNetHeader*)(pefile->data + header_start);
4543 header->pesig [0] = 'P';
4544 header->pesig [1] = 'E';
4546 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4547 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4548 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4549 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4550 if (assemblyb->pekind == 1) {
4552 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4555 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4558 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4560 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4561 header->pe.pe_major = 6;
4562 header->pe.pe_minor = 0;
4563 size = assembly->sections [MONO_SECTION_TEXT].size;
4564 size += FILE_ALIGN - 1;
4565 size &= ~(FILE_ALIGN - 1);
4566 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4567 size = assembly->sections [MONO_SECTION_RSRC].size;
4568 size += FILE_ALIGN - 1;
4569 size &= ~(FILE_ALIGN - 1);
4570 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4571 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4572 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4573 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4574 /* pe_rva_entry_point always at the beginning of the text section */
4575 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4577 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4578 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4579 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4580 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4581 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4582 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4583 size = section_start;
4584 size += FILE_ALIGN - 1;
4585 size &= ~(FILE_ALIGN - 1);
4586 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4588 size += VIRT_ALIGN - 1;
4589 size &= ~(VIRT_ALIGN - 1);
4590 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4593 // Translate the PEFileKind value to the value expected by the Windows loader
4599 // PEFileKinds.Dll == 1
4600 // PEFileKinds.ConsoleApplication == 2
4601 // PEFileKinds.WindowApplication == 3
4604 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4605 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4607 if (assemblyb->pekind == 3)
4612 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4614 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4615 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4616 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4617 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4618 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4619 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4621 /* fill data directory entries */
4623 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4624 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4626 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4627 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4629 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4630 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4631 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4632 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4633 /* patch imported function RVA name */
4634 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4635 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4637 /* the import table */
4638 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4639 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4640 /* patch imported dll RVA name and other entries in the dir */
4641 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4642 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4643 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4644 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4645 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4646 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4648 p = (assembly->code.data + assembly->ilt_offset);
4649 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4650 *p++ = (value) & 0xff;
4651 *p++ = (value >> 8) & (0xff);
4652 *p++ = (value >> 16) & (0xff);
4653 *p++ = (value >> 24) & (0xff);
4655 /* the CLI header info */
4656 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4657 cli_header->ch_size = GUINT32_FROM_LE (72);
4658 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4659 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4660 if (assemblyb->entry_point) {
4661 guint32 table_idx = 0;
4662 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4663 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4664 table_idx = methodb->table_idx;
4667 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4668 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4671 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4672 /* The embedded managed resources */
4673 text_offset = assembly->text_rva + assembly->code.index;
4674 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4675 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4676 text_offset += assembly->resources.index;
4677 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4678 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4679 text_offset += assembly->meta_size;
4680 if (assembly->strong_name_size) {
4681 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4682 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4683 text_offset += assembly->strong_name_size;
4686 /* write the section tables and section content */
4687 section = (MonoSectionTable*)(pefile->data + section_start);
4688 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4689 static const char *section_names [] = {
4690 ".text", ".rsrc", ".reloc"
4692 if (!assembly->sections [i].size)
4694 strcpy (section->st_name, section_names [i]);
4695 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4696 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4697 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4698 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4699 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4700 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4701 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4703 case MONO_SECTION_TEXT:
4704 /* patch entry point */
4705 p = (assembly->code.data + 2);
4706 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4707 *p++ = (value) & 0xff;
4708 *p++ = (value >> 8) & 0xff;
4709 *p++ = (value >> 16) & 0xff;
4710 *p++ = (value >> 24) & 0xff;
4712 text_offset = assembly->sections [i].offset;
4713 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4714 text_offset += assembly->code.index;
4715 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4716 text_offset += assembly->resources.index;
4717 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4718 text_offset += assembly->meta_size;
4719 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4721 g_free (assembly->image.raw_metadata);
4723 case MONO_SECTION_RELOC:
4724 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4725 *rva = GUINT32_FROM_LE (assembly->text_rva);
4727 *rva = GUINT32_FROM_LE (12);
4729 data16 = (guint16*)rva;
4731 * the entrypoint is always at the start of the text section
4732 * 3 is IMAGE_REL_BASED_HIGHLOW
4733 * 2 is patch_size_rva - text_rva
4735 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4737 *data16 = 0; /* terminate */
4739 case MONO_SECTION_RSRC:
4740 if (assembly->win32_res) {
4741 text_offset = assembly->sections [i].offset;
4743 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4744 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4746 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4750 g_assert_not_reached ();
4755 /* check that the file is properly padded */
4758 FILE *f = fopen ("mypetest.exe", "w");
4759 fwrite (pefile->data, pefile->index, 1, f);
4765 MonoReflectionModule *
4766 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4770 MonoImageOpenStatus status;
4771 MonoDynamicAssembly *assembly;
4773 name = mono_string_to_utf8 (fileName);
4775 image = mono_image_open (name, &status);
4778 if (status == MONO_IMAGE_ERROR_ERRNO)
4779 exc = mono_get_exception_file_not_found (fileName);
4781 exc = mono_get_exception_bad_image_format (name);
4783 mono_raise_exception (exc);
4788 assembly = ab->dynamic_assembly;
4789 image->assembly = (MonoAssembly*)assembly;
4791 mono_assembly_load_references (image, &status);
4793 mono_image_close (image);
4794 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4797 return mono_module_get_object (mono_domain_get (), image);
4801 * We need to return always the same object for MethodInfo, FieldInfo etc..
4802 * but we need to consider the reflected type.
4803 * type uses a different hash, since it uses custom hash/equal functions.
4808 MonoClass *refclass;
4812 reflected_equal (gconstpointer a, gconstpointer b) {
4813 const ReflectedEntry *ea = a;
4814 const ReflectedEntry *eb = b;
4816 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4820 reflected_hash (gconstpointer a) {
4821 const ReflectedEntry *ea = a;
4822 return GPOINTER_TO_UINT (ea->item);
4825 #define CHECK_OBJECT(t,p,k) \
4831 mono_domain_lock (domain); \
4832 if (!domain->refobject_hash) \
4833 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4834 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4835 mono_domain_unlock (domain); \
4841 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4843 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4846 #define CACHE_OBJECT(p,o,k) \
4848 ReflectedEntry *e = ALLOC_REFENTRY; \
4850 e->refclass = (k); \
4851 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4852 mono_domain_unlock (domain); \
4856 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4858 /* this is done only once */
4859 mono_domain_lock (domain);
4860 CACHE_OBJECT (assembly, res, NULL);
4864 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4866 /* this is done only once */
4867 mono_domain_lock (domain);
4868 CACHE_OBJECT (module, res, NULL);
4872 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4874 MonoDynamicImage *image = moduleb->dynamic_image;
4875 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4878 * FIXME: we already created an image in mono_image_basic_init (), but
4879 * we don't know which module it belongs to, since that is only
4880 * determined at assembly save time.
4882 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4883 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4885 moduleb->module.image = &image->image;
4886 moduleb->dynamic_image = image;
4887 register_module (mono_object_domain (moduleb), moduleb, image);
4892 * mono_assembly_get_object:
4893 * @domain: an app domain
4894 * @assembly: an assembly
4896 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4898 MonoReflectionAssembly*
4899 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4901 static MonoClass *System_Reflection_Assembly;
4902 MonoReflectionAssembly *res;
4904 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4905 if (!System_Reflection_Assembly)
4906 System_Reflection_Assembly = mono_class_from_name (
4907 mono_defaults.corlib, "System.Reflection", "Assembly");
4908 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4909 res->assembly = assembly;
4910 CACHE_OBJECT (assembly, res, NULL);
4916 MonoReflectionModule*
4917 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4919 static MonoClass *System_Reflection_Module;
4920 MonoReflectionModule *res;
4922 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4923 if (!System_Reflection_Module)
4924 System_Reflection_Module = mono_class_from_name (
4925 mono_defaults.corlib, "System.Reflection", "Module");
4926 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4929 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4931 res->fqname = mono_string_new (domain, image->name);
4932 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4933 res->scopename = mono_string_new (domain, image->module_name);
4935 mono_image_addref (image);
4937 CACHE_OBJECT (image, res, NULL);
4941 MonoReflectionModule*
4942 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4944 static MonoClass *System_Reflection_Module;
4945 MonoReflectionModule *res;
4946 MonoTableInfo *table;
4947 guint32 cols [MONO_FILE_SIZE];
4949 guint32 i, name_idx;
4952 if (!System_Reflection_Module)
4953 System_Reflection_Module = mono_class_from_name (
4954 mono_defaults.corlib, "System.Reflection", "Module");
4955 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4957 table = &image->tables [MONO_TABLE_FILE];
4958 g_assert (table_index < table->rows);
4959 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4962 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4963 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4965 /* Check whenever the row has a corresponding row in the moduleref table */
4966 table = &image->tables [MONO_TABLE_MODULEREF];
4967 for (i = 0; i < table->rows; ++i) {
4968 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4969 val = mono_metadata_string_heap (image, name_idx);
4970 if (strcmp (val, name) == 0)
4971 res->image = image->modules [i];
4974 res->fqname = mono_string_new (domain, name);
4975 res->name = mono_string_new (domain, name);
4976 res->scopename = mono_string_new (domain, name);
4977 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4983 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4985 if ((t1->type != t2->type) ||
4986 (t1->byref != t2->byref))
4990 case MONO_TYPE_VOID:
4991 case MONO_TYPE_BOOLEAN:
4992 case MONO_TYPE_CHAR:
5003 case MONO_TYPE_STRING:
5006 case MONO_TYPE_OBJECT:
5007 case MONO_TYPE_TYPEDBYREF:
5009 case MONO_TYPE_VALUETYPE:
5010 case MONO_TYPE_CLASS:
5011 case MONO_TYPE_SZARRAY:
5012 return t1->data.klass == t2->data.klass;
5014 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5015 case MONO_TYPE_ARRAY:
5016 if (t1->data.array->rank != t2->data.array->rank)
5018 return t1->data.array->eklass == t2->data.array->eklass;
5019 case MONO_TYPE_GENERICINST: {
5021 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5023 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5025 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5026 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5032 case MONO_TYPE_MVAR:
5033 return t1->data.generic_param == t2->data.generic_param;
5035 g_error ("implement type compare for %0x!", t1->type);
5043 mymono_metadata_type_hash (MonoType *t1)
5049 hash |= t1->byref << 6; /* do not collide with t1->type values */
5051 case MONO_TYPE_VALUETYPE:
5052 case MONO_TYPE_CLASS:
5053 case MONO_TYPE_SZARRAY:
5054 /* check if the distribution is good enough */
5055 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5057 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5062 static MonoReflectionGenericInst*
5063 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5065 static MonoClass *System_Reflection_MonoGenericInst;
5066 MonoReflectionGenericInst *res;
5067 MonoGenericInst *ginst;
5070 if (!System_Reflection_MonoGenericInst) {
5071 System_Reflection_MonoGenericInst = mono_class_from_name (
5072 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5073 g_assert (System_Reflection_MonoGenericInst);
5076 ginst = geninst->data.generic_inst;
5077 gklass = mono_class_from_mono_type (ginst->generic_type);
5079 mono_class_init (ginst->klass);
5081 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5083 res->type.type = geninst;
5084 if (gklass->wastypebuilder && gklass->reflection_info)
5085 res->generic_type = gklass->reflection_info;
5087 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5093 * mono_type_get_object:
5094 * @domain: an app domain
5097 * Return an System.MonoType object representing the type @type.
5100 mono_type_get_object (MonoDomain *domain, MonoType *type)
5102 MonoReflectionType *res;
5103 MonoClass *klass = mono_class_from_mono_type (type);
5105 mono_domain_lock (domain);
5106 if (!domain->type_hash)
5107 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5108 (GCompareFunc)mymono_metadata_type_equal);
5109 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5110 mono_domain_unlock (domain);
5113 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5114 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5115 mono_g_hash_table_insert (domain->type_hash, type, res);
5116 mono_domain_unlock (domain);
5119 if (klass->reflection_info && !klass->wastypebuilder) {
5120 /* g_assert_not_reached (); */
5121 /* should this be considered an error condition? */
5123 mono_domain_unlock (domain);
5124 return klass->reflection_info;
5127 mono_class_init (klass);
5128 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5130 mono_g_hash_table_insert (domain->type_hash, type, res);
5131 mono_domain_unlock (domain);
5136 * mono_method_get_object:
5137 * @domain: an app domain
5139 * @refclass: the reflected type (can be NULL)
5141 * Return an System.Reflection.MonoMethod object representing the method @method.
5143 MonoReflectionMethod*
5144 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5147 * We use the same C representation for methods and constructors, but the type
5148 * name in C# is different.
5152 MonoReflectionMethod *ret;
5155 refclass = method->klass;
5157 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5158 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5159 cname = "MonoCMethod";
5161 cname = "MonoMethod";
5162 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5164 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5165 ret->method = method;
5166 ret->name = mono_string_new (domain, method->name);
5167 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5168 CACHE_OBJECT (method, ret, refclass);
5173 * mono_field_get_object:
5174 * @domain: an app domain
5178 * Return an System.Reflection.MonoField object representing the field @field
5181 MonoReflectionField*
5182 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5184 MonoReflectionField *res;
5187 CHECK_OBJECT (MonoReflectionField *, field, klass);
5188 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5189 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5192 res->name = mono_string_new (domain, field->name);
5193 res->attrs = field->type->attrs;
5194 res->type = mono_type_get_object (domain, field->type);
5195 CACHE_OBJECT (field, res, klass);
5200 * mono_property_get_object:
5201 * @domain: an app domain
5203 * @property: a property
5205 * Return an System.Reflection.MonoProperty object representing the property @property
5208 MonoReflectionProperty*
5209 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5211 MonoReflectionProperty *res;
5214 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5215 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5216 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5218 res->property = property;
5219 CACHE_OBJECT (property, res, klass);
5224 * mono_event_get_object:
5225 * @domain: an app domain
5229 * Return an System.Reflection.MonoEvent object representing the event @event
5232 MonoReflectionEvent*
5233 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5235 MonoReflectionEvent *res;
5238 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5239 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5240 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5243 CACHE_OBJECT (event, res, klass);
5248 * mono_param_get_objects:
5249 * @domain: an app domain
5252 * Return an System.Reflection.ParameterInfo array object representing the parameters
5253 * in the method @method.
5256 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5258 static MonoClass *System_Reflection_ParameterInfo;
5259 MonoArray *res = NULL;
5260 MonoReflectionMethod *member = NULL;
5261 MonoReflectionParameter *param = NULL;
5265 if (!System_Reflection_ParameterInfo)
5266 System_Reflection_ParameterInfo = mono_class_from_name (
5267 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5269 if (!method->signature->param_count)
5270 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5272 /* Note: the cache is based on the address of the signature into the method
5273 * since we already cache MethodInfos with the method as keys.
5275 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5277 member = mono_method_get_object (domain, method, NULL);
5278 names = g_new (char *, method->signature->param_count);
5279 mono_method_get_param_names (method, (const char **) names);
5281 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5282 for (i = 0; i < method->signature->param_count; ++i) {
5283 param = (MonoReflectionParameter *)mono_object_new (domain,
5284 System_Reflection_ParameterInfo);
5285 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5286 param->DefaultValueImpl = NULL; /* FIXME */
5287 param->MemberImpl = (MonoObject*)member;
5288 param->NameImpl = mono_string_new (domain, names [i]);
5289 param->PositionImpl = i;
5290 param->AttrsImpl = method->signature->params [i]->attrs;
5291 mono_array_set (res, gpointer, i, param);
5294 CACHE_OBJECT (&(method->signature), res, NULL);
5299 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5303 memset (assembly, 0, sizeof (MonoAssemblyName));
5305 assembly->culture = "";
5306 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5308 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5311 while (*p == ' ' || *p == ',') {
5320 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5322 assembly->major = strtoul (p, &s, 10);
5323 if (s == p || *s != '.')
5326 assembly->minor = strtoul (p, &s, 10);
5327 if (s == p || *s != '.')
5330 assembly->build = strtoul (p, &s, 10);
5331 if (s == p || *s != '.')
5334 assembly->revision = strtoul (p, &s, 10);
5338 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5340 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5341 assembly->culture = "";
5344 assembly->culture = p;
5345 while (*p && *p != ',') {
5349 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5351 if (strncmp (p, "null", 4) == 0) {
5356 while (*p && *p != ',') {
5359 len = (p - start + 1);
5360 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5361 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5362 g_strlcpy (assembly->public_key_token, start, len);
5365 while (*p && *p != ',')
5369 while (*p == ' ' || *p == ',') {
5383 * mono_reflection_parse_type:
5386 * Parse a type name as accepted by the GetType () method and output the info
5387 * extracted in the info structure.
5388 * the name param will be mangled, so, make a copy before passing it to this function.
5389 * The fields in info will be valid until the memory pointed to by name is valid.
5390 * Returns 0 on parse error.
5391 * See also mono_type_get_name () below.
5394 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5396 char *start, *p, *w, *last_point, *startn;
5397 int in_modifiers = 0;
5398 int isbyref = 0, rank;
5400 start = p = w = name;
5402 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5403 info->name = info->name_space = NULL;
5404 info->nested = NULL;
5405 info->modifiers = NULL;
5407 /* last_point separates the namespace from the name */
5413 *p = 0; /* NULL terminate the name */
5415 info->nested = g_list_append (info->nested, startn);
5416 /* we have parsed the nesting namespace + name */
5420 info->name_space = start;
5422 info->name = last_point + 1;
5424 info->name_space = (char *)"";
5450 info->name_space = start;
5452 info->name = last_point + 1;
5454 info->name_space = (char *)"";
5461 if (isbyref) /* only one level allowed by the spec */
5464 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5468 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5479 else if (*p != '*') /* '*' means unknown lower bound */
5485 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5497 return 0; /* missing assembly name */
5498 if (!assembly_name_to_aname (&info->assembly, p))
5505 if (info->assembly.name)
5508 *w = 0; /* terminate class name */
5509 if (!info->name || !*info->name)
5511 /* add other consistency checks */
5516 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5523 image = mono_defaults.corlib;
5526 klass = mono_class_from_name_case (image, info->name_space, info->name);
5528 klass = mono_class_from_name (image, info->name_space, info->name);
5531 for (mod = info->nested; mod; mod = mod->next) {
5534 mono_class_init (klass);
5535 nested = klass->nested_classes;
5538 klass = nested->data;
5540 if (g_strcasecmp (klass->name, mod->data) == 0)
5543 if (strcmp (klass->name, mod->data) == 0)
5547 nested = nested->next;
5554 mono_class_init (klass);
5555 for (mod = info->modifiers; mod; mod = mod->next) {
5556 modval = GPOINTER_TO_UINT (mod->data);
5557 if (!modval) { /* byref: must be last modifier */
5558 return &klass->this_arg;
5559 } else if (modval == -1) {
5560 klass = mono_ptr_class_get (&klass->byval_arg);
5561 } else { /* array rank */
5562 klass = mono_array_class_get (klass, modval);
5564 mono_class_init (klass);
5567 return &klass->byval_arg;
5571 * mono_reflection_get_type:
5572 * @image: a metadata context
5573 * @info: type description structure
5574 * @ignorecase: flag for case-insensitive string compares
5576 * Build a MonoType from the type description in @info.
5581 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5584 MonoReflectionAssembly *assembly;
5588 type = mono_reflection_get_type_internal (image, info, ignorecase);
5591 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5594 /* Reconstruct the type name */
5595 fullName = g_string_new ("");
5596 if (info->name_space && (info->name_space [0] != '\0'))
5597 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5599 g_string_printf (fullName, info->name);
5600 for (mod = info->nested; mod; mod = mod->next)
5601 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5604 mono_domain_try_type_resolve (
5605 mono_domain_get (), fullName->str, NULL);
5606 if (assembly && (!image || (assembly->assembly->image == image))) {
5608 if (assembly->assembly->dynamic) {
5609 /* Enumerate all modules */
5610 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5614 if (abuilder->modules) {
5615 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5616 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5617 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5623 if (!type && abuilder->loaded_modules) {
5624 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5625 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5626 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5633 type = mono_reflection_get_type_internal (assembly->assembly->image,
5636 g_string_free (fullName, TRUE);
5641 * mono_reflection_type_from_name:
5643 * @image: a metadata context (can be NULL).
5645 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5646 * it defaults to get the type from @image or, if @image is NULL or loading
5647 * from it fails, uses corlib.
5651 mono_reflection_type_from_name (char *name, MonoImage *image)
5654 MonoTypeNameParse info;
5655 MonoAssembly *assembly;
5658 /* Make a copy since parse_type modifies its argument */
5659 tmp = g_strdup (name);
5661 /*g_print ("requested type %s\n", str);*/
5662 if (!mono_reflection_parse_type (tmp, &info)) {
5664 g_list_free (info.modifiers);
5665 g_list_free (info.nested);
5669 if (info.assembly.name) {
5670 assembly = mono_assembly_loaded (&info.assembly);
5672 /* then we must load the assembly ourselve - see #60439 */
5673 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5676 g_list_free (info.modifiers);
5677 g_list_free (info.nested);
5681 image = assembly->image;
5682 } else if (image == NULL) {
5683 image = mono_defaults.corlib;
5686 type = mono_reflection_get_type (image, &info, FALSE);
5687 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5688 image = mono_defaults.corlib;
5689 type = mono_reflection_get_type (image, &info, FALSE);
5693 g_list_free (info.modifiers);
5694 g_list_free (info.nested);
5699 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5701 int slen, type = t->type;
5706 case MONO_TYPE_BOOLEAN: {
5707 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5712 case MONO_TYPE_CHAR:
5714 case MONO_TYPE_I2: {
5715 guint16 *val = g_malloc (sizeof (guint16));
5720 #if SIZEOF_VOID_P == 4
5726 case MONO_TYPE_I4: {
5727 guint32 *val = g_malloc (sizeof (guint32));
5732 #if SIZEOF_VOID_P == 8
5733 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5738 case MONO_TYPE_I8: {
5739 guint64 *val = g_malloc (sizeof (guint64));
5744 case MONO_TYPE_VALUETYPE:
5745 if (t->data.klass->enumtype) {
5746 type = t->data.klass->enum_basetype->type;
5749 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5752 case MONO_TYPE_STRING:
5753 if (*p == (char)0xFF) {
5757 slen = mono_metadata_decode_value (p, &p);
5759 return mono_string_new_len (mono_domain_get (), p, slen);
5760 case MONO_TYPE_CLASS: {
5763 if (*p == (char)0xFF) {
5768 slen = mono_metadata_decode_value (p, &p);
5769 n = g_memdup (p, slen + 1);
5771 t = mono_reflection_type_from_name (n, image);
5773 g_warning ("Cannot load type '%s'", n);
5777 return mono_type_get_object (mono_domain_get (), t);
5781 case MONO_TYPE_OBJECT: {
5784 MonoClass *subc = NULL;
5789 } else if (subt == 0x0E) {
5790 type = MONO_TYPE_STRING;
5792 } else if (subt == 0x55) {
5795 slen = mono_metadata_decode_value (p, &p);
5796 n = g_memdup (p, slen + 1);
5798 t = mono_reflection_type_from_name (n, image);
5800 g_warning ("Cannot load type '%s'", n);
5803 subc = mono_class_from_mono_type (t);
5804 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5805 MonoType simple_type = {{0}};
5806 simple_type.type = subt;
5807 subc = mono_class_from_mono_type (&simple_type);
5809 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5811 val = load_cattr_value (image, &subc->byval_arg, p, end);
5812 obj = mono_object_new (mono_domain_get (), subc);
5813 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5817 case MONO_TYPE_SZARRAY:
5820 guint32 i, alen, basetype;
5823 if (alen == 0xffffffff) {
5827 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5828 basetype = t->data.klass->byval_arg.type;
5833 case MONO_TYPE_BOOLEAN:
5834 for (i=0;i<alen;i++)
5836 MonoBoolean val=*p++;
5837 mono_array_set(arr,MonoBoolean,i,val);
5840 case MONO_TYPE_CHAR:
5843 for (i=0;i<alen;i++)
5845 guint16 val=read16(p);
5846 mono_array_set(arr,guint16,i,val);
5853 for (i=0;i<alen;i++)
5855 guint32 val=read32(p);
5856 mono_array_set(arr,guint32,i,val);
5863 for (i=0;i<alen;i++)
5865 guint64 val=read64(p);
5866 mono_array_set(arr,guint64,i,val);
5870 case MONO_TYPE_CLASS:
5871 case MONO_TYPE_STRING:
5872 for (i = 0; i < alen; i++) {
5873 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5874 mono_array_set (arr, gpointer, i, item);
5878 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5884 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5890 type_is_reference (MonoType *type)
5892 switch (type->type) {
5893 case MONO_TYPE_BOOLEAN:
5894 case MONO_TYPE_CHAR:
5907 case MONO_TYPE_VALUETYPE:
5915 free_param_data (MonoMethodSignature *sig, void **params) {
5917 for (i = 0; i < sig->param_count; ++i) {
5918 if (!type_is_reference (sig->params [i]))
5919 g_free (params [i]);
5924 * Find the method index in the metadata methodDef table.
5925 * Later put these three helper methods in metadata and export them.
5928 find_method_index (MonoMethod *method) {
5929 MonoClass *klass = method->klass;
5932 for (i = 0; i < klass->method.count; ++i) {
5933 if (method == klass->methods [i])
5934 return klass->method.first + 1 + i;
5940 * Find the field index in the metadata FieldDef table.
5943 find_field_index (MonoClass *klass, MonoClassField *field) {
5946 for (i = 0; i < klass->field.count; ++i) {
5947 if (field == &klass->fields [i])
5948 return klass->field.first + 1 + i;
5954 * Find the property index in the metadata Property table.
5957 find_property_index (MonoClass *klass, MonoProperty *property) {
5960 for (i = 0; i < klass->property.count; ++i) {
5961 if (property == &klass->properties [i])
5962 return klass->property.first + 1 + i;
5968 * Find the event index in the metadata Event table.
5971 find_event_index (MonoClass *klass, MonoEvent *event) {
5974 for (i = 0; i < klass->event.count; ++i) {
5975 if (event == &klass->events [i])
5976 return klass->event.first + 1 + i;
5982 create_custom_attr (MonoImage *image, MonoMethod *method,
5983 const char *data, guint32 len)
5985 const char *p = data;
5987 guint32 i, j, num_named;
5991 mono_class_init (method->klass);
5994 attr = mono_object_new (mono_domain_get (), method->klass);
5995 mono_runtime_invoke (method, attr, NULL, NULL);
5999 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6002 /*g_print ("got attr %s\n", method->klass->name);*/
6004 params = g_new (void*, method->signature->param_count);
6008 for (i = 0; i < method->signature->param_count; ++i) {
6009 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6013 attr = mono_object_new (mono_domain_get (), method->klass);
6014 mono_runtime_invoke (method, attr, params, NULL);
6015 free_param_data (method->signature, params);
6017 num_named = read16 (named);
6019 for (j = 0; j < num_named; j++) {
6021 char *name, named_type, data_type;
6022 named_type = *named++;
6023 data_type = *named++; /* type of data */
6024 if (data_type == 0x55) {
6027 type_len = mono_metadata_decode_blob_size (named, &named);
6028 type_name = g_malloc (type_len + 1);
6029 memcpy (type_name, named, type_len);
6030 type_name [type_len] = 0;
6032 /* FIXME: lookup the type and check type consistency */
6033 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6034 /* this seems to be the type of the element of the array */
6035 /* g_print ("skipping 0x%02x after prop\n", *named); */
6038 name_len = mono_metadata_decode_blob_size (named, &named);
6039 name = g_malloc (name_len + 1);
6040 memcpy (name, named, name_len);
6041 name [name_len] = 0;
6043 if (named_type == 0x53) {
6044 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6045 void *val = load_cattr_value (image, field->type, named, &named);
6046 mono_field_set_value (attr, field, val);
6047 if (!type_is_reference (field->type))
6049 } else if (named_type == 0x54) {
6052 MonoType *prop_type;
6054 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6055 /* can we have more that 1 arg in a custom attr named property? */
6056 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6057 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6058 mono_property_set_value (prop, attr, pparams, NULL);
6059 if (!type_is_reference (prop_type))
6060 g_free (pparams [0]);
6069 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6076 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6077 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6078 for (i = 0; i < cinfo->num_attrs; ++i) {
6079 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6080 mono_array_set (result, gpointer, i, attr);
6086 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6088 guint32 mtoken, i, len;
6089 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6091 MonoCustomAttrInfo *ainfo;
6092 GList *tmp, *list = NULL;
6095 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6097 i = mono_metadata_custom_attrs_from_index (image, idx);
6101 while (i < ca->rows) {
6102 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6104 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6107 len = g_list_length (list);
6110 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6111 ainfo->num_attrs = len;
6112 ainfo->image = image;
6113 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6114 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6115 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6116 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6117 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6118 mtoken |= MONO_TOKEN_METHOD_DEF;
6120 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6121 mtoken |= MONO_TOKEN_MEMBER_REF;
6124 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6127 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6128 if (!ainfo->attrs [i].ctor)
6129 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6130 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6131 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6132 ainfo->attrs [i].data = data;
6140 mono_custom_attrs_from_method (MonoMethod *method)
6142 MonoCustomAttrInfo *cinfo;
6145 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6147 idx = find_method_index (method);
6148 idx <<= MONO_CUSTOM_ATTR_BITS;
6149 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6150 return mono_custom_attrs_from_index (method->klass->image, idx);
6154 mono_custom_attrs_from_class (MonoClass *klass)
6156 MonoCustomAttrInfo *cinfo;
6159 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6161 idx = mono_metadata_token_index (klass->type_token);
6162 idx <<= MONO_CUSTOM_ATTR_BITS;
6163 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6164 return mono_custom_attrs_from_index (klass->image, idx);
6168 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6170 MonoCustomAttrInfo *cinfo;
6173 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6175 idx = 1; /* there is only one assembly */
6176 idx <<= MONO_CUSTOM_ATTR_BITS;
6177 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6178 return mono_custom_attrs_from_index (assembly->image, idx);
6181 static MonoCustomAttrInfo*
6182 mono_custom_attrs_from_module (MonoImage *image)
6184 MonoCustomAttrInfo *cinfo;
6187 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6189 idx = 1; /* there is only one module */
6190 idx <<= MONO_CUSTOM_ATTR_BITS;
6191 idx |= MONO_CUSTOM_ATTR_MODULE;
6192 return mono_custom_attrs_from_index (image, idx);
6196 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6198 MonoCustomAttrInfo *cinfo;
6201 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6203 idx = find_property_index (klass, property);
6204 idx <<= MONO_CUSTOM_ATTR_BITS;
6205 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6206 return mono_custom_attrs_from_index (klass->image, idx);
6210 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6212 MonoCustomAttrInfo *cinfo;
6215 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6217 idx = find_event_index (klass, event);
6218 idx <<= MONO_CUSTOM_ATTR_BITS;
6219 idx |= MONO_CUSTOM_ATTR_EVENT;
6220 return mono_custom_attrs_from_index (klass->image, idx);
6224 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6226 MonoCustomAttrInfo *cinfo;
6229 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6231 idx = find_field_index (klass, field);
6232 idx <<= MONO_CUSTOM_ATTR_BITS;
6233 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6234 return mono_custom_attrs_from_index (klass->image, idx);
6238 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6241 guint32 i, idx, method_index;
6242 guint32 param_list, param_last, param_pos, found;
6244 MonoReflectionMethodAux *aux;
6246 if (method->klass->image->dynamic) {
6247 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6248 if (!aux || !aux->param_cattr)
6250 return aux->param_cattr [param];
6253 image = method->klass->image;
6254 method_index = find_method_index (method);
6255 ca = &image->tables [MONO_TABLE_METHOD];
6257 if (method->klass->generic_inst || method->klass->gen_params ||
6258 method->signature->generic_param_count) {
6259 /* FIXME FIXME FIXME */
6263 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6264 if (method_index == ca->rows) {
6265 ca = &image->tables [MONO_TABLE_PARAM];
6266 param_last = ca->rows + 1;
6268 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6269 ca = &image->tables [MONO_TABLE_PARAM];
6272 for (i = param_list; i < param_last; ++i) {
6273 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6274 if (param_pos == param) {
6282 idx <<= MONO_CUSTOM_ATTR_BITS;
6283 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6284 return mono_custom_attrs_from_index (image, idx);
6288 * mono_reflection_get_custom_attrs:
6289 * @obj: a reflection object handle
6291 * Return an array with all the custom attributes defined of the
6292 * reflection handle @obj. The objects are fully build.
6295 mono_reflection_get_custom_attrs (MonoObject *obj)
6299 MonoCustomAttrInfo *cinfo = NULL;
6301 MONO_ARCH_SAVE_REGS;
6303 klass = obj->vtable->klass;
6304 /* FIXME: need to handle: Module */
6305 if (klass == mono_defaults.monotype_class) {
6306 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6307 klass = mono_class_from_mono_type (rtype->type);
6308 cinfo = mono_custom_attrs_from_class (klass);
6309 } else if (strcmp ("Assembly", klass->name) == 0) {
6310 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6311 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6312 } else if (strcmp ("Module", klass->name) == 0) {
6313 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6314 cinfo = mono_custom_attrs_from_module (module->image);
6315 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6316 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6317 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6318 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6319 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6320 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6321 } else if (strcmp ("MonoField", klass->name) == 0) {
6322 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6323 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6324 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6325 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6326 cinfo = mono_custom_attrs_from_method (rmethod->method);
6327 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6328 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6329 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6330 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6331 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6332 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6333 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6334 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6335 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6336 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6337 } else { /* handle other types here... */
6338 g_error ("get custom attrs not yet supported for %s", klass->name);
6342 result = mono_custom_attrs_construct (cinfo);
6344 mono_custom_attrs_free (cinfo);
6346 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6347 result = mono_array_new (mono_domain_get (), klass, 0);
6353 static MonoMethodSignature*
6354 parameters_to_signature (MonoArray *parameters) {
6355 MonoMethodSignature *sig;
6358 count = parameters? mono_array_length (parameters): 0;
6360 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6361 sig->param_count = count;
6362 sig->sentinelpos = -1; /* FIXME */
6363 for (i = 0; i < count; ++i) {
6364 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6365 sig->params [i] = pt->type;
6370 static MonoMethodSignature*
6371 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6372 MonoMethodSignature *sig;
6374 sig = parameters_to_signature (ctor->parameters);
6375 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6376 sig->ret = &mono_defaults.void_class->byval_arg;
6380 static MonoMethodSignature*
6381 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6382 MonoMethodSignature *sig;
6384 sig = parameters_to_signature (method->parameters);
6385 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6386 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6387 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6391 static MonoMethodSignature*
6392 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6393 MonoMethodSignature *sig;
6395 sig = parameters_to_signature (method->parameters);
6396 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6397 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6398 sig->generic_param_count = 0;
6403 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6405 MonoClass *klass = mono_object_class (prop);
6406 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6407 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6408 *name = mono_string_to_utf8 (pb->name);
6409 *type = pb->type->type;
6411 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6412 *name = g_strdup (p->property->name);
6413 if (p->property->get)
6414 *type = p->property->get->signature->ret;
6416 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6421 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6423 MonoClass *klass = mono_object_class (field);
6424 if (strcmp (klass->name, "FieldBuilder") == 0) {
6425 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6426 *name = mono_string_to_utf8 (fb->name);
6427 *type = fb->type->type;
6429 MonoReflectionField *f = (MonoReflectionField *)field;
6430 *name = g_strdup (f->field->name);
6431 *type = f->field->type;
6436 * Encode a value in a custom attribute stream of bytes.
6437 * The value to encode is either supplied as an object in argument val
6438 * (valuetypes are boxed), or as a pointer to the data in the
6440 * @type represents the type of the value
6441 * @buffer is the start of the buffer
6442 * @p the current position in the buffer
6443 * @buflen contains the size of the buffer and is used to return the new buffer size
6444 * if this needs to be realloced.
6445 * @retbuffer and @retp return the start and the position of the buffer
6448 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6450 MonoTypeEnum simple_type;
6452 if ((p-buffer) + 10 >= *buflen) {
6455 newbuf = g_realloc (buffer, *buflen);
6456 p = newbuf + (p-buffer);
6460 argval = ((char*)arg + sizeof (MonoObject));
6461 simple_type = type->type;
6463 switch (simple_type) {
6464 case MONO_TYPE_BOOLEAN:
6469 case MONO_TYPE_CHAR:
6472 swap_with_size (p, argval, 2, 1);
6478 swap_with_size (p, argval, 4, 1);
6484 swap_with_size (p, argval, 8, 1);
6487 case MONO_TYPE_VALUETYPE:
6488 if (type->data.klass->enumtype) {
6489 simple_type = type->data.klass->enum_basetype->type;
6492 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6495 case MONO_TYPE_STRING: {
6502 str = mono_string_to_utf8 ((MonoString*)arg);
6503 slen = strlen (str);
6504 if ((p-buffer) + 10 + slen >= *buflen) {
6508 newbuf = g_realloc (buffer, *buflen);
6509 p = newbuf + (p-buffer);
6512 mono_metadata_encode_value (slen, p, &p);
6513 memcpy (p, str, slen);
6518 case MONO_TYPE_CLASS: {
6526 k = mono_object_class (arg);
6527 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6528 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6529 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6531 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6532 slen = strlen (str);
6533 if ((p-buffer) + 10 + slen >= *buflen) {
6537 newbuf = g_realloc (buffer, *buflen);
6538 p = newbuf + (p-buffer);
6541 mono_metadata_encode_value (slen, p, &p);
6542 memcpy (p, str, slen);
6547 case MONO_TYPE_SZARRAY: {
6549 MonoClass *eclass, *arg_eclass;
6552 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6555 len = mono_array_length ((MonoArray*)arg);
6557 *p++ = (len >> 8) & 0xff;
6558 *p++ = (len >> 16) & 0xff;
6559 *p++ = (len >> 24) & 0xff;
6561 *retbuffer = buffer;
6562 eclass = type->data.klass;
6563 arg_eclass = mono_object_class (arg)->element_class;
6564 if (eclass->valuetype && arg_eclass->valuetype) {
6565 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6566 int elsize = mono_class_array_element_size (eclass);
6567 for (i = 0; i < len; ++i) {
6568 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6572 for (i = 0; i < len; ++i) {
6573 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6578 /* it may be a boxed value or a Type */
6579 case MONO_TYPE_OBJECT: {
6580 MonoClass *klass = mono_object_class (arg);
6584 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6587 } else if (klass->enumtype) {
6589 } else if (klass == mono_defaults.string_class) {
6590 simple_type = MONO_TYPE_STRING;
6593 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6594 *p++ = simple_type = klass->byval_arg.type;
6597 g_error ("unhandled type in custom attr");
6599 str = type_get_qualified_name (klass->enum_basetype, NULL);
6600 slen = strlen (str);
6601 if ((p-buffer) + 10 + slen >= *buflen) {
6605 newbuf = g_realloc (buffer, *buflen);
6606 p = newbuf + (p-buffer);
6609 mono_metadata_encode_value (slen, p, &p);
6610 memcpy (p, str, slen);
6613 simple_type = klass->enum_basetype->type;
6617 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6620 *retbuffer = buffer;
6624 * mono_reflection_get_custom_attrs_blob:
6625 * @ctor: custom attribute constructor
6626 * @ctorArgs: arguments o the constructor
6632 * Creates the blob of data that needs to be saved in the metadata and that represents
6633 * the custom attributed described by @ctor, @ctorArgs etc.
6634 * Returns: a Byte array representing the blob of data.
6637 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6640 MonoMethodSignature *sig;
6645 MONO_ARCH_SAVE_REGS;
6647 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6648 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6650 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6652 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6654 p = buffer = g_malloc (buflen);
6655 /* write the prolog */
6658 for (i = 0; i < sig->param_count; ++i) {
6659 arg = mono_array_get (ctorArgs, MonoObject*, i);
6660 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6664 i += mono_array_length (properties);
6666 i += mono_array_length (fields);
6668 *p++ = (i >> 8) & 0xff;
6671 for (i = 0; i < mono_array_length (properties); ++i) {
6676 prop = mono_array_get (properties, gpointer, i);
6677 get_prop_name_and_type (prop, &pname, &ptype);
6678 *p++ = 0x54; /* PROPERTY signature */
6680 /* Preallocate a large enough buffer */
6681 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6682 char *str = type_get_qualified_name (ptype, NULL);
6688 len += strlen (pname);
6690 if ((p-buffer) + 20 + len >= buflen) {
6694 newbuf = g_realloc (buffer, buflen);
6695 p = newbuf + (p-buffer);
6699 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6700 char *str = type_get_qualified_name (ptype, NULL);
6701 int slen = strlen (str);
6705 * This seems to be optional...
6708 mono_metadata_encode_value (slen, p, &p);
6709 memcpy (p, str, slen);
6713 mono_metadata_encode_value (ptype->type, p, &p);
6714 if (ptype->type == MONO_TYPE_SZARRAY)
6715 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6717 len = strlen (pname);
6718 mono_metadata_encode_value (len, p, &p);
6719 memcpy (p, pname, len);
6721 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6728 for (i = 0; i < mono_array_length (fields); ++i) {
6733 field = mono_array_get (fields, gpointer, i);
6734 get_field_name_and_type (field, &fname, &ftype);
6735 *p++ = 0x53; /* FIELD signature */
6736 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6737 char *str = type_get_qualified_name (ftype, NULL);
6738 int slen = strlen (str);
6739 if ((p-buffer) + 10 + slen >= buflen) {
6743 newbuf = g_realloc (buffer, buflen);
6744 p = newbuf + (p-buffer);
6749 * This seems to be optional...
6752 mono_metadata_encode_value (slen, p, &p);
6753 memcpy (p, str, slen);
6757 mono_metadata_encode_value (ftype->type, p, &p);
6758 if (ftype->type == MONO_TYPE_SZARRAY)
6759 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6761 len = strlen (fname);
6762 mono_metadata_encode_value (len, p, &p);
6763 memcpy (p, fname, len);
6765 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6770 g_assert (p - buffer <= buflen);
6771 buflen = p - buffer;
6772 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6773 p = mono_array_addr (result, char, 0);
6774 memcpy (p, buffer, buflen);
6776 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6782 * mono_reflection_setup_internal_class:
6783 * @tb: a TypeBuilder object
6785 * Creates a MonoClass that represents the TypeBuilder.
6786 * This is a trick that lets us simplify a lot of reflection code
6787 * (and will allow us to support Build and Run assemblies easier).
6790 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6792 MonoClass *klass, *parent;
6794 MONO_ARCH_SAVE_REGS;
6797 /* check so we can compile corlib correctly */
6798 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6799 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6800 parent = tb->parent->type->data.klass;
6802 parent = my_mono_class_from_mono_type (tb->parent->type);
6806 /* the type has already being created: it means we just have to change the parent */
6807 if (tb->type.type) {
6808 klass = mono_class_from_mono_type (tb->type.type);
6809 klass->parent = NULL;
6810 /* fool mono_class_setup_parent */
6811 g_free (klass->supertypes);
6812 klass->supertypes = NULL;
6813 mono_class_setup_parent (klass, parent);
6817 klass = g_new0 (MonoClass, 1);
6819 klass->image = &tb->module->dynamic_image->image;
6821 klass->inited = 1; /* we lie to the runtime */
6822 klass->name = mono_string_to_utf8 (tb->name);
6823 klass->name_space = mono_string_to_utf8 (tb->nspace);
6824 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6825 klass->flags = tb->attrs;
6827 klass->element_class = klass;
6828 klass->reflection_info = tb; /* need to pin. */
6830 /* Put into cache so mono_class_get () will find it */
6831 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6834 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6835 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6839 mono_class_setup_parent (klass, parent);
6840 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6841 const char *old_n = klass->name;
6842 /* trick to get relative numbering right when compiling corlib */
6843 klass->name = "BuildingObject";
6844 mono_class_setup_parent (klass, mono_defaults.object_class);
6845 klass->name = old_n;
6847 mono_class_setup_mono_type (klass);
6849 mono_class_setup_supertypes (klass);
6852 * FIXME: handle interfaces.
6855 tb->type.type = &klass->byval_arg;
6857 if (tb->nesting_type) {
6858 g_assert (tb->nesting_type->type);
6859 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6862 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6866 * mono_reflection_setup_generic_class:
6867 * @tb: a TypeBuilder object
6869 * Setup the generic class after all generic parameters have been added.
6872 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6877 MONO_ARCH_SAVE_REGS;
6879 klass = my_mono_class_from_mono_type (tb->type.type);
6881 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6883 if (klass->gen_params || (count == 0))
6886 klass->num_gen_params = count;
6887 klass->gen_params = g_new0 (MonoGenericParam, count);
6889 for (i = 0; i < count; i++) {
6890 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6891 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6896 * mono_reflection_create_internal_class:
6897 * @tb: a TypeBuilder object
6899 * Actually create the MonoClass that is associated with the TypeBuilder.
6902 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6906 MONO_ARCH_SAVE_REGS;
6908 klass = my_mono_class_from_mono_type (tb->type.type);
6910 if (klass->enumtype && klass->enum_basetype == NULL) {
6911 MonoReflectionFieldBuilder *fb;
6913 g_assert (tb->fields != NULL);
6914 g_assert (mono_array_length (tb->fields) >= 1);
6916 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6918 klass->enum_basetype = fb->type->type;
6919 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6920 if (!klass->element_class)
6921 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6922 klass->instance_size = klass->element_class->instance_size;
6923 klass->size_inited = 1;
6925 * this is almost safe to do with enums and it's needed to be able
6926 * to create objects of the enum type (for use in SetConstant).
6928 /* FIXME: Does this mean enums can't have method overrides ? */
6929 mono_class_setup_vtable (klass, NULL, 0);
6933 static MonoMarshalSpec*
6934 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6935 MonoReflectionMarshal *minfo)
6937 MonoMarshalSpec *res;
6939 res = g_new0 (MonoMarshalSpec, 1);
6940 res->native = minfo->type;
6942 switch (minfo->type) {
6943 case MONO_NATIVE_LPARRAY:
6944 res->data.array_data.elem_type = minfo->eltype;
6945 res->data.array_data.param_num = 0; /* Not yet */
6946 res->data.array_data.num_elem = minfo->count;
6949 case MONO_NATIVE_BYVALTSTR:
6950 case MONO_NATIVE_BYVALARRAY:
6951 res->data.array_data.num_elem = minfo->count;
6954 case MONO_NATIVE_CUSTOM:
6955 if (minfo->marshaltyperef)
6956 res->data.custom_data.custom_name =
6957 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6959 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6970 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6971 ReflectionMethodBuilder *rmb,
6972 MonoMethodSignature *sig)
6975 MonoMethodNormal *pm;
6976 MonoMarshalSpec **specs;
6977 MonoReflectionMethodAux *method_aux;
6980 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6981 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6982 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6985 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6987 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6989 pm = (MonoMethodNormal*)m;
6992 m->flags = rmb->attrs;
6993 m->iflags = rmb->iattrs;
6994 m->name = mono_string_to_utf8 (rmb->name);
6998 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7000 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7001 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7004 m->signature->pinvoke = 1;
7005 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7007 m->signature->pinvoke = 1;
7009 } else if (!m->klass->dummy &&
7010 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7011 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7012 MonoMethodHeader *header;
7014 gint32 max_stack, i;
7015 gint32 num_locals = 0;
7016 gint32 num_clauses = 0;
7020 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7021 code_size = rmb->ilgen->code_len;
7022 max_stack = rmb->ilgen->max_stack;
7023 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7024 if (rmb->ilgen->ex_handlers)
7025 num_clauses = method_count_clauses (rmb->ilgen);
7028 code = mono_array_addr (rmb->code, guint8, 0);
7029 code_size = mono_array_length (rmb->code);
7030 /* we probably need to run a verifier on the code... */
7040 header = g_malloc0 (sizeof (MonoMethodHeader) +
7041 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7042 header->code_size = code_size;
7043 header->code = g_malloc (code_size);
7044 memcpy ((char*)header->code, code, code_size);
7045 header->max_stack = max_stack;
7046 header->init_locals = rmb->init_locals;
7047 header->num_locals = num_locals;
7049 for (i = 0; i < num_locals; ++i) {
7050 MonoReflectionLocalBuilder *lb =
7051 mono_array_get (rmb->ilgen->locals,
7052 MonoReflectionLocalBuilder*, i);
7054 header->locals [i] = g_new0 (MonoType, 1);
7055 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7058 header->num_clauses = num_clauses;
7060 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7065 if (rmb->generic_params) {
7066 int count = mono_array_length (rmb->generic_params);
7067 header->gen_params = g_new0 (MonoGenericParam, count);
7068 for (i = 0; i < count; i++) {
7069 MonoReflectionGenericParam *gp =
7070 mono_array_get (rmb->generic_params,
7071 MonoReflectionGenericParam*, i);
7073 header->gen_params [i] = *gp->type.type->data.generic_param;
7077 pm->header = header;
7081 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7084 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7086 for (i = 0; i < rmb->nrefs; ++i)
7087 mw->data = g_list_append (mw->data, rmb->refs [i]);
7092 /* Parameter names */
7095 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7096 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7097 for (i = 0; i <= m->signature->param_count; ++i) {
7098 MonoReflectionParamBuilder *pb;
7099 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7101 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7103 if (!method_aux->param_cattr)
7104 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7105 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7111 /* Parameter marshalling */
7114 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7115 MonoReflectionParamBuilder *pb;
7116 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7117 if (pb->marshal_info) {
7119 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7120 specs [pb->position] =
7121 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7125 if (specs != NULL) {
7127 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7128 method_aux->param_marshall = specs;
7131 if (klass->image->dynamic && method_aux)
7132 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7138 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7140 ReflectionMethodBuilder rmb;
7141 MonoMethodSignature *sig;
7143 sig = ctor_builder_to_signature (mb);
7145 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7147 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7148 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7150 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7151 /* ilgen is no longer needed */
7159 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7161 ReflectionMethodBuilder rmb;
7162 MonoMethodSignature *sig;
7164 sig = method_builder_to_signature (mb);
7166 reflection_methodbuilder_from_method_builder (&rmb, mb);
7168 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7169 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7171 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7172 /* ilgen is no longer needed */
7178 static MonoClassField*
7179 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7181 MonoClassField *field;
7188 field = g_new0 (MonoClassField, 1);
7190 field->name = mono_string_to_utf8 (fb->name);
7192 /* FIXME: handle type modifiers */
7193 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7194 field->type->attrs = fb->attrs;
7196 field->type = fb->type->type;
7198 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7199 field->data = mono_array_addr (fb->rva_data, char, 0);
7200 if (fb->offset != -1)
7201 field->offset = fb->offset;
7202 field->parent = klass;
7204 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7206 if (fb->def_value) {
7207 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7208 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7209 field->def_value = g_new0 (MonoConstant, 1);
7210 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7211 /* Copy the data from the blob since it might get realloc-ed */
7212 p = assembly->blob.data + idx;
7213 len = mono_metadata_decode_blob_size (p, &p2);
7215 field->def_value->value = g_malloc (len);
7216 memcpy (field->def_value->value, p, len);
7223 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7227 MonoReflectionTypeBuilder *tb = NULL;
7228 MonoGenericInst *ginst;
7233 klass = mono_class_from_mono_type (type->type);
7234 if (!klass->gen_params && !klass->generic_inst &&
7235 !(klass->nested_in && klass->nested_in->gen_params))
7238 mono_loader_lock ();
7240 domain = mono_object_domain (type);
7242 ginst = g_new0 (MonoGenericInst, 1);
7244 if (!klass->generic_inst) {
7245 ginst->type_argc = type_argc;
7246 ginst->type_argv = types;
7248 for (i = 0; i < ginst->type_argc; ++i) {
7249 if (!ginst->is_open)
7250 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7253 ginst->generic_type = &klass->byval_arg;
7255 MonoGenericInst *kginst = klass->generic_inst;
7257 ginst->type_argc = kginst->type_argc;
7258 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7260 for (i = 0; i < ginst->type_argc; i++) {
7261 MonoType *t = kginst->type_argv [i];
7263 if (t->type == MONO_TYPE_VAR)
7264 t = types [t->data.generic_param->num];
7266 if (!ginst->is_open)
7267 ginst->is_open = mono_class_is_open_constructed_type (t);
7269 ginst->type_argv [i] = t;
7272 ginst->generic_type = kginst->generic_type;
7275 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7278 mono_loader_unlock ();
7282 ginst->context = g_new0 (MonoGenericContext, 1);
7283 ginst->context->ginst = ginst;
7285 geninst = g_new0 (MonoType, 1);
7286 geninst->type = MONO_TYPE_GENERICINST;
7287 geninst->data.generic_inst = ginst;
7289 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7290 tb = (MonoReflectionTypeBuilder *) type;
7292 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7293 ginst->is_dynamic = TRUE;
7294 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7295 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7296 MonoReflectionType *rgt = rgi->generic_type;
7298 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7299 tb = (MonoReflectionTypeBuilder *) rgt;
7301 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7302 ginst->is_dynamic = TRUE;
7304 icount = klass->interface_count;
7306 ginst->ifaces = g_new0 (MonoType *, icount);
7307 ginst->count_ifaces = icount;
7309 for (i = 0; i < icount; i++) {
7310 MonoReflectionType *itype;
7313 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7315 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7316 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7317 if (!ginst->ifaces [i])
7318 ginst->ifaces [i] = itype->type;
7321 mono_class_create_generic (ginst);
7323 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7325 mono_loader_unlock ();
7331 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7333 MonoClass *klass, *pklass = NULL;
7334 MonoReflectionType *parent = NULL;
7336 MonoReflectionTypeBuilder *tb = NULL;
7337 MonoGenericInst *ginst;
7340 domain = mono_object_domain (type);
7341 klass = mono_class_from_mono_type (type->type);
7343 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7344 tb = (MonoReflectionTypeBuilder *) type;
7347 parent = tb->parent;
7348 pklass = mono_class_from_mono_type (parent->type);
7351 pklass = klass->parent;
7353 parent = mono_type_get_object (domain, &pklass->byval_arg);
7356 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7360 ginst = geninst->data.generic_inst;
7362 if (pklass && pklass->generic_inst)
7363 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7368 MonoReflectionMethod*
7369 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7371 MonoMethod *method, *inflated;
7372 MonoReflectionMethodBuilder *mb = NULL;
7373 MonoGenericMethod *gmethod;
7374 MonoGenericContext *context;
7377 MONO_ARCH_SAVE_REGS;
7378 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7379 MonoReflectionTypeBuilder *tb;
7382 mb = (MonoReflectionMethodBuilder *) rmethod;
7383 tb = (MonoReflectionTypeBuilder *) mb->type;
7384 klass = mono_class_from_mono_type (tb->type.type);
7386 method = methodbuilder_to_mono_method (klass, mb);
7388 method = rmethod->method;
7390 count = method->signature->generic_param_count;
7391 if (count != mono_array_length (types))
7394 gmethod = g_new0 (MonoGenericMethod, 1);
7395 gmethod->mtype_argc = count;
7396 gmethod->mtype_argv = g_new0 (MonoType *, count);
7397 for (i = 0; i < count; i++) {
7398 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7399 gmethod->mtype_argv [i] = garg->type;
7402 context = g_new0 (MonoGenericContext, 1);
7403 context->ginst = method->klass->generic_inst;
7404 context->gmethod = gmethod;
7406 inflated = mono_class_inflate_generic_method (method, context, NULL);
7408 return mono_method_get_object (
7409 mono_object_domain (rmethod), inflated, NULL);
7413 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7415 MonoGenericMethod *gmethod;
7416 MonoGenericInst *ginst;
7417 MonoGenericContext *context;
7420 ginst = type->type.type->data.generic_inst;
7422 gmethod = g_new0 (MonoGenericMethod, 1);
7423 gmethod->reflection_info = obj;
7425 gmethod->mtype_argc = method->signature->generic_param_count;
7426 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7428 for (i = 0; i < gmethod->mtype_argc; i++) {
7429 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7430 MonoGenericParam *gparam = &mn->header->gen_params [i];
7432 g_assert (gparam->pklass);
7433 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7436 context = g_new0 (MonoGenericContext, 1);
7437 context->ginst = ginst;
7438 context->gmethod = gmethod;
7440 return mono_class_inflate_generic_method (method, context, ginst->klass);
7444 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7449 klass = mono_class_from_mono_type (type->type.type);
7451 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7452 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7453 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7454 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7455 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7456 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7457 method = ((MonoReflectionMethod *) obj)->method;
7459 method = NULL; /* prevent compiler warning */
7460 g_assert_not_reached ();
7463 return inflate_mono_method (type, method, obj);
7467 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7468 MonoArray *methods, MonoArray *ctors,
7469 MonoArray *fields, MonoArray *properties,
7472 MonoGenericInst *ginst;
7473 MonoDynamicGenericInst *dginst;
7474 MonoClass *klass, *gklass, *pklass;
7477 MONO_ARCH_SAVE_REGS;
7479 klass = mono_class_from_mono_type (type->type.type);
7480 ginst = type->type.type->data.generic_inst;
7482 if (ginst->initialized)
7485 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7487 gklass = mono_class_from_mono_type (ginst->generic_type);
7488 mono_class_init (gklass);
7491 pklass = mono_class_from_mono_type (ginst->parent);
7493 pklass = gklass->parent;
7495 mono_class_setup_parent (klass, pklass);
7497 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7498 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7499 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7500 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7501 dginst->count_events = events ? mono_array_length (events) : 0;
7503 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7504 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7505 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7506 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7507 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7509 for (i = 0; i < dginst->count_methods; i++) {
7510 MonoObject *obj = mono_array_get (methods, gpointer, i);
7512 dginst->methods [i] = inflate_method (type, obj);
7515 for (i = 0; i < dginst->count_ctors; i++) {
7516 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7518 dginst->ctors [i] = inflate_method (type, obj);
7521 for (i = 0; i < dginst->count_fields; i++) {
7522 MonoObject *obj = mono_array_get (fields, gpointer, i);
7523 MonoClassField *field;
7524 MonoInflatedField *ifield;
7526 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7527 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7528 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7529 field = ((MonoReflectionField *) obj)->field;
7531 field = NULL; /* prevent compiler warning */
7532 g_assert_not_reached ();
7535 ifield = g_new0 (MonoInflatedField, 1);
7536 ifield->generic_type = field->type;
7537 ifield->reflection_info = obj;
7539 dginst->fields [i] = *field;
7540 dginst->fields [i].generic_info = ifield;
7541 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7544 for (i = 0; i < dginst->count_properties; i++) {
7545 MonoObject *obj = mono_array_get (properties, gpointer, i);
7546 MonoProperty *property = &dginst->properties [i];
7548 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7549 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7551 property->parent = klass;
7552 property->attrs = pb->attrs;
7553 property->name = mono_string_to_utf8 (pb->name);
7555 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7557 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7558 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7559 *property = *((MonoReflectionProperty *) obj)->property;
7562 property->get = inflate_mono_method (type, property->get, NULL);
7564 property->set = inflate_mono_method (type, property->set, NULL);
7566 g_assert_not_reached ();
7569 for (i = 0; i < dginst->count_events; i++) {
7570 MonoObject *obj = mono_array_get (events, gpointer, i);
7571 MonoEvent *event = &dginst->events [i];
7573 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7574 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7576 event->parent = klass;
7577 event->attrs = eb->attrs;
7578 event->name = mono_string_to_utf8 (eb->name);
7580 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7581 if (eb->remove_method)
7582 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7583 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7584 *event = *((MonoReflectionEvent *) obj)->event;
7587 event->add = inflate_mono_method (type, event->add, NULL);
7589 event->remove = inflate_mono_method (type, event->remove, NULL);
7591 g_assert_not_reached ();
7594 ginst->initialized = TRUE;
7598 ensure_runtime_vtable (MonoClass *klass)
7600 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7601 int i, num, j, onum;
7602 MonoMethod **overrides;
7604 if (!tb || klass->wastypebuilder)
7607 ensure_runtime_vtable (klass->parent);
7609 num = tb->ctors? mono_array_length (tb->ctors): 0;
7610 num += tb->num_methods;
7611 klass->method.count = num;
7612 klass->methods = g_new (MonoMethod*, num);
7613 num = tb->ctors? mono_array_length (tb->ctors): 0;
7614 for (i = 0; i < num; ++i)
7615 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7616 num = tb->num_methods;
7618 for (i = 0; i < num; ++i)
7619 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7621 klass->wastypebuilder = TRUE;
7622 if (tb->interfaces) {
7623 klass->interface_count = mono_array_length (tb->interfaces);
7624 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7625 for (i = 0; i < klass->interface_count; ++i) {
7626 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7627 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7631 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7632 for (i = 0; i < klass->method.count; ++i)
7633 klass->methods [i]->slot = i;
7638 for (i = 0; i < tb->num_methods; ++i) {
7639 MonoReflectionMethodBuilder *mb =
7640 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7641 if (mb->override_method)
7646 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7650 for (i = 0; i < tb->num_methods; ++i) {
7651 MonoReflectionMethodBuilder *mb =
7652 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7653 if (mb->override_method) {
7654 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7655 overrides [onum * 2] =
7656 mb->override_method->method;
7657 overrides [onum * 2 + 1] =
7660 g_assert (mb->mhandle);
7667 mono_class_setup_vtable (klass, overrides, onum);
7671 typebuilder_setup_fields (MonoClass *klass)
7673 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7674 MonoReflectionFieldBuilder *fb;
7675 MonoClassField *field;
7680 klass->field.count = tb->num_fields;
7681 klass->field.first = 0;
7682 klass->field.last = klass->field.count;
7684 if (!klass->field.count)
7687 klass->fields = g_new0 (MonoClassField, klass->field.count);
7689 for (i = 0; i < klass->field.count; ++i) {
7690 fb = mono_array_get (tb->fields, gpointer, i);
7691 field = &klass->fields [i];
7692 field->name = mono_string_to_utf8 (fb->name);
7694 /* FIXME: handle type modifiers */
7695 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7696 field->type->attrs = fb->attrs;
7698 field->type = fb->type->type;
7700 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7701 field->data = mono_array_addr (fb->rva_data, char, 0);
7702 if (fb->offset != -1)
7703 field->offset = fb->offset;
7704 field->parent = klass;
7706 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7708 if (fb->def_value) {
7709 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7710 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7711 field->def_value = g_new0 (MonoConstant, 1);
7712 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7713 /* Copy the data from the blob since it might get realloc-ed */
7714 p = assembly->blob.data + idx;
7715 len = mono_metadata_decode_blob_size (p, &p2);
7717 field->def_value->value = g_malloc (len);
7718 memcpy (field->def_value->value, p, len);
7721 mono_class_layout_fields (klass);
7725 typebuilder_setup_properties (MonoClass *klass)
7727 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7728 MonoReflectionPropertyBuilder *pb;
7731 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7732 klass->property.first = 0;
7733 klass->property.last = klass->property.count;
7735 klass->properties = g_new0 (MonoProperty, klass->property.count);
7736 for (i = 0; i < klass->property.count; ++i) {
7737 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7738 klass->properties [i].parent = klass;
7739 klass->properties [i].attrs = pb->attrs;
7740 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7742 klass->properties [i].get = pb->get_method->mhandle;
7744 klass->properties [i].set = pb->set_method->mhandle;
7748 MonoReflectionEvent *
7749 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7751 MonoEvent *event = g_new0 (MonoEvent, 1);
7755 klass = my_mono_class_from_mono_type (tb->type.type);
7757 event->parent = klass;
7758 event->attrs = eb->attrs;
7759 event->name = mono_string_to_utf8 (eb->name);
7761 event->add = eb->add_method->mhandle;
7762 if (eb->remove_method)
7763 event->remove = eb->remove_method->mhandle;
7764 if (eb->raise_method)
7765 event->raise = eb->raise_method->mhandle;
7767 if (eb->other_methods) {
7768 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7769 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7770 MonoReflectionMethodBuilder *mb =
7771 mono_array_get (eb->other_methods,
7772 MonoReflectionMethodBuilder*, j);
7773 event->other [j] = mb->mhandle;
7777 return mono_event_get_object (mono_object_domain (tb), klass, event);
7781 typebuilder_setup_events (MonoClass *klass)
7783 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7784 MonoReflectionEventBuilder *eb;
7787 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7788 klass->event.first = 0;
7789 klass->event.last = klass->event.count;
7791 klass->events = g_new0 (MonoEvent, klass->event.count);
7792 for (i = 0; i < klass->event.count; ++i) {
7793 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7794 klass->events [i].parent = klass;
7795 klass->events [i].attrs = eb->attrs;
7796 klass->events [i].name = mono_string_to_utf8 (eb->name);
7798 klass->events [i].add = eb->add_method->mhandle;
7799 if (eb->remove_method)
7800 klass->events [i].remove = eb->remove_method->mhandle;
7801 if (eb->raise_method)
7802 klass->events [i].raise = eb->raise_method->mhandle;
7804 if (eb->other_methods) {
7805 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7806 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7807 MonoReflectionMethodBuilder *mb =
7808 mono_array_get (eb->other_methods,
7809 MonoReflectionMethodBuilder*, j);
7810 klass->events [i].other [j] = mb->mhandle;
7817 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7820 MonoReflectionType* res;
7822 MONO_ARCH_SAVE_REGS;
7824 klass = my_mono_class_from_mono_type (tb->type.type);
7826 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7829 * Fields to set in klass:
7830 * the various flags: delegate/unicode/contextbound etc.
7833 klass->flags = tb->attrs;
7835 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7836 /* No need to fully construct the type */
7837 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7839 /* enums are done right away */
7840 if (!klass->enumtype)
7841 ensure_runtime_vtable (klass);
7843 /* fields and object layout */
7844 if (klass->parent) {
7845 if (!klass->parent->size_inited)
7846 mono_class_init (klass->parent);
7847 klass->instance_size += klass->parent->instance_size;
7848 klass->class_size += klass->parent->class_size;
7849 klass->min_align = klass->parent->min_align;
7851 klass->instance_size = sizeof (MonoObject);
7852 klass->min_align = 1;
7855 /* FIXME: handle packing_size and instance_size */
7856 typebuilder_setup_fields (klass);
7858 typebuilder_setup_properties (klass);
7860 typebuilder_setup_events (klass);
7862 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7863 /* with enums res == tb: need to fix that. */
7864 if (!klass->enumtype)
7865 g_assert (res != (MonoReflectionType*)tb);
7870 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7872 MonoGenericParam *param;
7875 MONO_ARCH_SAVE_REGS;
7877 param = g_new0 (MonoGenericParam, 1);
7879 param->method = NULL;
7880 param->name = mono_string_to_utf8 (gparam->name);
7881 param->num = gparam->index;
7883 image = &gparam->tbuilder->module->dynamic_image->image;
7884 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7886 param->pklass->reflection_info = gparam;
7888 gparam->type.type = g_new0 (MonoType, 1);
7889 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7890 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7891 gparam->type.type->data.generic_param = param;
7895 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7897 MonoDynamicImage *assembly = sig->module->dynamic_image;
7898 guint32 na = mono_array_length (sig->arguments);
7903 MONO_ARCH_SAVE_REGS;
7905 p = buf = g_malloc (10 + na * 10);
7907 mono_metadata_encode_value (0x07, p, &p);
7908 mono_metadata_encode_value (na, p, &p);
7909 for (i = 0; i < na; ++i) {
7910 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7911 encode_reflection_type (assembly, type, p, &p);
7915 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7916 p = mono_array_addr (result, char, 0);
7917 memcpy (p, buf, buflen);
7924 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7926 MonoDynamicImage *assembly = sig->module->dynamic_image;
7927 guint32 na = mono_array_length (sig->arguments);
7932 MONO_ARCH_SAVE_REGS;
7934 p = buf = g_malloc (10 + na * 10);
7936 mono_metadata_encode_value (0x06, p, &p);
7937 for (i = 0; i < na; ++i) {
7938 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7939 encode_reflection_type (assembly, type, p, &p);
7943 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7944 p = mono_array_addr (result, char, 0);
7945 memcpy (p, buf, buflen);
7952 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7954 ReflectionMethodBuilder rmb;
7955 MonoMethodSignature *sig;
7958 sig = dynamic_method_to_signature (mb);
7960 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7963 * Resolve references.
7965 rmb.nrefs = mb->nrefs;
7966 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7967 for (i = 0; i < mb->nrefs; ++i) {
7968 gpointer ref = resolve_object (mb->module->image,
7969 mono_array_get (mb->refs, MonoObject*, i));
7972 mono_raise_exception (mono_get_exception_type_load (NULL));
7979 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7983 /* ilgen is no longer needed */
7988 * mono_reflection_lookup_dynamic_token:
7990 * Finish the Builder object pointed to by TOKEN and return the corresponding
7991 * runtime structure.
7994 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7996 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7999 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8002 return resolve_object (image, obj);
8006 resolve_object (MonoImage *image, MonoObject *obj)
8008 gpointer result = NULL;
8010 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8011 result = mono_string_intern ((MonoString*)obj);
8014 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8015 MonoReflectionType *tb = (MonoReflectionType*)obj;
8016 result = mono_class_from_mono_type (tb->type);
8019 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8020 result = ((MonoReflectionMethod*)obj)->method;
8023 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8024 result = ((MonoReflectionMethod*)obj)->method;
8027 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8028 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8029 result = mb->mhandle;
8031 /* Type is not yet created */
8032 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8034 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8037 * Hopefully this has been filled in by calling CreateType() on the
8041 * TODO: This won't work if the application finishes another
8042 * TypeBuilder instance instead of this one.
8044 result = mb->mhandle;
8047 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8048 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8050 result = cb->mhandle;
8052 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8054 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8055 result = cb->mhandle;
8058 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8059 result = ((MonoReflectionField*)obj)->field;
8062 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8063 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8064 result = fb->handle;
8067 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8069 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8070 result = fb->handle;
8073 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8074 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8077 klass = tb->type.type->data.klass;
8078 if (klass->wastypebuilder) {
8079 /* Already created */
8083 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8084 result = tb->type.type->data.klass;
8088 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8089 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8090 MonoMethodSignature *sig;
8093 if (helper->arguments)
8094 nargs = mono_array_length (helper->arguments);
8098 sig = mono_metadata_signature_alloc (image, nargs);
8099 sig->explicit_this = helper->call_conv & 64;
8100 sig->hasthis = helper->call_conv & 32;
8102 if (helper->call_conv == 0) /* unmanaged */
8103 sig->call_convention = helper->unmanaged_call_conv - 1;
8105 if (helper->call_conv & 0x02)
8106 sig->call_convention = MONO_CALL_VARARG;
8108 sig->call_convention = MONO_CALL_DEFAULT;
8110 sig->param_count = nargs;
8111 /* TODO: Copy type ? */
8112 sig->ret = helper->return_type->type;
8113 for (i = 0; i < nargs; ++i) {
8114 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8115 sig->params [i] = rt->type;
8121 g_print (obj->vtable->klass->name);
8122 g_assert_not_reached ();