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] ? (char *)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) &&
2720 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2721 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2723 alloc_table (table, table->rows);
2724 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2725 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2726 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2727 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2730 /* handle interfaces */
2731 if (tb->interfaces) {
2732 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2734 table->rows += mono_array_length (tb->interfaces);
2735 alloc_table (table, table->rows);
2736 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2737 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2738 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2739 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2740 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2741 values += MONO_INTERFACEIMPL_SIZE;
2745 /* handle generic parameters */
2746 if (tb->generic_params) {
2747 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2748 table->rows += mono_array_length (tb->generic_params);
2749 alloc_table (table, table->rows);
2750 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2751 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2753 mono_image_get_generic_param_info (
2754 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2760 table = &assembly->tables [MONO_TABLE_FIELD];
2761 table->rows += tb->num_fields;
2762 alloc_table (table, table->rows);
2763 for (i = 0; i < tb->num_fields; ++i)
2764 mono_image_get_field_info (
2765 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2768 /* handle constructors */
2770 table = &assembly->tables [MONO_TABLE_METHOD];
2771 table->rows += mono_array_length (tb->ctors);
2772 alloc_table (table, table->rows);
2773 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2774 mono_image_get_ctor_info (domain,
2775 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2778 /* handle methods */
2780 table = &assembly->tables [MONO_TABLE_METHOD];
2781 table->rows += tb->num_methods;
2782 alloc_table (table, table->rows);
2783 for (i = 0; i < tb->num_methods; ++i)
2784 mono_image_get_method_info (
2785 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2788 /* Do the same with properties etc.. */
2789 if (tb->events && mono_array_length (tb->events)) {
2790 table = &assembly->tables [MONO_TABLE_EVENT];
2791 table->rows += mono_array_length (tb->events);
2792 alloc_table (table, table->rows);
2793 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2795 alloc_table (table, table->rows);
2796 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2797 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2798 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2799 for (i = 0; i < mono_array_length (tb->events); ++i)
2800 mono_image_get_event_info (
2801 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2803 if (tb->properties && mono_array_length (tb->properties)) {
2804 table = &assembly->tables [MONO_TABLE_PROPERTY];
2805 table->rows += mono_array_length (tb->properties);
2806 alloc_table (table, table->rows);
2807 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2809 alloc_table (table, table->rows);
2810 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2811 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2812 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2813 for (i = 0; i < mono_array_length (tb->properties); ++i)
2814 mono_image_get_property_info (
2815 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2818 mono_image_add_decl_security (assembly,
2819 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2823 MonoDynamicTable *ntable;
2825 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2826 ntable->rows += mono_array_length (tb->subtypes);
2827 alloc_table (ntable, ntable->rows);
2828 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2830 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2831 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2833 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2834 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2835 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2836 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2837 mono_string_to_utf8 (tb->name), tb->table_idx,
2838 ntable->next_idx, ntable->rows);*/
2839 values += MONO_NESTED_CLASS_SIZE;
2846 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2850 g_ptr_array_add (types, type);
2852 if (!type->subtypes)
2855 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2856 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2857 collect_types (types, subtype);
2862 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1,
2863 MonoReflectionTypeBuilder **type2)
2865 if ((*type1)->table_idx < (*type2)->table_idx)
2868 if ((*type1)->table_idx > (*type2)->table_idx)
2875 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2880 for (i = 0; i < mono_array_length (pinfo); ++i) {
2881 MonoReflectionParamBuilder *pb;
2882 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2885 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2890 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2893 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2895 for (i = 0; i < tb->num_fields; ++i) {
2896 MonoReflectionFieldBuilder* fb;
2897 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2898 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2902 for (i = 0; i < mono_array_length (tb->events); ++i) {
2903 MonoReflectionEventBuilder* eb;
2904 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2905 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2908 if (tb->properties) {
2909 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2910 MonoReflectionPropertyBuilder* pb;
2911 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2912 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2916 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2917 MonoReflectionCtorBuilder* cb;
2918 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2919 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2920 params_add_cattrs (assembly, cb->pinfo);
2925 for (i = 0; i < tb->num_methods; ++i) {
2926 MonoReflectionMethodBuilder* mb;
2927 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2928 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2929 params_add_cattrs (assembly, mb->pinfo);
2934 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2935 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2940 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2943 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
2945 /* no types in the module */
2949 for (i = 0; i < mb->num_types; ++i)
2950 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2954 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2955 MonoDynamicImage *assembly)
2957 MonoDynamicTable *table;
2961 char *b = blob_size;
2964 table = &assembly->tables [MONO_TABLE_FILE];
2966 alloc_table (table, table->rows);
2967 values = table->values + table->next_idx * MONO_FILE_SIZE;
2968 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2969 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2970 if (module->image->dynamic) {
2971 /* This depends on the fact that the main module is emitted last */
2972 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2973 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2977 path = g_strdup (module->image->name);
2979 mono_sha1_get_digest_from_file (path, hash);
2982 mono_metadata_encode_value (20, b, &b);
2983 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2984 mono_image_add_stream_data (&assembly->blob, hash, 20);
2989 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2991 MonoDynamicTable *table;
2995 table = &assembly->tables [MONO_TABLE_MODULE];
2996 mb->table_idx = table->next_idx ++;
2997 name = mono_string_to_utf8 (mb->module.name);
2998 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3000 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3003 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3004 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3005 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3009 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3010 guint32 module_index, guint32 parent_index,
3011 MonoDynamicImage *assembly)
3013 MonoDynamicTable *table;
3017 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3018 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3021 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3023 alloc_table (table, table->rows);
3024 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3026 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3027 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3028 if (klass->nested_in)
3029 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3031 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3032 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3033 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3035 res = table->next_idx;
3039 /* Emit nested types */
3040 if (klass->nested_classes) {
3043 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3044 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3051 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3052 guint32 module_index, guint32 parent_index,
3053 MonoDynamicImage *assembly)
3058 klass = mono_class_from_mono_type (tb->type.type);
3060 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3062 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3063 parent_index, assembly);
3067 * We need to do this ourselves since klass->nested_classes is not set up.
3070 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3071 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3076 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3077 guint32 module_index,
3078 MonoDynamicImage *assembly)
3080 MonoImage *image = module->image;
3084 t = &image->tables [MONO_TABLE_TYPEDEF];
3086 for (i = 0; i < t->rows; ++i) {
3087 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3089 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3090 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3094 #define align_pointer(base,p)\
3096 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3098 (p) += 4 - (__diff & 3);\
3102 compare_semantics (const void *a, const void *b)
3104 const guint32 *a_values = a;
3105 const guint32 *b_values = b;
3106 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3109 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3113 compare_custom_attrs (const void *a, const void *b)
3115 const guint32 *a_values = a;
3116 const guint32 *b_values = b;
3118 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3122 compare_field_marshal (const void *a, const void *b)
3124 const guint32 *a_values = a;
3125 const guint32 *b_values = b;
3127 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3131 compare_nested (const void *a, const void *b)
3133 const guint32 *a_values = a;
3134 const guint32 *b_values = b;
3136 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3140 pad_heap (MonoDynamicStream *sh)
3142 if (sh->index & 3) {
3143 int sz = 4 - (sh->index & 3);
3144 memset (sh->data + sh->index, 0, sz);
3150 * build_compressed_metadata() fills in the blob of data that represents the
3151 * raw metadata as it will be saved in the PE file. The five streams are output
3152 * and the metadata tables are comnpressed from the guint32 array representation,
3153 * to the compressed on-disk format.
3156 build_compressed_metadata (MonoDynamicImage *assembly)
3158 MonoDynamicTable *table;
3160 guint64 valid_mask = 0;
3161 guint64 sorted_mask;
3162 guint32 heapt_size = 0;
3163 guint32 meta_size = 256; /* allow for header and other stuff */
3164 guint32 table_offset;
3165 guint32 ntables = 0;
3174 MonoDynamicStream *stream;
3177 stream_desc[0].name = "#~"; stream_desc[0].stream = &assembly->tstream;
3178 stream_desc[1].name = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3179 stream_desc[2].name = "#US"; stream_desc[2].stream = &assembly->us;
3180 stream_desc[3].name = "#Blob"; stream_desc[3].stream = &assembly->blob;
3181 stream_desc[4].name = "#GUID"; stream_desc[4].stream = &assembly->guid;
3183 /* tables that are sorted */
3184 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3185 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3186 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3187 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3188 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3189 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3191 /* Compute table sizes */
3192 /* the MonoImage has already been created in mono_image_basic_init() */
3193 meta = &assembly->image;
3195 /* sizes should be multiple of 4 */
3196 pad_heap (&assembly->blob);
3197 pad_heap (&assembly->guid);
3198 pad_heap (&assembly->sheap);
3199 pad_heap (&assembly->us);
3201 /* Setup the info used by compute_sizes () */
3202 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3203 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3204 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3206 meta_size += assembly->blob.index;
3207 meta_size += assembly->guid.index;
3208 meta_size += assembly->sheap.index;
3209 meta_size += assembly->us.index;
3211 for (i=0; i < 64; ++i)
3212 meta->tables [i].rows = assembly->tables [i].rows;
3214 for (i = 0; i < 64; i++){
3215 if (meta->tables [i].rows == 0)
3217 valid_mask |= (guint64)1 << i;
3219 meta->tables [i].row_size = mono_metadata_compute_size (
3220 meta, i, &meta->tables [i].size_bitfield);
3221 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3223 heapt_size += 24; /* #~ header size */
3224 heapt_size += ntables * 4;
3225 /* make multiple of 4 */
3228 meta_size += heapt_size;
3229 meta->raw_metadata = g_malloc0 (meta_size);
3230 p = meta->raw_metadata;
3231 /* the metadata signature */
3232 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3233 /* version numbers and 4 bytes reserved */
3234 int16val = (guint16*)p;
3235 *int16val++ = GUINT16_TO_LE (1);
3236 *int16val = GUINT16_TO_LE (1);
3238 /* version string */
3239 int32val = (guint32*)p;
3240 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3242 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3243 p += GUINT32_FROM_LE (*int32val);
3244 align_pointer (meta->raw_metadata, p);
3245 int16val = (guint16*)p;
3246 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3247 *int16val = GUINT16_TO_LE (5); /* number of streams */
3251 * write the stream info.
3253 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3254 table_offset += 3; table_offset &= ~3;
3256 assembly->tstream.index = heapt_size;
3257 for (i = 0; i < 5; ++i) {
3258 int32val = (guint32*)p;
3259 stream_desc [i].stream->offset = table_offset;
3260 *int32val++ = GUINT32_TO_LE (table_offset);
3261 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3262 table_offset += GUINT32_FROM_LE (*int32val);
3263 table_offset += 3; table_offset &= ~3;
3265 strcpy (p, stream_desc [i].name);
3266 p += strlen (stream_desc [i].name) + 1;
3267 align_pointer (meta->raw_metadata, p);
3270 * now copy the data, the table stream header and contents goes first.
3272 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3273 p = meta->raw_metadata + assembly->tstream.offset;
3274 int32val = (guint32*)p;
3275 *int32val = GUINT32_TO_LE (0); /* reserved */
3278 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3279 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3280 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3281 *p++ = 1; /* version */
3284 *p++ = 1; /* version */
3288 if (meta->idx_string_wide)
3290 if (meta->idx_guid_wide)
3292 if (meta->idx_blob_wide)
3295 *p++ = 0; /* reserved */
3296 int64val = (guint64*)p;
3297 *int64val++ = GUINT64_TO_LE (valid_mask);
3298 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3300 int32val = (guint32*)p;
3301 for (i = 0; i < 64; i++){
3302 if (meta->tables [i].rows == 0)
3304 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3306 p = (unsigned char*)int32val;
3308 /* sort the tables that still need sorting */
3309 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3311 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3312 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3314 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3315 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3317 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3318 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3320 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3322 /* compress the tables */
3323 for (i = 0; i < 64; i++){
3326 guint32 bitfield = meta->tables [i].size_bitfield;
3327 if (!meta->tables [i].rows)
3329 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3330 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3331 meta->tables [i].base = p;
3332 for (row = 1; row <= meta->tables [i].rows; ++row) {
3333 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3334 for (col = 0; col < assembly->tables [i].columns; ++col) {
3335 switch (mono_metadata_table_size (bitfield, col)) {
3337 *p++ = values [col];
3340 *p++ = values [col] & 0xff;
3341 *p++ = (values [col] >> 8) & 0xff;
3344 *p++ = values [col] & 0xff;
3345 *p++ = (values [col] >> 8) & 0xff;
3346 *p++ = (values [col] >> 16) & 0xff;
3347 *p++ = (values [col] >> 24) & 0xff;
3350 g_assert_not_reached ();
3354 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3357 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3358 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3359 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3360 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3361 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3363 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3367 * Some tables in metadata need to be sorted according to some criteria, but
3368 * when methods and fields are first created with reflection, they may be assigned a token
3369 * that doesn't correspond to the final token they will get assigned after the sorting.
3370 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3371 * with the reflection objects that represent them. Once all the tables are set up, the
3372 * reflection objects will contains the correct table index. fixup_method() will fixup the
3373 * tokens for the method with ILGenerator @ilgen.
3376 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3377 guint32 code_idx = GPOINTER_TO_UINT (value);
3378 MonoReflectionILTokenInfo *iltoken;
3379 MonoReflectionFieldBuilder *field;
3380 MonoReflectionCtorBuilder *ctor;
3381 MonoReflectionMethodBuilder *method;
3382 MonoReflectionTypeBuilder *tb;
3383 MonoReflectionArrayMethod *am;
3385 unsigned char *target;
3387 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3388 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3389 target = assembly->code.data + code_idx + iltoken->code_pos;
3390 switch (target [3]) {
3391 case MONO_TABLE_FIELD:
3392 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3393 field = (MonoReflectionFieldBuilder *)iltoken->member;
3394 idx = field->table_idx;
3395 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3396 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3397 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3399 g_assert_not_reached ();
3402 case MONO_TABLE_METHOD:
3403 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3404 method = (MonoReflectionMethodBuilder *)iltoken->member;
3405 idx = method->table_idx;
3406 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3407 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3408 idx = ctor->table_idx;
3409 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3410 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3411 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3412 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3414 g_assert_not_reached ();
3417 case MONO_TABLE_TYPEDEF:
3418 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3419 g_assert_not_reached ();
3420 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3421 idx = tb->table_idx;
3423 case MONO_TABLE_MEMBERREF:
3424 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3425 am = (MonoReflectionArrayMethod*)iltoken->member;
3426 idx = am->table_idx;
3427 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3428 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3429 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3430 g_assert (m->klass->generic_inst);
3432 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3434 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3435 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3436 g_assert (f->generic_info);
3438 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3441 g_assert_not_reached ();
3444 case MONO_TABLE_METHODSPEC:
3445 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3446 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3447 g_assert (m->signature->generic_param_count);
3450 g_assert_not_reached ();
3454 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3456 target [0] = idx & 0xff;
3457 target [1] = (idx >> 8) & 0xff;
3458 target [2] = (idx >> 16) & 0xff;
3465 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3466 * value is not known when the table is emitted.
3469 fixup_cattrs (MonoDynamicImage *assembly)
3471 MonoDynamicTable *table;
3473 guint32 type, i, idx, token;
3476 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3478 for (i = 0; i < table->rows; ++i) {
3479 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3481 type = values [MONO_CUSTOM_ATTR_TYPE];
3482 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3483 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3484 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3485 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3488 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3489 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3490 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3491 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3498 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3500 MonoDynamicTable *table;
3504 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3506 alloc_table (table, table->rows);
3507 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3508 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3509 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3510 name = mono_string_to_utf8 (rsrc->name);
3511 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3513 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3518 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3520 MonoDynamicTable *table;
3524 char *b = blob_size;
3526 guint32 idx, offset;
3528 if (rsrc->filename) {
3529 name = mono_string_to_utf8 (rsrc->filename);
3530 sname = g_path_get_basename (name);
3532 table = &assembly->tables [MONO_TABLE_FILE];
3534 alloc_table (table, table->rows);
3535 values = table->values + table->next_idx * MONO_FILE_SIZE;
3536 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3537 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3540 mono_sha1_get_digest_from_file (name, hash);
3541 mono_metadata_encode_value (20, b, &b);
3542 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3543 mono_image_add_stream_data (&assembly->blob, hash, 20);
3545 idx = table->next_idx++;
3547 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3550 offset = mono_array_length (rsrc->data);
3551 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3552 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3553 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3554 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3558 * The entry should be emitted into the MANIFESTRESOURCE table of
3559 * the main module, but that needs to reference the FILE table
3560 * which isn't emitted yet.
3567 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3571 set_version_from_string (MonoString *version, guint32 *values)
3573 gchar *ver, *p, *str;
3576 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3577 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3578 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3579 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3582 ver = str = mono_string_to_utf8 (version);
3583 for (i = 0; i < 4; ++i) {
3584 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3590 /* handle Revision and Build */
3600 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3604 char *b = blob_size;
3609 len = mono_array_length (pkey);
3610 mono_metadata_encode_value (len, b, &b);
3611 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3612 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3614 /* need to get the actual value from the key type... */
3615 assembly->strong_name_size = 128;
3616 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3622 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3624 MonoDynamicTable *table;
3625 MonoDynamicImage *assembly;
3626 MonoReflectionAssemblyBuilder *assemblyb;
3631 guint32 module_index;
3633 assemblyb = moduleb->assemblyb;
3634 assembly = moduleb->dynamic_image;
3635 domain = mono_object_domain (assemblyb);
3637 /* Emit ASSEMBLY table */
3638 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3639 alloc_table (table, 1);
3640 values = table->values + MONO_ASSEMBLY_SIZE;
3641 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3642 name = mono_string_to_utf8 (assemblyb->name);
3643 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3645 if (assemblyb->culture) {
3646 name = mono_string_to_utf8 (assemblyb->culture);
3647 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3650 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3652 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3653 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3654 set_version_from_string (assemblyb->version, values);
3656 /* Emit FILE + EXPORTED_TYPE table */
3658 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3660 MonoReflectionModuleBuilder *file_module =
3661 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3662 if (file_module != moduleb) {
3663 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3665 if (file_module->types) {
3666 for (j = 0; j < file_module->num_types; ++j) {
3667 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3668 mono_image_fill_export_table (domain, tb, module_index, 0,
3674 if (assemblyb->loaded_modules) {
3675 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3676 MonoReflectionModule *file_module =
3677 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3678 mono_image_fill_file_table (domain, file_module, assembly);
3680 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3684 /* Emit MANIFESTRESOURCE table */
3686 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3688 MonoReflectionModuleBuilder *file_module =
3689 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3690 /* The table for the main module is emitted later */
3691 if (file_module != moduleb) {
3693 if (file_module->resources) {
3694 int len = mono_array_length (file_module->resources);
3695 for (j = 0; j < len; ++j) {
3696 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3697 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3705 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3706 * for the modulebuilder @moduleb.
3707 * At the end of the process, method and field tokens are fixed up and the
3708 * on-disk compressed metadata representation is created.
3711 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3713 MonoDynamicTable *table;
3714 MonoDynamicImage *assembly;
3715 MonoReflectionAssemblyBuilder *assemblyb;
3720 assemblyb = moduleb->assemblyb;
3721 assembly = moduleb->dynamic_image;
3722 domain = mono_object_domain (assemblyb);
3724 if (assembly->text_rva)
3727 assembly->text_rva = START_TEXT_RVA;
3729 if (moduleb->is_main) {
3730 mono_image_emit_manifest (moduleb);
3733 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3734 table->rows = 1; /* .<Module> */
3736 alloc_table (table, table->rows);
3738 * Set the first entry.
3740 values = table->values + table->columns;
3741 values [MONO_TYPEDEF_FLAGS] = 0;
3742 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3743 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3744 values [MONO_TYPEDEF_EXTENDS] = 0;
3745 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3746 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3749 * handle global methods
3750 * FIXME: test what to do when global methods are defined in multiple modules.
3752 if (moduleb->global_methods) {
3753 table = &assembly->tables [MONO_TABLE_METHOD];
3754 table->rows += mono_array_length (moduleb->global_methods);
3755 alloc_table (table, table->rows);
3756 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3757 mono_image_get_method_info (
3758 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3760 if (moduleb->global_fields) {
3761 table = &assembly->tables [MONO_TABLE_FIELD];
3762 table->rows += mono_array_length (moduleb->global_fields);
3763 alloc_table (table, table->rows);
3764 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3765 mono_image_get_field_info (
3766 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3769 table = &assembly->tables [MONO_TABLE_MODULE];
3770 alloc_table (table, 1);
3771 mono_image_fill_module_table (domain, moduleb, assembly);
3775 /* Collect all types into a list sorted by their table_idx */
3776 GPtrArray *types = g_ptr_array_new ();
3779 for (i = 0; i < moduleb->num_types; ++i) {
3780 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3781 collect_types (types, type);
3784 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3785 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3786 table->rows += types->len;
3787 alloc_table (table, table->rows);
3789 for (i = 0; i < types->len; ++i) {
3790 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3791 mono_image_get_type_info (domain, type, assembly);
3793 g_ptr_array_free (types, TRUE);
3797 * table->rows is already set above and in mono_image_fill_module_table.
3799 /* add all the custom attributes at the end, once all the indexes are stable */
3800 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3802 module_add_cattrs (assembly, moduleb);
3805 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3806 fixup_cattrs (assembly);
3810 * mono_image_insert_string:
3811 * @module: module builder object
3814 * Insert @str into the user string stream of @module.
3817 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3819 MonoDynamicImage *assembly;
3824 MONO_ARCH_SAVE_REGS;
3826 if (!module->dynamic_image)
3827 mono_image_module_basic_init (module);
3829 assembly = module->dynamic_image;
3831 if (assembly->save) {
3832 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3833 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3836 char *swapped = g_malloc (2 * mono_string_length (str));
3837 const char *p = (const char*)mono_string_chars (str);
3839 swap_with_size (swapped, p, 2, mono_string_length (str));
3840 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3844 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3846 mono_image_add_stream_data (&assembly->us, "", 1);
3849 idx = assembly->us.index ++;
3851 mono_g_hash_table_insert (assembly->tokens,
3852 GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3854 return MONO_TOKEN_STRING | idx;
3858 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj,
3859 MonoArray *opt_param_types)
3864 klass = obj->vtable->klass;
3865 if (strcmp (klass->name, "MonoMethod") == 0) {
3866 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3867 MonoMethodSignature *sig, *old;
3868 guint32 sig_token, parent;
3871 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3873 nargs = mono_array_length (opt_param_types);
3874 old = method->signature;
3875 sig = mono_metadata_signature_alloc (
3876 &assembly->image, old->param_count + nargs);
3878 sig->hasthis = old->hasthis;
3879 sig->explicit_this = old->explicit_this;
3880 sig->call_convention = old->call_convention;
3881 sig->generic_param_count = old->generic_param_count;
3882 sig->param_count = old->param_count + nargs;
3883 sig->sentinelpos = old->param_count;
3884 sig->ret = old->ret;
3886 for (i = 0; i < old->param_count; i++)
3887 sig->params [i] = old->params [i];
3889 for (i = 0; i < nargs; i++) {
3890 MonoReflectionType *rt = mono_array_get (
3891 opt_param_types, MonoReflectionType *, i);
3892 sig->params [old->param_count + i] = rt->type;
3895 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
3896 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
3897 parent >>= MONO_TYPEDEFORREF_BITS;
3899 parent <<= MONO_MEMBERREF_PARENT_BITS;
3900 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
3902 sig_token = method_encode_signature (assembly, sig);
3903 token = mono_image_get_varargs_method_token (
3904 assembly, parent, method->name, sig_token);
3905 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
3906 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3907 ReflectionMethodBuilder rmb;
3908 guint32 parent, sig;
3910 reflection_methodbuilder_from_method_builder (&rmb, mb);
3911 rmb.opt_types = opt_param_types;
3913 sig = method_builder_encode_signature (assembly, &rmb);
3915 parent = mono_image_create_token (assembly, obj);
3916 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
3918 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
3919 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
3921 token = mono_image_get_varargs_method_token (
3922 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
3924 g_error ("requested method token for %s\n", klass->name);
3930 * mono_image_create_token:
3931 * @assembly: a dynamic assembly
3934 * Get a token to insert in the IL code stream for the given MemberInfo.
3935 * @obj can be one of:
3936 * ConstructorBuilder
3946 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3951 klass = obj->vtable->klass;
3952 if (strcmp (klass->name, "MethodBuilder") == 0) {
3953 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3955 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3956 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3958 token = mono_image_get_methodbuilder_token (assembly, mb);
3959 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3961 else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3962 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3964 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3965 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3967 token = mono_image_get_ctorbuilder_token (assembly, mb);
3968 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3970 else if (strcmp (klass->name, "FieldBuilder") == 0) {
3971 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3972 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3973 if (tb->generic_params) {
3974 token = mono_image_get_generic_field_token (assembly, fb);
3976 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3979 else if (strcmp (klass->name, "TypeBuilder") == 0) {
3980 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3981 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3983 else if (strcmp (klass->name, "MonoType") == 0 ||
3984 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3985 MonoReflectionType *tb = (MonoReflectionType *)obj;
3986 token = mono_metadata_token_from_dor (
3987 mono_image_typedef_or_ref (assembly, tb->type));
3989 else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3990 MonoReflectionType *tb = (MonoReflectionType *)obj;
3991 token = mono_metadata_token_from_dor (
3992 mono_image_typedef_or_ref (assembly, tb->type));
3994 else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3995 strcmp (klass->name, "MonoMethod") == 0) {
3996 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3997 if (m->method->signature->is_inflated) {
3998 token = mono_image_get_methodspec_token (assembly, m->method);
3999 } else if (m->method->signature->generic_param_count) {
4000 g_assert_not_reached ();
4001 } else if ((m->method->klass->image == &assembly->image) &&
4002 !m->method->klass->generic_inst) {
4003 static guint32 method_table_idx = 0xffffff;
4004 if (m->method->klass->wastypebuilder) {
4005 /* we use the same token as the one that was assigned
4006 * to the Methodbuilder.
4007 * FIXME: do the equivalent for Fields.
4009 token = m->method->token;
4012 * Each token should have a unique index, but the indexes are
4013 * assigned by managed code, so we don't know about them. An
4014 * easy solution is to count backwards...
4016 method_table_idx --;
4017 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4020 token = mono_image_get_methodref_token (assembly, m->method);
4021 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4023 else if (strcmp (klass->name, "MonoField") == 0) {
4024 MonoReflectionField *f = (MonoReflectionField *)obj;
4025 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4026 static guint32 field_table_idx = 0xffffff;
4028 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4030 token = mono_image_get_fieldref_token (assembly, f);
4031 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4033 else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4034 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4035 token = mono_image_get_array_token (assembly, m);
4037 else if (strcmp (klass->name, "SignatureHelper") == 0) {
4038 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4039 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4042 g_error ("requested token for %s\n", klass->name);
4044 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
4051 guint32 import_lookup_table;
4055 guint32 import_address_table_rva;
4063 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4065 static MonoDynamicImage*
4066 create_dynamic_mono_image (MonoDynamicAssembly *assembly,
4067 char *assembly_name, char *module_name)
4069 static const guchar entrycode [16] = {0xff, 0x25, 0};
4070 MonoDynamicImage *image;
4073 const char *version = mono_get_runtime_version ();
4076 image = GC_MALLOC (sizeof (MonoDynamicImage));
4078 image = g_new0 (MonoDynamicImage, 1);
4081 /* keep in sync with image.c */
4082 image->image.name = assembly_name;
4083 image->image.assembly_name = image->image.name; /* they may be different */
4084 image->image.module_name = module_name;
4085 image->image.version = g_strdup (version);
4086 image->image.dynamic = TRUE;
4088 image->image.references = g_new0 (MonoAssembly*, 1);
4089 image->image.references [0] = NULL;
4091 mono_image_init (&image->image);
4093 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4094 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4095 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4096 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4097 image->handleref = g_hash_table_new (NULL, NULL);
4098 image->tokens = mono_g_hash_table_new (NULL, NULL);
4099 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4100 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4101 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4103 string_heap_init (&image->sheap);
4104 mono_image_add_stream_data (&image->us, "", 1);
4105 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4106 /* import tables... */
4107 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4108 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4109 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4110 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4111 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4112 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4113 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4114 stream_data_align (&image->code);
4116 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4118 for (i=0; i < 64; ++i) {
4119 image->tables [i].next_idx = 1;
4120 image->tables [i].columns = table_sizes [i];
4123 image->image.assembly = (MonoAssembly*)assembly;
4124 image->run = assembly->run;
4125 image->save = assembly->save;
4131 * mono_image_basic_init:
4132 * @assembly: an assembly builder object
4134 * Create the MonoImage that represents the assembly builder and setup some
4135 * of the helper hash table and the basic metadata streams.
4138 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4140 MonoDynamicAssembly *assembly;
4141 MonoDynamicImage *image;
4143 MONO_ARCH_SAVE_REGS;
4145 if (assemblyb->dynamic_assembly)
4149 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4151 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4154 assembly->assembly.dynamic = TRUE;
4155 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4156 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4157 if (assemblyb->culture)
4158 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4160 assembly->assembly.aname.culture = g_strdup ("");
4162 assembly->run = assemblyb->access != 2;
4163 assembly->save = assemblyb->access != 1;
4165 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4166 assembly->assembly.aname.name = image->image.name;
4167 assembly->assembly.image = &image->image;
4169 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4170 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4174 calc_section_size (MonoDynamicImage *assembly)
4178 /* alignment constraints */
4179 assembly->code.index += 3;
4180 assembly->code.index &= ~3;
4181 assembly->meta_size += 3;
4182 assembly->meta_size &= ~3;
4183 assembly->resources.index += 3;
4184 assembly->resources.index &= ~3;
4186 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4187 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4190 if (assembly->win32_res) {
4191 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4193 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4194 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4198 assembly->sections [MONO_SECTION_RELOC].size = 12;
4199 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4209 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4213 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4215 ResTreeNode *t1 = (ResTreeNode*)a;
4216 ResTreeNode *t2 = (ResTreeNode*)b;
4218 return t1->id - t2->id;
4222 * resource_tree_create:
4224 * Organize the resources into a resource tree.
4226 static ResTreeNode *
4227 resource_tree_create (MonoArray *win32_resources)
4229 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4233 tree = g_new0 (ResTreeNode, 1);
4235 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4236 MonoReflectionWin32Resource *win32_res =
4237 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4241 lang_node = g_new0 (ResTreeNode, 1);
4242 lang_node->id = win32_res->lang_id;
4243 lang_node->win32_res = win32_res;
4245 /* Create type node if neccesary */
4247 for (l = tree->children; l; l = l->next)
4248 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4249 type_node = (ResTreeNode*)l->data;
4254 type_node = g_new0 (ResTreeNode, 1);
4255 type_node->id = win32_res->res_type;
4258 * The resource types have to be sorted otherwise
4259 * Windows Explorer can't display the version information.
4261 tree->children = g_slist_insert_sorted (tree->children, type_node,
4262 resource_tree_compare_by_id);
4265 /* Create res node if neccesary */
4267 for (l = type_node->children; l; l = l->next)
4268 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4269 res_node = (ResTreeNode*)l->data;
4274 res_node = g_new0 (ResTreeNode, 1);
4275 res_node->id = win32_res->res_id;
4276 type_node->children = g_slist_append (type_node->children, res_node);
4279 res_node->children = g_slist_append (res_node->children, lang_node);
4286 * resource_tree_encode:
4288 * Encode the resource tree into the format used in the PE file.
4291 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4294 MonoPEResourceDir dir;
4295 MonoPEResourceDirEntry dir_entry;
4296 MonoPEResourceDataEntry data_entry;
4300 * For the format of the resource directory, see the article
4301 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4305 memset (&dir, 0, sizeof (dir));
4306 memset (&dir_entry, 0, sizeof (dir_entry));
4307 memset (&data_entry, 0, sizeof (data_entry));
4309 g_assert (sizeof (dir) == 16);
4310 g_assert (sizeof (dir_entry) == 8);
4311 g_assert (sizeof (data_entry) == 16);
4313 node->offset = p - begin;
4315 /* IMAGE_RESOURCE_DIRECTORY */
4316 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4318 memcpy (p, &dir, sizeof (dir));
4321 /* Reserve space for entries */
4323 p += sizeof (dir_entry) * dir.res_id_entries;
4325 /* Write children */
4326 for (l = node->children; l; l = l->next) {
4327 ResTreeNode *child = (ResTreeNode*)l->data;
4329 if (child->win32_res) {
4331 child->offset = p - begin;
4333 /* IMAGE_RESOURCE_DATA_ENTRY */
4334 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4335 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4337 memcpy (p, &data_entry, sizeof (data_entry));
4338 p += sizeof (data_entry);
4340 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4341 p += data_entry.rde_size;
4344 resource_tree_encode (child, begin, p, &p);
4347 /* IMAGE_RESOURCE_ENTRY */
4348 for (l = node->children; l; l = l->next) {
4349 ResTreeNode *child = (ResTreeNode*)l->data;
4350 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4352 dir_entry.is_dir = child->win32_res ? 0 : 1;
4353 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4355 memcpy (entries, &dir_entry, sizeof (dir_entry));
4356 entries += sizeof (dir_entry);
4363 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4368 MonoReflectionWin32Resource *win32_res;
4371 if (!assemblyb->win32_resources)
4375 * Resources are stored in a three level tree inside the PE file.
4376 * - level one contains a node for each type of resource
4377 * - level two contains a node for each resource
4378 * - level three contains a node for each instance of a resource for a
4379 * specific language.
4382 tree = resource_tree_create (assemblyb->win32_resources);
4384 /* Estimate the size of the encoded tree */
4386 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4387 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4388 size += mono_array_length (win32_res->res_data);
4390 /* Directory structure */
4391 size += mono_array_length (assemblyb->win32_resources) * 256;
4392 p = buf = g_malloc (size);
4394 resource_tree_encode (tree, p, p, &p);
4396 g_assert (p - buf < size);
4398 assembly->win32_res = g_malloc (p - buf);
4399 assembly->win32_res_size = p - buf;
4400 memcpy (assembly->win32_res, buf, p - buf);
4406 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4408 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4411 p += sizeof (MonoPEResourceDir);
4412 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4413 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4414 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4415 if (dir_entry->is_dir)
4416 fixup_resource_directory (res_section, child, rva);
4418 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4419 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4422 p += sizeof (MonoPEResourceDirEntry);
4427 * mono_image_create_pefile:
4428 * @mb: a module builder object
4430 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4431 * assembly->pefile where it can be easily retrieved later in chunks.
4434 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4435 MonoMSDOSHeader *msdos;
4436 MonoDotNetHeader *header;
4437 MonoSectionTable *section;
4438 MonoCLIHeader *cli_header;
4439 guint32 size, image_size, virtual_base, text_offset;
4440 guint32 header_start, section_start, file_offset, virtual_offset;
4441 MonoDynamicImage *assembly;
4442 MonoReflectionAssemblyBuilder *assemblyb;
4443 MonoDynamicStream *pefile;
4445 guint32 *rva, value;
4448 static const unsigned char msheader[] = {
4449 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4450 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4453 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4454 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4455 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4456 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4459 assemblyb = mb->assemblyb;
4461 mono_image_basic_init (assemblyb);
4462 assembly = mb->dynamic_image;
4464 /* already created */
4465 if (assembly->pefile.index)
4468 mono_image_build_metadata (mb);
4470 if (mb->is_main && assemblyb->resources) {
4471 int len = mono_array_length (assemblyb->resources);
4472 for (i = 0; i < len; ++i)
4473 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4476 if (mb->resources) {
4477 int len = mono_array_length (mb->resources);
4478 for (i = 0; i < len; ++i)
4479 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4482 build_compressed_metadata (assembly);
4485 assembly_add_win32_resources (assembly, assemblyb);
4487 nsections = calc_section_size (assembly);
4489 pefile = &assembly->pefile;
4491 /* The DOS header and stub */
4492 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4493 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4495 /* the dotnet header */
4496 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4498 /* the section tables */
4499 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4501 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4502 virtual_offset = VIRT_ALIGN;
4505 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4506 if (!assembly->sections [i].size)
4509 file_offset += FILE_ALIGN - 1;
4510 file_offset &= ~(FILE_ALIGN - 1);
4511 virtual_offset += VIRT_ALIGN - 1;
4512 virtual_offset &= ~(VIRT_ALIGN - 1);
4514 assembly->sections [i].offset = file_offset;
4515 assembly->sections [i].rva = virtual_offset;
4517 file_offset += assembly->sections [i].size;
4518 virtual_offset += assembly->sections [i].size;
4519 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4522 file_offset += FILE_ALIGN - 1;
4523 file_offset &= ~(FILE_ALIGN - 1);
4524 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4526 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4528 /* back-patch info */
4529 msdos = (MonoMSDOSHeader*)pefile->data;
4530 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4531 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4532 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4534 header = (MonoDotNetHeader*)(pefile->data + header_start);
4535 header->pesig [0] = 'P';
4536 header->pesig [1] = 'E';
4538 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4539 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4540 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4541 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4542 if (assemblyb->pekind == 1) {
4544 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4547 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4550 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4552 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4553 header->pe.pe_major = 6;
4554 header->pe.pe_minor = 0;
4555 size = assembly->sections [MONO_SECTION_TEXT].size;
4556 size += FILE_ALIGN - 1;
4557 size &= ~(FILE_ALIGN - 1);
4558 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4559 size = assembly->sections [MONO_SECTION_RSRC].size;
4560 size += FILE_ALIGN - 1;
4561 size &= ~(FILE_ALIGN - 1);
4562 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4563 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4564 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4565 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4566 /* pe_rva_entry_point always at the beginning of the text section */
4567 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4569 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4570 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4571 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4572 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4573 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4574 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4575 size = section_start;
4576 size += FILE_ALIGN - 1;
4577 size &= ~(FILE_ALIGN - 1);
4578 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4580 size += VIRT_ALIGN - 1;
4581 size &= ~(VIRT_ALIGN - 1);
4582 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4585 // Translate the PEFileKind value to the value expected by the Windows loader
4591 // PEFileKinds.Dll == 1
4592 // PEFileKinds.ConsoleApplication == 2
4593 // PEFileKinds.WindowApplication == 3
4596 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4597 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4599 if (assemblyb->pekind == 3)
4604 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4606 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4607 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4608 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4609 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4610 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4611 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4613 /* fill data directory entries */
4615 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4616 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4618 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4619 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4621 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4622 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4623 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4624 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4625 /* patch imported function RVA name */
4626 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4627 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4629 /* the import table */
4630 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4631 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4632 /* patch imported dll RVA name and other entries in the dir */
4633 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4634 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4635 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4636 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4637 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4638 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4640 p = (assembly->code.data + assembly->ilt_offset);
4641 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4642 *p++ = (value) & 0xff;
4643 *p++ = (value >> 8) & (0xff);
4644 *p++ = (value >> 16) & (0xff);
4645 *p++ = (value >> 24) & (0xff);
4647 /* the CLI header info */
4648 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4649 cli_header->ch_size = GUINT32_FROM_LE (72);
4650 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4651 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4652 if (assemblyb->entry_point) {
4653 guint32 table_idx = 0;
4654 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4655 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4656 table_idx = methodb->table_idx;
4659 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4660 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4663 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4664 /* The embedded managed resources */
4665 text_offset = assembly->text_rva + assembly->code.index;
4666 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4667 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4668 text_offset += assembly->resources.index;
4669 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4670 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4671 text_offset += assembly->meta_size;
4672 if (assembly->strong_name_size) {
4673 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4674 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4675 text_offset += assembly->strong_name_size;
4678 /* write the section tables and section content */
4679 section = (MonoSectionTable*)(pefile->data + section_start);
4680 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4681 static const char *section_names [] = {
4682 ".text", ".rsrc", ".reloc"
4684 if (!assembly->sections [i].size)
4686 strcpy (section->st_name, section_names [i]);
4687 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4688 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4689 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4690 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4691 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4692 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4693 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4695 case MONO_SECTION_TEXT:
4696 /* patch entry point */
4697 p = (assembly->code.data + 2);
4698 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4699 *p++ = (value) & 0xff;
4700 *p++ = (value >> 8) & 0xff;
4701 *p++ = (value >> 16) & 0xff;
4702 *p++ = (value >> 24) & 0xff;
4704 text_offset = assembly->sections [i].offset;
4705 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4706 text_offset += assembly->code.index;
4707 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4708 text_offset += assembly->resources.index;
4709 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4710 text_offset += assembly->meta_size;
4711 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4713 g_free (assembly->image.raw_metadata);
4715 case MONO_SECTION_RELOC:
4716 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4717 *rva = GUINT32_FROM_LE (assembly->text_rva);
4719 *rva = GUINT32_FROM_LE (12);
4721 data16 = (guint16*)rva;
4723 * the entrypoint is always at the start of the text section
4724 * 3 is IMAGE_REL_BASED_HIGHLOW
4725 * 2 is patch_size_rva - text_rva
4727 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4729 *data16 = 0; /* terminate */
4731 case MONO_SECTION_RSRC:
4732 if (assembly->win32_res) {
4733 text_offset = assembly->sections [i].offset;
4735 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4736 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4738 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4742 g_assert_not_reached ();
4747 /* check that the file is properly padded */
4750 FILE *f = fopen ("mypetest.exe", "w");
4751 fwrite (pefile->data, pefile->index, 1, f);
4757 MonoReflectionModule *
4758 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4762 MonoImageOpenStatus status;
4763 MonoDynamicAssembly *assembly;
4765 name = mono_string_to_utf8 (fileName);
4767 image = mono_image_open (name, &status);
4770 if (status == MONO_IMAGE_ERROR_ERRNO)
4771 exc = mono_get_exception_file_not_found (fileName);
4773 exc = mono_get_exception_bad_image_format (name);
4775 mono_raise_exception (exc);
4780 assembly = ab->dynamic_assembly;
4781 image->assembly = (MonoAssembly*)assembly;
4783 mono_assembly_load_references (image, &status);
4785 mono_image_close (image);
4786 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4789 return mono_module_get_object (mono_domain_get (), image);
4793 * We need to return always the same object for MethodInfo, FieldInfo etc..
4794 * but we need to consider the reflected type.
4795 * type uses a different hash, since it uses custom hash/equal functions.
4800 MonoClass *refclass;
4804 reflected_equal (gconstpointer a, gconstpointer b) {
4805 const ReflectedEntry *ea = a;
4806 const ReflectedEntry *eb = b;
4808 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4812 reflected_hash (gconstpointer a) {
4813 const ReflectedEntry *ea = a;
4814 return GPOINTER_TO_UINT (ea->item);
4817 #define CHECK_OBJECT(t,p,k) \
4823 mono_domain_lock (domain); \
4824 if (!domain->refobject_hash) \
4825 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4826 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4827 mono_domain_unlock (domain); \
4833 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4835 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4838 #define CACHE_OBJECT(p,o,k) \
4840 ReflectedEntry *e = ALLOC_REFENTRY; \
4842 e->refclass = (k); \
4843 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4844 mono_domain_unlock (domain); \
4848 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4850 /* this is done only once */
4851 mono_domain_lock (domain);
4852 CACHE_OBJECT (assembly, res, NULL);
4856 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4858 /* this is done only once */
4859 mono_domain_lock (domain);
4860 CACHE_OBJECT (module, res, NULL);
4864 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4866 MonoDynamicImage *image = moduleb->dynamic_image;
4867 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4870 * FIXME: we already created an image in mono_image_basic_init (), but
4871 * we don't know which module it belongs to, since that is only
4872 * determined at assembly save time.
4874 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4875 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4877 moduleb->module.image = &image->image;
4878 moduleb->dynamic_image = image;
4879 register_module (mono_object_domain (moduleb), moduleb, image);
4884 * mono_assembly_get_object:
4885 * @domain: an app domain
4886 * @assembly: an assembly
4888 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4890 MonoReflectionAssembly*
4891 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4893 static MonoClass *System_Reflection_Assembly;
4894 MonoReflectionAssembly *res;
4896 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4897 if (!System_Reflection_Assembly)
4898 System_Reflection_Assembly = mono_class_from_name (
4899 mono_defaults.corlib, "System.Reflection", "Assembly");
4900 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4901 res->assembly = assembly;
4902 CACHE_OBJECT (assembly, res, NULL);
4908 MonoReflectionModule*
4909 mono_module_get_object (MonoDomain *domain, MonoImage *image)
4911 static MonoClass *System_Reflection_Module;
4912 MonoReflectionModule *res;
4914 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4915 if (!System_Reflection_Module)
4916 System_Reflection_Module = mono_class_from_name (
4917 mono_defaults.corlib, "System.Reflection", "Module");
4918 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4921 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4923 res->fqname = mono_string_new (domain, image->name);
4924 res->name = mono_string_new (domain, g_path_get_basename (image->name));
4925 res->scopename = mono_string_new (domain, image->module_name);
4927 mono_image_addref (image);
4929 CACHE_OBJECT (image, res, NULL);
4933 MonoReflectionModule*
4934 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4936 static MonoClass *System_Reflection_Module;
4937 MonoReflectionModule *res;
4938 MonoTableInfo *table;
4939 guint32 cols [MONO_FILE_SIZE];
4941 guint32 i, name_idx;
4944 if (!System_Reflection_Module)
4945 System_Reflection_Module = mono_class_from_name (
4946 mono_defaults.corlib, "System.Reflection", "Module");
4947 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4949 table = &image->tables [MONO_TABLE_FILE];
4950 g_assert (table_index < table->rows);
4951 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4954 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4955 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4957 /* Check whenever the row has a corresponding row in the moduleref table */
4958 table = &image->tables [MONO_TABLE_MODULEREF];
4959 for (i = 0; i < table->rows; ++i) {
4960 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4961 val = mono_metadata_string_heap (image, name_idx);
4962 if (strcmp (val, name) == 0)
4963 res->image = image->modules [i];
4966 res->fqname = mono_string_new (domain, name);
4967 res->name = mono_string_new (domain, name);
4968 res->scopename = mono_string_new (domain, name);
4969 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4975 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4977 if ((t1->type != t2->type) ||
4978 (t1->byref != t2->byref))
4982 case MONO_TYPE_VOID:
4983 case MONO_TYPE_BOOLEAN:
4984 case MONO_TYPE_CHAR:
4995 case MONO_TYPE_STRING:
4998 case MONO_TYPE_OBJECT:
4999 case MONO_TYPE_TYPEDBYREF:
5001 case MONO_TYPE_VALUETYPE:
5002 case MONO_TYPE_CLASS:
5003 case MONO_TYPE_SZARRAY:
5004 return t1->data.klass == t2->data.klass;
5006 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5007 case MONO_TYPE_ARRAY:
5008 if (t1->data.array->rank != t2->data.array->rank)
5010 return t1->data.array->eklass == t2->data.array->eklass;
5011 case MONO_TYPE_GENERICINST: {
5013 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5015 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5017 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5018 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5024 case MONO_TYPE_MVAR:
5025 return t1->data.generic_param == t2->data.generic_param;
5027 g_error ("implement type compare for %0x!", t1->type);
5035 mymono_metadata_type_hash (MonoType *t1)
5041 hash |= t1->byref << 6; /* do not collide with t1->type values */
5043 case MONO_TYPE_VALUETYPE:
5044 case MONO_TYPE_CLASS:
5045 case MONO_TYPE_SZARRAY:
5046 /* check if the distribution is good enough */
5047 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5049 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5054 static MonoReflectionGenericInst*
5055 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5057 static MonoClass *System_Reflection_MonoGenericInst;
5058 MonoReflectionGenericInst *res;
5059 MonoGenericInst *ginst;
5062 if (!System_Reflection_MonoGenericInst) {
5063 System_Reflection_MonoGenericInst = mono_class_from_name (
5064 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5065 g_assert (System_Reflection_MonoGenericInst);
5068 ginst = geninst->data.generic_inst;
5069 gklass = mono_class_from_mono_type (ginst->generic_type);
5071 mono_class_init (ginst->klass);
5073 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5075 res->type.type = geninst;
5076 if (gklass->wastypebuilder && gklass->reflection_info)
5077 res->generic_type = gklass->reflection_info;
5079 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5085 * mono_type_get_object:
5086 * @domain: an app domain
5089 * Return an System.MonoType object representing the type @type.
5092 mono_type_get_object (MonoDomain *domain, MonoType *type)
5094 MonoReflectionType *res;
5095 MonoClass *klass = mono_class_from_mono_type (type);
5097 mono_domain_lock (domain);
5098 if (!domain->type_hash)
5099 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5100 (GCompareFunc)mymono_metadata_type_equal);
5101 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5102 mono_domain_unlock (domain);
5105 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5106 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5107 mono_g_hash_table_insert (domain->type_hash, type, res);
5108 mono_domain_unlock (domain);
5111 if (klass->reflection_info && !klass->wastypebuilder) {
5112 /* g_assert_not_reached (); */
5113 /* should this be considered an error condition? */
5115 mono_domain_unlock (domain);
5116 return klass->reflection_info;
5119 mono_class_init (klass);
5120 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5122 mono_g_hash_table_insert (domain->type_hash, type, res);
5123 mono_domain_unlock (domain);
5128 * mono_method_get_object:
5129 * @domain: an app domain
5131 * @refclass: the reflected type (can be NULL)
5133 * Return an System.Reflection.MonoMethod object representing the method @method.
5135 MonoReflectionMethod*
5136 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5139 * We use the same C representation for methods and constructors, but the type
5140 * name in C# is different.
5144 MonoReflectionMethod *ret;
5147 refclass = method->klass;
5149 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5150 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5151 cname = "MonoCMethod";
5153 cname = "MonoMethod";
5154 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5156 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5157 ret->method = method;
5158 ret->name = mono_string_new (domain, method->name);
5159 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5160 CACHE_OBJECT (method, ret, refclass);
5165 * mono_field_get_object:
5166 * @domain: an app domain
5170 * Return an System.Reflection.MonoField object representing the field @field
5173 MonoReflectionField*
5174 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5176 MonoReflectionField *res;
5179 CHECK_OBJECT (MonoReflectionField *, field, klass);
5180 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5181 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5184 res->name = mono_string_new (domain, field->name);
5185 if (field->generic_info)
5186 res->attrs = field->generic_info->generic_type->attrs;
5188 res->attrs = field->type->attrs;
5189 res->type = mono_type_get_object (domain, field->type);
5190 CACHE_OBJECT (field, res, klass);
5195 * mono_property_get_object:
5196 * @domain: an app domain
5198 * @property: a property
5200 * Return an System.Reflection.MonoProperty object representing the property @property
5203 MonoReflectionProperty*
5204 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5206 MonoReflectionProperty *res;
5209 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5210 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5211 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5213 res->property = property;
5214 CACHE_OBJECT (property, res, klass);
5219 * mono_event_get_object:
5220 * @domain: an app domain
5224 * Return an System.Reflection.MonoEvent object representing the event @event
5227 MonoReflectionEvent*
5228 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5230 MonoReflectionEvent *res;
5233 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5234 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5235 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5238 CACHE_OBJECT (event, res, klass);
5243 * mono_param_get_objects:
5244 * @domain: an app domain
5247 * Return an System.Reflection.ParameterInfo array object representing the parameters
5248 * in the method @method.
5251 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5253 static MonoClass *System_Reflection_ParameterInfo;
5254 MonoArray *res = NULL;
5255 MonoReflectionMethod *member = NULL;
5256 MonoReflectionParameter *param = NULL;
5260 if (!System_Reflection_ParameterInfo)
5261 System_Reflection_ParameterInfo = mono_class_from_name (
5262 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5264 if (!method->signature->param_count)
5265 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5267 /* Note: the cache is based on the address of the signature into the method
5268 * since we already cache MethodInfos with the method as keys.
5270 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5272 member = mono_method_get_object (domain, method, NULL);
5273 names = g_new (char *, method->signature->param_count);
5274 mono_method_get_param_names (method, (const char **) names);
5276 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5277 for (i = 0; i < method->signature->param_count; ++i) {
5278 param = (MonoReflectionParameter *)mono_object_new (domain,
5279 System_Reflection_ParameterInfo);
5280 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5281 param->DefaultValueImpl = NULL; /* FIXME */
5282 param->MemberImpl = (MonoObject*)member;
5283 param->NameImpl = mono_string_new (domain, names [i]);
5284 param->PositionImpl = i;
5285 param->AttrsImpl = method->signature->params [i]->attrs;
5286 mono_array_set (res, gpointer, i, param);
5289 CACHE_OBJECT (&(method->signature), res, NULL);
5294 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5298 memset (assembly, 0, sizeof (MonoAssemblyName));
5300 assembly->culture = "";
5301 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5303 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5306 while (*p == ' ' || *p == ',') {
5315 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5317 assembly->major = strtoul (p, &s, 10);
5318 if (s == p || *s != '.')
5321 assembly->minor = strtoul (p, &s, 10);
5322 if (s == p || *s != '.')
5325 assembly->build = strtoul (p, &s, 10);
5326 if (s == p || *s != '.')
5329 assembly->revision = strtoul (p, &s, 10);
5333 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5335 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5336 assembly->culture = "";
5339 assembly->culture = p;
5340 while (*p && *p != ',') {
5344 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5346 if (strncmp (p, "null", 4) == 0) {
5351 while (*p && *p != ',') {
5354 len = (p - start + 1);
5355 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5356 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5357 g_strlcpy (assembly->public_key_token, start, len);
5360 while (*p && *p != ',')
5364 while (*p == ' ' || *p == ',') {
5378 * mono_reflection_parse_type:
5381 * Parse a type name as accepted by the GetType () method and output the info
5382 * extracted in the info structure.
5383 * the name param will be mangled, so, make a copy before passing it to this function.
5384 * The fields in info will be valid until the memory pointed to by name is valid.
5385 * Returns 0 on parse error.
5386 * See also mono_type_get_name () below.
5389 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5391 char *start, *p, *w, *last_point, *startn;
5392 int in_modifiers = 0;
5393 int isbyref = 0, rank;
5395 start = p = w = name;
5397 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5398 info->name = info->name_space = NULL;
5399 info->nested = NULL;
5400 info->modifiers = NULL;
5402 /* last_point separates the namespace from the name */
5408 *p = 0; /* NULL terminate the name */
5410 info->nested = g_list_append (info->nested, startn);
5411 /* we have parsed the nesting namespace + name */
5415 info->name_space = start;
5417 info->name = last_point + 1;
5419 info->name_space = (char *)"";
5445 info->name_space = start;
5447 info->name = last_point + 1;
5449 info->name_space = (char *)"";
5456 if (isbyref) /* only one level allowed by the spec */
5459 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5463 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5474 else if (*p != '*') /* '*' means unknown lower bound */
5480 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5492 return 0; /* missing assembly name */
5493 if (!assembly_name_to_aname (&info->assembly, p))
5500 if (info->assembly.name)
5503 *w = 0; /* terminate class name */
5504 if (!info->name || !*info->name)
5506 /* add other consistency checks */
5511 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5518 image = mono_defaults.corlib;
5521 klass = mono_class_from_name_case (image, info->name_space, info->name);
5523 klass = mono_class_from_name (image, info->name_space, info->name);
5526 for (mod = info->nested; mod; mod = mod->next) {
5529 mono_class_init (klass);
5530 nested = klass->nested_classes;
5533 klass = nested->data;
5535 if (g_strcasecmp (klass->name, mod->data) == 0)
5538 if (strcmp (klass->name, mod->data) == 0)
5542 nested = nested->next;
5549 mono_class_init (klass);
5550 for (mod = info->modifiers; mod; mod = mod->next) {
5551 modval = GPOINTER_TO_UINT (mod->data);
5552 if (!modval) { /* byref: must be last modifier */
5553 return &klass->this_arg;
5554 } else if (modval == -1) {
5555 klass = mono_ptr_class_get (&klass->byval_arg);
5556 } else { /* array rank */
5557 klass = mono_array_class_get (klass, modval);
5559 mono_class_init (klass);
5562 return &klass->byval_arg;
5566 * mono_reflection_get_type:
5567 * @image: a metadata context
5568 * @info: type description structure
5569 * @ignorecase: flag for case-insensitive string compares
5571 * Build a MonoType from the type description in @info.
5576 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5579 MonoReflectionAssembly *assembly;
5583 type = mono_reflection_get_type_internal (image, info, ignorecase);
5586 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5589 /* Reconstruct the type name */
5590 fullName = g_string_new ("");
5591 if (info->name_space && (info->name_space [0] != '\0'))
5592 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5594 g_string_printf (fullName, info->name);
5595 for (mod = info->nested; mod; mod = mod->next)
5596 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5599 mono_domain_try_type_resolve (
5600 mono_domain_get (), fullName->str, NULL);
5601 if (assembly && (!image || (assembly->assembly->image == image))) {
5603 if (assembly->assembly->dynamic) {
5604 /* Enumerate all modules */
5605 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5609 if (abuilder->modules) {
5610 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5611 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5612 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5618 if (!type && abuilder->loaded_modules) {
5619 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5620 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5621 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5628 type = mono_reflection_get_type_internal (assembly->assembly->image,
5631 g_string_free (fullName, TRUE);
5636 * mono_reflection_type_from_name:
5638 * @image: a metadata context (can be NULL).
5640 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5641 * it defaults to get the type from @image or, if @image is NULL or loading
5642 * from it fails, uses corlib.
5646 mono_reflection_type_from_name (char *name, MonoImage *image)
5649 MonoTypeNameParse info;
5650 MonoAssembly *assembly;
5653 /* Make a copy since parse_type modifies its argument */
5654 tmp = g_strdup (name);
5656 /*g_print ("requested type %s\n", str);*/
5657 if (!mono_reflection_parse_type (tmp, &info)) {
5659 g_list_free (info.modifiers);
5660 g_list_free (info.nested);
5664 if (info.assembly.name) {
5665 assembly = mono_assembly_loaded (&info.assembly);
5667 /* then we must load the assembly ourselve - see #60439 */
5668 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5671 g_list_free (info.modifiers);
5672 g_list_free (info.nested);
5676 image = assembly->image;
5677 } else if (image == NULL) {
5678 image = mono_defaults.corlib;
5681 type = mono_reflection_get_type (image, &info, FALSE);
5682 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5683 image = mono_defaults.corlib;
5684 type = mono_reflection_get_type (image, &info, FALSE);
5688 g_list_free (info.modifiers);
5689 g_list_free (info.nested);
5694 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5696 int slen, type = t->type;
5701 case MONO_TYPE_BOOLEAN: {
5702 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5707 case MONO_TYPE_CHAR:
5709 case MONO_TYPE_I2: {
5710 guint16 *val = g_malloc (sizeof (guint16));
5715 #if SIZEOF_VOID_P == 4
5721 case MONO_TYPE_I4: {
5722 guint32 *val = g_malloc (sizeof (guint32));
5727 #if SIZEOF_VOID_P == 8
5728 case MONO_TYPE_U: /* error out instead? this should probably not happen */
5733 case MONO_TYPE_I8: {
5734 guint64 *val = g_malloc (sizeof (guint64));
5739 case MONO_TYPE_VALUETYPE:
5740 if (t->data.klass->enumtype) {
5741 type = t->data.klass->enum_basetype->type;
5744 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5747 case MONO_TYPE_STRING:
5748 if (*p == (char)0xFF) {
5752 slen = mono_metadata_decode_value (p, &p);
5754 return mono_string_new_len (mono_domain_get (), p, slen);
5755 case MONO_TYPE_CLASS: {
5758 if (*p == (char)0xFF) {
5763 slen = mono_metadata_decode_value (p, &p);
5764 n = g_memdup (p, slen + 1);
5766 t = mono_reflection_type_from_name (n, image);
5768 g_warning ("Cannot load type '%s'", n);
5772 return mono_type_get_object (mono_domain_get (), t);
5776 case MONO_TYPE_OBJECT: {
5779 MonoClass *subc = NULL;
5784 } else if (subt == 0x0E) {
5785 type = MONO_TYPE_STRING;
5787 } else if (subt == 0x55) {
5790 slen = mono_metadata_decode_value (p, &p);
5791 n = g_memdup (p, slen + 1);
5793 t = mono_reflection_type_from_name (n, image);
5795 g_warning ("Cannot load type '%s'", n);
5798 subc = mono_class_from_mono_type (t);
5799 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5800 MonoType simple_type = {{0}};
5801 simple_type.type = subt;
5802 subc = mono_class_from_mono_type (&simple_type);
5804 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5806 val = load_cattr_value (image, &subc->byval_arg, p, end);
5807 obj = mono_object_new (mono_domain_get (), subc);
5808 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5812 case MONO_TYPE_SZARRAY:
5815 guint32 i, alen, basetype;
5818 if (alen == 0xffffffff) {
5822 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5823 basetype = t->data.klass->byval_arg.type;
5828 case MONO_TYPE_BOOLEAN:
5829 for (i=0;i<alen;i++)
5831 MonoBoolean val=*p++;
5832 mono_array_set(arr,MonoBoolean,i,val);
5835 case MONO_TYPE_CHAR:
5838 for (i=0;i<alen;i++)
5840 guint16 val=read16(p);
5841 mono_array_set(arr,guint16,i,val);
5848 for (i=0;i<alen;i++)
5850 guint32 val=read32(p);
5851 mono_array_set(arr,guint32,i,val);
5858 for (i=0;i<alen;i++)
5860 guint64 val=read64(p);
5861 mono_array_set(arr,guint64,i,val);
5865 case MONO_TYPE_CLASS:
5866 case MONO_TYPE_OBJECT:
5867 case MONO_TYPE_STRING:
5868 for (i = 0; i < alen; i++) {
5869 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5870 mono_array_set (arr, gpointer, i, item);
5874 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5880 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5886 type_is_reference (MonoType *type)
5888 switch (type->type) {
5889 case MONO_TYPE_BOOLEAN:
5890 case MONO_TYPE_CHAR:
5903 case MONO_TYPE_VALUETYPE:
5911 free_param_data (MonoMethodSignature *sig, void **params) {
5913 for (i = 0; i < sig->param_count; ++i) {
5914 if (!type_is_reference (sig->params [i]))
5915 g_free (params [i]);
5920 * Find the method index in the metadata methodDef table.
5921 * Later put these three helper methods in metadata and export them.
5924 find_method_index (MonoMethod *method) {
5925 MonoClass *klass = method->klass;
5928 for (i = 0; i < klass->method.count; ++i) {
5929 if (method == klass->methods [i])
5930 return klass->method.first + 1 + i;
5936 * Find the field index in the metadata FieldDef table.
5939 find_field_index (MonoClass *klass, MonoClassField *field) {
5942 for (i = 0; i < klass->field.count; ++i) {
5943 if (field == &klass->fields [i])
5944 return klass->field.first + 1 + i;
5950 * Find the property index in the metadata Property table.
5953 find_property_index (MonoClass *klass, MonoProperty *property) {
5956 for (i = 0; i < klass->property.count; ++i) {
5957 if (property == &klass->properties [i])
5958 return klass->property.first + 1 + i;
5964 * Find the event index in the metadata Event table.
5967 find_event_index (MonoClass *klass, MonoEvent *event) {
5970 for (i = 0; i < klass->event.count; ++i) {
5971 if (event == &klass->events [i])
5972 return klass->event.first + 1 + i;
5978 create_custom_attr (MonoImage *image, MonoMethod *method,
5979 const char *data, guint32 len)
5981 const char *p = data;
5983 guint32 i, j, num_named;
5987 mono_class_init (method->klass);
5990 attr = mono_object_new (mono_domain_get (), method->klass);
5991 mono_runtime_invoke (method, attr, NULL, NULL);
5995 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5998 /*g_print ("got attr %s\n", method->klass->name);*/
6000 params = g_new (void*, method->signature->param_count);
6004 for (i = 0; i < method->signature->param_count; ++i) {
6005 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6009 attr = mono_object_new (mono_domain_get (), method->klass);
6010 mono_runtime_invoke (method, attr, params, NULL);
6011 free_param_data (method->signature, params);
6013 num_named = read16 (named);
6015 for (j = 0; j < num_named; j++) {
6017 char *name, named_type, data_type;
6018 named_type = *named++;
6019 data_type = *named++; /* type of data */
6020 if (data_type == 0x55) {
6023 type_len = mono_metadata_decode_blob_size (named, &named);
6024 type_name = g_malloc (type_len + 1);
6025 memcpy (type_name, named, type_len);
6026 type_name [type_len] = 0;
6028 /* FIXME: lookup the type and check type consistency */
6029 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6030 /* this seems to be the type of the element of the array */
6031 /* g_print ("skipping 0x%02x after prop\n", *named); */
6034 name_len = mono_metadata_decode_blob_size (named, &named);
6035 name = g_malloc (name_len + 1);
6036 memcpy (name, named, name_len);
6037 name [name_len] = 0;
6039 if (named_type == 0x53) {
6040 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6041 void *val = load_cattr_value (image, field->type, named, &named);
6042 mono_field_set_value (attr, field, val);
6043 if (!type_is_reference (field->type))
6045 } else if (named_type == 0x54) {
6048 MonoType *prop_type;
6050 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6051 /* can we have more that 1 arg in a custom attr named property? */
6052 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6053 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6054 mono_property_set_value (prop, attr, pparams, NULL);
6055 if (!type_is_reference (prop_type))
6056 g_free (pparams [0]);
6065 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6072 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6073 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6074 for (i = 0; i < cinfo->num_attrs; ++i) {
6075 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6076 mono_array_set (result, gpointer, i, attr);
6082 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6084 guint32 mtoken, i, len;
6085 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6087 MonoCustomAttrInfo *ainfo;
6088 GList *tmp, *list = NULL;
6091 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6093 i = mono_metadata_custom_attrs_from_index (image, idx);
6097 while (i < ca->rows) {
6098 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6100 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6103 len = g_list_length (list);
6106 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6107 ainfo->num_attrs = len;
6108 ainfo->image = image;
6109 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6110 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6111 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6112 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6113 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6114 mtoken |= MONO_TOKEN_METHOD_DEF;
6116 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6117 mtoken |= MONO_TOKEN_MEMBER_REF;
6120 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6123 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6124 if (!ainfo->attrs [i].ctor)
6125 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6126 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6127 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6128 ainfo->attrs [i].data = data;
6136 mono_custom_attrs_from_method (MonoMethod *method)
6138 MonoCustomAttrInfo *cinfo;
6141 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6143 idx = find_method_index (method);
6144 idx <<= MONO_CUSTOM_ATTR_BITS;
6145 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6146 return mono_custom_attrs_from_index (method->klass->image, idx);
6150 mono_custom_attrs_from_class (MonoClass *klass)
6152 MonoCustomAttrInfo *cinfo;
6155 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6157 idx = mono_metadata_token_index (klass->type_token);
6158 idx <<= MONO_CUSTOM_ATTR_BITS;
6159 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6160 return mono_custom_attrs_from_index (klass->image, idx);
6164 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6166 MonoCustomAttrInfo *cinfo;
6169 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6171 idx = 1; /* there is only one assembly */
6172 idx <<= MONO_CUSTOM_ATTR_BITS;
6173 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6174 return mono_custom_attrs_from_index (assembly->image, idx);
6177 static MonoCustomAttrInfo*
6178 mono_custom_attrs_from_module (MonoImage *image)
6180 MonoCustomAttrInfo *cinfo;
6183 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6185 idx = 1; /* there is only one module */
6186 idx <<= MONO_CUSTOM_ATTR_BITS;
6187 idx |= MONO_CUSTOM_ATTR_MODULE;
6188 return mono_custom_attrs_from_index (image, idx);
6192 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6194 MonoCustomAttrInfo *cinfo;
6197 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6199 idx = find_property_index (klass, property);
6200 idx <<= MONO_CUSTOM_ATTR_BITS;
6201 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6202 return mono_custom_attrs_from_index (klass->image, idx);
6206 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6208 MonoCustomAttrInfo *cinfo;
6211 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6213 idx = find_event_index (klass, event);
6214 idx <<= MONO_CUSTOM_ATTR_BITS;
6215 idx |= MONO_CUSTOM_ATTR_EVENT;
6216 return mono_custom_attrs_from_index (klass->image, idx);
6220 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6222 MonoCustomAttrInfo *cinfo;
6225 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6227 idx = find_field_index (klass, field);
6228 idx <<= MONO_CUSTOM_ATTR_BITS;
6229 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6230 return mono_custom_attrs_from_index (klass->image, idx);
6234 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6237 guint32 i, idx, method_index;
6238 guint32 param_list, param_last, param_pos, found;
6240 MonoReflectionMethodAux *aux;
6242 if (method->klass->image->dynamic) {
6243 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6244 if (!aux || !aux->param_cattr)
6246 return aux->param_cattr [param];
6249 image = method->klass->image;
6250 method_index = find_method_index (method);
6251 ca = &image->tables [MONO_TABLE_METHOD];
6253 if (method->klass->generic_inst || method->klass->gen_params ||
6254 method->signature->generic_param_count) {
6255 /* FIXME FIXME FIXME */
6259 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6260 if (method_index == ca->rows) {
6261 ca = &image->tables [MONO_TABLE_PARAM];
6262 param_last = ca->rows + 1;
6264 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6265 ca = &image->tables [MONO_TABLE_PARAM];
6268 for (i = param_list; i < param_last; ++i) {
6269 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6270 if (param_pos == param) {
6278 idx <<= MONO_CUSTOM_ATTR_BITS;
6279 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6280 return mono_custom_attrs_from_index (image, idx);
6284 * mono_reflection_get_custom_attrs:
6285 * @obj: a reflection object handle
6287 * Return an array with all the custom attributes defined of the
6288 * reflection handle @obj. The objects are fully build.
6291 mono_reflection_get_custom_attrs (MonoObject *obj)
6295 MonoCustomAttrInfo *cinfo = NULL;
6297 MONO_ARCH_SAVE_REGS;
6299 klass = obj->vtable->klass;
6300 /* FIXME: need to handle: Module */
6301 if (klass == mono_defaults.monotype_class) {
6302 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6303 klass = mono_class_from_mono_type (rtype->type);
6304 cinfo = mono_custom_attrs_from_class (klass);
6305 } else if (strcmp ("Assembly", klass->name) == 0) {
6306 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6307 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6308 } else if (strcmp ("Module", klass->name) == 0) {
6309 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6310 cinfo = mono_custom_attrs_from_module (module->image);
6311 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6312 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6313 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6314 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6315 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6316 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6317 } else if (strcmp ("MonoField", klass->name) == 0) {
6318 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6319 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6320 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6321 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6322 cinfo = mono_custom_attrs_from_method (rmethod->method);
6323 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6324 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6325 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6326 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6327 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6328 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6329 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6330 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6331 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6332 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6333 } else { /* handle other types here... */
6334 g_error ("get custom attrs not yet supported for %s", klass->name);
6338 result = mono_custom_attrs_construct (cinfo);
6340 mono_custom_attrs_free (cinfo);
6342 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6343 result = mono_array_new (mono_domain_get (), klass, 0);
6349 static MonoMethodSignature*
6350 parameters_to_signature (MonoArray *parameters) {
6351 MonoMethodSignature *sig;
6354 count = parameters? mono_array_length (parameters): 0;
6356 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6357 sig->param_count = count;
6358 sig->sentinelpos = -1; /* FIXME */
6359 for (i = 0; i < count; ++i) {
6360 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6361 sig->params [i] = pt->type;
6366 static MonoMethodSignature*
6367 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6368 MonoMethodSignature *sig;
6370 sig = parameters_to_signature (ctor->parameters);
6371 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6372 sig->ret = &mono_defaults.void_class->byval_arg;
6376 static MonoMethodSignature*
6377 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6378 MonoMethodSignature *sig;
6380 sig = parameters_to_signature (method->parameters);
6381 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6382 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6383 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6387 static MonoMethodSignature*
6388 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6389 MonoMethodSignature *sig;
6391 sig = parameters_to_signature (method->parameters);
6392 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6393 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6394 sig->generic_param_count = 0;
6399 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6401 MonoClass *klass = mono_object_class (prop);
6402 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6403 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6404 *name = mono_string_to_utf8 (pb->name);
6405 *type = pb->type->type;
6407 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6408 *name = g_strdup (p->property->name);
6409 if (p->property->get)
6410 *type = p->property->get->signature->ret;
6412 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6417 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6419 MonoClass *klass = mono_object_class (field);
6420 if (strcmp (klass->name, "FieldBuilder") == 0) {
6421 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6422 *name = mono_string_to_utf8 (fb->name);
6423 *type = fb->type->type;
6425 MonoReflectionField *f = (MonoReflectionField *)field;
6426 *name = g_strdup (f->field->name);
6427 *type = f->field->type;
6432 * Encode a value in a custom attribute stream of bytes.
6433 * The value to encode is either supplied as an object in argument val
6434 * (valuetypes are boxed), or as a pointer to the data in the
6436 * @type represents the type of the value
6437 * @buffer is the start of the buffer
6438 * @p the current position in the buffer
6439 * @buflen contains the size of the buffer and is used to return the new buffer size
6440 * if this needs to be realloced.
6441 * @retbuffer and @retp return the start and the position of the buffer
6444 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6446 MonoTypeEnum simple_type;
6448 if ((p-buffer) + 10 >= *buflen) {
6451 newbuf = g_realloc (buffer, *buflen);
6452 p = newbuf + (p-buffer);
6456 argval = ((char*)arg + sizeof (MonoObject));
6457 simple_type = type->type;
6459 switch (simple_type) {
6460 case MONO_TYPE_BOOLEAN:
6465 case MONO_TYPE_CHAR:
6468 swap_with_size (p, argval, 2, 1);
6474 swap_with_size (p, argval, 4, 1);
6480 swap_with_size (p, argval, 8, 1);
6483 case MONO_TYPE_VALUETYPE:
6484 if (type->data.klass->enumtype) {
6485 simple_type = type->data.klass->enum_basetype->type;
6488 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6491 case MONO_TYPE_STRING: {
6498 str = mono_string_to_utf8 ((MonoString*)arg);
6499 slen = strlen (str);
6500 if ((p-buffer) + 10 + slen >= *buflen) {
6504 newbuf = g_realloc (buffer, *buflen);
6505 p = newbuf + (p-buffer);
6508 mono_metadata_encode_value (slen, p, &p);
6509 memcpy (p, str, slen);
6514 case MONO_TYPE_CLASS: {
6522 k = mono_object_class (arg);
6523 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6524 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6525 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6527 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6528 slen = strlen (str);
6529 if ((p-buffer) + 10 + slen >= *buflen) {
6533 newbuf = g_realloc (buffer, *buflen);
6534 p = newbuf + (p-buffer);
6537 mono_metadata_encode_value (slen, p, &p);
6538 memcpy (p, str, slen);
6543 case MONO_TYPE_SZARRAY: {
6545 MonoClass *eclass, *arg_eclass;
6548 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6551 len = mono_array_length ((MonoArray*)arg);
6553 *p++ = (len >> 8) & 0xff;
6554 *p++ = (len >> 16) & 0xff;
6555 *p++ = (len >> 24) & 0xff;
6557 *retbuffer = buffer;
6558 eclass = type->data.klass;
6559 arg_eclass = mono_object_class (arg)->element_class;
6560 if (eclass->valuetype && arg_eclass->valuetype) {
6561 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6562 int elsize = mono_class_array_element_size (eclass);
6563 for (i = 0; i < len; ++i) {
6564 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6568 for (i = 0; i < len; ++i) {
6569 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6574 /* it may be a boxed value or a Type */
6575 case MONO_TYPE_OBJECT: {
6576 MonoClass *klass = mono_object_class (arg);
6580 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6583 } else if (klass->enumtype) {
6585 } else if (klass == mono_defaults.string_class) {
6586 simple_type = MONO_TYPE_STRING;
6589 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6590 *p++ = simple_type = klass->byval_arg.type;
6593 g_error ("unhandled type in custom attr");
6595 str = type_get_qualified_name (klass->enum_basetype, NULL);
6596 slen = strlen (str);
6597 if ((p-buffer) + 10 + slen >= *buflen) {
6601 newbuf = g_realloc (buffer, *buflen);
6602 p = newbuf + (p-buffer);
6605 mono_metadata_encode_value (slen, p, &p);
6606 memcpy (p, str, slen);
6609 simple_type = klass->enum_basetype->type;
6613 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6616 *retbuffer = buffer;
6620 * mono_reflection_get_custom_attrs_blob:
6621 * @ctor: custom attribute constructor
6622 * @ctorArgs: arguments o the constructor
6628 * Creates the blob of data that needs to be saved in the metadata and that represents
6629 * the custom attributed described by @ctor, @ctorArgs etc.
6630 * Returns: a Byte array representing the blob of data.
6633 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6636 MonoMethodSignature *sig;
6641 MONO_ARCH_SAVE_REGS;
6643 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6644 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6646 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6648 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6650 p = buffer = g_malloc (buflen);
6651 /* write the prolog */
6654 for (i = 0; i < sig->param_count; ++i) {
6655 arg = mono_array_get (ctorArgs, MonoObject*, i);
6656 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6660 i += mono_array_length (properties);
6662 i += mono_array_length (fields);
6664 *p++ = (i >> 8) & 0xff;
6667 for (i = 0; i < mono_array_length (properties); ++i) {
6672 prop = mono_array_get (properties, gpointer, i);
6673 get_prop_name_and_type (prop, &pname, &ptype);
6674 *p++ = 0x54; /* PROPERTY signature */
6676 /* Preallocate a large enough buffer */
6677 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6678 char *str = type_get_qualified_name (ptype, NULL);
6684 len += strlen (pname);
6686 if ((p-buffer) + 20 + len >= buflen) {
6690 newbuf = g_realloc (buffer, buflen);
6691 p = newbuf + (p-buffer);
6695 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6696 char *str = type_get_qualified_name (ptype, NULL);
6697 int slen = strlen (str);
6701 * This seems to be optional...
6704 mono_metadata_encode_value (slen, p, &p);
6705 memcpy (p, str, slen);
6709 mono_metadata_encode_value (ptype->type, p, &p);
6710 if (ptype->type == MONO_TYPE_SZARRAY)
6711 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6713 len = strlen (pname);
6714 mono_metadata_encode_value (len, p, &p);
6715 memcpy (p, pname, len);
6717 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6724 for (i = 0; i < mono_array_length (fields); ++i) {
6729 field = mono_array_get (fields, gpointer, i);
6730 get_field_name_and_type (field, &fname, &ftype);
6731 *p++ = 0x53; /* FIELD signature */
6732 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6733 char *str = type_get_qualified_name (ftype, NULL);
6734 int slen = strlen (str);
6735 if ((p-buffer) + 10 + slen >= buflen) {
6739 newbuf = g_realloc (buffer, buflen);
6740 p = newbuf + (p-buffer);
6745 * This seems to be optional...
6748 mono_metadata_encode_value (slen, p, &p);
6749 memcpy (p, str, slen);
6753 mono_metadata_encode_value (ftype->type, p, &p);
6754 if (ftype->type == MONO_TYPE_SZARRAY)
6755 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6757 len = strlen (fname);
6758 mono_metadata_encode_value (len, p, &p);
6759 memcpy (p, fname, len);
6761 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6766 g_assert (p - buffer <= buflen);
6767 buflen = p - buffer;
6768 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6769 p = mono_array_addr (result, char, 0);
6770 memcpy (p, buffer, buflen);
6772 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6778 * mono_reflection_setup_internal_class:
6779 * @tb: a TypeBuilder object
6781 * Creates a MonoClass that represents the TypeBuilder.
6782 * This is a trick that lets us simplify a lot of reflection code
6783 * (and will allow us to support Build and Run assemblies easier).
6786 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6788 MonoClass *klass, *parent;
6790 MONO_ARCH_SAVE_REGS;
6793 /* check so we can compile corlib correctly */
6794 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6795 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6796 parent = tb->parent->type->data.klass;
6798 parent = my_mono_class_from_mono_type (tb->parent->type);
6802 /* the type has already being created: it means we just have to change the parent */
6803 if (tb->type.type) {
6804 klass = mono_class_from_mono_type (tb->type.type);
6805 klass->parent = NULL;
6806 /* fool mono_class_setup_parent */
6807 g_free (klass->supertypes);
6808 klass->supertypes = NULL;
6809 mono_class_setup_parent (klass, parent);
6813 klass = g_new0 (MonoClass, 1);
6815 klass->image = &tb->module->dynamic_image->image;
6817 klass->inited = 1; /* we lie to the runtime */
6818 klass->name = mono_string_to_utf8 (tb->name);
6819 klass->name_space = mono_string_to_utf8 (tb->nspace);
6820 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6821 klass->flags = tb->attrs;
6823 klass->element_class = klass;
6824 klass->reflection_info = tb; /* need to pin. */
6826 /* Put into cache so mono_class_get () will find it */
6827 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6830 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6831 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6835 mono_class_setup_parent (klass, parent);
6836 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6837 const char *old_n = klass->name;
6838 /* trick to get relative numbering right when compiling corlib */
6839 klass->name = "BuildingObject";
6840 mono_class_setup_parent (klass, mono_defaults.object_class);
6841 klass->name = old_n;
6843 mono_class_setup_mono_type (klass);
6845 mono_class_setup_supertypes (klass);
6848 * FIXME: handle interfaces.
6851 tb->type.type = &klass->byval_arg;
6853 if (tb->nesting_type) {
6854 g_assert (tb->nesting_type->type);
6855 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6858 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6862 * mono_reflection_setup_generic_class:
6863 * @tb: a TypeBuilder object
6865 * Setup the generic class after all generic parameters have been added.
6868 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6873 MONO_ARCH_SAVE_REGS;
6875 klass = my_mono_class_from_mono_type (tb->type.type);
6877 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6879 if (klass->gen_params || (count == 0))
6882 klass->num_gen_params = count;
6883 klass->gen_params = g_new0 (MonoGenericParam, count);
6885 for (i = 0; i < count; i++) {
6886 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6887 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6892 * mono_reflection_create_internal_class:
6893 * @tb: a TypeBuilder object
6895 * Actually create the MonoClass that is associated with the TypeBuilder.
6898 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6902 MONO_ARCH_SAVE_REGS;
6904 klass = my_mono_class_from_mono_type (tb->type.type);
6906 if (klass->enumtype && klass->enum_basetype == NULL) {
6907 MonoReflectionFieldBuilder *fb;
6909 g_assert (tb->fields != NULL);
6910 g_assert (mono_array_length (tb->fields) >= 1);
6912 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6914 klass->enum_basetype = fb->type->type;
6915 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6916 if (!klass->element_class)
6917 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6918 klass->instance_size = klass->element_class->instance_size;
6919 klass->size_inited = 1;
6921 * this is almost safe to do with enums and it's needed to be able
6922 * to create objects of the enum type (for use in SetConstant).
6924 /* FIXME: Does this mean enums can't have method overrides ? */
6925 mono_class_setup_vtable (klass, NULL, 0);
6929 static MonoMarshalSpec*
6930 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6931 MonoReflectionMarshal *minfo)
6933 MonoMarshalSpec *res;
6935 res = g_new0 (MonoMarshalSpec, 1);
6936 res->native = minfo->type;
6938 switch (minfo->type) {
6939 case MONO_NATIVE_LPARRAY:
6940 res->data.array_data.elem_type = minfo->eltype;
6941 res->data.array_data.param_num = 0; /* Not yet */
6942 res->data.array_data.num_elem = minfo->count;
6945 case MONO_NATIVE_BYVALTSTR:
6946 case MONO_NATIVE_BYVALARRAY:
6947 res->data.array_data.num_elem = minfo->count;
6950 case MONO_NATIVE_CUSTOM:
6951 if (minfo->marshaltyperef)
6952 res->data.custom_data.custom_name =
6953 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6955 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6966 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6967 ReflectionMethodBuilder *rmb,
6968 MonoMethodSignature *sig)
6971 MonoMethodNormal *pm;
6972 MonoMarshalSpec **specs;
6973 MonoReflectionMethodAux *method_aux;
6976 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6977 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6978 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6981 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6983 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6985 pm = (MonoMethodNormal*)m;
6988 m->flags = rmb->attrs;
6989 m->iflags = rmb->iattrs;
6990 m->name = mono_string_to_utf8 (rmb->name);
6994 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6996 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6997 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7000 m->signature->pinvoke = 1;
7001 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7003 m->signature->pinvoke = 1;
7005 } else if (!m->klass->dummy &&
7006 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7007 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7008 MonoMethodHeader *header;
7010 gint32 max_stack, i;
7011 gint32 num_locals = 0;
7012 gint32 num_clauses = 0;
7016 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7017 code_size = rmb->ilgen->code_len;
7018 max_stack = rmb->ilgen->max_stack;
7019 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7020 if (rmb->ilgen->ex_handlers)
7021 num_clauses = method_count_clauses (rmb->ilgen);
7024 code = mono_array_addr (rmb->code, guint8, 0);
7025 code_size = mono_array_length (rmb->code);
7026 /* we probably need to run a verifier on the code... */
7036 header = g_malloc0 (sizeof (MonoMethodHeader) +
7037 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7038 header->code_size = code_size;
7039 header->code = g_malloc (code_size);
7040 memcpy ((char*)header->code, code, code_size);
7041 header->max_stack = max_stack;
7042 header->init_locals = rmb->init_locals;
7043 header->num_locals = num_locals;
7045 for (i = 0; i < num_locals; ++i) {
7046 MonoReflectionLocalBuilder *lb =
7047 mono_array_get (rmb->ilgen->locals,
7048 MonoReflectionLocalBuilder*, i);
7050 header->locals [i] = g_new0 (MonoType, 1);
7051 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7054 header->num_clauses = num_clauses;
7056 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7061 if (rmb->generic_params) {
7062 int count = mono_array_length (rmb->generic_params);
7063 header->gen_params = g_new0 (MonoGenericParam, count);
7064 for (i = 0; i < count; i++) {
7065 MonoReflectionGenericParam *gp =
7066 mono_array_get (rmb->generic_params,
7067 MonoReflectionGenericParam*, i);
7069 header->gen_params [i] = *gp->type.type->data.generic_param;
7073 pm->header = header;
7077 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7080 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7082 for (i = 0; i < rmb->nrefs; ++i)
7083 mw->data = g_list_append (mw->data, rmb->refs [i]);
7088 /* Parameter names */
7091 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7092 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7093 for (i = 0; i <= m->signature->param_count; ++i) {
7094 MonoReflectionParamBuilder *pb;
7095 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7097 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7099 if (!method_aux->param_cattr)
7100 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7101 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7107 /* Parameter marshalling */
7110 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7111 MonoReflectionParamBuilder *pb;
7112 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7113 if (pb->marshal_info) {
7115 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7116 specs [pb->position] =
7117 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7121 if (specs != NULL) {
7123 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7124 method_aux->param_marshall = specs;
7127 if (klass->image->dynamic && method_aux)
7128 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7134 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7136 ReflectionMethodBuilder rmb;
7137 MonoMethodSignature *sig;
7139 sig = ctor_builder_to_signature (mb);
7141 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7143 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7144 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7146 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7147 /* ilgen is no longer needed */
7155 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7157 ReflectionMethodBuilder rmb;
7158 MonoMethodSignature *sig;
7160 sig = method_builder_to_signature (mb);
7162 reflection_methodbuilder_from_method_builder (&rmb, mb);
7164 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7165 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7167 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7168 /* ilgen is no longer needed */
7174 static MonoClassField*
7175 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7177 MonoClassField *field;
7184 field = g_new0 (MonoClassField, 1);
7186 field->name = mono_string_to_utf8 (fb->name);
7188 /* FIXME: handle type modifiers */
7189 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7190 field->type->attrs = fb->attrs;
7192 field->type = fb->type->type;
7194 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7195 field->data = mono_array_addr (fb->rva_data, char, 0);
7196 if (fb->offset != -1)
7197 field->offset = fb->offset;
7198 field->parent = klass;
7200 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7202 if (fb->def_value) {
7203 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7204 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7205 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7206 /* Copy the data from the blob since it might get realloc-ed */
7207 p = assembly->blob.data + idx;
7208 len = mono_metadata_decode_blob_size (p, &p2);
7210 field->data = g_malloc (len);
7211 memcpy (field->data, p, len);
7218 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7222 MonoReflectionTypeBuilder *tb = NULL;
7223 MonoGenericInst *ginst;
7228 klass = mono_class_from_mono_type (type->type);
7229 if (!klass->gen_params && !klass->generic_inst &&
7230 !(klass->nested_in && klass->nested_in->gen_params))
7233 mono_loader_lock ();
7235 domain = mono_object_domain (type);
7237 ginst = g_new0 (MonoGenericInst, 1);
7239 if (!klass->generic_inst) {
7240 ginst->type_argc = type_argc;
7241 ginst->type_argv = types;
7243 for (i = 0; i < ginst->type_argc; ++i) {
7244 if (!ginst->is_open)
7245 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7248 ginst->generic_type = &klass->byval_arg;
7250 MonoGenericInst *kginst = klass->generic_inst;
7252 ginst->type_argc = kginst->type_argc;
7253 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7255 for (i = 0; i < ginst->type_argc; i++) {
7256 MonoType *t = kginst->type_argv [i];
7258 if (t->type == MONO_TYPE_VAR)
7259 t = types [t->data.generic_param->num];
7261 if (!ginst->is_open)
7262 ginst->is_open = mono_class_is_open_constructed_type (t);
7264 ginst->type_argv [i] = t;
7267 ginst->generic_type = kginst->generic_type;
7270 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7273 mono_loader_unlock ();
7277 ginst->context = g_new0 (MonoGenericContext, 1);
7278 ginst->context->ginst = ginst;
7280 geninst = g_new0 (MonoType, 1);
7281 geninst->type = MONO_TYPE_GENERICINST;
7282 geninst->data.generic_inst = ginst;
7284 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7285 tb = (MonoReflectionTypeBuilder *) type;
7287 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7288 ginst->is_dynamic = TRUE;
7289 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7290 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7291 MonoReflectionType *rgt = rgi->generic_type;
7293 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7294 tb = (MonoReflectionTypeBuilder *) rgt;
7296 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7297 ginst->is_dynamic = TRUE;
7299 icount = klass->interface_count;
7301 ginst->ifaces = g_new0 (MonoType *, icount);
7302 ginst->count_ifaces = icount;
7304 for (i = 0; i < icount; i++) {
7305 MonoReflectionType *itype;
7308 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7310 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7311 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7312 if (!ginst->ifaces [i])
7313 ginst->ifaces [i] = itype->type;
7316 mono_class_create_generic (ginst);
7318 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7320 mono_loader_unlock ();
7326 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7328 MonoClass *klass, *pklass = NULL;
7329 MonoReflectionType *parent = NULL;
7331 MonoReflectionTypeBuilder *tb = NULL;
7332 MonoGenericInst *ginst;
7335 domain = mono_object_domain (type);
7336 klass = mono_class_from_mono_type (type->type);
7338 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7339 tb = (MonoReflectionTypeBuilder *) type;
7342 parent = tb->parent;
7343 pklass = mono_class_from_mono_type (parent->type);
7346 pklass = klass->parent;
7348 parent = mono_type_get_object (domain, &pklass->byval_arg);
7351 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7355 ginst = geninst->data.generic_inst;
7357 if (pklass && pklass->generic_inst)
7358 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7363 MonoReflectionMethod*
7364 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7366 MonoMethod *method, *inflated;
7367 MonoReflectionMethodBuilder *mb = NULL;
7368 MonoGenericMethod *gmethod;
7369 MonoGenericContext *context;
7372 MONO_ARCH_SAVE_REGS;
7373 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7374 MonoReflectionTypeBuilder *tb;
7377 mb = (MonoReflectionMethodBuilder *) rmethod;
7378 tb = (MonoReflectionTypeBuilder *) mb->type;
7379 klass = mono_class_from_mono_type (tb->type.type);
7381 method = methodbuilder_to_mono_method (klass, mb);
7383 method = rmethod->method;
7385 count = method->signature->generic_param_count;
7386 if (count != mono_array_length (types))
7389 gmethod = g_new0 (MonoGenericMethod, 1);
7390 gmethod->mtype_argc = count;
7391 gmethod->mtype_argv = g_new0 (MonoType *, count);
7392 for (i = 0; i < count; i++) {
7393 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7394 gmethod->mtype_argv [i] = garg->type;
7397 gmethod->reflection_info = rmethod;
7399 context = g_new0 (MonoGenericContext, 1);
7400 context->ginst = method->klass->generic_inst;
7401 context->gmethod = gmethod;
7403 inflated = mono_class_inflate_generic_method (method, context, NULL);
7405 return mono_method_get_object (
7406 mono_object_domain (rmethod), inflated, NULL);
7410 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7412 MonoGenericMethod *gmethod;
7413 MonoGenericInst *ginst;
7414 MonoGenericContext *context;
7417 ginst = type->type.type->data.generic_inst;
7419 gmethod = g_new0 (MonoGenericMethod, 1);
7420 gmethod->reflection_info = obj;
7422 gmethod->mtype_argc = method->signature->generic_param_count;
7423 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7425 for (i = 0; i < gmethod->mtype_argc; i++) {
7426 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7427 MonoGenericParam *gparam = &mn->header->gen_params [i];
7429 g_assert (gparam->pklass);
7430 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7433 context = g_new0 (MonoGenericContext, 1);
7434 context->ginst = ginst;
7435 context->gmethod = gmethod;
7437 return mono_class_inflate_generic_method (method, context, ginst->klass);
7441 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7446 klass = mono_class_from_mono_type (type->type.type);
7448 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7449 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7450 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7451 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7452 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7453 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7454 method = ((MonoReflectionMethod *) obj)->method;
7456 method = NULL; /* prevent compiler warning */
7457 g_assert_not_reached ();
7460 return inflate_mono_method (type, method, obj);
7464 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7465 MonoArray *methods, MonoArray *ctors,
7466 MonoArray *fields, MonoArray *properties,
7469 MonoGenericInst *ginst;
7470 MonoDynamicGenericInst *dginst;
7471 MonoClass *klass, *gklass, *pklass;
7474 MONO_ARCH_SAVE_REGS;
7476 klass = mono_class_from_mono_type (type->type.type);
7477 ginst = type->type.type->data.generic_inst;
7479 if (ginst->initialized)
7482 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7484 gklass = mono_class_from_mono_type (ginst->generic_type);
7485 mono_class_init (gklass);
7488 pklass = mono_class_from_mono_type (ginst->parent);
7490 pklass = gklass->parent;
7492 mono_class_setup_parent (klass, pklass);
7494 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7495 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7496 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7497 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7498 dginst->count_events = events ? mono_array_length (events) : 0;
7500 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7501 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7502 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7503 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7504 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7506 for (i = 0; i < dginst->count_methods; i++) {
7507 MonoObject *obj = mono_array_get (methods, gpointer, i);
7509 dginst->methods [i] = inflate_method (type, obj);
7512 for (i = 0; i < dginst->count_ctors; i++) {
7513 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7515 dginst->ctors [i] = inflate_method (type, obj);
7518 for (i = 0; i < dginst->count_fields; i++) {
7519 MonoObject *obj = mono_array_get (fields, gpointer, i);
7520 MonoClassField *field;
7521 MonoInflatedField *ifield;
7523 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7524 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7525 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7526 field = ((MonoReflectionField *) obj)->field;
7528 field = NULL; /* prevent compiler warning */
7529 g_assert_not_reached ();
7532 ifield = g_new0 (MonoInflatedField, 1);
7533 ifield->generic_type = field->type;
7534 ifield->reflection_info = obj;
7536 dginst->fields [i] = *field;
7537 dginst->fields [i].generic_info = ifield;
7538 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7541 for (i = 0; i < dginst->count_properties; i++) {
7542 MonoObject *obj = mono_array_get (properties, gpointer, i);
7543 MonoProperty *property = &dginst->properties [i];
7545 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7546 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7548 property->parent = klass;
7549 property->attrs = pb->attrs;
7550 property->name = mono_string_to_utf8 (pb->name);
7552 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7554 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7555 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7556 *property = *((MonoReflectionProperty *) obj)->property;
7559 property->get = inflate_mono_method (type, property->get, NULL);
7561 property->set = inflate_mono_method (type, property->set, NULL);
7563 g_assert_not_reached ();
7566 for (i = 0; i < dginst->count_events; i++) {
7567 MonoObject *obj = mono_array_get (events, gpointer, i);
7568 MonoEvent *event = &dginst->events [i];
7570 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7571 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7573 event->parent = klass;
7574 event->attrs = eb->attrs;
7575 event->name = mono_string_to_utf8 (eb->name);
7577 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7578 if (eb->remove_method)
7579 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7580 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7581 *event = *((MonoReflectionEvent *) obj)->event;
7584 event->add = inflate_mono_method (type, event->add, NULL);
7586 event->remove = inflate_mono_method (type, event->remove, NULL);
7588 g_assert_not_reached ();
7591 ginst->initialized = TRUE;
7595 ensure_runtime_vtable (MonoClass *klass)
7597 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7598 int i, num, j, onum;
7599 MonoMethod **overrides;
7601 if (!tb || klass->wastypebuilder)
7604 ensure_runtime_vtable (klass->parent);
7606 num = tb->ctors? mono_array_length (tb->ctors): 0;
7607 num += tb->num_methods;
7608 klass->method.count = num;
7609 klass->methods = g_new (MonoMethod*, num);
7610 num = tb->ctors? mono_array_length (tb->ctors): 0;
7611 for (i = 0; i < num; ++i)
7612 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7613 num = tb->num_methods;
7615 for (i = 0; i < num; ++i)
7616 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7618 klass->wastypebuilder = TRUE;
7619 if (tb->interfaces) {
7620 klass->interface_count = mono_array_length (tb->interfaces);
7621 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7622 for (i = 0; i < klass->interface_count; ++i) {
7623 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7624 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7628 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7629 for (i = 0; i < klass->method.count; ++i)
7630 klass->methods [i]->slot = i;
7635 for (i = 0; i < tb->num_methods; ++i) {
7636 MonoReflectionMethodBuilder *mb =
7637 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7638 if (mb->override_method)
7643 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7647 for (i = 0; i < tb->num_methods; ++i) {
7648 MonoReflectionMethodBuilder *mb =
7649 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7650 if (mb->override_method) {
7651 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7652 overrides [onum * 2] =
7653 mb->override_method->method;
7654 overrides [onum * 2 + 1] =
7657 g_assert (mb->mhandle);
7664 mono_class_setup_vtable (klass, overrides, onum);
7668 typebuilder_setup_fields (MonoClass *klass)
7670 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7671 MonoReflectionFieldBuilder *fb;
7672 MonoClassField *field;
7677 klass->field.count = tb->num_fields;
7678 klass->field.first = 0;
7679 klass->field.last = klass->field.count;
7681 if (!klass->field.count)
7684 klass->fields = g_new0 (MonoClassField, klass->field.count);
7686 for (i = 0; i < klass->field.count; ++i) {
7687 fb = mono_array_get (tb->fields, gpointer, i);
7688 field = &klass->fields [i];
7689 field->name = mono_string_to_utf8 (fb->name);
7691 /* FIXME: handle type modifiers */
7692 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7693 field->type->attrs = fb->attrs;
7695 field->type = fb->type->type;
7697 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7698 field->data = mono_array_addr (fb->rva_data, char, 0);
7699 if (fb->offset != -1)
7700 field->offset = fb->offset;
7701 field->parent = klass;
7703 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7705 if (fb->def_value) {
7706 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7707 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7708 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7709 /* Copy the data from the blob since it might get realloc-ed */
7710 p = assembly->blob.data + idx;
7711 len = mono_metadata_decode_blob_size (p, &p2);
7713 field->data = g_malloc (len);
7714 memcpy (field->data, p, len);
7717 mono_class_layout_fields (klass);
7721 typebuilder_setup_properties (MonoClass *klass)
7723 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7724 MonoReflectionPropertyBuilder *pb;
7727 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7728 klass->property.first = 0;
7729 klass->property.last = klass->property.count;
7731 klass->properties = g_new0 (MonoProperty, klass->property.count);
7732 for (i = 0; i < klass->property.count; ++i) {
7733 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7734 klass->properties [i].parent = klass;
7735 klass->properties [i].attrs = pb->attrs;
7736 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7738 klass->properties [i].get = pb->get_method->mhandle;
7740 klass->properties [i].set = pb->set_method->mhandle;
7744 MonoReflectionEvent *
7745 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7747 MonoEvent *event = g_new0 (MonoEvent, 1);
7751 klass = my_mono_class_from_mono_type (tb->type.type);
7753 event->parent = klass;
7754 event->attrs = eb->attrs;
7755 event->name = mono_string_to_utf8 (eb->name);
7757 event->add = eb->add_method->mhandle;
7758 if (eb->remove_method)
7759 event->remove = eb->remove_method->mhandle;
7760 if (eb->raise_method)
7761 event->raise = eb->raise_method->mhandle;
7763 if (eb->other_methods) {
7764 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7765 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7766 MonoReflectionMethodBuilder *mb =
7767 mono_array_get (eb->other_methods,
7768 MonoReflectionMethodBuilder*, j);
7769 event->other [j] = mb->mhandle;
7773 return mono_event_get_object (mono_object_domain (tb), klass, event);
7777 typebuilder_setup_events (MonoClass *klass)
7779 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7780 MonoReflectionEventBuilder *eb;
7783 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7784 klass->event.first = 0;
7785 klass->event.last = klass->event.count;
7787 klass->events = g_new0 (MonoEvent, klass->event.count);
7788 for (i = 0; i < klass->event.count; ++i) {
7789 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7790 klass->events [i].parent = klass;
7791 klass->events [i].attrs = eb->attrs;
7792 klass->events [i].name = mono_string_to_utf8 (eb->name);
7794 klass->events [i].add = eb->add_method->mhandle;
7795 if (eb->remove_method)
7796 klass->events [i].remove = eb->remove_method->mhandle;
7797 if (eb->raise_method)
7798 klass->events [i].raise = eb->raise_method->mhandle;
7800 if (eb->other_methods) {
7801 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7802 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7803 MonoReflectionMethodBuilder *mb =
7804 mono_array_get (eb->other_methods,
7805 MonoReflectionMethodBuilder*, j);
7806 klass->events [i].other [j] = mb->mhandle;
7813 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7816 MonoReflectionType* res;
7818 MONO_ARCH_SAVE_REGS;
7820 klass = my_mono_class_from_mono_type (tb->type.type);
7822 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7825 * Fields to set in klass:
7826 * the various flags: delegate/unicode/contextbound etc.
7829 klass->flags = tb->attrs;
7831 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7832 /* No need to fully construct the type */
7833 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7835 /* enums are done right away */
7836 if (!klass->enumtype)
7837 ensure_runtime_vtable (klass);
7839 /* fields and object layout */
7840 if (klass->parent) {
7841 if (!klass->parent->size_inited)
7842 mono_class_init (klass->parent);
7843 klass->instance_size += klass->parent->instance_size;
7844 klass->class_size += klass->parent->class_size;
7845 klass->min_align = klass->parent->min_align;
7847 klass->instance_size = sizeof (MonoObject);
7848 klass->min_align = 1;
7851 /* FIXME: handle packing_size and instance_size */
7852 typebuilder_setup_fields (klass);
7854 typebuilder_setup_properties (klass);
7856 typebuilder_setup_events (klass);
7858 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7859 /* with enums res == tb: need to fix that. */
7860 if (!klass->enumtype)
7861 g_assert (res != (MonoReflectionType*)tb);
7866 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7868 MonoGenericParam *param;
7871 MONO_ARCH_SAVE_REGS;
7873 param = g_new0 (MonoGenericParam, 1);
7875 param->method = NULL;
7876 param->name = mono_string_to_utf8 (gparam->name);
7877 param->num = gparam->index;
7879 image = &gparam->tbuilder->module->dynamic_image->image;
7880 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7882 param->pklass->reflection_info = gparam;
7884 gparam->type.type = g_new0 (MonoType, 1);
7885 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7886 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7887 gparam->type.type->data.generic_param = param;
7891 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7893 MonoDynamicImage *assembly = sig->module->dynamic_image;
7894 guint32 na = mono_array_length (sig->arguments);
7899 MONO_ARCH_SAVE_REGS;
7901 p = buf = g_malloc (10 + na * 10);
7903 mono_metadata_encode_value (0x07, p, &p);
7904 mono_metadata_encode_value (na, p, &p);
7905 for (i = 0; i < na; ++i) {
7906 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7907 encode_reflection_type (assembly, type, p, &p);
7911 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7912 p = mono_array_addr (result, char, 0);
7913 memcpy (p, buf, buflen);
7920 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7922 MonoDynamicImage *assembly = sig->module->dynamic_image;
7923 guint32 na = mono_array_length (sig->arguments);
7928 MONO_ARCH_SAVE_REGS;
7930 p = buf = g_malloc (10 + na * 10);
7932 mono_metadata_encode_value (0x06, p, &p);
7933 for (i = 0; i < na; ++i) {
7934 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7935 encode_reflection_type (assembly, type, p, &p);
7939 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7940 p = mono_array_addr (result, char, 0);
7941 memcpy (p, buf, buflen);
7948 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7950 ReflectionMethodBuilder rmb;
7951 MonoMethodSignature *sig;
7954 sig = dynamic_method_to_signature (mb);
7956 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7959 * Resolve references.
7961 rmb.nrefs = mb->nrefs;
7962 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7963 for (i = 0; i < mb->nrefs; ++i) {
7964 gpointer ref = resolve_object (mb->module->image,
7965 mono_array_get (mb->refs, MonoObject*, i));
7968 mono_raise_exception (mono_get_exception_type_load (NULL));
7975 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7979 /* ilgen is no longer needed */
7984 * mono_reflection_lookup_dynamic_token:
7986 * Finish the Builder object pointed to by TOKEN and return the corresponding
7987 * runtime structure.
7990 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7992 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7995 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7998 return resolve_object (image, obj);
8002 resolve_object (MonoImage *image, MonoObject *obj)
8004 gpointer result = NULL;
8006 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8007 result = mono_string_intern ((MonoString*)obj);
8010 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8011 MonoReflectionType *tb = (MonoReflectionType*)obj;
8012 result = mono_class_from_mono_type (tb->type);
8015 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8016 result = ((MonoReflectionMethod*)obj)->method;
8019 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8020 result = ((MonoReflectionMethod*)obj)->method;
8023 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8024 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8025 result = mb->mhandle;
8027 /* Type is not yet created */
8028 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8030 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8033 * Hopefully this has been filled in by calling CreateType() on the
8037 * TODO: This won't work if the application finishes another
8038 * TypeBuilder instance instead of this one.
8040 result = mb->mhandle;
8043 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8044 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8046 result = cb->mhandle;
8048 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8050 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8051 result = cb->mhandle;
8054 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8055 result = ((MonoReflectionField*)obj)->field;
8058 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8059 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8060 result = fb->handle;
8063 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8065 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8066 result = fb->handle;
8069 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8070 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8073 klass = tb->type.type->data.klass;
8074 if (klass->wastypebuilder) {
8075 /* Already created */
8079 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8080 result = tb->type.type->data.klass;
8084 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8085 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8086 MonoMethodSignature *sig;
8089 if (helper->arguments)
8090 nargs = mono_array_length (helper->arguments);
8094 sig = mono_metadata_signature_alloc (image, nargs);
8095 sig->explicit_this = helper->call_conv & 64;
8096 sig->hasthis = helper->call_conv & 32;
8098 if (helper->call_conv == 0) /* unmanaged */
8099 sig->call_convention = helper->unmanaged_call_conv - 1;
8101 if (helper->call_conv & 0x02)
8102 sig->call_convention = MONO_CALL_VARARG;
8104 sig->call_convention = MONO_CALL_DEFAULT;
8106 sig->param_count = nargs;
8107 /* TODO: Copy type ? */
8108 sig->ret = helper->return_type->type;
8109 for (i = 0; i < nargs; ++i) {
8110 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8111 sig->params [i] = rt->type;
8117 g_print (obj->vtable->klass->name);
8118 g_assert_not_reached ();