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_STRING:
5867 for (i = 0; i < alen; i++) {
5868 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5869 mono_array_set (arr, gpointer, i, item);
5873 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5879 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5885 type_is_reference (MonoType *type)
5887 switch (type->type) {
5888 case MONO_TYPE_BOOLEAN:
5889 case MONO_TYPE_CHAR:
5902 case MONO_TYPE_VALUETYPE:
5910 free_param_data (MonoMethodSignature *sig, void **params) {
5912 for (i = 0; i < sig->param_count; ++i) {
5913 if (!type_is_reference (sig->params [i]))
5914 g_free (params [i]);
5919 * Find the method index in the metadata methodDef table.
5920 * Later put these three helper methods in metadata and export them.
5923 find_method_index (MonoMethod *method) {
5924 MonoClass *klass = method->klass;
5927 for (i = 0; i < klass->method.count; ++i) {
5928 if (method == klass->methods [i])
5929 return klass->method.first + 1 + i;
5935 * Find the field index in the metadata FieldDef table.
5938 find_field_index (MonoClass *klass, MonoClassField *field) {
5941 for (i = 0; i < klass->field.count; ++i) {
5942 if (field == &klass->fields [i])
5943 return klass->field.first + 1 + i;
5949 * Find the property index in the metadata Property table.
5952 find_property_index (MonoClass *klass, MonoProperty *property) {
5955 for (i = 0; i < klass->property.count; ++i) {
5956 if (property == &klass->properties [i])
5957 return klass->property.first + 1 + i;
5963 * Find the event index in the metadata Event table.
5966 find_event_index (MonoClass *klass, MonoEvent *event) {
5969 for (i = 0; i < klass->event.count; ++i) {
5970 if (event == &klass->events [i])
5971 return klass->event.first + 1 + i;
5977 create_custom_attr (MonoImage *image, MonoMethod *method,
5978 const char *data, guint32 len)
5980 const char *p = data;
5982 guint32 i, j, num_named;
5986 mono_class_init (method->klass);
5989 attr = mono_object_new (mono_domain_get (), method->klass);
5990 mono_runtime_invoke (method, attr, NULL, NULL);
5994 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5997 /*g_print ("got attr %s\n", method->klass->name);*/
5999 params = g_new (void*, method->signature->param_count);
6003 for (i = 0; i < method->signature->param_count; ++i) {
6004 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6008 attr = mono_object_new (mono_domain_get (), method->klass);
6009 mono_runtime_invoke (method, attr, params, NULL);
6010 free_param_data (method->signature, params);
6012 num_named = read16 (named);
6014 for (j = 0; j < num_named; j++) {
6016 char *name, named_type, data_type;
6017 named_type = *named++;
6018 data_type = *named++; /* type of data */
6019 if (data_type == 0x55) {
6022 type_len = mono_metadata_decode_blob_size (named, &named);
6023 type_name = g_malloc (type_len + 1);
6024 memcpy (type_name, named, type_len);
6025 type_name [type_len] = 0;
6027 /* FIXME: lookup the type and check type consistency */
6028 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6029 /* this seems to be the type of the element of the array */
6030 /* g_print ("skipping 0x%02x after prop\n", *named); */
6033 name_len = mono_metadata_decode_blob_size (named, &named);
6034 name = g_malloc (name_len + 1);
6035 memcpy (name, named, name_len);
6036 name [name_len] = 0;
6038 if (named_type == 0x53) {
6039 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6040 void *val = load_cattr_value (image, field->type, named, &named);
6041 mono_field_set_value (attr, field, val);
6042 if (!type_is_reference (field->type))
6044 } else if (named_type == 0x54) {
6047 MonoType *prop_type;
6049 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6050 /* can we have more that 1 arg in a custom attr named property? */
6051 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6052 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6053 mono_property_set_value (prop, attr, pparams, NULL);
6054 if (!type_is_reference (prop_type))
6055 g_free (pparams [0]);
6064 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6071 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6072 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6073 for (i = 0; i < cinfo->num_attrs; ++i) {
6074 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6075 mono_array_set (result, gpointer, i, attr);
6081 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6083 guint32 mtoken, i, len;
6084 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6086 MonoCustomAttrInfo *ainfo;
6087 GList *tmp, *list = NULL;
6090 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6092 i = mono_metadata_custom_attrs_from_index (image, idx);
6096 while (i < ca->rows) {
6097 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6099 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6102 len = g_list_length (list);
6105 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6106 ainfo->num_attrs = len;
6107 ainfo->image = image;
6108 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6109 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6110 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6111 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6112 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6113 mtoken |= MONO_TOKEN_METHOD_DEF;
6115 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6116 mtoken |= MONO_TOKEN_MEMBER_REF;
6119 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6122 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6123 if (!ainfo->attrs [i].ctor)
6124 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6125 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6126 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6127 ainfo->attrs [i].data = data;
6135 mono_custom_attrs_from_method (MonoMethod *method)
6137 MonoCustomAttrInfo *cinfo;
6140 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6142 idx = find_method_index (method);
6143 idx <<= MONO_CUSTOM_ATTR_BITS;
6144 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6145 return mono_custom_attrs_from_index (method->klass->image, idx);
6149 mono_custom_attrs_from_class (MonoClass *klass)
6151 MonoCustomAttrInfo *cinfo;
6154 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6156 idx = mono_metadata_token_index (klass->type_token);
6157 idx <<= MONO_CUSTOM_ATTR_BITS;
6158 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6159 return mono_custom_attrs_from_index (klass->image, idx);
6163 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6165 MonoCustomAttrInfo *cinfo;
6168 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6170 idx = 1; /* there is only one assembly */
6171 idx <<= MONO_CUSTOM_ATTR_BITS;
6172 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6173 return mono_custom_attrs_from_index (assembly->image, idx);
6176 static MonoCustomAttrInfo*
6177 mono_custom_attrs_from_module (MonoImage *image)
6179 MonoCustomAttrInfo *cinfo;
6182 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6184 idx = 1; /* there is only one module */
6185 idx <<= MONO_CUSTOM_ATTR_BITS;
6186 idx |= MONO_CUSTOM_ATTR_MODULE;
6187 return mono_custom_attrs_from_index (image, idx);
6191 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6193 MonoCustomAttrInfo *cinfo;
6196 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6198 idx = find_property_index (klass, property);
6199 idx <<= MONO_CUSTOM_ATTR_BITS;
6200 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6201 return mono_custom_attrs_from_index (klass->image, idx);
6205 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6207 MonoCustomAttrInfo *cinfo;
6210 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6212 idx = find_event_index (klass, event);
6213 idx <<= MONO_CUSTOM_ATTR_BITS;
6214 idx |= MONO_CUSTOM_ATTR_EVENT;
6215 return mono_custom_attrs_from_index (klass->image, idx);
6219 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6221 MonoCustomAttrInfo *cinfo;
6224 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6226 idx = find_field_index (klass, field);
6227 idx <<= MONO_CUSTOM_ATTR_BITS;
6228 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6229 return mono_custom_attrs_from_index (klass->image, idx);
6233 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6236 guint32 i, idx, method_index;
6237 guint32 param_list, param_last, param_pos, found;
6239 MonoReflectionMethodAux *aux;
6241 if (method->klass->image->dynamic) {
6242 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6243 if (!aux || !aux->param_cattr)
6245 return aux->param_cattr [param];
6248 image = method->klass->image;
6249 method_index = find_method_index (method);
6250 ca = &image->tables [MONO_TABLE_METHOD];
6252 if (method->klass->generic_inst || method->klass->gen_params ||
6253 method->signature->generic_param_count) {
6254 /* FIXME FIXME FIXME */
6258 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6259 if (method_index == ca->rows) {
6260 ca = &image->tables [MONO_TABLE_PARAM];
6261 param_last = ca->rows + 1;
6263 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6264 ca = &image->tables [MONO_TABLE_PARAM];
6267 for (i = param_list; i < param_last; ++i) {
6268 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6269 if (param_pos == param) {
6277 idx <<= MONO_CUSTOM_ATTR_BITS;
6278 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6279 return mono_custom_attrs_from_index (image, idx);
6283 * mono_reflection_get_custom_attrs:
6284 * @obj: a reflection object handle
6286 * Return an array with all the custom attributes defined of the
6287 * reflection handle @obj. The objects are fully build.
6290 mono_reflection_get_custom_attrs (MonoObject *obj)
6294 MonoCustomAttrInfo *cinfo = NULL;
6296 MONO_ARCH_SAVE_REGS;
6298 klass = obj->vtable->klass;
6299 /* FIXME: need to handle: Module */
6300 if (klass == mono_defaults.monotype_class) {
6301 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6302 klass = mono_class_from_mono_type (rtype->type);
6303 cinfo = mono_custom_attrs_from_class (klass);
6304 } else if (strcmp ("Assembly", klass->name) == 0) {
6305 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6306 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6307 } else if (strcmp ("Module", klass->name) == 0) {
6308 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6309 cinfo = mono_custom_attrs_from_module (module->image);
6310 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6311 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6312 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6313 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6314 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6315 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6316 } else if (strcmp ("MonoField", klass->name) == 0) {
6317 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6318 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6319 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6320 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6321 cinfo = mono_custom_attrs_from_method (rmethod->method);
6322 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6323 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6324 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6325 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6326 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6327 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6328 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6329 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6330 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6331 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6332 } else { /* handle other types here... */
6333 g_error ("get custom attrs not yet supported for %s", klass->name);
6337 result = mono_custom_attrs_construct (cinfo);
6339 mono_custom_attrs_free (cinfo);
6341 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6342 result = mono_array_new (mono_domain_get (), klass, 0);
6348 static MonoMethodSignature*
6349 parameters_to_signature (MonoArray *parameters) {
6350 MonoMethodSignature *sig;
6353 count = parameters? mono_array_length (parameters): 0;
6355 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6356 sig->param_count = count;
6357 sig->sentinelpos = -1; /* FIXME */
6358 for (i = 0; i < count; ++i) {
6359 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6360 sig->params [i] = pt->type;
6365 static MonoMethodSignature*
6366 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6367 MonoMethodSignature *sig;
6369 sig = parameters_to_signature (ctor->parameters);
6370 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6371 sig->ret = &mono_defaults.void_class->byval_arg;
6375 static MonoMethodSignature*
6376 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6377 MonoMethodSignature *sig;
6379 sig = parameters_to_signature (method->parameters);
6380 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6381 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6382 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6386 static MonoMethodSignature*
6387 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6388 MonoMethodSignature *sig;
6390 sig = parameters_to_signature (method->parameters);
6391 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6392 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6393 sig->generic_param_count = 0;
6398 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6400 MonoClass *klass = mono_object_class (prop);
6401 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6402 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6403 *name = mono_string_to_utf8 (pb->name);
6404 *type = pb->type->type;
6406 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6407 *name = g_strdup (p->property->name);
6408 if (p->property->get)
6409 *type = p->property->get->signature->ret;
6411 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6416 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6418 MonoClass *klass = mono_object_class (field);
6419 if (strcmp (klass->name, "FieldBuilder") == 0) {
6420 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6421 *name = mono_string_to_utf8 (fb->name);
6422 *type = fb->type->type;
6424 MonoReflectionField *f = (MonoReflectionField *)field;
6425 *name = g_strdup (f->field->name);
6426 *type = f->field->type;
6431 * Encode a value in a custom attribute stream of bytes.
6432 * The value to encode is either supplied as an object in argument val
6433 * (valuetypes are boxed), or as a pointer to the data in the
6435 * @type represents the type of the value
6436 * @buffer is the start of the buffer
6437 * @p the current position in the buffer
6438 * @buflen contains the size of the buffer and is used to return the new buffer size
6439 * if this needs to be realloced.
6440 * @retbuffer and @retp return the start and the position of the buffer
6443 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6445 MonoTypeEnum simple_type;
6447 if ((p-buffer) + 10 >= *buflen) {
6450 newbuf = g_realloc (buffer, *buflen);
6451 p = newbuf + (p-buffer);
6455 argval = ((char*)arg + sizeof (MonoObject));
6456 simple_type = type->type;
6458 switch (simple_type) {
6459 case MONO_TYPE_BOOLEAN:
6464 case MONO_TYPE_CHAR:
6467 swap_with_size (p, argval, 2, 1);
6473 swap_with_size (p, argval, 4, 1);
6479 swap_with_size (p, argval, 8, 1);
6482 case MONO_TYPE_VALUETYPE:
6483 if (type->data.klass->enumtype) {
6484 simple_type = type->data.klass->enum_basetype->type;
6487 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6490 case MONO_TYPE_STRING: {
6497 str = mono_string_to_utf8 ((MonoString*)arg);
6498 slen = strlen (str);
6499 if ((p-buffer) + 10 + slen >= *buflen) {
6503 newbuf = g_realloc (buffer, *buflen);
6504 p = newbuf + (p-buffer);
6507 mono_metadata_encode_value (slen, p, &p);
6508 memcpy (p, str, slen);
6513 case MONO_TYPE_CLASS: {
6521 k = mono_object_class (arg);
6522 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6523 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6524 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6526 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6527 slen = strlen (str);
6528 if ((p-buffer) + 10 + slen >= *buflen) {
6532 newbuf = g_realloc (buffer, *buflen);
6533 p = newbuf + (p-buffer);
6536 mono_metadata_encode_value (slen, p, &p);
6537 memcpy (p, str, slen);
6542 case MONO_TYPE_SZARRAY: {
6544 MonoClass *eclass, *arg_eclass;
6547 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6550 len = mono_array_length ((MonoArray*)arg);
6552 *p++ = (len >> 8) & 0xff;
6553 *p++ = (len >> 16) & 0xff;
6554 *p++ = (len >> 24) & 0xff;
6556 *retbuffer = buffer;
6557 eclass = type->data.klass;
6558 arg_eclass = mono_object_class (arg)->element_class;
6559 if (eclass->valuetype && arg_eclass->valuetype) {
6560 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6561 int elsize = mono_class_array_element_size (eclass);
6562 for (i = 0; i < len; ++i) {
6563 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6567 for (i = 0; i < len; ++i) {
6568 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6573 /* it may be a boxed value or a Type */
6574 case MONO_TYPE_OBJECT: {
6575 MonoClass *klass = mono_object_class (arg);
6579 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6582 } else if (klass->enumtype) {
6584 } else if (klass == mono_defaults.string_class) {
6585 simple_type = MONO_TYPE_STRING;
6588 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6589 *p++ = simple_type = klass->byval_arg.type;
6592 g_error ("unhandled type in custom attr");
6594 str = type_get_qualified_name (klass->enum_basetype, NULL);
6595 slen = strlen (str);
6596 if ((p-buffer) + 10 + slen >= *buflen) {
6600 newbuf = g_realloc (buffer, *buflen);
6601 p = newbuf + (p-buffer);
6604 mono_metadata_encode_value (slen, p, &p);
6605 memcpy (p, str, slen);
6608 simple_type = klass->enum_basetype->type;
6612 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6615 *retbuffer = buffer;
6619 * mono_reflection_get_custom_attrs_blob:
6620 * @ctor: custom attribute constructor
6621 * @ctorArgs: arguments o the constructor
6627 * Creates the blob of data that needs to be saved in the metadata and that represents
6628 * the custom attributed described by @ctor, @ctorArgs etc.
6629 * Returns: a Byte array representing the blob of data.
6632 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
6635 MonoMethodSignature *sig;
6640 MONO_ARCH_SAVE_REGS;
6642 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6643 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6645 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6647 g_assert (mono_array_length (ctorArgs) == sig->param_count);
6649 p = buffer = g_malloc (buflen);
6650 /* write the prolog */
6653 for (i = 0; i < sig->param_count; ++i) {
6654 arg = mono_array_get (ctorArgs, MonoObject*, i);
6655 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6659 i += mono_array_length (properties);
6661 i += mono_array_length (fields);
6663 *p++ = (i >> 8) & 0xff;
6666 for (i = 0; i < mono_array_length (properties); ++i) {
6671 prop = mono_array_get (properties, gpointer, i);
6672 get_prop_name_and_type (prop, &pname, &ptype);
6673 *p++ = 0x54; /* PROPERTY signature */
6675 /* Preallocate a large enough buffer */
6676 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6677 char *str = type_get_qualified_name (ptype, NULL);
6683 len += strlen (pname);
6685 if ((p-buffer) + 20 + len >= buflen) {
6689 newbuf = g_realloc (buffer, buflen);
6690 p = newbuf + (p-buffer);
6694 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6695 char *str = type_get_qualified_name (ptype, NULL);
6696 int slen = strlen (str);
6700 * This seems to be optional...
6703 mono_metadata_encode_value (slen, p, &p);
6704 memcpy (p, str, slen);
6708 mono_metadata_encode_value (ptype->type, p, &p);
6709 if (ptype->type == MONO_TYPE_SZARRAY)
6710 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6712 len = strlen (pname);
6713 mono_metadata_encode_value (len, p, &p);
6714 memcpy (p, pname, len);
6716 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6723 for (i = 0; i < mono_array_length (fields); ++i) {
6728 field = mono_array_get (fields, gpointer, i);
6729 get_field_name_and_type (field, &fname, &ftype);
6730 *p++ = 0x53; /* FIELD signature */
6731 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6732 char *str = type_get_qualified_name (ftype, NULL);
6733 int slen = strlen (str);
6734 if ((p-buffer) + 10 + slen >= buflen) {
6738 newbuf = g_realloc (buffer, buflen);
6739 p = newbuf + (p-buffer);
6744 * This seems to be optional...
6747 mono_metadata_encode_value (slen, p, &p);
6748 memcpy (p, str, slen);
6752 mono_metadata_encode_value (ftype->type, p, &p);
6753 if (ftype->type == MONO_TYPE_SZARRAY)
6754 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6756 len = strlen (fname);
6757 mono_metadata_encode_value (len, p, &p);
6758 memcpy (p, fname, len);
6760 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6765 g_assert (p - buffer <= buflen);
6766 buflen = p - buffer;
6767 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6768 p = mono_array_addr (result, char, 0);
6769 memcpy (p, buffer, buflen);
6771 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6777 * mono_reflection_setup_internal_class:
6778 * @tb: a TypeBuilder object
6780 * Creates a MonoClass that represents the TypeBuilder.
6781 * This is a trick that lets us simplify a lot of reflection code
6782 * (and will allow us to support Build and Run assemblies easier).
6785 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6787 MonoClass *klass, *parent;
6789 MONO_ARCH_SAVE_REGS;
6792 /* check so we can compile corlib correctly */
6793 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6794 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6795 parent = tb->parent->type->data.klass;
6797 parent = my_mono_class_from_mono_type (tb->parent->type);
6801 /* the type has already being created: it means we just have to change the parent */
6802 if (tb->type.type) {
6803 klass = mono_class_from_mono_type (tb->type.type);
6804 klass->parent = NULL;
6805 /* fool mono_class_setup_parent */
6806 g_free (klass->supertypes);
6807 klass->supertypes = NULL;
6808 mono_class_setup_parent (klass, parent);
6812 klass = g_new0 (MonoClass, 1);
6814 klass->image = &tb->module->dynamic_image->image;
6816 klass->inited = 1; /* we lie to the runtime */
6817 klass->name = mono_string_to_utf8 (tb->name);
6818 klass->name_space = mono_string_to_utf8 (tb->nspace);
6819 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6820 klass->flags = tb->attrs;
6822 klass->element_class = klass;
6823 klass->reflection_info = tb; /* need to pin. */
6825 /* Put into cache so mono_class_get () will find it */
6826 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6829 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6830 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6834 mono_class_setup_parent (klass, parent);
6835 else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6836 const char *old_n = klass->name;
6837 /* trick to get relative numbering right when compiling corlib */
6838 klass->name = "BuildingObject";
6839 mono_class_setup_parent (klass, mono_defaults.object_class);
6840 klass->name = old_n;
6842 mono_class_setup_mono_type (klass);
6844 mono_class_setup_supertypes (klass);
6847 * FIXME: handle interfaces.
6850 tb->type.type = &klass->byval_arg;
6852 if (tb->nesting_type) {
6853 g_assert (tb->nesting_type->type);
6854 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6857 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6861 * mono_reflection_setup_generic_class:
6862 * @tb: a TypeBuilder object
6864 * Setup the generic class after all generic parameters have been added.
6867 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6872 MONO_ARCH_SAVE_REGS;
6874 klass = my_mono_class_from_mono_type (tb->type.type);
6876 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6878 if (klass->gen_params || (count == 0))
6881 klass->num_gen_params = count;
6882 klass->gen_params = g_new0 (MonoGenericParam, count);
6884 for (i = 0; i < count; i++) {
6885 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6886 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6891 * mono_reflection_create_internal_class:
6892 * @tb: a TypeBuilder object
6894 * Actually create the MonoClass that is associated with the TypeBuilder.
6897 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6901 MONO_ARCH_SAVE_REGS;
6903 klass = my_mono_class_from_mono_type (tb->type.type);
6905 if (klass->enumtype && klass->enum_basetype == NULL) {
6906 MonoReflectionFieldBuilder *fb;
6908 g_assert (tb->fields != NULL);
6909 g_assert (mono_array_length (tb->fields) >= 1);
6911 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6913 klass->enum_basetype = fb->type->type;
6914 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6915 if (!klass->element_class)
6916 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6917 klass->instance_size = klass->element_class->instance_size;
6918 klass->size_inited = 1;
6920 * this is almost safe to do with enums and it's needed to be able
6921 * to create objects of the enum type (for use in SetConstant).
6923 /* FIXME: Does this mean enums can't have method overrides ? */
6924 mono_class_setup_vtable (klass, NULL, 0);
6928 static MonoMarshalSpec*
6929 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6930 MonoReflectionMarshal *minfo)
6932 MonoMarshalSpec *res;
6934 res = g_new0 (MonoMarshalSpec, 1);
6935 res->native = minfo->type;
6937 switch (minfo->type) {
6938 case MONO_NATIVE_LPARRAY:
6939 res->data.array_data.elem_type = minfo->eltype;
6940 res->data.array_data.param_num = 0; /* Not yet */
6941 res->data.array_data.num_elem = minfo->count;
6944 case MONO_NATIVE_BYVALTSTR:
6945 case MONO_NATIVE_BYVALARRAY:
6946 res->data.array_data.num_elem = minfo->count;
6949 case MONO_NATIVE_CUSTOM:
6950 if (minfo->marshaltyperef)
6951 res->data.custom_data.custom_name =
6952 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6954 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6965 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6966 ReflectionMethodBuilder *rmb,
6967 MonoMethodSignature *sig)
6970 MonoMethodNormal *pm;
6971 MonoMarshalSpec **specs;
6972 MonoReflectionMethodAux *method_aux;
6975 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6976 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6977 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6980 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6982 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6984 pm = (MonoMethodNormal*)m;
6987 m->flags = rmb->attrs;
6988 m->iflags = rmb->iattrs;
6989 m->name = mono_string_to_utf8 (rmb->name);
6993 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6995 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6996 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6999 m->signature->pinvoke = 1;
7000 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7002 m->signature->pinvoke = 1;
7004 } else if (!m->klass->dummy &&
7005 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7006 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7007 MonoMethodHeader *header;
7009 gint32 max_stack, i;
7010 gint32 num_locals = 0;
7011 gint32 num_clauses = 0;
7015 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7016 code_size = rmb->ilgen->code_len;
7017 max_stack = rmb->ilgen->max_stack;
7018 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7019 if (rmb->ilgen->ex_handlers)
7020 num_clauses = method_count_clauses (rmb->ilgen);
7023 code = mono_array_addr (rmb->code, guint8, 0);
7024 code_size = mono_array_length (rmb->code);
7025 /* we probably need to run a verifier on the code... */
7035 header = g_malloc0 (sizeof (MonoMethodHeader) +
7036 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7037 header->code_size = code_size;
7038 header->code = g_malloc (code_size);
7039 memcpy ((char*)header->code, code, code_size);
7040 header->max_stack = max_stack;
7041 header->init_locals = rmb->init_locals;
7042 header->num_locals = num_locals;
7044 for (i = 0; i < num_locals; ++i) {
7045 MonoReflectionLocalBuilder *lb =
7046 mono_array_get (rmb->ilgen->locals,
7047 MonoReflectionLocalBuilder*, i);
7049 header->locals [i] = g_new0 (MonoType, 1);
7050 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7053 header->num_clauses = num_clauses;
7055 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7060 if (rmb->generic_params) {
7061 int count = mono_array_length (rmb->generic_params);
7062 header->gen_params = g_new0 (MonoGenericParam, count);
7063 for (i = 0; i < count; i++) {
7064 MonoReflectionGenericParam *gp =
7065 mono_array_get (rmb->generic_params,
7066 MonoReflectionGenericParam*, i);
7068 header->gen_params [i] = *gp->type.type->data.generic_param;
7072 pm->header = header;
7076 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7079 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7081 for (i = 0; i < rmb->nrefs; ++i)
7082 mw->data = g_list_append (mw->data, rmb->refs [i]);
7087 /* Parameter names */
7090 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7091 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7092 for (i = 0; i <= m->signature->param_count; ++i) {
7093 MonoReflectionParamBuilder *pb;
7094 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7096 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7098 if (!method_aux->param_cattr)
7099 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7100 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7106 /* Parameter marshalling */
7109 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7110 MonoReflectionParamBuilder *pb;
7111 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7112 if (pb->marshal_info) {
7114 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7115 specs [pb->position] =
7116 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7120 if (specs != NULL) {
7122 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7123 method_aux->param_marshall = specs;
7126 if (klass->image->dynamic && method_aux)
7127 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7133 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7135 ReflectionMethodBuilder rmb;
7136 MonoMethodSignature *sig;
7138 sig = ctor_builder_to_signature (mb);
7140 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7142 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7143 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7145 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7146 /* ilgen is no longer needed */
7154 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7156 ReflectionMethodBuilder rmb;
7157 MonoMethodSignature *sig;
7159 sig = method_builder_to_signature (mb);
7161 reflection_methodbuilder_from_method_builder (&rmb, mb);
7163 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7164 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7166 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7167 /* ilgen is no longer needed */
7173 static MonoClassField*
7174 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7176 MonoClassField *field;
7183 field = g_new0 (MonoClassField, 1);
7185 field->name = mono_string_to_utf8 (fb->name);
7187 /* FIXME: handle type modifiers */
7188 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7189 field->type->attrs = fb->attrs;
7191 field->type = fb->type->type;
7193 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7194 field->data = mono_array_addr (fb->rva_data, char, 0);
7195 if (fb->offset != -1)
7196 field->offset = fb->offset;
7197 field->parent = klass;
7199 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7201 if (fb->def_value) {
7202 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7203 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7204 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7205 /* Copy the data from the blob since it might get realloc-ed */
7206 p = assembly->blob.data + idx;
7207 len = mono_metadata_decode_blob_size (p, &p2);
7209 field->data = g_malloc (len);
7210 memcpy (field->data, p, len);
7217 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7221 MonoReflectionTypeBuilder *tb = NULL;
7222 MonoGenericInst *ginst;
7227 klass = mono_class_from_mono_type (type->type);
7228 if (!klass->gen_params && !klass->generic_inst &&
7229 !(klass->nested_in && klass->nested_in->gen_params))
7232 mono_loader_lock ();
7234 domain = mono_object_domain (type);
7236 ginst = g_new0 (MonoGenericInst, 1);
7238 if (!klass->generic_inst) {
7239 ginst->type_argc = type_argc;
7240 ginst->type_argv = types;
7242 for (i = 0; i < ginst->type_argc; ++i) {
7243 if (!ginst->is_open)
7244 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7247 ginst->generic_type = &klass->byval_arg;
7249 MonoGenericInst *kginst = klass->generic_inst;
7251 ginst->type_argc = kginst->type_argc;
7252 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7254 for (i = 0; i < ginst->type_argc; i++) {
7255 MonoType *t = kginst->type_argv [i];
7257 if (t->type == MONO_TYPE_VAR)
7258 t = types [t->data.generic_param->num];
7260 if (!ginst->is_open)
7261 ginst->is_open = mono_class_is_open_constructed_type (t);
7263 ginst->type_argv [i] = t;
7266 ginst->generic_type = kginst->generic_type;
7269 geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7272 mono_loader_unlock ();
7276 ginst->context = g_new0 (MonoGenericContext, 1);
7277 ginst->context->ginst = ginst;
7279 geninst = g_new0 (MonoType, 1);
7280 geninst->type = MONO_TYPE_GENERICINST;
7281 geninst->data.generic_inst = ginst;
7283 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7284 tb = (MonoReflectionTypeBuilder *) type;
7286 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7287 ginst->is_dynamic = TRUE;
7288 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7289 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7290 MonoReflectionType *rgt = rgi->generic_type;
7292 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7293 tb = (MonoReflectionTypeBuilder *) rgt;
7295 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7296 ginst->is_dynamic = TRUE;
7298 icount = klass->interface_count;
7300 ginst->ifaces = g_new0 (MonoType *, icount);
7301 ginst->count_ifaces = icount;
7303 for (i = 0; i < icount; i++) {
7304 MonoReflectionType *itype;
7307 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7309 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7310 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7311 if (!ginst->ifaces [i])
7312 ginst->ifaces [i] = itype->type;
7315 mono_class_create_generic (ginst);
7317 g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7319 mono_loader_unlock ();
7325 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7327 MonoClass *klass, *pklass = NULL;
7328 MonoReflectionType *parent = NULL;
7330 MonoReflectionTypeBuilder *tb = NULL;
7331 MonoGenericInst *ginst;
7334 domain = mono_object_domain (type);
7335 klass = mono_class_from_mono_type (type->type);
7337 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7338 tb = (MonoReflectionTypeBuilder *) type;
7341 parent = tb->parent;
7342 pklass = mono_class_from_mono_type (parent->type);
7345 pklass = klass->parent;
7347 parent = mono_type_get_object (domain, &pklass->byval_arg);
7350 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7354 ginst = geninst->data.generic_inst;
7356 if (pklass && pklass->generic_inst)
7357 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7362 MonoReflectionMethod*
7363 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7365 MonoMethod *method, *inflated;
7366 MonoReflectionMethodBuilder *mb = NULL;
7367 MonoGenericMethod *gmethod;
7368 MonoGenericContext *context;
7371 MONO_ARCH_SAVE_REGS;
7372 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7373 MonoReflectionTypeBuilder *tb;
7376 mb = (MonoReflectionMethodBuilder *) rmethod;
7377 tb = (MonoReflectionTypeBuilder *) mb->type;
7378 klass = mono_class_from_mono_type (tb->type.type);
7380 method = methodbuilder_to_mono_method (klass, mb);
7382 method = rmethod->method;
7384 count = method->signature->generic_param_count;
7385 if (count != mono_array_length (types))
7388 gmethod = g_new0 (MonoGenericMethod, 1);
7389 gmethod->mtype_argc = count;
7390 gmethod->mtype_argv = g_new0 (MonoType *, count);
7391 for (i = 0; i < count; i++) {
7392 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7393 gmethod->mtype_argv [i] = garg->type;
7396 gmethod->reflection_info = rmethod;
7398 context = g_new0 (MonoGenericContext, 1);
7399 context->ginst = method->klass->generic_inst;
7400 context->gmethod = gmethod;
7402 inflated = mono_class_inflate_generic_method (method, context, NULL);
7404 return mono_method_get_object (
7405 mono_object_domain (rmethod), inflated, NULL);
7409 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7411 MonoGenericMethod *gmethod;
7412 MonoGenericInst *ginst;
7413 MonoGenericContext *context;
7416 ginst = type->type.type->data.generic_inst;
7418 gmethod = g_new0 (MonoGenericMethod, 1);
7419 gmethod->reflection_info = obj;
7421 gmethod->mtype_argc = method->signature->generic_param_count;
7422 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7424 for (i = 0; i < gmethod->mtype_argc; i++) {
7425 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7426 MonoGenericParam *gparam = &mn->header->gen_params [i];
7428 g_assert (gparam->pklass);
7429 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7432 context = g_new0 (MonoGenericContext, 1);
7433 context->ginst = ginst;
7434 context->gmethod = gmethod;
7436 return mono_class_inflate_generic_method (method, context, ginst->klass);
7440 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7445 klass = mono_class_from_mono_type (type->type.type);
7447 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7448 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7449 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7450 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7451 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7452 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7453 method = ((MonoReflectionMethod *) obj)->method;
7455 method = NULL; /* prevent compiler warning */
7456 g_assert_not_reached ();
7459 return inflate_mono_method (type, method, obj);
7463 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7464 MonoArray *methods, MonoArray *ctors,
7465 MonoArray *fields, MonoArray *properties,
7468 MonoGenericInst *ginst;
7469 MonoDynamicGenericInst *dginst;
7470 MonoClass *klass, *gklass, *pklass;
7473 MONO_ARCH_SAVE_REGS;
7475 klass = mono_class_from_mono_type (type->type.type);
7476 ginst = type->type.type->data.generic_inst;
7478 if (ginst->initialized)
7481 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7483 gklass = mono_class_from_mono_type (ginst->generic_type);
7484 mono_class_init (gklass);
7487 pklass = mono_class_from_mono_type (ginst->parent);
7489 pklass = gklass->parent;
7491 mono_class_setup_parent (klass, pklass);
7493 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7494 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7495 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7496 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7497 dginst->count_events = events ? mono_array_length (events) : 0;
7499 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7500 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7501 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7502 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7503 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7505 for (i = 0; i < dginst->count_methods; i++) {
7506 MonoObject *obj = mono_array_get (methods, gpointer, i);
7508 dginst->methods [i] = inflate_method (type, obj);
7511 for (i = 0; i < dginst->count_ctors; i++) {
7512 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7514 dginst->ctors [i] = inflate_method (type, obj);
7517 for (i = 0; i < dginst->count_fields; i++) {
7518 MonoObject *obj = mono_array_get (fields, gpointer, i);
7519 MonoClassField *field;
7520 MonoInflatedField *ifield;
7522 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7523 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7524 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7525 field = ((MonoReflectionField *) obj)->field;
7527 field = NULL; /* prevent compiler warning */
7528 g_assert_not_reached ();
7531 ifield = g_new0 (MonoInflatedField, 1);
7532 ifield->generic_type = field->type;
7533 ifield->reflection_info = obj;
7535 dginst->fields [i] = *field;
7536 dginst->fields [i].generic_info = ifield;
7537 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7540 for (i = 0; i < dginst->count_properties; i++) {
7541 MonoObject *obj = mono_array_get (properties, gpointer, i);
7542 MonoProperty *property = &dginst->properties [i];
7544 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7545 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7547 property->parent = klass;
7548 property->attrs = pb->attrs;
7549 property->name = mono_string_to_utf8 (pb->name);
7551 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7553 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7554 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7555 *property = *((MonoReflectionProperty *) obj)->property;
7558 property->get = inflate_mono_method (type, property->get, NULL);
7560 property->set = inflate_mono_method (type, property->set, NULL);
7562 g_assert_not_reached ();
7565 for (i = 0; i < dginst->count_events; i++) {
7566 MonoObject *obj = mono_array_get (events, gpointer, i);
7567 MonoEvent *event = &dginst->events [i];
7569 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7570 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7572 event->parent = klass;
7573 event->attrs = eb->attrs;
7574 event->name = mono_string_to_utf8 (eb->name);
7576 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7577 if (eb->remove_method)
7578 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7579 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7580 *event = *((MonoReflectionEvent *) obj)->event;
7583 event->add = inflate_mono_method (type, event->add, NULL);
7585 event->remove = inflate_mono_method (type, event->remove, NULL);
7587 g_assert_not_reached ();
7590 ginst->initialized = TRUE;
7594 ensure_runtime_vtable (MonoClass *klass)
7596 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7597 int i, num, j, onum;
7598 MonoMethod **overrides;
7600 if (!tb || klass->wastypebuilder)
7603 ensure_runtime_vtable (klass->parent);
7605 num = tb->ctors? mono_array_length (tb->ctors): 0;
7606 num += tb->num_methods;
7607 klass->method.count = num;
7608 klass->methods = g_new (MonoMethod*, num);
7609 num = tb->ctors? mono_array_length (tb->ctors): 0;
7610 for (i = 0; i < num; ++i)
7611 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7612 num = tb->num_methods;
7614 for (i = 0; i < num; ++i)
7615 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7617 klass->wastypebuilder = TRUE;
7618 if (tb->interfaces) {
7619 klass->interface_count = mono_array_length (tb->interfaces);
7620 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7621 for (i = 0; i < klass->interface_count; ++i) {
7622 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7623 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7627 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7628 for (i = 0; i < klass->method.count; ++i)
7629 klass->methods [i]->slot = i;
7634 for (i = 0; i < tb->num_methods; ++i) {
7635 MonoReflectionMethodBuilder *mb =
7636 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7637 if (mb->override_method)
7642 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7646 for (i = 0; i < tb->num_methods; ++i) {
7647 MonoReflectionMethodBuilder *mb =
7648 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7649 if (mb->override_method) {
7650 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7651 overrides [onum * 2] =
7652 mb->override_method->method;
7653 overrides [onum * 2 + 1] =
7656 g_assert (mb->mhandle);
7663 mono_class_setup_vtable (klass, overrides, onum);
7667 typebuilder_setup_fields (MonoClass *klass)
7669 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7670 MonoReflectionFieldBuilder *fb;
7671 MonoClassField *field;
7676 klass->field.count = tb->num_fields;
7677 klass->field.first = 0;
7678 klass->field.last = klass->field.count;
7680 if (!klass->field.count)
7683 klass->fields = g_new0 (MonoClassField, klass->field.count);
7685 for (i = 0; i < klass->field.count; ++i) {
7686 fb = mono_array_get (tb->fields, gpointer, i);
7687 field = &klass->fields [i];
7688 field->name = mono_string_to_utf8 (fb->name);
7690 /* FIXME: handle type modifiers */
7691 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7692 field->type->attrs = fb->attrs;
7694 field->type = fb->type->type;
7696 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7697 field->data = mono_array_addr (fb->rva_data, char, 0);
7698 if (fb->offset != -1)
7699 field->offset = fb->offset;
7700 field->parent = klass;
7702 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7704 if (fb->def_value) {
7705 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7706 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7707 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7708 /* Copy the data from the blob since it might get realloc-ed */
7709 p = assembly->blob.data + idx;
7710 len = mono_metadata_decode_blob_size (p, &p2);
7712 field->data = g_malloc (len);
7713 memcpy (field->data, p, len);
7716 mono_class_layout_fields (klass);
7720 typebuilder_setup_properties (MonoClass *klass)
7722 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7723 MonoReflectionPropertyBuilder *pb;
7726 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7727 klass->property.first = 0;
7728 klass->property.last = klass->property.count;
7730 klass->properties = g_new0 (MonoProperty, klass->property.count);
7731 for (i = 0; i < klass->property.count; ++i) {
7732 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7733 klass->properties [i].parent = klass;
7734 klass->properties [i].attrs = pb->attrs;
7735 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7737 klass->properties [i].get = pb->get_method->mhandle;
7739 klass->properties [i].set = pb->set_method->mhandle;
7743 MonoReflectionEvent *
7744 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7746 MonoEvent *event = g_new0 (MonoEvent, 1);
7750 klass = my_mono_class_from_mono_type (tb->type.type);
7752 event->parent = klass;
7753 event->attrs = eb->attrs;
7754 event->name = mono_string_to_utf8 (eb->name);
7756 event->add = eb->add_method->mhandle;
7757 if (eb->remove_method)
7758 event->remove = eb->remove_method->mhandle;
7759 if (eb->raise_method)
7760 event->raise = eb->raise_method->mhandle;
7762 if (eb->other_methods) {
7763 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7764 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7765 MonoReflectionMethodBuilder *mb =
7766 mono_array_get (eb->other_methods,
7767 MonoReflectionMethodBuilder*, j);
7768 event->other [j] = mb->mhandle;
7772 return mono_event_get_object (mono_object_domain (tb), klass, event);
7776 typebuilder_setup_events (MonoClass *klass)
7778 MonoReflectionTypeBuilder *tb = klass->reflection_info;
7779 MonoReflectionEventBuilder *eb;
7782 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7783 klass->event.first = 0;
7784 klass->event.last = klass->event.count;
7786 klass->events = g_new0 (MonoEvent, klass->event.count);
7787 for (i = 0; i < klass->event.count; ++i) {
7788 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7789 klass->events [i].parent = klass;
7790 klass->events [i].attrs = eb->attrs;
7791 klass->events [i].name = mono_string_to_utf8 (eb->name);
7793 klass->events [i].add = eb->add_method->mhandle;
7794 if (eb->remove_method)
7795 klass->events [i].remove = eb->remove_method->mhandle;
7796 if (eb->raise_method)
7797 klass->events [i].raise = eb->raise_method->mhandle;
7799 if (eb->other_methods) {
7800 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7801 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7802 MonoReflectionMethodBuilder *mb =
7803 mono_array_get (eb->other_methods,
7804 MonoReflectionMethodBuilder*, j);
7805 klass->events [i].other [j] = mb->mhandle;
7812 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7815 MonoReflectionType* res;
7817 MONO_ARCH_SAVE_REGS;
7819 klass = my_mono_class_from_mono_type (tb->type.type);
7821 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7824 * Fields to set in klass:
7825 * the various flags: delegate/unicode/contextbound etc.
7828 klass->flags = tb->attrs;
7830 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7831 /* No need to fully construct the type */
7832 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7834 /* enums are done right away */
7835 if (!klass->enumtype)
7836 ensure_runtime_vtable (klass);
7838 /* fields and object layout */
7839 if (klass->parent) {
7840 if (!klass->parent->size_inited)
7841 mono_class_init (klass->parent);
7842 klass->instance_size += klass->parent->instance_size;
7843 klass->class_size += klass->parent->class_size;
7844 klass->min_align = klass->parent->min_align;
7846 klass->instance_size = sizeof (MonoObject);
7847 klass->min_align = 1;
7850 /* FIXME: handle packing_size and instance_size */
7851 typebuilder_setup_fields (klass);
7853 typebuilder_setup_properties (klass);
7855 typebuilder_setup_events (klass);
7857 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7858 /* with enums res == tb: need to fix that. */
7859 if (!klass->enumtype)
7860 g_assert (res != (MonoReflectionType*)tb);
7865 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7867 MonoGenericParam *param;
7870 MONO_ARCH_SAVE_REGS;
7872 param = g_new0 (MonoGenericParam, 1);
7874 param->method = NULL;
7875 param->name = mono_string_to_utf8 (gparam->name);
7876 param->num = gparam->index;
7878 image = &gparam->tbuilder->module->dynamic_image->image;
7879 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7881 param->pklass->reflection_info = gparam;
7883 gparam->type.type = g_new0 (MonoType, 1);
7884 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7885 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7886 gparam->type.type->data.generic_param = param;
7890 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7892 MonoDynamicImage *assembly = sig->module->dynamic_image;
7893 guint32 na = mono_array_length (sig->arguments);
7898 MONO_ARCH_SAVE_REGS;
7900 p = buf = g_malloc (10 + na * 10);
7902 mono_metadata_encode_value (0x07, p, &p);
7903 mono_metadata_encode_value (na, p, &p);
7904 for (i = 0; i < na; ++i) {
7905 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7906 encode_reflection_type (assembly, type, p, &p);
7910 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7911 p = mono_array_addr (result, char, 0);
7912 memcpy (p, buf, buflen);
7919 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7921 MonoDynamicImage *assembly = sig->module->dynamic_image;
7922 guint32 na = mono_array_length (sig->arguments);
7927 MONO_ARCH_SAVE_REGS;
7929 p = buf = g_malloc (10 + na * 10);
7931 mono_metadata_encode_value (0x06, p, &p);
7932 for (i = 0; i < na; ++i) {
7933 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7934 encode_reflection_type (assembly, type, p, &p);
7938 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7939 p = mono_array_addr (result, char, 0);
7940 memcpy (p, buf, buflen);
7947 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7949 ReflectionMethodBuilder rmb;
7950 MonoMethodSignature *sig;
7953 sig = dynamic_method_to_signature (mb);
7955 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7958 * Resolve references.
7960 rmb.nrefs = mb->nrefs;
7961 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7962 for (i = 0; i < mb->nrefs; ++i) {
7963 gpointer ref = resolve_object (mb->module->image,
7964 mono_array_get (mb->refs, MonoObject*, i));
7967 mono_raise_exception (mono_get_exception_type_load (NULL));
7974 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7978 /* ilgen is no longer needed */
7983 * mono_reflection_lookup_dynamic_token:
7985 * Finish the Builder object pointed to by TOKEN and return the corresponding
7986 * runtime structure.
7989 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7991 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7994 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7997 return resolve_object (image, obj);
8001 resolve_object (MonoImage *image, MonoObject *obj)
8003 gpointer result = NULL;
8005 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8006 result = mono_string_intern ((MonoString*)obj);
8009 else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8010 MonoReflectionType *tb = (MonoReflectionType*)obj;
8011 result = mono_class_from_mono_type (tb->type);
8014 else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8015 result = ((MonoReflectionMethod*)obj)->method;
8018 else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8019 result = ((MonoReflectionMethod*)obj)->method;
8022 else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8024 result = mb->mhandle;
8026 /* Type is not yet created */
8027 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8029 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8032 * Hopefully this has been filled in by calling CreateType() on the
8036 * TODO: This won't work if the application finishes another
8037 * TypeBuilder instance instead of this one.
8039 result = mb->mhandle;
8042 else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8043 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8045 result = cb->mhandle;
8047 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8049 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8050 result = cb->mhandle;
8053 else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8054 result = ((MonoReflectionField*)obj)->field;
8057 else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8058 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8059 result = fb->handle;
8062 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8064 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8065 result = fb->handle;
8068 else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8069 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8072 klass = tb->type.type->data.klass;
8073 if (klass->wastypebuilder) {
8074 /* Already created */
8078 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8079 result = tb->type.type->data.klass;
8083 else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8084 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8085 MonoMethodSignature *sig;
8088 if (helper->arguments)
8089 nargs = mono_array_length (helper->arguments);
8093 sig = mono_metadata_signature_alloc (image, nargs);
8094 sig->explicit_this = helper->call_conv & 64;
8095 sig->hasthis = helper->call_conv & 32;
8097 if (helper->call_conv == 0) /* unmanaged */
8098 sig->call_convention = helper->unmanaged_call_conv - 1;
8100 if (helper->call_conv & 0x02)
8101 sig->call_convention = MONO_CALL_VARARG;
8103 sig->call_convention = MONO_CALL_DEFAULT;
8105 sig->param_count = nargs;
8106 /* TODO: Copy type ? */
8107 sig->ret = helper->return_type->type;
8108 for (i = 0; i < nargs; ++i) {
8109 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8110 sig->params [i] = rt->type;
8116 g_print (obj->vtable->klass->name);
8117 g_assert_not_reached ();