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;
65 int charset, lasterr, native_cc;
66 MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
71 MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
74 const unsigned char table_sizes [64] = {
84 MONO_INTERFACEIMPL_SIZE,
85 MONO_MEMBERREF_SIZE, /* 0x0A */
87 MONO_CUSTOM_ATTR_SIZE,
88 MONO_FIELD_MARSHAL_SIZE,
89 MONO_DECL_SECURITY_SIZE,
90 MONO_CLASS_LAYOUT_SIZE,
91 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92 MONO_STAND_ALONE_SIGNATURE_SIZE,
96 MONO_PROPERTY_MAP_SIZE,
99 MONO_METHOD_SEMA_SIZE,
100 MONO_METHODIMPL_SIZE,
101 MONO_MODULEREF_SIZE, /* 0x1A */
107 MONO_ASSEMBLY_SIZE, /* 0x20 */
108 MONO_ASSEMBLY_PROCESSOR_SIZE,
109 MONO_ASSEMBLYOS_SIZE,
110 MONO_ASSEMBLYREF_SIZE,
111 MONO_ASSEMBLYREFPROC_SIZE,
112 MONO_ASSEMBLYREFOS_SIZE,
116 MONO_NESTED_CLASS_SIZE,
118 MONO_GENERICPARAM_SIZE, /* 0x2A */
119 MONO_METHODSPEC_SIZE,
120 MONO_GENPARCONSTRAINT_SIZE,
126 * These macros can be used to allocate long living atomic data so it won't be
127 * tracked by the garbage collector. We use libgc because it's apparently faster
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
160 alloc_table (MonoDynamicTable *table, guint nrows)
163 g_assert (table->columns);
164 if (nrows + 1 >= table->alloc_rows) {
165 while (nrows + 1 >= table->alloc_rows) {
166 if (table->alloc_rows == 0)
167 table->alloc_rows = 16;
169 table->alloc_rows *= 2;
173 table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
175 table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
180 make_room_in_stream (MonoDynamicStream *stream, int size)
182 while (stream->alloc_size <= size) {
183 if (stream->alloc_size < 4096)
184 stream->alloc_size = 4096;
186 stream->alloc_size *= 2;
189 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
191 stream->data = ALLOC_ATOMIC (stream->alloc_size);
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
199 gpointer oldkey, oldval;
201 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202 return GPOINTER_TO_UINT (oldval);
204 len = strlen (str) + 1;
206 if (idx + len > sh->alloc_size)
207 make_room_in_stream (sh, idx + len);
210 * We strdup the string even if we already copy them in sh->data
211 * so that the string pointers in the hash remain valid even if
212 * we need to realloc sh->data. We may want to avoid that later.
214 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215 memcpy (sh->data + idx, str, len);
221 string_heap_init (MonoDynamicStream *sh)
224 sh->alloc_size = 4096;
225 sh->data = ALLOC_ATOMIC (4096);
226 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227 string_heap_insert (sh, "");
230 #if 0 /* never used */
232 string_heap_free (MonoDynamicStream *sh)
234 FREE_ATOMIC (sh->data);
235 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236 g_hash_table_destroy (sh->hash);
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
244 if (stream->alloc_size < stream->index + len)
245 make_room_in_stream (stream, stream->index + len);
246 memcpy (stream->data + stream->index, data, len);
248 stream->index += len;
250 * align index? Not without adding an additional param that controls it since
251 * we may store a blob value in pieces.
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
260 if (stream->alloc_size < stream->index + len)
261 make_room_in_stream (stream, stream->index + len);
262 memset (stream->data + stream->index, 0, len);
264 stream->index += len;
269 stream_data_align (MonoDynamicStream *stream)
272 guint32 count = stream->index % 4;
274 /* we assume the stream data will be aligned */
276 mono_image_add_stream_data (stream, buf, 4 - count);
280 mono_blob_entry_hash (const char* str)
284 len = mono_metadata_decode_blob_size (str, &str);
288 for (str += 1; str < end; str++)
289 h = (h << 5) - h + *str;
297 mono_blob_entry_equal (const char *str1, const char *str2) {
301 len = mono_metadata_decode_blob_size (str1, &end1);
302 len2 = mono_metadata_decode_blob_size (str2, &end2);
305 return memcmp (end1, end2, len) == 0;
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
313 gpointer oldkey, oldval;
315 copy = ALLOC_ATOMIC (s1+s2);
316 memcpy (copy, b1, s1);
317 memcpy (copy + s1, b2, s2);
318 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
320 idx = GPOINTER_TO_UINT (oldval);
322 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323 mono_image_add_stream_data (&assembly->blob, b2, s2);
324 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
330 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331 * dest may be misaligned.
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
338 for (elem = 0; elem < nelem; ++elem) {
364 g_assert_not_reached ();
370 memcpy (dest, val, len * nelem);
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
379 guint32 idx = 0, len;
381 len = str->length * 2;
382 mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
385 char *swapped = g_malloc (2 * mono_string_length (str));
386 const char *p = (const char*)mono_string_chars (str);
388 swap_with_size (swapped, p, 2, mono_string_length (str));
389 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
393 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
398 /* modified version needed to handle building corlib */
400 my_mono_class_from_mono_type (MonoType *type) {
401 switch (type->type) {
402 case MONO_TYPE_ARRAY:
404 case MONO_TYPE_SZARRAY:
405 case MONO_TYPE_GENERICINST:
406 return mono_class_from_mono_type (type);
409 g_assert (type->data.generic_param->pklass);
410 return type->data.generic_param->pklass;
412 /* should be always valid when we reach this case... */
413 return type->data.klass;
418 default_class_from_mono_type (MonoType *type)
420 switch (type->type) {
421 case MONO_TYPE_OBJECT:
422 return mono_defaults.object_class;
424 return mono_defaults.void_class;
425 case MONO_TYPE_BOOLEAN:
426 return mono_defaults.boolean_class;
428 return mono_defaults.char_class;
430 return mono_defaults.sbyte_class;
432 return mono_defaults.byte_class;
434 return mono_defaults.int16_class;
436 return mono_defaults.uint16_class;
438 return mono_defaults.int32_class;
440 return mono_defaults.uint32_class;
442 return mono_defaults.int_class;
444 return mono_defaults.uint_class;
446 return mono_defaults.int64_class;
448 return mono_defaults.uint64_class;
450 return mono_defaults.single_class;
452 return mono_defaults.double_class;
453 case MONO_TYPE_STRING:
454 return mono_defaults.string_class;
456 g_warning ("implement me 0x%02x\n", type->type);
457 g_assert_not_reached ();
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
469 g_assert_not_reached ();
473 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474 encode_type (assembly, ginst->generic_type, p, &p);
475 mono_metadata_encode_value (ginst->type_argc, p, &p);
476 for (i = 0; i < ginst->type_argc; ++i)
477 encode_type (assembly, ginst->type_argv [i], p, &p);
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
486 g_assert_not_reached ();
491 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
495 case MONO_TYPE_BOOLEAN:
509 case MONO_TYPE_STRING:
510 case MONO_TYPE_OBJECT:
511 case MONO_TYPE_TYPEDBYREF:
512 mono_metadata_encode_value (type->type, p, &p);
515 mono_metadata_encode_value (type->type, p, &p);
516 encode_type (assembly, type->data.type, p, &p);
518 case MONO_TYPE_SZARRAY:
519 mono_metadata_encode_value (type->type, p, &p);
520 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
522 case MONO_TYPE_VALUETYPE:
523 case MONO_TYPE_CLASS: {
524 MonoClass *k = mono_class_from_mono_type (type);
525 mono_metadata_encode_value (type->type, p, &p);
527 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528 * otherwise two typerefs could point to the same type, leading to
529 * verification errors.
531 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
534 case MONO_TYPE_ARRAY:
535 mono_metadata_encode_value (type->type, p, &p);
536 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537 mono_metadata_encode_value (type->data.array->rank, p, &p);
538 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539 mono_metadata_encode_value (0, p, &p);
541 case MONO_TYPE_GENERICINST:
542 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
546 mono_metadata_encode_value (type->type, p, &p);
547 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
550 g_error ("need to encode type %x", type->type);
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
559 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
563 encode_type (assembly, type->type, p, endbuf);
567 g_assert_not_reached ();
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
577 for (i = 0; i < mono_array_length (modreq); ++i) {
578 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_REQD;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
585 for (i = 0; i < mono_array_length (modopt); ++i) {
586 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587 *p = MONO_TYPE_CMOD_OPT;
589 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
602 g_assert_not_reached ();
605 size += 1 + type_get_signature_size (ginst->generic_type);
607 for (i = 0; i < ginst->type_argc; ++i)
608 size += type_get_signature_size (ginst->type_argv [i]);
614 type_get_signature_size (MonoType *type)
619 g_assert_not_reached ();
627 case MONO_TYPE_BOOLEAN:
641 case MONO_TYPE_STRING:
642 case MONO_TYPE_OBJECT:
643 case MONO_TYPE_TYPEDBYREF:
646 return size + 1 + type_get_signature_size (type->data.type);
647 case MONO_TYPE_SZARRAY:
648 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649 case MONO_TYPE_VALUETYPE:
650 case MONO_TYPE_CLASS:
652 case MONO_TYPE_ARRAY:
653 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654 case MONO_TYPE_GENERICINST:
655 return size + generic_inst_get_signature_size (type->data.generic_inst);
660 g_error ("need to encode type %x", type->type);
666 method_get_signature_size (MonoMethodSignature *sig)
671 size = type_get_signature_size (sig->ret);
672 for (i = 0; i < sig->param_count; i++)
673 size += type_get_signature_size (sig->params [i]);
675 if (sig->generic_param_count)
677 if (sig->sentinelpos >= 0)
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
689 guint32 nparams = sig->param_count;
690 guint32 size = 11 + method_get_signature_size (sig);
698 p = buf = g_malloc (size);
700 * FIXME: vararg, explicit_this, differenc call_conv values...
702 *p = sig->call_convention;
704 *p |= 0x20; /* hasthis */
705 if (sig->generic_param_count)
706 *p |= 0x10; /* generic */
708 if (sig->generic_param_count)
709 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710 mono_metadata_encode_value (nparams, p, &p);
711 encode_type (assembly, sig->ret, p, &p);
712 for (i = 0; i < nparams; ++i) {
713 if (i == sig->sentinelpos)
714 *p++ = MONO_TYPE_SENTINEL;
715 encode_type (assembly, sig->params [i], p, &p);
718 g_assert (p - buf < size);
719 mono_metadata_encode_value (p-buf, b, &b);
720 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
729 * FIXME: reuse code from method_encode_signature().
734 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
735 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737 guint32 size = 21 + nparams * 20 + notypes * 20;
742 p = buf = g_malloc (size);
743 /* LAMESPEC: all the call conv spec is foobared */
744 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745 if (mb->call_conv & 2)
746 *p |= 0x5; /* vararg */
747 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748 *p |= 0x20; /* hasthis */
750 *p |= 0x10; /* generic */
753 mono_metadata_encode_value (ngparams, p, &p);
754 mono_metadata_encode_value (nparams + notypes, p, &p);
755 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756 encode_reflection_type (assembly, mb->rtype, p, &p);
757 for (i = 0; i < nparams; ++i) {
758 MonoArray *modreq = NULL;
759 MonoArray *modopt = NULL;
760 MonoReflectionType *pt;
762 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
771 *p++ = MONO_TYPE_SENTINEL;
772 for (i = 0; i < notypes; ++i) {
773 MonoReflectionType *pt;
775 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776 encode_reflection_type (assembly, pt, p, &p);
780 g_assert (p - buf < size);
781 mono_metadata_encode_value (p-buf, b, &b);
782 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
790 MonoDynamicTable *table;
793 guint32 idx, sig_idx, size;
794 guint nl = mono_array_length (ilgen->locals);
801 p = buf = g_malloc (size);
802 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803 idx = table->next_idx ++;
805 alloc_table (table, table->rows);
806 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
808 mono_metadata_encode_value (0x07, p, &p);
809 mono_metadata_encode_value (nl, p, &p);
810 for (i = 0; i < nl; ++i) {
811 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
814 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
816 encode_reflection_type (assembly, lb->type, p, &p);
818 g_assert (p - buf < size);
819 mono_metadata_encode_value (p-buf, b, &b);
820 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
823 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
829 method_count_clauses (MonoReflectionILGen *ilgen)
831 guint32 num_clauses = 0;
834 MonoILExceptionInfo *ex_info;
835 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837 if (ex_info->handlers)
838 num_clauses += mono_array_length (ex_info->handlers);
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
849 MonoExceptionClause *clauses;
850 MonoExceptionClause *clause;
851 MonoILExceptionInfo *ex_info;
852 MonoILExceptionBlock *ex_block;
853 guint32 finally_start;
854 int i, j, clause_index;;
856 clauses = g_new0 (MonoExceptionClause, num_clauses);
859 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861 finally_start = ex_info->start + ex_info->len;
862 g_assert (ex_info->handlers);
863 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865 clause = &(clauses [clause_index]);
867 clause->flags = ex_block->type;
868 clause->try_offset = ex_info->start;
870 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871 clause->try_len = finally_start - ex_info->start;
873 clause->try_len = ex_info->len;
874 clause->handler_offset = ex_block->start;
875 clause->handler_len = ex_block->len;
876 clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878 if (ex_block->extype) {
879 mono_g_hash_table_insert (assembly->tokens,
880 GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
882 finally_start = ex_block->start + ex_block->len;
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
898 gint32 num_locals = 0;
899 gint32 num_exception = 0;
902 char fat_header [12];
905 guint32 local_sig = 0;
906 guint32 header_size = 12;
909 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
914 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
916 code = mb->ilgen->code;
917 code_size = mb->ilgen->code_len;
918 max_stack = mb->ilgen->max_stack;
919 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920 if (mb->ilgen->ex_handlers)
921 num_exception = method_count_clauses (mb->ilgen);
925 char *name = mono_string_to_utf8 (mb->name);
926 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
930 mono_raise_exception (exception);
933 code_size = mono_array_length (code);
934 max_stack = 8; /* we probably need to run a verifier on the code... */
937 stream_data_align (&assembly->code);
939 /* check for exceptions, maxstack, locals */
940 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
942 if (code_size < 64 && !(code_size & 1)) {
943 flags = (code_size << 2) | 0x2;
944 } else if (code_size < 32 && (code_size & 1)) {
945 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
949 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
950 /* add to the fixup todo list */
951 if (mb->ilgen && mb->ilgen->num_token_fixups)
952 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
953 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
954 return assembly->text_rva + idx;
958 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
960 * FIXME: need to set also the header size in fat_flags.
961 * (and more sects and init locals flags)
965 fat_flags |= METHOD_HEADER_MORE_SECTS;
967 fat_flags |= METHOD_HEADER_INIT_LOCALS;
968 fat_header [0] = fat_flags;
969 fat_header [1] = (header_size / 4 ) << 4;
970 shortp = (guint16*)(fat_header + 2);
971 *shortp = GUINT16_TO_LE (max_stack);
972 intp = (guint32*)(fat_header + 4);
973 *intp = GUINT32_TO_LE (code_size);
974 intp = (guint32*)(fat_header + 8);
975 *intp = GUINT32_TO_LE (local_sig);
976 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
977 /* add to the fixup todo list */
978 if (mb->ilgen && mb->ilgen->num_token_fixups)
979 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
981 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
983 unsigned char sheader [4];
984 MonoExceptionClause clause;
985 MonoILExceptionInfo * ex_info;
986 MonoILExceptionBlock * ex_block;
989 stream_data_align (&assembly->code);
990 /* always use fat format for now */
991 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
992 num_exception *= sizeof (MonoExceptionClause);
993 num_exception += 4; /* include the size of the header */
994 sheader [1] = num_exception & 0xff;
995 sheader [2] = (num_exception >> 8) & 0xff;
996 sheader [3] = (num_exception >> 16) & 0xff;
997 mono_image_add_stream_data (&assembly->code, sheader, 4);
998 /* fat header, so we are already aligned */
1000 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1001 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1002 if (ex_info->handlers) {
1003 int finally_start = ex_info->start + ex_info->len;
1004 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1005 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1006 clause.flags = GUINT32_TO_LE (ex_block->type);
1007 clause.try_offset = GUINT32_TO_LE (ex_info->start);
1008 /* need fault, too, probably */
1009 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1010 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1012 clause.try_len = GUINT32_TO_LE (ex_info->len);
1013 clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1014 clause.handler_len = GUINT32_TO_LE (ex_block->len);
1015 finally_start = ex_block->start + ex_block->len;
1016 clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1017 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1018 clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1019 /*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",
1020 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);*/
1021 mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1024 g_error ("No clauses for ex info block %d", i);
1028 return assembly->text_rva + idx;
1032 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1035 MonoDynamicTable *table;
1038 table = &assembly->tables [table_idx];
1040 g_assert (col < table->columns);
1042 values = table->values + table->columns;
1043 for (i = 1; i <= table->rows; ++i) {
1044 if (values [col] == token)
1046 values += table->columns;
1051 static GHashTable *dynamic_custom_attrs = NULL;
1053 static MonoCustomAttrInfo*
1054 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1057 MonoCustomAttrInfo *ainfo;
1058 MonoReflectionCustomAttr *cattr;
1062 /* FIXME: check in assembly the Run flag is set */
1064 count = mono_array_length (cattrs);
1066 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1068 ainfo->image = image;
1069 ainfo->num_attrs = count;
1070 for (i = 0; i < count; ++i) {
1071 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1072 ainfo->attrs [i].ctor = cattr->ctor->method;
1073 /* FIXME: might want to memdup the data here */
1074 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1075 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1082 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1084 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1089 if (!dynamic_custom_attrs)
1090 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1092 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1093 ainfo->cached = TRUE;
1097 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1099 /* they are cached, so we don't free them */
1100 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1106 * idx is the table index of the object
1107 * type is one of MONO_CUSTOM_ATTR_*
1110 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1112 MonoDynamicTable *table;
1113 MonoReflectionCustomAttr *cattr;
1115 guint32 count, i, token;
1117 char *p = blob_size;
1119 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1122 count = mono_array_length (cattrs);
1123 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1124 table->rows += count;
1125 alloc_table (table, table->rows);
1126 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1127 idx <<= MONO_CUSTOM_ATTR_BITS;
1129 for (i = 0; i < count; ++i) {
1130 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1131 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1132 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1133 type = mono_metadata_token_index (token);
1134 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1135 switch (mono_metadata_token_table (token)) {
1136 case MONO_TABLE_METHOD:
1137 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1139 case MONO_TABLE_MEMBERREF:
1140 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1143 g_warning ("got wrong token in custom attr");
1146 values [MONO_CUSTOM_ATTR_TYPE] = type;
1148 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1149 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1150 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1151 values += MONO_CUSTOM_ATTR_SIZE;
1157 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1159 MonoDynamicTable *table;
1161 guint32 count, i, idx;
1162 MonoReflectionPermissionSet *perm;
1167 count = mono_array_length (permissions);
1168 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1169 table->rows += count;
1170 alloc_table (table, table->rows);
1172 for (i = 0; i < mono_array_length (permissions); ++i) {
1173 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1175 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1177 idx = mono_metadata_token_index (parent_token);
1178 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1179 switch (mono_metadata_token_table (parent_token)) {
1180 case MONO_TABLE_TYPEDEF:
1181 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1183 case MONO_TABLE_METHOD:
1184 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1186 case MONO_TABLE_ASSEMBLY:
1187 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1190 g_assert_not_reached ();
1193 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1194 values [MONO_DECL_SECURITY_PARENT] = idx;
1195 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1202 * Fill in the MethodDef and ParamDef tables for a method.
1203 * This is used for both normal methods and constructors.
1206 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1208 MonoDynamicTable *table;
1213 /* room in this table is already allocated */
1214 table = &assembly->tables [MONO_TABLE_METHOD];
1215 *mb->table_idx = table->next_idx ++;
1216 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1217 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1218 name = mono_string_to_utf8 (mb->name);
1219 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1221 values [MONO_METHOD_FLAGS] = mb->attrs;
1222 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1223 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1224 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1226 table = &assembly->tables [MONO_TABLE_PARAM];
1227 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1229 mono_image_add_decl_security (assembly,
1230 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1233 MonoDynamicTable *mtable;
1236 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1237 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1240 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1241 if (mono_array_get (mb->pinfo, gpointer, i))
1244 table->rows += count;
1245 alloc_table (table, table->rows);
1246 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1247 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1248 MonoReflectionParamBuilder *pb;
1249 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1250 values [MONO_PARAM_FLAGS] = pb->attrs;
1251 values [MONO_PARAM_SEQUENCE] = i;
1252 if (pb->name != NULL) {
1253 name = mono_string_to_utf8 (pb->name);
1254 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1257 values [MONO_PARAM_NAME] = 0;
1259 values += MONO_PARAM_SIZE;
1260 if (pb->marshal_info) {
1262 alloc_table (mtable, mtable->rows);
1263 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1264 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1265 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1267 pb->table_idx = table->next_idx++;
1268 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1269 guint32 field_type = 0;
1270 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1272 alloc_table (mtable, mtable->rows);
1273 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1274 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1275 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1276 mvalues [MONO_CONSTANT_TYPE] = field_type;
1277 mvalues [MONO_CONSTANT_PADDING] = 0;
1285 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1287 rmb->ilgen = mb->ilgen;
1288 rmb->rtype = mb->rtype;
1289 rmb->parameters = mb->parameters;
1290 rmb->generic_params = mb->generic_params;
1291 rmb->opt_types = NULL;
1292 rmb->pinfo = mb->pinfo;
1293 rmb->attrs = mb->attrs;
1294 rmb->iattrs = mb->iattrs;
1295 rmb->call_conv = mb->call_conv;
1296 rmb->code = mb->code;
1297 rmb->type = mb->type;
1298 rmb->name = mb->name;
1299 rmb->table_idx = &mb->table_idx;
1300 rmb->init_locals = mb->init_locals;
1301 rmb->return_modreq = mb->return_modreq;
1302 rmb->return_modopt = mb->return_modopt;
1303 rmb->param_modreq = mb->param_modreq;
1304 rmb->param_modopt = mb->param_modopt;
1305 rmb->permissions = mb->permissions;
1306 rmb->mhandle = mb->mhandle;
1311 rmb->charset = rmb->charset & 0xf;
1312 rmb->lasterr = rmb->charset & 0x40;
1313 rmb->native_cc = rmb->native_cc;
1314 rmb->dllentry = mb->dllentry;
1320 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1322 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1324 rmb->ilgen = mb->ilgen;
1325 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1326 rmb->parameters = mb->parameters;
1327 rmb->generic_params = NULL;
1328 rmb->opt_types = NULL;
1329 rmb->pinfo = mb->pinfo;
1330 rmb->attrs = mb->attrs;
1331 rmb->iattrs = mb->iattrs;
1332 rmb->call_conv = mb->call_conv;
1334 rmb->type = mb->type;
1335 rmb->name = mono_string_new (mono_domain_get (), name);
1336 rmb->table_idx = &mb->table_idx;
1337 rmb->init_locals = mb->init_locals;
1338 rmb->return_modreq = NULL;
1339 rmb->return_modopt = NULL;
1340 rmb->param_modreq = mb->param_modreq;
1341 rmb->param_modopt = mb->param_modopt;
1342 rmb->permissions = mb->permissions;
1343 rmb->mhandle = mb->mhandle;
1349 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1351 rmb->ilgen = mb->ilgen;
1352 rmb->rtype = mb->rtype;
1353 rmb->parameters = mb->parameters;
1354 rmb->generic_params = NULL;
1355 rmb->opt_types = NULL;
1357 rmb->attrs = mb->attrs;
1359 rmb->call_conv = mb->call_conv;
1362 rmb->name = mb->name;
1363 rmb->table_idx = NULL;
1364 rmb->init_locals = mb->init_locals;
1365 rmb->return_modreq = NULL;
1366 rmb->return_modopt = NULL;
1367 rmb->param_modreq = NULL;
1368 rmb->param_modopt = NULL;
1369 rmb->permissions = NULL;
1370 rmb->mhandle = mb->mhandle;
1376 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1378 MonoDynamicTable *table;
1381 ReflectionMethodBuilder rmb;
1384 reflection_methodbuilder_from_method_builder (&rmb, mb);
1386 mono_image_basic_method (&rmb, assembly);
1388 if (mb->dll) { /* It's a P/Invoke method */
1390 int charset = mb->charset & 0xf;
1391 int lasterr = mb->charset & 0x40;
1392 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1394 alloc_table (table, table->rows);
1395 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1396 /* map CharSet values to on-disk values */
1398 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1399 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1400 name = mono_string_to_utf8 (mb->dllentry);
1401 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1403 name = mono_string_to_utf8 (mb->dll);
1404 moduleref = string_heap_insert (&assembly->sheap, name);
1406 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1407 table = &assembly->tables [MONO_TABLE_MODULEREF];
1409 alloc_table (table, table->rows);
1410 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1411 values [MONO_IMPLMAP_SCOPE] = table->rows;
1415 if (mb->override_method) {
1416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1418 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1420 alloc_table (table, table->rows);
1421 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1422 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1423 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1425 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1426 switch (mono_metadata_token_table (tok)) {
1427 case MONO_TABLE_MEMBERREF:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1430 case MONO_TABLE_METHOD:
1431 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1434 g_assert_not_reached ();
1436 values [MONO_METHODIMPL_DECLARATION] = tok;
1439 if (mb->generic_params) {
1440 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1441 table->rows += mono_array_length (mb->generic_params);
1442 alloc_table (table, table->rows);
1443 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1444 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1446 mono_image_get_generic_param_info (
1447 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1454 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1456 ReflectionMethodBuilder rmb;
1458 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1460 mono_image_basic_method (&rmb, assembly);
1464 type_get_fully_qualified_name (MonoType *type) {
1465 char *name, *result;
1469 name = mono_type_get_name (type);
1470 klass = my_mono_class_from_mono_type (type);
1471 ta = klass->image->assembly;
1473 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1474 name, ta->aname.name,
1475 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1476 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1477 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1483 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1487 klass = my_mono_class_from_mono_type (type);
1489 return mono_type_get_name (type);
1490 ta = klass->image->assembly;
1491 if (ta == ass || klass->image == mono_defaults.corlib)
1492 return mono_type_get_name (type);
1494 return type_get_fully_qualified_name (type);
1498 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1500 char blob_size [64];
1501 char *b = blob_size;
1506 if (!assembly->save)
1509 p = buf = g_malloc (64);
1511 mono_metadata_encode_value (0x06, p, &p);
1512 /* encode custom attributes before the type */
1513 encode_type (assembly, type, p, &p);
1514 g_assert (p-buf < 64);
1515 mono_metadata_encode_value (p-buf, b, &b);
1516 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1522 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1524 char blob_size [64];
1525 char *b = blob_size;
1530 p = buf = g_malloc (64);
1532 mono_metadata_encode_value (0x06, p, &p);
1533 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1534 /* encode custom attributes before the type */
1535 encode_reflection_type (assembly, fb->type, p, &p);
1536 g_assert (p-buf < 64);
1537 mono_metadata_encode_value (p-buf, b, &b);
1538 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1544 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1545 char blob_size [64];
1546 char *b = blob_size;
1549 guint32 idx = 0, len = 0, dummy = 0;
1551 p = buf = g_malloc (64);
1553 *ret_type = MONO_TYPE_CLASS;
1555 box_val = (char*)&dummy;
1557 box_val = ((char*)val) + sizeof (MonoObject);
1558 *ret_type = val->vtable->klass->byval_arg.type;
1561 switch (*ret_type) {
1562 case MONO_TYPE_BOOLEAN:
1567 case MONO_TYPE_CHAR:
1582 case MONO_TYPE_VALUETYPE:
1583 if (val->vtable->klass->enumtype) {
1584 *ret_type = val->vtable->klass->enum_basetype->type;
1587 g_error ("we can't encode valuetypes");
1588 case MONO_TYPE_CLASS:
1590 case MONO_TYPE_STRING: {
1591 MonoString *str = (MonoString*)val;
1592 /* there is no signature */
1593 len = str->length * 2;
1594 mono_metadata_encode_value (len, b, &b);
1595 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1597 char *swapped = g_malloc (2 * mono_string_length (str));
1598 const char *p = (const char*)mono_string_chars (str);
1600 swap_with_size (swapped, p, 2, mono_string_length (str));
1601 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1605 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1612 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1615 /* there is no signature */
1616 mono_metadata_encode_value (len, b, &b);
1617 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1618 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1619 swap_with_size (blob_size, box_val, len, 1);
1620 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1622 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1630 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1631 char blob_size [64];
1632 char *b = blob_size;
1633 char *p, *buf, *str;
1634 guint32 idx, len, bufsize = 256;
1636 p = buf = g_malloc (bufsize);
1638 switch (minfo->type) {
1639 case MONO_NATIVE_BYVALTSTR:
1640 case MONO_NATIVE_BYVALARRAY:
1641 mono_metadata_encode_value (minfo->type, p, &p);
1642 mono_metadata_encode_value (minfo->count, p, &p);
1644 case MONO_NATIVE_LPARRAY:
1645 mono_metadata_encode_value (minfo->type, p, &p);
1646 if (minfo->eltype || (minfo->count > 0)) {
1647 mono_metadata_encode_value (minfo->eltype, p, &p);
1648 if (minfo->count > 0) {
1649 mono_metadata_encode_value (0, p, &p);
1650 mono_metadata_encode_value (minfo->count, p, &p);
1654 case MONO_NATIVE_CUSTOM:
1655 mono_metadata_encode_value (minfo->type, p, &p);
1657 str = mono_string_to_utf8 (minfo->guid);
1659 mono_metadata_encode_value (len, p, &p);
1660 memcpy (p, str, len);
1664 mono_metadata_encode_value (0, p, &p);
1666 if (minfo->marshaltype) {
1667 str = mono_string_to_utf8 (minfo->marshaltype);
1669 mono_metadata_encode_value (len, p, &p);
1670 if (p + len >= buf + bufsize) {
1673 buf = g_realloc (buf, bufsize);
1676 memcpy (p, str, len);
1680 mono_metadata_encode_value (0, p, &p);
1682 if (minfo->marshaltyperef) {
1683 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1685 mono_metadata_encode_value (len, p, &p);
1686 if (p + len >= buf + bufsize) {
1689 buf = g_realloc (buf, bufsize);
1692 memcpy (p, str, len);
1696 mono_metadata_encode_value (0, p, &p);
1698 if (minfo->mcookie) {
1699 str = mono_string_to_utf8 (minfo->mcookie);
1701 mono_metadata_encode_value (len, p, &p);
1702 if (p + len >= buf + bufsize) {
1705 buf = g_realloc (buf, bufsize);
1708 memcpy (p, str, len);
1712 mono_metadata_encode_value (0, p, &p);
1716 mono_metadata_encode_value (minfo->type, p, &p);
1720 mono_metadata_encode_value (len, b, &b);
1721 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1727 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1729 MonoDynamicTable *table;
1733 /* maybe this fixup should be done in the C# code */
1734 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1735 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1736 table = &assembly->tables [MONO_TABLE_FIELD];
1737 fb->table_idx = table->next_idx ++;
1738 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1739 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1740 name = mono_string_to_utf8 (fb->name);
1741 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1743 values [MONO_FIELD_FLAGS] = fb->attrs;
1744 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1746 if (fb->offset != -1) {
1747 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1749 alloc_table (table, table->rows);
1750 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1751 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1752 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1754 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1755 guint32 field_type = 0;
1756 table = &assembly->tables [MONO_TABLE_CONSTANT];
1758 alloc_table (table, table->rows);
1759 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1760 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1761 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1762 values [MONO_CONSTANT_TYPE] = field_type;
1763 values [MONO_CONSTANT_PADDING] = 0;
1765 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1767 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1769 alloc_table (table, table->rows);
1770 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1771 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1773 * We store it in the code section because it's simpler for now.
1776 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1778 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1779 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1781 if (fb->marshal_info) {
1782 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1784 alloc_table (table, table->rows);
1785 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1786 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1787 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1792 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1796 char *b = blob_size;
1797 guint32 nparams = 0;
1798 MonoReflectionMethodBuilder *mb = fb->get_method;
1799 MonoReflectionMethodBuilder *smb = fb->set_method;
1800 guint32 idx, i, size;
1802 if (mb && mb->parameters)
1803 nparams = mono_array_length (mb->parameters);
1804 if (!mb && smb && smb->parameters)
1805 nparams = mono_array_length (smb->parameters) - 1;
1806 size = 24 + nparams * 10;
1807 buf = p = g_malloc (size);
1810 mono_metadata_encode_value (nparams, p, &p);
1812 encode_reflection_type (assembly, mb->rtype, p, &p);
1813 for (i = 0; i < nparams; ++i) {
1814 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1815 encode_reflection_type (assembly, pt, p, &p);
1818 /* the property type is the last param */
1819 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1820 for (i = 0; i < nparams; ++i) {
1821 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1822 encode_reflection_type (assembly, pt, p, &p);
1826 g_assert (p - buf < size);
1827 mono_metadata_encode_value (p-buf, b, &b);
1828 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1834 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1836 MonoDynamicTable *table;
1839 guint num_methods = 0;
1843 * we need to set things in the following tables:
1844 * PROPERTYMAP (info already filled in _get_type_info ())
1845 * PROPERTY (rows already preallocated in _get_type_info ())
1846 * METHOD (method info already done with the generic method code)
1849 table = &assembly->tables [MONO_TABLE_PROPERTY];
1850 pb->table_idx = table->next_idx ++;
1851 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1852 name = mono_string_to_utf8 (pb->name);
1853 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1855 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1856 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1858 /* FIXME: we still don't handle 'other' methods */
1859 if (pb->get_method) num_methods ++;
1860 if (pb->set_method) num_methods ++;
1862 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1863 table->rows += num_methods;
1864 alloc_table (table, table->rows);
1866 if (pb->get_method) {
1867 semaidx = table->next_idx ++;
1868 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1869 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1870 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1871 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1873 if (pb->set_method) {
1874 semaidx = table->next_idx ++;
1875 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1876 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1877 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1878 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1883 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1885 MonoDynamicTable *table;
1888 guint num_methods = 0;
1892 * we need to set things in the following tables:
1893 * EVENTMAP (info already filled in _get_type_info ())
1894 * EVENT (rows already preallocated in _get_type_info ())
1895 * METHOD (method info already done with the generic method code)
1898 table = &assembly->tables [MONO_TABLE_EVENT];
1899 eb->table_idx = table->next_idx ++;
1900 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1901 name = mono_string_to_utf8 (eb->name);
1902 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1904 values [MONO_EVENT_FLAGS] = eb->attrs;
1905 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1908 * FIXME: we still don't handle 'other' methods
1910 if (eb->add_method) num_methods ++;
1911 if (eb->remove_method) num_methods ++;
1912 if (eb->raise_method) num_methods ++;
1914 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1915 table->rows += num_methods;
1916 alloc_table (table, table->rows);
1918 if (eb->add_method) {
1919 semaidx = table->next_idx ++;
1920 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1921 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1922 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1923 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1925 if (eb->remove_method) {
1926 semaidx = table->next_idx ++;
1927 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1928 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1929 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1930 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 if (eb->raise_method) {
1933 semaidx = table->next_idx ++;
1934 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1935 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1936 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1937 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1942 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1944 static MonoClass *NewConstraintAttr;
1945 static MonoMethod *NewConstraintAttr_ctor;
1946 MonoDynamicTable *table;
1948 guint32 token, type;
1949 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1952 if (!NewConstraintAttr)
1953 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1954 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1955 g_assert (NewConstraintAttr);
1957 if (!NewConstraintAttr_ctor) {
1960 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1961 MonoMethod *m = NewConstraintAttr->methods [i];
1963 if (strcmp (m->name, ".ctor"))
1966 NewConstraintAttr_ctor = m;
1970 g_assert (NewConstraintAttr_ctor);
1973 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1975 alloc_table (table, table->rows);
1977 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1978 owner <<= MONO_CUSTOM_ATTR_BITS;
1979 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1980 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1982 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1984 type = mono_metadata_token_index (token);
1985 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1986 switch (mono_metadata_token_table (token)) {
1987 case MONO_TABLE_METHOD:
1988 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1990 case MONO_TABLE_MEMBERREF:
1991 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1994 g_warning ("got wrong token in custom attr");
1997 values [MONO_CUSTOM_ATTR_TYPE] = type;
1999 buf = p = g_malloc (1);
2000 mono_metadata_encode_value (4, p, &p);
2001 g_assert (p-buf == 1);
2003 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2005 values += MONO_CUSTOM_ATTR_SIZE;
2010 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2013 guint32 num_constraints, i;
2017 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2018 num_constraints = gparam->iface_constraints ?
2019 mono_array_length (gparam->iface_constraints) : 0;
2020 table->rows += num_constraints;
2021 if (gparam->base_type)
2023 alloc_table (table, table->rows);
2025 if (gparam->base_type) {
2026 table_idx = table->next_idx ++;
2027 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2029 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2030 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2031 assembly, gparam->base_type->type);
2034 for (i = 0; i < num_constraints; i++) {
2035 MonoReflectionType *constraint = mono_array_get (
2036 gparam->iface_constraints, gpointer, i);
2038 table_idx = table->next_idx ++;
2039 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2041 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2042 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2043 assembly, constraint->type);
2046 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2047 encode_new_constraint (assembly, owner);
2051 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2053 GenericParamTableEntry *entry;
2056 * The GenericParam table must be sorted according to the `owner' field.
2057 * We need to do this sorting prior to writing the GenericParamConstraint
2058 * table, since we have to use the final GenericParam table indices there
2059 * and they must also be sorted.
2062 entry = g_new0 (GenericParamTableEntry, 1);
2063 entry->owner = owner;
2064 entry->gparam = gparam;
2066 g_ptr_array_add (assembly->gen_params, entry);
2070 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2072 MonoDynamicTable *table;
2073 MonoGenericParam *param;
2077 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2078 table_idx = table->next_idx ++;
2079 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2081 param = entry->gparam->type.type->data.generic_param;
2083 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2084 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2085 values [MONO_GENERICPARAM_NUMBER] = param->num;
2086 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2087 values [MONO_GENERICPARAM_KIND] = 0;
2089 encode_constraints (entry->gparam, table_idx, assembly);
2093 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2095 MonoDynamicTable *table;
2098 guint32 cols [MONO_ASSEMBLY_SIZE];
2102 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2105 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2106 table = &assembly->tables [MONO_TABLE_MODULEREF];
2107 token = table->next_idx ++;
2109 alloc_table (table, table->rows);
2110 values = table->values + token * MONO_MODULEREF_SIZE;
2111 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2113 token <<= MONO_RESOLTION_SCOPE_BITS;
2114 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2115 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2120 if (image->assembly->dynamic)
2122 memset (cols, 0, sizeof (cols));
2124 /* image->assembly->image is the manifest module */
2125 image = image->assembly->image;
2126 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2129 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2130 token = table->next_idx ++;
2132 alloc_table (table, table->rows);
2133 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2134 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2135 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2136 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2137 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2138 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2139 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2140 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2141 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2143 if (strcmp ("", image->assembly->aname.culture)) {
2144 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2145 image->assembly->aname.culture);
2148 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2149 guchar pubtoken [9];
2151 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2152 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2154 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2156 token <<= MONO_RESOLTION_SCOPE_BITS;
2157 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2158 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2163 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2165 MonoDynamicTable *table;
2171 char *b = blob_size;
2173 switch (type->type) {
2174 case MONO_TYPE_FNPTR:
2176 case MONO_TYPE_SZARRAY:
2177 case MONO_TYPE_ARRAY:
2179 case MONO_TYPE_MVAR:
2180 case MONO_TYPE_GENERICINST:
2181 encode_type (assembly, type, p, &p);
2183 case MONO_TYPE_CLASS:
2184 case MONO_TYPE_VALUETYPE: {
2185 MonoClass *k = mono_class_from_mono_type (type);
2186 if (!k || !k->generic_inst)
2188 encode_generic_inst (assembly, k->generic_inst, p, &p);
2195 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2196 if (assembly->save) {
2197 g_assert (p-sig < 128);
2198 mono_metadata_encode_value (p-sig, b, &b);
2199 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2200 alloc_table (table, table->rows + 1);
2201 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2202 values [MONO_TYPESPEC_SIGNATURE] = token;
2205 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2206 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2212 * Despite the name, we handle also TypeSpec (with the above helper).
2215 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2217 MonoDynamicTable *table;
2219 guint32 token, scope, enclosing;
2222 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2225 token = create_typespec (assembly, type);
2228 klass = my_mono_class_from_mono_type (type);
2230 klass = mono_class_from_mono_type (type);
2233 * If it's in the same module and not a generic type parameter:
2235 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2236 (type->type != MONO_TYPE_MVAR)) {
2237 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2238 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2239 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2243 if (klass->nested_in) {
2244 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2245 /* get the typeref idx of the enclosing type */
2246 enclosing >>= MONO_TYPEDEFORREF_BITS;
2247 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2249 scope = resolution_scope_from_image (assembly, klass->image);
2251 table = &assembly->tables [MONO_TABLE_TYPEREF];
2252 if (assembly->save) {
2253 alloc_table (table, table->rows + 1);
2254 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2255 values [MONO_TYPEREF_SCOPE] = scope;
2256 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2257 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2259 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2260 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2262 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2267 * Insert a memberef row into the metadata: the token that point to the memberref
2268 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2269 * mono_image_get_fieldref_token()).
2270 * The sig param is an index to an already built signature.
2273 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2275 MonoDynamicTable *table;
2277 guint32 token, pclass;
2280 parent = mono_image_typedef_or_ref (assembly, type);
2281 switch (parent & MONO_TYPEDEFORREF_MASK) {
2282 case MONO_TYPEDEFORREF_TYPEREF:
2283 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2285 case MONO_TYPEDEFORREF_TYPESPEC:
2286 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2288 case MONO_TYPEDEFORREF_TYPEDEF:
2289 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2292 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2295 /* extract the index */
2296 parent >>= MONO_TYPEDEFORREF_BITS;
2298 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2300 if (assembly->save) {
2301 alloc_table (table, table->rows + 1);
2302 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2303 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2304 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2305 values [MONO_MEMBERREF_SIGNATURE] = sig;
2308 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2315 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2318 MonoMethodSignature *sig;
2320 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2325 * A methodref signature can't contain an unmanaged calling convention.
2327 sig = mono_metadata_signature_dup (method->signature);
2328 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2329 sig->call_convention = MONO_CALL_DEFAULT;
2330 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2331 method->name, method_encode_signature (assembly, sig));
2333 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2338 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2339 const gchar *name, guint32 sig)
2341 MonoDynamicTable *table;
2345 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2347 if (assembly->save) {
2348 alloc_table (table, table->rows + 1);
2349 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2350 values [MONO_MEMBERREF_CLASS] = original;
2351 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2352 values [MONO_MEMBERREF_SIGNATURE] = sig;
2355 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2362 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2365 ReflectionMethodBuilder rmb;
2367 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2371 reflection_methodbuilder_from_method_builder (&rmb, mb);
2373 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2374 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2375 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2380 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2383 ReflectionMethodBuilder rmb;
2385 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2389 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2391 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2392 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2393 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2398 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2403 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2406 g_assert (f->field->parent);
2407 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2408 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2409 f->field->name, fieldref_encode_signature (assembly, type));
2410 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2420 guint32 nparams = gmethod->mtype_argc;
2421 guint32 size = 10 + nparams * 10;
2424 char *b = blob_size;
2426 if (!assembly->save)
2429 p = buf = g_malloc (size);
2431 * FIXME: vararg, explicit_this, differenc call_conv values...
2433 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2434 mono_metadata_encode_value (nparams, p, &p);
2436 for (i = 0; i < nparams; i++)
2437 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2440 g_assert (p - buf < size);
2441 mono_metadata_encode_value (p-buf, b, &b);
2442 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2450 MonoDynamicTable *table;
2452 guint32 token, mtoken = 0, sig;
2453 MonoMethodInflated *imethod;
2454 MonoMethod *declaring;
2456 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2458 g_assert (method->signature->is_inflated);
2459 imethod = (MonoMethodInflated *) method;
2460 declaring = imethod->declaring;
2462 sig = method_encode_signature (assembly, declaring->signature);
2463 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2465 if (!declaring->signature->generic_param_count)
2468 switch (mono_metadata_token_table (mtoken)) {
2469 case MONO_TABLE_MEMBERREF:
2470 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2472 case MONO_TABLE_METHOD:
2473 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2476 g_assert_not_reached ();
2479 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2481 if (assembly->save) {
2482 alloc_table (table, table->rows + 1);
2483 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2484 values [MONO_METHODSPEC_METHOD] = mtoken;
2485 values [MONO_METHODSPEC_SIGNATURE] = sig;
2488 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2497 MonoMethodInflated *imethod;
2500 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2504 g_assert (m->signature->is_inflated);
2505 imethod = (MonoMethodInflated *) m;
2507 if (imethod->declaring->signature->generic_param_count) {
2508 token = method_encode_methodspec (assembly, m);
2510 guint32 sig = method_encode_signature (
2511 assembly, imethod->declaring->signature);
2512 token = mono_image_get_memberref_token (
2513 assembly, &m->klass->byval_arg, m->name, sig);
2516 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2523 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2526 sig = method_encode_signature (assembly, imethod->declaring->signature);
2527 token = mono_image_get_memberref_token (
2528 assembly, &m->klass->byval_arg, m->name, sig);
2534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2536 MonoDynamicTable *table;
2543 char *b = blob_size;
2547 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2548 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2549 * Because of this, we must not insert it into the `typeref' hash table.
2552 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2556 g_assert (tb->generic_params);
2557 klass = mono_class_from_mono_type (tb->type.type);
2559 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2560 encode_type (assembly, &klass->byval_arg, p, &p);
2562 count = mono_array_length (tb->generic_params);
2563 mono_metadata_encode_value (count, p, &p);
2564 for (i = 0; i < count; i++) {
2565 MonoReflectionGenericParam *gparam;
2567 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2569 encode_type (assembly, gparam->type.type, p, &p);
2572 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2573 if (assembly->save) {
2574 g_assert (p-sig < 128);
2575 mono_metadata_encode_value (p-sig, b, &b);
2576 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2577 alloc_table (table, table->rows + 1);
2578 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2579 values [MONO_TYPESPEC_SIGNATURE] = token;
2582 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2583 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2589 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2591 MonoDynamicTable *table;
2594 guint32 token, pclass, parent, sig;
2597 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2601 klass = mono_class_from_mono_type (fb->typeb->type);
2602 name = mono_string_to_utf8 (fb->name);
2604 sig = fieldref_encode_signature (assembly, fb->type->type);
2606 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2607 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2609 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2610 parent >>= MONO_TYPEDEFORREF_BITS;
2612 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2614 if (assembly->save) {
2615 alloc_table (table, table->rows + 1);
2616 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2617 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2618 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2619 values [MONO_MEMBERREF_SIGNATURE] = sig;
2622 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2624 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2629 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2637 char *b = blob_size;
2639 if (!assembly->save)
2643 g_assert (helper->type == 2);
2645 if (helper->arguments)
2646 nargs = mono_array_length (helper->arguments);
2650 size = 10 + (nargs * 10);
2652 p = buf = g_malloc (size);
2654 /* Encode calling convention */
2655 /* Change Any to Standard */
2656 if ((helper->call_conv & 0x03) == 0x03)
2657 helper->call_conv = 0x01;
2658 /* explicit_this implies has_this */
2659 if (helper->call_conv & 0x40)
2660 helper->call_conv &= 0x20;
2662 if (helper->call_conv == 0) { /* Unmanaged */
2663 *p = helper->unmanaged_call_conv - 1;
2666 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2667 if (helper->call_conv & 0x02) /* varargs */
2672 mono_metadata_encode_value (nargs, p, &p);
2673 encode_reflection_type (assembly, helper->return_type, p, &p);
2674 for (i = 0; i < nargs; ++i) {
2675 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2676 encode_reflection_type (assembly, pt, p, &p);
2679 g_assert (p - buf < size);
2680 mono_metadata_encode_value (p-buf, b, &b);
2681 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2688 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2691 MonoDynamicTable *table;
2694 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2695 idx = table->next_idx ++;
2697 alloc_table (table, table->rows);
2698 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2700 values [MONO_STAND_ALONE_SIGNATURE] =
2701 mono_reflection_encode_sighelper (assembly, helper);
2707 reflection_cc_to_file (int call_conv) {
2708 switch (call_conv & 0x3) {
2710 case 1: return MONO_CALL_DEFAULT;
2711 case 2: return MONO_CALL_VARARG;
2713 g_assert_not_reached ();
2720 MonoMethodSignature *sig;
2726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2731 MonoMethodSignature *sig;
2734 name = mono_string_to_utf8 (m->name);
2735 nparams = mono_array_length (m->parameters);
2736 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2738 sig->sentinelpos = -1;
2739 sig->call_convention = reflection_cc_to_file (m->call_conv);
2740 sig->param_count = nparams;
2741 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2742 for (i = 0; i < nparams; ++i) {
2743 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2744 sig->params [i] = t->type;
2747 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2749 if (strcmp (name, am->name) == 0 &&
2750 mono_metadata_type_equal (am->parent, m->parent->type) &&
2751 mono_metadata_signature_equal (am->sig, sig)) {
2754 m->table_idx = am->token & 0xffffff;
2758 am = g_new0 (ArrayMethod, 1);
2761 am->parent = m->parent->type;
2762 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2763 method_encode_signature (assembly, sig));
2764 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2765 m->table_idx = am->token & 0xffffff;
2770 * Insert into the metadata tables all the info about the TypeBuilder tb.
2771 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2774 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2776 MonoDynamicTable *table;
2778 int i, is_object = 0, is_system = 0;
2781 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2782 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2783 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2784 n = mono_string_to_utf8 (tb->name);
2785 if (strcmp (n, "Object") == 0)
2787 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2789 n = mono_string_to_utf8 (tb->nspace);
2790 if (strcmp (n, "System") == 0)
2792 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2794 if (tb->parent && !(is_system && is_object) &&
2795 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2796 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2798 values [MONO_TYPEDEF_EXTENDS] = 0;
2800 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2801 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2804 * if we have explicitlayout or sequentiallayouts, output data in the
2805 * ClassLayout table.
2807 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2808 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2809 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2811 alloc_table (table, table->rows);
2812 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2813 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2814 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2815 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2818 /* handle interfaces */
2819 if (tb->interfaces) {
2820 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2822 table->rows += mono_array_length (tb->interfaces);
2823 alloc_table (table, table->rows);
2824 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2825 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2826 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2827 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2828 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2829 values += MONO_INTERFACEIMPL_SIZE;
2835 table = &assembly->tables [MONO_TABLE_FIELD];
2836 table->rows += tb->num_fields;
2837 alloc_table (table, table->rows);
2838 for (i = 0; i < tb->num_fields; ++i)
2839 mono_image_get_field_info (
2840 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2843 /* handle constructors */
2845 table = &assembly->tables [MONO_TABLE_METHOD];
2846 table->rows += mono_array_length (tb->ctors);
2847 alloc_table (table, table->rows);
2848 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2849 mono_image_get_ctor_info (domain,
2850 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2853 /* handle methods */
2855 table = &assembly->tables [MONO_TABLE_METHOD];
2856 table->rows += tb->num_methods;
2857 alloc_table (table, table->rows);
2858 for (i = 0; i < tb->num_methods; ++i)
2859 mono_image_get_method_info (
2860 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2863 /* Do the same with properties etc.. */
2864 if (tb->events && mono_array_length (tb->events)) {
2865 table = &assembly->tables [MONO_TABLE_EVENT];
2866 table->rows += mono_array_length (tb->events);
2867 alloc_table (table, table->rows);
2868 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2870 alloc_table (table, table->rows);
2871 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2872 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2873 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2874 for (i = 0; i < mono_array_length (tb->events); ++i)
2875 mono_image_get_event_info (
2876 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2878 if (tb->properties && mono_array_length (tb->properties)) {
2879 table = &assembly->tables [MONO_TABLE_PROPERTY];
2880 table->rows += mono_array_length (tb->properties);
2881 alloc_table (table, table->rows);
2882 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2884 alloc_table (table, table->rows);
2885 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2886 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2887 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2888 for (i = 0; i < mono_array_length (tb->properties); ++i)
2889 mono_image_get_property_info (
2890 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2893 /* handle generic parameters */
2894 if (tb->generic_params) {
2895 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2896 table->rows += mono_array_length (tb->generic_params);
2897 alloc_table (table, table->rows);
2898 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2899 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2901 mono_image_get_generic_param_info (
2902 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2906 mono_image_add_decl_security (assembly,
2907 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2910 MonoDynamicTable *ntable;
2912 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2913 ntable->rows += mono_array_length (tb->subtypes);
2914 alloc_table (ntable, ntable->rows);
2915 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2917 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2918 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2920 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2921 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2922 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2923 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2924 mono_string_to_utf8 (tb->name), tb->table_idx,
2925 ntable->next_idx, ntable->rows);*/
2926 values += MONO_NESTED_CLASS_SIZE;
2933 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2937 g_ptr_array_add (types, type);
2939 if (!type->subtypes)
2942 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2943 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2944 collect_types (types, subtype);
2949 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2951 if ((*type1)->table_idx < (*type2)->table_idx)
2954 if ((*type1)->table_idx > (*type2)->table_idx)
2961 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2966 for (i = 0; i < mono_array_length (pinfo); ++i) {
2967 MonoReflectionParamBuilder *pb;
2968 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2971 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2976 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2979 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2981 for (i = 0; i < tb->num_fields; ++i) {
2982 MonoReflectionFieldBuilder* fb;
2983 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2984 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2988 for (i = 0; i < mono_array_length (tb->events); ++i) {
2989 MonoReflectionEventBuilder* eb;
2990 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2991 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2994 if (tb->properties) {
2995 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2996 MonoReflectionPropertyBuilder* pb;
2997 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2998 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3002 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3003 MonoReflectionCtorBuilder* cb;
3004 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3005 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3006 params_add_cattrs (assembly, cb->pinfo);
3011 for (i = 0; i < tb->num_methods; ++i) {
3012 MonoReflectionMethodBuilder* mb;
3013 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3014 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3015 params_add_cattrs (assembly, mb->pinfo);
3020 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3021 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3026 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3029 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3031 /* no types in the module */
3035 for (i = 0; i < mb->num_types; ++i)
3036 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3040 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3042 MonoDynamicTable *table;
3046 char *b = blob_size;
3049 table = &assembly->tables [MONO_TABLE_FILE];
3051 alloc_table (table, table->rows);
3052 values = table->values + table->next_idx * MONO_FILE_SIZE;
3053 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3054 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3055 if (module->image->dynamic) {
3056 /* This depends on the fact that the main module is emitted last */
3057 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3058 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3061 path = g_strdup (module->image->name);
3063 mono_sha1_get_digest_from_file (path, hash);
3066 mono_metadata_encode_value (20, b, &b);
3067 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3068 mono_image_add_stream_data (&assembly->blob, hash, 20);
3073 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3075 MonoDynamicTable *table;
3079 table = &assembly->tables [MONO_TABLE_MODULE];
3080 mb->table_idx = table->next_idx ++;
3081 name = mono_string_to_utf8 (mb->module.name);
3082 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3084 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3088 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3089 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3093 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3094 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3096 MonoDynamicTable *table;
3100 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3101 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3104 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3106 alloc_table (table, table->rows);
3107 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3109 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3110 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3111 if (klass->nested_in)
3112 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3114 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3115 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3116 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3118 res = table->next_idx;
3122 /* Emit nested types */
3123 if (klass->nested_classes) {
3126 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3127 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3134 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3135 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3140 klass = mono_class_from_mono_type (tb->type.type);
3142 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3144 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3145 parent_index, assembly);
3149 * We need to do this ourselves since klass->nested_classes is not set up.
3152 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3153 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3158 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3159 guint32 module_index, MonoDynamicImage *assembly)
3161 MonoImage *image = module->image;
3165 t = &image->tables [MONO_TABLE_TYPEDEF];
3167 for (i = 0; i < t->rows; ++i) {
3168 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3170 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3171 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3175 #define align_pointer(base,p)\
3177 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3179 (p) += 4 - (__diff & 3);\
3183 compare_semantics (const void *a, const void *b)
3185 const guint32 *a_values = a;
3186 const guint32 *b_values = b;
3187 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3190 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3194 compare_custom_attrs (const void *a, const void *b)
3196 const guint32 *a_values = a;
3197 const guint32 *b_values = b;
3199 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3203 compare_field_marshal (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3208 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3212 compare_nested (const void *a, const void *b)
3214 const guint32 *a_values = a;
3215 const guint32 *b_values = b;
3217 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3221 compare_genericparam (const void *a, const void *b)
3223 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3224 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3226 return (*a_entry)->owner - (*b_entry)->owner;
3230 compare_declsecurity_attrs (const void *a, const void *b)
3232 const guint32 *a_values = a;
3233 const guint32 *b_values = b;
3235 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3239 pad_heap (MonoDynamicStream *sh)
3241 if (sh->index & 3) {
3242 int sz = 4 - (sh->index & 3);
3243 memset (sh->data + sh->index, 0, sz);
3250 MonoDynamicStream *stream;
3254 * build_compressed_metadata() fills in the blob of data that represents the
3255 * raw metadata as it will be saved in the PE file. The five streams are output
3256 * and the metadata tables are comnpressed from the guint32 array representation,
3257 * to the compressed on-disk format.
3260 build_compressed_metadata (MonoDynamicImage *assembly)
3262 MonoDynamicTable *table;
3264 guint64 valid_mask = 0;
3265 guint64 sorted_mask;
3266 guint32 heapt_size = 0;
3267 guint32 meta_size = 256; /* allow for header and other stuff */
3268 guint32 table_offset;
3269 guint32 ntables = 0;
3275 struct StreamDesc stream_desc [5];
3277 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3278 for (i = 0; i < assembly->gen_params->len; i++){
3279 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3280 write_generic_param_entry (assembly, entry);
3283 stream_desc [0].name = "#~";
3284 stream_desc [0].stream = &assembly->tstream;
3285 stream_desc [1].name = "#Strings";
3286 stream_desc [1].stream = &assembly->sheap;
3287 stream_desc [2].name = "#US";
3288 stream_desc [2].stream = &assembly->us;
3289 stream_desc [3].name = "#Blob";
3290 stream_desc [3].stream = &assembly->blob;
3291 stream_desc [4].name = "#GUID";
3292 stream_desc [4].stream = &assembly->guid;
3294 /* tables that are sorted */
3295 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3296 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3297 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3298 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3299 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3300 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3302 /* Compute table sizes */
3303 /* the MonoImage has already been created in mono_image_basic_init() */
3304 meta = &assembly->image;
3306 /* sizes should be multiple of 4 */
3307 pad_heap (&assembly->blob);
3308 pad_heap (&assembly->guid);
3309 pad_heap (&assembly->sheap);
3310 pad_heap (&assembly->us);
3312 /* Setup the info used by compute_sizes () */
3313 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3314 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3315 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3317 meta_size += assembly->blob.index;
3318 meta_size += assembly->guid.index;
3319 meta_size += assembly->sheap.index;
3320 meta_size += assembly->us.index;
3322 for (i=0; i < 64; ++i)
3323 meta->tables [i].rows = assembly->tables [i].rows;
3325 for (i = 0; i < 64; i++){
3326 if (meta->tables [i].rows == 0)
3328 valid_mask |= (guint64)1 << i;
3330 meta->tables [i].row_size = mono_metadata_compute_size (
3331 meta, i, &meta->tables [i].size_bitfield);
3332 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3334 heapt_size += 24; /* #~ header size */
3335 heapt_size += ntables * 4;
3336 /* make multiple of 4 */
3339 meta_size += heapt_size;
3340 meta->raw_metadata = g_malloc0 (meta_size);
3341 p = meta->raw_metadata;
3342 /* the metadata signature */
3343 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3344 /* version numbers and 4 bytes reserved */
3345 int16val = (guint16*)p;
3346 *int16val++ = GUINT16_TO_LE (1);
3347 *int16val = GUINT16_TO_LE (1);
3349 /* version string */
3350 int32val = (guint32*)p;
3351 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3353 memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3354 p += GUINT32_FROM_LE (*int32val);
3355 align_pointer (meta->raw_metadata, p);
3356 int16val = (guint16*)p;
3357 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3358 *int16val = GUINT16_TO_LE (5); /* number of streams */
3362 * write the stream info.
3364 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3365 table_offset += 3; table_offset &= ~3;
3367 assembly->tstream.index = heapt_size;
3368 for (i = 0; i < 5; ++i) {
3369 int32val = (guint32*)p;
3370 stream_desc [i].stream->offset = table_offset;
3371 *int32val++ = GUINT32_TO_LE (table_offset);
3372 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3373 table_offset += GUINT32_FROM_LE (*int32val);
3374 table_offset += 3; table_offset &= ~3;
3376 strcpy (p, stream_desc [i].name);
3377 p += strlen (stream_desc [i].name) + 1;
3378 align_pointer (meta->raw_metadata, p);
3381 * now copy the data, the table stream header and contents goes first.
3383 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3384 p = meta->raw_metadata + assembly->tstream.offset;
3385 int32val = (guint32*)p;
3386 *int32val = GUINT32_TO_LE (0); /* reserved */
3389 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3390 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3391 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3392 *p++ = 1; /* version */
3395 *p++ = 1; /* version */
3399 if (meta->idx_string_wide)
3401 if (meta->idx_guid_wide)
3403 if (meta->idx_blob_wide)
3406 *p++ = 0; /* reserved */
3407 int64val = (guint64*)p;
3408 *int64val++ = GUINT64_TO_LE (valid_mask);
3409 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3411 int32val = (guint32*)p;
3412 for (i = 0; i < 64; i++){
3413 if (meta->tables [i].rows == 0)
3415 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3417 p = (unsigned char*)int32val;
3419 /* sort the tables that still need sorting */
3420 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3422 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3423 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3425 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3426 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3428 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3429 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3431 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3432 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3433 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3435 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3437 /* compress the tables */
3438 for (i = 0; i < 64; i++){
3441 guint32 bitfield = meta->tables [i].size_bitfield;
3442 if (!meta->tables [i].rows)
3444 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3445 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3446 meta->tables [i].base = p;
3447 for (row = 1; row <= meta->tables [i].rows; ++row) {
3448 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3449 for (col = 0; col < assembly->tables [i].columns; ++col) {
3450 switch (mono_metadata_table_size (bitfield, col)) {
3452 *p++ = values [col];
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3459 *p++ = values [col] & 0xff;
3460 *p++ = (values [col] >> 8) & 0xff;
3461 *p++ = (values [col] >> 16) & 0xff;
3462 *p++ = (values [col] >> 24) & 0xff;
3465 g_assert_not_reached ();
3469 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3472 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3473 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3474 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3475 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3476 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3478 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 * Some tables in metadata need to be sorted according to some criteria, but
3483 * when methods and fields are first created with reflection, they may be assigned a token
3484 * that doesn't correspond to the final token they will get assigned after the sorting.
3485 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3486 * with the reflection objects that represent them. Once all the tables are set up, the
3487 * reflection objects will contains the correct table index. fixup_method() will fixup the
3488 * tokens for the method with ILGenerator @ilgen.
3491 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3492 guint32 code_idx = GPOINTER_TO_UINT (value);
3493 MonoReflectionILTokenInfo *iltoken;
3494 MonoReflectionFieldBuilder *field;
3495 MonoReflectionCtorBuilder *ctor;
3496 MonoReflectionMethodBuilder *method;
3497 MonoReflectionTypeBuilder *tb;
3498 MonoReflectionArrayMethod *am;
3500 unsigned char *target;
3502 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3503 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3504 target = assembly->code.data + code_idx + iltoken->code_pos;
3505 switch (target [3]) {
3506 case MONO_TABLE_FIELD:
3507 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3508 field = (MonoReflectionFieldBuilder *)iltoken->member;
3509 idx = field->table_idx;
3510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3511 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3512 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3514 g_assert_not_reached ();
3517 case MONO_TABLE_METHOD:
3518 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3519 method = (MonoReflectionMethodBuilder *)iltoken->member;
3520 idx = method->table_idx;
3521 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3522 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3523 idx = ctor->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3525 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3526 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3527 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3529 g_assert_not_reached ();
3532 case MONO_TABLE_TYPEDEF:
3533 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3534 g_assert_not_reached ();
3535 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3536 idx = tb->table_idx;
3538 case MONO_TABLE_MEMBERREF:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3540 am = (MonoReflectionArrayMethod*)iltoken->member;
3541 idx = am->table_idx;
3542 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3543 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3544 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3545 g_assert (m->klass->generic_inst);
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3550 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3551 g_assert (f->generic_info);
3553 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3556 g_assert_not_reached ();
3559 case MONO_TABLE_METHODSPEC:
3560 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3561 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3562 g_assert (m->signature->generic_param_count);
3565 g_assert_not_reached ();
3569 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3571 target [0] = idx & 0xff;
3572 target [1] = (idx >> 8) & 0xff;
3573 target [2] = (idx >> 16) & 0xff;
3580 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3581 * value is not known when the table is emitted.
3584 fixup_cattrs (MonoDynamicImage *assembly)
3586 MonoDynamicTable *table;
3588 guint32 type, i, idx, token;
3591 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3593 for (i = 0; i < table->rows; ++i) {
3594 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3596 type = values [MONO_CUSTOM_ATTR_TYPE];
3597 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3598 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3599 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3600 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3603 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3604 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3605 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3606 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3613 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3615 MonoDynamicTable *table;
3619 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3621 alloc_table (table, table->rows);
3622 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3623 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3624 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3625 name = mono_string_to_utf8 (rsrc->name);
3626 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3628 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3633 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3635 MonoDynamicTable *table;
3639 char *b = blob_size;
3641 guint32 idx, offset;
3643 if (rsrc->filename) {
3644 name = mono_string_to_utf8 (rsrc->filename);
3645 sname = g_path_get_basename (name);
3647 table = &assembly->tables [MONO_TABLE_FILE];
3649 alloc_table (table, table->rows);
3650 values = table->values + table->next_idx * MONO_FILE_SIZE;
3651 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3652 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3655 mono_sha1_get_digest_from_file (name, hash);
3656 mono_metadata_encode_value (20, b, &b);
3657 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3658 mono_image_add_stream_data (&assembly->blob, hash, 20);
3660 idx = table->next_idx++;
3662 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3665 offset = mono_array_length (rsrc->data);
3666 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3667 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3668 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3669 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3673 * The entry should be emitted into the MANIFESTRESOURCE table of
3674 * the main module, but that needs to reference the FILE table
3675 * which isn't emitted yet.
3682 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3686 set_version_from_string (MonoString *version, guint32 *values)
3688 gchar *ver, *p, *str;
3691 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3692 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3693 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3694 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3697 ver = str = mono_string_to_utf8 (version);
3698 for (i = 0; i < 4; ++i) {
3699 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3705 /* handle Revision and Build */
3715 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3719 char *b = blob_size;
3724 len = mono_array_length (pkey);
3725 mono_metadata_encode_value (len, b, &b);
3726 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3727 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3729 /* need to get the actual value from the key type... */
3730 assembly->strong_name_size = 128;
3731 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3737 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3739 MonoDynamicTable *table;
3740 MonoDynamicImage *assembly;
3741 MonoReflectionAssemblyBuilder *assemblyb;
3746 guint32 module_index;
3748 assemblyb = moduleb->assemblyb;
3749 assembly = moduleb->dynamic_image;
3750 domain = mono_object_domain (assemblyb);
3752 /* Emit ASSEMBLY table */
3753 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3754 alloc_table (table, 1);
3755 values = table->values + MONO_ASSEMBLY_SIZE;
3756 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3757 name = mono_string_to_utf8 (assemblyb->name);
3758 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3760 if (assemblyb->culture) {
3761 name = mono_string_to_utf8 (assemblyb->culture);
3762 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3765 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3767 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3768 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3769 set_version_from_string (assemblyb->version, values);
3771 /* Emit FILE + EXPORTED_TYPE table */
3773 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3775 MonoReflectionModuleBuilder *file_module =
3776 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3777 if (file_module != moduleb) {
3778 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3780 if (file_module->types) {
3781 for (j = 0; j < file_module->num_types; ++j) {
3782 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3783 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3788 if (assemblyb->loaded_modules) {
3789 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3790 MonoReflectionModule *file_module =
3791 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3792 mono_image_fill_file_table (domain, file_module, assembly);
3794 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3798 /* Emit MANIFESTRESOURCE table */
3800 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3802 MonoReflectionModuleBuilder *file_module =
3803 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3804 /* The table for the main module is emitted later */
3805 if (file_module != moduleb) {
3807 if (file_module->resources) {
3808 int len = mono_array_length (file_module->resources);
3809 for (j = 0; j < len; ++j) {
3810 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3811 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3819 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3820 * for the modulebuilder @moduleb.
3821 * At the end of the process, method and field tokens are fixed up and the
3822 * on-disk compressed metadata representation is created.
3825 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3827 MonoDynamicTable *table;
3828 MonoDynamicImage *assembly;
3829 MonoReflectionAssemblyBuilder *assemblyb;
3834 assemblyb = moduleb->assemblyb;
3835 assembly = moduleb->dynamic_image;
3836 domain = mono_object_domain (assemblyb);
3838 if (assembly->text_rva)
3841 assembly->text_rva = START_TEXT_RVA;
3843 if (moduleb->is_main) {
3844 mono_image_emit_manifest (moduleb);
3847 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3848 table->rows = 1; /* .<Module> */
3850 alloc_table (table, table->rows);
3852 * Set the first entry.
3854 values = table->values + table->columns;
3855 values [MONO_TYPEDEF_FLAGS] = 0;
3856 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3857 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3858 values [MONO_TYPEDEF_EXTENDS] = 0;
3859 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3860 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3863 * handle global methods
3864 * FIXME: test what to do when global methods are defined in multiple modules.
3866 if (moduleb->global_methods) {
3867 table = &assembly->tables [MONO_TABLE_METHOD];
3868 table->rows += mono_array_length (moduleb->global_methods);
3869 alloc_table (table, table->rows);
3870 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3871 mono_image_get_method_info (
3872 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3874 if (moduleb->global_fields) {
3875 table = &assembly->tables [MONO_TABLE_FIELD];
3876 table->rows += mono_array_length (moduleb->global_fields);
3877 alloc_table (table, table->rows);
3878 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3879 mono_image_get_field_info (
3880 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3883 table = &assembly->tables [MONO_TABLE_MODULE];
3884 alloc_table (table, 1);
3885 mono_image_fill_module_table (domain, moduleb, assembly);
3889 /* Collect all types into a list sorted by their table_idx */
3890 GPtrArray *types = g_ptr_array_new ();
3893 for (i = 0; i < moduleb->num_types; ++i) {
3894 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3895 collect_types (types, type);
3898 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3899 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3900 table->rows += types->len;
3901 alloc_table (table, table->rows);
3903 for (i = 0; i < types->len; ++i) {
3904 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3905 mono_image_get_type_info (domain, type, assembly);
3907 g_ptr_array_free (types, TRUE);
3911 * table->rows is already set above and in mono_image_fill_module_table.
3913 /* add all the custom attributes at the end, once all the indexes are stable */
3914 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3916 /* CAS assembly permissions */
3917 if (assemblyb->permissions_minimum)
3918 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3919 if (assemblyb->permissions_optional)
3920 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3921 if (assemblyb->permissions_refused)
3922 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3924 module_add_cattrs (assembly, moduleb);
3927 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3928 fixup_cattrs (assembly);
3932 * mono_image_insert_string:
3933 * @module: module builder object
3936 * Insert @str into the user string stream of @module.
3939 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3941 MonoDynamicImage *assembly;
3946 MONO_ARCH_SAVE_REGS;
3948 if (!module->dynamic_image)
3949 mono_image_module_basic_init (module);
3951 assembly = module->dynamic_image;
3953 if (assembly->save) {
3954 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3955 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3956 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3958 char *swapped = g_malloc (2 * mono_string_length (str));
3959 const char *p = (const char*)mono_string_chars (str);
3961 swap_with_size (swapped, p, 2, mono_string_length (str));
3962 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3966 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3968 mono_image_add_stream_data (&assembly->us, "", 1);
3970 idx = assembly->us.index ++;
3973 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3975 return MONO_TOKEN_STRING | idx;
3979 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3984 klass = obj->vtable->klass;
3985 if (strcmp (klass->name, "MonoMethod") == 0) {
3986 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3987 MonoMethodSignature *sig, *old;
3988 guint32 sig_token, parent;
3991 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3993 nargs = mono_array_length (opt_param_types);
3994 old = method->signature;
3995 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3997 sig->hasthis = old->hasthis;
3998 sig->explicit_this = old->explicit_this;
3999 sig->call_convention = old->call_convention;
4000 sig->generic_param_count = old->generic_param_count;
4001 sig->param_count = old->param_count + nargs;
4002 sig->sentinelpos = old->param_count;
4003 sig->ret = old->ret;
4005 for (i = 0; i < old->param_count; i++)
4006 sig->params [i] = old->params [i];
4008 for (i = 0; i < nargs; i++) {
4009 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4010 sig->params [old->param_count + i] = rt->type;
4013 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4014 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4015 parent >>= MONO_TYPEDEFORREF_BITS;
4017 parent <<= MONO_MEMBERREF_PARENT_BITS;
4018 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4020 sig_token = method_encode_signature (assembly, sig);
4021 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4022 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4023 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4024 ReflectionMethodBuilder rmb;
4025 guint32 parent, sig;
4027 reflection_methodbuilder_from_method_builder (&rmb, mb);
4028 rmb.opt_types = opt_param_types;
4030 sig = method_builder_encode_signature (assembly, &rmb);
4032 parent = mono_image_create_token (assembly, obj, TRUE);
4033 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4035 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4036 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4038 token = mono_image_get_varargs_method_token (
4039 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4041 g_error ("requested method token for %s\n", klass->name);
4048 * mono_image_create_token:
4049 * @assembly: a dynamic assembly
4052 * Get a token to insert in the IL code stream for the given MemberInfo.
4053 * @obj can be one of:
4054 * ConstructorBuilder
4064 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4069 klass = obj->vtable->klass;
4070 if (strcmp (klass->name, "MethodBuilder") == 0) {
4071 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4073 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4074 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4076 token = mono_image_get_methodbuilder_token (assembly, mb);
4077 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4078 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4079 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4081 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4082 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4084 token = mono_image_get_ctorbuilder_token (assembly, mb);
4085 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4086 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4087 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4088 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4089 if (tb->generic_params) {
4090 token = mono_image_get_generic_field_token (assembly, fb);
4092 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4094 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4095 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4096 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4097 } else if (strcmp (klass->name, "MonoType") == 0 ||
4098 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4099 MonoReflectionType *tb = (MonoReflectionType *)obj;
4100 token = mono_metadata_token_from_dor (
4101 mono_image_typedef_or_ref (assembly, tb->type));
4102 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4103 MonoReflectionType *tb = (MonoReflectionType *)obj;
4104 token = mono_metadata_token_from_dor (
4105 mono_image_typedef_or_ref (assembly, tb->type));
4106 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4107 strcmp (klass->name, "MonoMethod") == 0) {
4108 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4109 if (m->method->signature->is_inflated) {
4110 if (create_methodspec)
4111 token = mono_image_get_methodspec_token (assembly, m->method);
4113 token = mono_image_get_inflated_method_token (assembly, m->method);
4114 } else if (m->method->signature->generic_param_count) {
4115 g_assert_not_reached ();
4116 } else if ((m->method->klass->image == &assembly->image) &&
4117 !m->method->klass->generic_inst) {
4118 static guint32 method_table_idx = 0xffffff;
4119 if (m->method->klass->wastypebuilder) {
4120 /* we use the same token as the one that was assigned
4121 * to the Methodbuilder.
4122 * FIXME: do the equivalent for Fields.
4124 token = m->method->token;
4127 * Each token should have a unique index, but the indexes are
4128 * assigned by managed code, so we don't know about them. An
4129 * easy solution is to count backwards...
4131 method_table_idx --;
4132 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4135 token = mono_image_get_methodref_token (assembly, m->method);
4137 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4138 } else if (strcmp (klass->name, "MonoField") == 0) {
4139 MonoReflectionField *f = (MonoReflectionField *)obj;
4140 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4141 static guint32 field_table_idx = 0xffffff;
4143 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4145 token = mono_image_get_fieldref_token (assembly, f);
4147 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4148 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4149 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4150 token = mono_image_get_array_token (assembly, m);
4151 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4152 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4153 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4155 g_error ("requested token for %s\n", klass->name);
4158 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4164 guint32 import_lookup_table;
4168 guint32 import_address_table_rva;
4176 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4178 static MonoDynamicImage*
4179 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4181 static const guchar entrycode [16] = {0xff, 0x25, 0};
4182 MonoDynamicImage *image;
4185 const char *version = mono_get_runtime_version ();
4188 image = GC_MALLOC (sizeof (MonoDynamicImage));
4190 image = g_new0 (MonoDynamicImage, 1);
4193 /* keep in sync with image.c */
4194 image->image.name = assembly_name;
4195 image->image.assembly_name = image->image.name; /* they may be different */
4196 image->image.module_name = module_name;
4197 image->image.version = g_strdup (version);
4198 image->image.dynamic = TRUE;
4200 image->image.references = g_new0 (MonoAssembly*, 1);
4201 image->image.references [0] = NULL;
4203 mono_image_init (&image->image);
4205 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4206 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4207 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4208 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4209 image->handleref = g_hash_table_new (NULL, NULL);
4210 image->tokens = mono_g_hash_table_new (NULL, NULL);
4211 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4212 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4213 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4214 image->gen_params = g_ptr_array_new ();
4216 string_heap_init (&image->sheap);
4217 mono_image_add_stream_data (&image->us, "", 1);
4218 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4219 /* import tables... */
4220 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4221 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4222 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4223 mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4224 image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4225 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4226 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4227 stream_data_align (&image->code);
4229 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4231 for (i=0; i < 64; ++i) {
4232 image->tables [i].next_idx = 1;
4233 image->tables [i].columns = table_sizes [i];
4236 image->image.assembly = (MonoAssembly*)assembly;
4237 image->run = assembly->run;
4238 image->save = assembly->save;
4244 * mono_image_basic_init:
4245 * @assembly: an assembly builder object
4247 * Create the MonoImage that represents the assembly builder and setup some
4248 * of the helper hash table and the basic metadata streams.
4251 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4253 MonoDynamicAssembly *assembly;
4254 MonoDynamicImage *image;
4256 MONO_ARCH_SAVE_REGS;
4258 if (assemblyb->dynamic_assembly)
4262 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4264 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4267 assembly->assembly.dynamic = TRUE;
4268 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4269 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4270 if (assemblyb->culture)
4271 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4273 assembly->assembly.aname.culture = g_strdup ("");
4275 assembly->run = assemblyb->access != 2;
4276 assembly->save = assemblyb->access != 1;
4278 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4279 assembly->assembly.aname.name = image->image.name;
4280 assembly->assembly.image = &image->image;
4282 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4283 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4287 calc_section_size (MonoDynamicImage *assembly)
4291 /* alignment constraints */
4292 assembly->code.index += 3;
4293 assembly->code.index &= ~3;
4294 assembly->meta_size += 3;
4295 assembly->meta_size &= ~3;
4296 assembly->resources.index += 3;
4297 assembly->resources.index &= ~3;
4299 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4300 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4303 if (assembly->win32_res) {
4304 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4306 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4307 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4311 assembly->sections [MONO_SECTION_RELOC].size = 12;
4312 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4322 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4326 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4328 ResTreeNode *t1 = (ResTreeNode*)a;
4329 ResTreeNode *t2 = (ResTreeNode*)b;
4331 return t1->id - t2->id;
4335 * resource_tree_create:
4337 * Organize the resources into a resource tree.
4339 static ResTreeNode *
4340 resource_tree_create (MonoArray *win32_resources)
4342 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4346 tree = g_new0 (ResTreeNode, 1);
4348 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4349 MonoReflectionWin32Resource *win32_res =
4350 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4354 lang_node = g_new0 (ResTreeNode, 1);
4355 lang_node->id = win32_res->lang_id;
4356 lang_node->win32_res = win32_res;
4358 /* Create type node if neccesary */
4360 for (l = tree->children; l; l = l->next)
4361 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4362 type_node = (ResTreeNode*)l->data;
4367 type_node = g_new0 (ResTreeNode, 1);
4368 type_node->id = win32_res->res_type;
4371 * The resource types have to be sorted otherwise
4372 * Windows Explorer can't display the version information.
4374 tree->children = g_slist_insert_sorted (tree->children,
4375 type_node, resource_tree_compare_by_id);
4378 /* Create res node if neccesary */
4380 for (l = type_node->children; l; l = l->next)
4381 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4382 res_node = (ResTreeNode*)l->data;
4387 res_node = g_new0 (ResTreeNode, 1);
4388 res_node->id = win32_res->res_id;
4389 type_node->children = g_slist_append (type_node->children, res_node);
4392 res_node->children = g_slist_append (res_node->children, lang_node);
4399 * resource_tree_encode:
4401 * Encode the resource tree into the format used in the PE file.
4404 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4407 MonoPEResourceDir dir;
4408 MonoPEResourceDirEntry dir_entry;
4409 MonoPEResourceDataEntry data_entry;
4413 * For the format of the resource directory, see the article
4414 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4418 memset (&dir, 0, sizeof (dir));
4419 memset (&dir_entry, 0, sizeof (dir_entry));
4420 memset (&data_entry, 0, sizeof (data_entry));
4422 g_assert (sizeof (dir) == 16);
4423 g_assert (sizeof (dir_entry) == 8);
4424 g_assert (sizeof (data_entry) == 16);
4426 node->offset = p - begin;
4428 /* IMAGE_RESOURCE_DIRECTORY */
4429 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4431 memcpy (p, &dir, sizeof (dir));
4434 /* Reserve space for entries */
4436 p += sizeof (dir_entry) * dir.res_id_entries;
4438 /* Write children */
4439 for (l = node->children; l; l = l->next) {
4440 ResTreeNode *child = (ResTreeNode*)l->data;
4442 if (child->win32_res) {
4444 child->offset = p - begin;
4446 /* IMAGE_RESOURCE_DATA_ENTRY */
4447 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4448 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4450 memcpy (p, &data_entry, sizeof (data_entry));
4451 p += sizeof (data_entry);
4453 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4454 p += data_entry.rde_size;
4456 resource_tree_encode (child, begin, p, &p);
4460 /* IMAGE_RESOURCE_ENTRY */
4461 for (l = node->children; l; l = l->next) {
4462 ResTreeNode *child = (ResTreeNode*)l->data;
4463 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4465 dir_entry.is_dir = child->win32_res ? 0 : 1;
4466 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4468 memcpy (entries, &dir_entry, sizeof (dir_entry));
4469 entries += sizeof (dir_entry);
4476 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4481 MonoReflectionWin32Resource *win32_res;
4484 if (!assemblyb->win32_resources)
4488 * Resources are stored in a three level tree inside the PE file.
4489 * - level one contains a node for each type of resource
4490 * - level two contains a node for each resource
4491 * - level three contains a node for each instance of a resource for a
4492 * specific language.
4495 tree = resource_tree_create (assemblyb->win32_resources);
4497 /* Estimate the size of the encoded tree */
4499 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4500 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4501 size += mono_array_length (win32_res->res_data);
4503 /* Directory structure */
4504 size += mono_array_length (assemblyb->win32_resources) * 256;
4505 p = buf = g_malloc (size);
4507 resource_tree_encode (tree, p, p, &p);
4509 g_assert (p - buf < size);
4511 assembly->win32_res = g_malloc (p - buf);
4512 assembly->win32_res_size = p - buf;
4513 memcpy (assembly->win32_res, buf, p - buf);
4519 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4521 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4524 p += sizeof (MonoPEResourceDir);
4525 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4526 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4527 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4528 if (dir_entry->is_dir) {
4529 fixup_resource_directory (res_section, child, rva);
4531 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4532 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4535 p += sizeof (MonoPEResourceDirEntry);
4540 * mono_image_create_pefile:
4541 * @mb: a module builder object
4543 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4544 * assembly->pefile where it can be easily retrieved later in chunks.
4547 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4548 MonoMSDOSHeader *msdos;
4549 MonoDotNetHeader *header;
4550 MonoSectionTable *section;
4551 MonoCLIHeader *cli_header;
4552 guint32 size, image_size, virtual_base, text_offset;
4553 guint32 header_start, section_start, file_offset, virtual_offset;
4554 MonoDynamicImage *assembly;
4555 MonoReflectionAssemblyBuilder *assemblyb;
4556 MonoDynamicStream *pefile;
4558 guint32 *rva, value;
4561 static const unsigned char msheader[] = {
4562 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4563 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4566 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4567 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4568 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4569 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4572 assemblyb = mb->assemblyb;
4574 mono_image_basic_init (assemblyb);
4575 assembly = mb->dynamic_image;
4577 /* already created */
4578 if (assembly->pefile.index)
4581 mono_image_build_metadata (mb);
4583 if (mb->is_main && assemblyb->resources) {
4584 int len = mono_array_length (assemblyb->resources);
4585 for (i = 0; i < len; ++i)
4586 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4589 if (mb->resources) {
4590 int len = mono_array_length (mb->resources);
4591 for (i = 0; i < len; ++i)
4592 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4595 build_compressed_metadata (assembly);
4598 assembly_add_win32_resources (assembly, assemblyb);
4600 nsections = calc_section_size (assembly);
4602 pefile = &assembly->pefile;
4604 /* The DOS header and stub */
4605 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4606 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4608 /* the dotnet header */
4609 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4611 /* the section tables */
4612 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4614 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4615 virtual_offset = VIRT_ALIGN;
4618 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4619 if (!assembly->sections [i].size)
4622 file_offset += FILE_ALIGN - 1;
4623 file_offset &= ~(FILE_ALIGN - 1);
4624 virtual_offset += VIRT_ALIGN - 1;
4625 virtual_offset &= ~(VIRT_ALIGN - 1);
4627 assembly->sections [i].offset = file_offset;
4628 assembly->sections [i].rva = virtual_offset;
4630 file_offset += assembly->sections [i].size;
4631 virtual_offset += assembly->sections [i].size;
4632 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4635 file_offset += FILE_ALIGN - 1;
4636 file_offset &= ~(FILE_ALIGN - 1);
4637 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4639 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4641 /* back-patch info */
4642 msdos = (MonoMSDOSHeader*)pefile->data;
4643 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4644 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4645 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4647 header = (MonoDotNetHeader*)(pefile->data + header_start);
4648 header->pesig [0] = 'P';
4649 header->pesig [1] = 'E';
4651 header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4652 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4653 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4654 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4655 if (assemblyb->pekind == 1) {
4657 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4660 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4663 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4665 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4666 header->pe.pe_major = 6;
4667 header->pe.pe_minor = 0;
4668 size = assembly->sections [MONO_SECTION_TEXT].size;
4669 size += FILE_ALIGN - 1;
4670 size &= ~(FILE_ALIGN - 1);
4671 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4672 size = assembly->sections [MONO_SECTION_RSRC].size;
4673 size += FILE_ALIGN - 1;
4674 size &= ~(FILE_ALIGN - 1);
4675 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4676 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4677 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4678 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4679 /* pe_rva_entry_point always at the beginning of the text section */
4680 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4682 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4683 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4684 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4685 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4686 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4687 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4688 size = section_start;
4689 size += FILE_ALIGN - 1;
4690 size &= ~(FILE_ALIGN - 1);
4691 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4693 size += VIRT_ALIGN - 1;
4694 size &= ~(VIRT_ALIGN - 1);
4695 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4698 // Translate the PEFileKind value to the value expected by the Windows loader
4704 // PEFileKinds.Dll == 1
4705 // PEFileKinds.ConsoleApplication == 2
4706 // PEFileKinds.WindowApplication == 3
4709 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4710 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4712 if (assemblyb->pekind == 3)
4717 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4719 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4720 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4721 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4722 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4723 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4724 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4726 /* fill data directory entries */
4728 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4729 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4731 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4732 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4734 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4735 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4736 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4737 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4738 /* patch imported function RVA name */
4739 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4740 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4742 /* the import table */
4743 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4744 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4745 /* patch imported dll RVA name and other entries in the dir */
4746 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4747 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4748 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4749 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4750 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4751 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4753 p = (assembly->code.data + assembly->ilt_offset);
4754 value = (assembly->text_rva + assembly->imp_names_offset - 2);
4755 *p++ = (value) & 0xff;
4756 *p++ = (value >> 8) & (0xff);
4757 *p++ = (value >> 16) & (0xff);
4758 *p++ = (value >> 24) & (0xff);
4760 /* the CLI header info */
4761 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4762 cli_header->ch_size = GUINT32_FROM_LE (72);
4763 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4764 cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4765 if (assemblyb->entry_point) {
4766 guint32 table_idx = 0;
4767 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4768 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4769 table_idx = methodb->table_idx;
4771 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4773 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4775 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4777 /* The embedded managed resources */
4778 text_offset = assembly->text_rva + assembly->code.index;
4779 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4780 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4781 text_offset += assembly->resources.index;
4782 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4783 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4784 text_offset += assembly->meta_size;
4785 if (assembly->strong_name_size) {
4786 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4787 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4788 text_offset += assembly->strong_name_size;
4791 /* write the section tables and section content */
4792 section = (MonoSectionTable*)(pefile->data + section_start);
4793 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4794 static const char *section_names [] = {
4795 ".text", ".rsrc", ".reloc"
4797 if (!assembly->sections [i].size)
4799 strcpy (section->st_name, section_names [i]);
4800 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4801 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4802 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4803 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4804 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4805 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4806 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4808 case MONO_SECTION_TEXT:
4809 /* patch entry point */
4810 p = (assembly->code.data + 2);
4811 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4812 *p++ = (value) & 0xff;
4813 *p++ = (value >> 8) & 0xff;
4814 *p++ = (value >> 16) & 0xff;
4815 *p++ = (value >> 24) & 0xff;
4817 text_offset = assembly->sections [i].offset;
4818 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4819 text_offset += assembly->code.index;
4820 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4821 text_offset += assembly->resources.index;
4822 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4823 text_offset += assembly->meta_size;
4824 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4826 g_free (assembly->image.raw_metadata);
4828 case MONO_SECTION_RELOC:
4829 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4830 *rva = GUINT32_FROM_LE (assembly->text_rva);
4832 *rva = GUINT32_FROM_LE (12);
4834 data16 = (guint16*)rva;
4836 * the entrypoint is always at the start of the text section
4837 * 3 is IMAGE_REL_BASED_HIGHLOW
4838 * 2 is patch_size_rva - text_rva
4840 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4842 *data16 = 0; /* terminate */
4844 case MONO_SECTION_RSRC:
4845 if (assembly->win32_res) {
4846 text_offset = assembly->sections [i].offset;
4848 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4849 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4851 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4855 g_assert_not_reached ();
4860 /* check that the file is properly padded */
4863 FILE *f = fopen ("mypetest.exe", "w");
4864 fwrite (pefile->data, pefile->index, 1, f);
4870 MonoReflectionModule *
4871 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4875 MonoImageOpenStatus status;
4876 MonoDynamicAssembly *assembly;
4877 guint32 module_count;
4878 MonoImage **new_modules;
4880 name = mono_string_to_utf8 (fileName);
4882 image = mono_image_open (name, &status);
4885 if (status == MONO_IMAGE_ERROR_ERRNO)
4886 exc = mono_get_exception_file_not_found (fileName);
4888 exc = mono_get_exception_bad_image_format (name);
4890 mono_raise_exception (exc);
4895 assembly = ab->dynamic_assembly;
4896 image->assembly = (MonoAssembly*)assembly;
4898 module_count = image->assembly->image->module_count;
4899 new_modules = g_new0 (MonoImage *, module_count + 1);
4901 if (image->assembly->image->modules)
4902 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4903 new_modules [module_count] = image;
4905 g_free (image->assembly->image->modules);
4906 image->assembly->image->modules = new_modules;
4907 image->assembly->image->module_count ++;
4909 mono_assembly_load_references (image, &status);
4911 mono_image_close (image);
4912 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4915 return mono_module_get_object (mono_domain_get (), image);
4919 * We need to return always the same object for MethodInfo, FieldInfo etc..
4920 * but we need to consider the reflected type.
4921 * type uses a different hash, since it uses custom hash/equal functions.
4926 MonoClass *refclass;
4930 reflected_equal (gconstpointer a, gconstpointer b) {
4931 const ReflectedEntry *ea = a;
4932 const ReflectedEntry *eb = b;
4934 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4938 reflected_hash (gconstpointer a) {
4939 const ReflectedEntry *ea = a;
4940 return GPOINTER_TO_UINT (ea->item);
4943 #define CHECK_OBJECT(t,p,k) \
4949 mono_domain_lock (domain); \
4950 if (!domain->refobject_hash) \
4951 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4952 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4953 mono_domain_unlock (domain); \
4959 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4961 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4964 #define CACHE_OBJECT(p,o,k) \
4966 ReflectedEntry *e = ALLOC_REFENTRY; \
4968 e->refclass = (k); \
4969 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4970 mono_domain_unlock (domain); \
4974 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4976 /* this is done only once */
4977 mono_domain_lock (domain);
4978 CACHE_OBJECT (assembly, res, NULL);
4982 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4984 /* this is done only once */
4985 mono_domain_lock (domain);
4986 CACHE_OBJECT (module, res, NULL);
4990 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4992 MonoDynamicImage *image = moduleb->dynamic_image;
4993 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4996 * FIXME: we already created an image in mono_image_basic_init (), but
4997 * we don't know which module it belongs to, since that is only
4998 * determined at assembly save time.
5000 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5001 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5003 moduleb->module.image = &image->image;
5004 moduleb->dynamic_image = image;
5005 register_module (mono_object_domain (moduleb), moduleb, image);
5010 * mono_assembly_get_object:
5011 * @domain: an app domain
5012 * @assembly: an assembly
5014 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5016 MonoReflectionAssembly*
5017 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5019 static MonoClass *System_Reflection_Assembly;
5020 MonoReflectionAssembly *res;
5022 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5023 if (!System_Reflection_Assembly)
5024 System_Reflection_Assembly = mono_class_from_name (
5025 mono_defaults.corlib, "System.Reflection", "Assembly");
5026 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5027 res->assembly = assembly;
5028 CACHE_OBJECT (assembly, res, NULL);
5034 MonoReflectionModule*
5035 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5037 static MonoClass *System_Reflection_Module;
5038 MonoReflectionModule *res;
5040 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5041 if (!System_Reflection_Module)
5042 System_Reflection_Module = mono_class_from_name (
5043 mono_defaults.corlib, "System.Reflection", "Module");
5044 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5047 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5049 res->fqname = mono_string_new (domain, image->name);
5050 res->name = mono_string_new (domain, g_path_get_basename (image->name));
5051 res->scopename = mono_string_new (domain, image->module_name);
5053 if (image->assembly->image == image) {
5054 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5057 g_assert (image->assembly->image->modules);
5059 for (i = 0; i < image->assembly->image->module_count; i++) {
5060 if (image->assembly->image->modules [i] == image)
5061 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5063 g_assert (res->token);
5066 mono_image_addref (image);
5068 CACHE_OBJECT (image, res, NULL);
5072 MonoReflectionModule*
5073 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5075 static MonoClass *System_Reflection_Module;
5076 MonoReflectionModule *res;
5077 MonoTableInfo *table;
5078 guint32 cols [MONO_FILE_SIZE];
5080 guint32 i, name_idx;
5083 if (!System_Reflection_Module)
5084 System_Reflection_Module = mono_class_from_name (
5085 mono_defaults.corlib, "System.Reflection", "Module");
5086 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5088 table = &image->tables [MONO_TABLE_FILE];
5089 g_assert (table_index < table->rows);
5090 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5093 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5094 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5096 /* Check whenever the row has a corresponding row in the moduleref table */
5097 table = &image->tables [MONO_TABLE_MODULEREF];
5098 for (i = 0; i < table->rows; ++i) {
5099 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5100 val = mono_metadata_string_heap (image, name_idx);
5101 if (strcmp (val, name) == 0)
5102 res->image = image->modules [i];
5105 res->fqname = mono_string_new (domain, name);
5106 res->name = mono_string_new (domain, name);
5107 res->scopename = mono_string_new (domain, name);
5108 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5109 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5115 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5117 if ((t1->type != t2->type) ||
5118 (t1->byref != t2->byref))
5122 case MONO_TYPE_VOID:
5123 case MONO_TYPE_BOOLEAN:
5124 case MONO_TYPE_CHAR:
5135 case MONO_TYPE_STRING:
5138 case MONO_TYPE_OBJECT:
5139 case MONO_TYPE_TYPEDBYREF:
5141 case MONO_TYPE_VALUETYPE:
5142 case MONO_TYPE_CLASS:
5143 case MONO_TYPE_SZARRAY:
5144 return t1->data.klass == t2->data.klass;
5146 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5147 case MONO_TYPE_ARRAY:
5148 if (t1->data.array->rank != t2->data.array->rank)
5150 return t1->data.array->eklass == t2->data.array->eklass;
5151 case MONO_TYPE_GENERICINST: {
5153 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5155 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5157 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5158 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5164 case MONO_TYPE_MVAR:
5165 return t1->data.generic_param == t2->data.generic_param;
5167 g_error ("implement type compare for %0x!", t1->type);
5175 mymono_metadata_type_hash (MonoType *t1)
5181 hash |= t1->byref << 6; /* do not collide with t1->type values */
5183 case MONO_TYPE_VALUETYPE:
5184 case MONO_TYPE_CLASS:
5185 case MONO_TYPE_SZARRAY:
5186 /* check if the distribution is good enough */
5187 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5189 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5194 static MonoReflectionGenericInst*
5195 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5197 static MonoClass *System_Reflection_MonoGenericInst;
5198 MonoReflectionGenericInst *res;
5199 MonoGenericInst *ginst;
5202 if (!System_Reflection_MonoGenericInst) {
5203 System_Reflection_MonoGenericInst = mono_class_from_name (
5204 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5205 g_assert (System_Reflection_MonoGenericInst);
5208 ginst = geninst->data.generic_inst;
5209 gklass = mono_class_from_mono_type (ginst->generic_type);
5211 mono_class_init (ginst->klass);
5213 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5215 res->type.type = geninst;
5216 if (gklass->wastypebuilder && gklass->reflection_info)
5217 res->generic_type = gklass->reflection_info;
5219 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5225 * mono_type_get_object:
5226 * @domain: an app domain
5229 * Return an System.MonoType object representing the type @type.
5232 mono_type_get_object (MonoDomain *domain, MonoType *type)
5234 MonoReflectionType *res;
5235 MonoClass *klass = mono_class_from_mono_type (type);
5237 mono_domain_lock (domain);
5238 if (!domain->type_hash)
5239 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5240 (GCompareFunc)mymono_metadata_type_equal);
5241 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5242 mono_domain_unlock (domain);
5245 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5246 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5247 mono_g_hash_table_insert (domain->type_hash, type, res);
5248 mono_domain_unlock (domain);
5251 if (klass->reflection_info && !klass->wastypebuilder) {
5252 /* g_assert_not_reached (); */
5253 /* should this be considered an error condition? */
5255 mono_domain_unlock (domain);
5256 return klass->reflection_info;
5259 mono_class_init (klass);
5260 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5262 mono_g_hash_table_insert (domain->type_hash, type, res);
5263 mono_domain_unlock (domain);
5268 * mono_method_get_object:
5269 * @domain: an app domain
5271 * @refclass: the reflected type (can be NULL)
5273 * Return an System.Reflection.MonoMethod object representing the method @method.
5275 MonoReflectionMethod*
5276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5279 * We use the same C representation for methods and constructors, but the type
5280 * name in C# is different.
5284 MonoReflectionMethod *ret;
5287 refclass = method->klass;
5289 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5290 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5291 cname = "MonoCMethod";
5293 cname = "MonoMethod";
5294 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5296 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5297 ret->method = method;
5298 ret->name = mono_string_new (domain, method->name);
5299 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5300 CACHE_OBJECT (method, ret, refclass);
5305 * mono_field_get_object:
5306 * @domain: an app domain
5310 * Return an System.Reflection.MonoField object representing the field @field
5313 MonoReflectionField*
5314 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5316 MonoReflectionField *res;
5319 CHECK_OBJECT (MonoReflectionField *, field, klass);
5320 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5321 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5324 res->name = mono_string_new (domain, field->name);
5325 if (field->generic_info)
5326 res->attrs = field->generic_info->generic_type->attrs;
5328 res->attrs = field->type->attrs;
5329 res->type = mono_type_get_object (domain, field->type);
5330 CACHE_OBJECT (field, res, klass);
5335 * mono_property_get_object:
5336 * @domain: an app domain
5338 * @property: a property
5340 * Return an System.Reflection.MonoProperty object representing the property @property
5343 MonoReflectionProperty*
5344 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5346 MonoReflectionProperty *res;
5349 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5350 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5351 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5353 res->property = property;
5354 CACHE_OBJECT (property, res, klass);
5359 * mono_event_get_object:
5360 * @domain: an app domain
5364 * Return an System.Reflection.MonoEvent object representing the event @event
5367 MonoReflectionEvent*
5368 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5370 MonoReflectionEvent *res;
5373 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5374 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5375 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5378 CACHE_OBJECT (event, res, klass);
5383 * mono_param_get_objects:
5384 * @domain: an app domain
5387 * Return an System.Reflection.ParameterInfo array object representing the parameters
5388 * in the method @method.
5391 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5393 static MonoClass *System_Reflection_ParameterInfo;
5394 MonoArray *res = NULL;
5395 MonoReflectionMethod *member = NULL;
5396 MonoReflectionParameter *param = NULL;
5397 char **names, **blobs = NULL;
5398 MonoObject *dbnull = mono_get_dbnull_object (domain);
5399 MonoMarshalSpec **mspecs;
5402 if (!System_Reflection_ParameterInfo)
5403 System_Reflection_ParameterInfo = mono_class_from_name (
5404 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5406 if (!method->signature->param_count)
5407 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5409 /* Note: the cache is based on the address of the signature into the method
5410 * since we already cache MethodInfos with the method as keys.
5412 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5414 member = mono_method_get_object (domain, method, NULL);
5415 names = g_new (char *, method->signature->param_count);
5416 mono_method_get_param_names (method, (const char **) names);
5418 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5419 mono_method_get_marshal_info (method, mspecs);
5421 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5422 for (i = 0; i < method->signature->param_count; ++i) {
5423 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5424 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5425 param->MemberImpl = (MonoObject*)member;
5426 param->NameImpl = mono_string_new (domain, names [i]);
5427 param->PositionImpl = i;
5428 param->AttrsImpl = method->signature->params [i]->attrs;
5430 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5431 param->DefaultValueImpl = dbnull;
5433 MonoType *type = param->ClassImpl->type;
5436 blobs = g_new0 (char *, method->signature->param_count);
5437 get_default_param_value_blobs (method, blobs);
5440 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5442 if (!param->DefaultValueImpl) {
5443 param->DefaultValueImpl = dbnull;
5448 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5450 mono_array_set (res, gpointer, i, param);
5455 for (i = method->signature->param_count; i >= 0; i--)
5457 mono_metadata_free_marshal_spec (mspecs [i]);
5460 CACHE_OBJECT (&(method->signature), res, NULL);
5465 mono_get_dbnull_object (MonoDomain *domain)
5469 static MonoClassField *dbnull_value_field = NULL;
5471 if (!dbnull_value_field) {
5472 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5473 mono_class_init (klass);
5474 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5475 g_assert (dbnull_value_field);
5477 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5484 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5486 guint32 param_index, i, lastp, crow = 0;
5487 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5490 MonoClass *klass = method->klass;
5491 MonoImage *image = klass->image;
5492 MonoMethodSignature *methodsig = method->signature;
5494 MonoTableInfo *constt;
5495 MonoTableInfo *methodt;
5496 MonoTableInfo *paramt;
5498 if (!methodsig->param_count)
5501 if (klass->generic_inst) {
5502 return; /* FIXME - ??? */
5505 mono_class_init (klass);
5507 if (klass->image->dynamic) {
5511 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5512 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5513 constt = &image->tables [MONO_TABLE_CONSTANT];
5515 for (i = 0; i < klass->method.count; ++i) {
5516 if (method == klass->methods [i]) {
5517 idx = klass->method.first + i;
5522 g_assert (idx != -1);
5524 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5525 if (idx + 1 < methodt->rows)
5526 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5528 lastp = paramt->rows + 1;
5530 for (i = param_index; i < lastp; ++i) {
5533 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5534 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5536 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5539 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5544 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5545 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5552 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5561 klass = mono_class_from_mono_type (type);
5562 if (klass->valuetype) {
5563 object = mono_object_new (domain, klass);
5564 retval = ((gchar *) object + sizeof (MonoObject));
5569 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5576 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5580 memset (assembly, 0, sizeof (MonoAssemblyName));
5582 assembly->culture = "";
5583 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5585 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5588 while (*p == ' ' || *p == ',') {
5597 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5599 assembly->major = strtoul (p, &s, 10);
5600 if (s == p || *s != '.')
5603 assembly->minor = strtoul (p, &s, 10);
5604 if (s == p || *s != '.')
5607 assembly->build = strtoul (p, &s, 10);
5608 if (s == p || *s != '.')
5611 assembly->revision = strtoul (p, &s, 10);
5615 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5617 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5618 assembly->culture = "";
5621 assembly->culture = p;
5622 while (*p && *p != ',') {
5626 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5628 if (strncmp (p, "null", 4) == 0) {
5633 while (*p && *p != ',') {
5636 len = (p - start + 1);
5637 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5638 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5639 g_strlcpy (assembly->public_key_token, start, len);
5642 while (*p && *p != ',')
5646 while (*p == ' ' || *p == ',') {
5660 * mono_reflection_parse_type:
5663 * Parse a type name as accepted by the GetType () method and output the info
5664 * extracted in the info structure.
5665 * the name param will be mangled, so, make a copy before passing it to this function.
5666 * The fields in info will be valid until the memory pointed to by name is valid.
5667 * Returns 0 on parse error.
5668 * See also mono_type_get_name () below.
5671 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5673 char *start, *p, *w, *last_point, *startn;
5674 int in_modifiers = 0;
5675 int isbyref = 0, rank;
5677 start = p = w = name;
5679 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5680 info->name = info->name_space = NULL;
5681 info->nested = NULL;
5682 info->modifiers = NULL;
5684 /* last_point separates the namespace from the name */
5690 *p = 0; /* NULL terminate the name */
5692 info->nested = g_list_append (info->nested, startn);
5693 /* we have parsed the nesting namespace + name */
5697 info->name_space = start;
5699 info->name = last_point + 1;
5701 info->name_space = (char *)"";
5727 info->name_space = start;
5729 info->name = last_point + 1;
5731 info->name_space = (char *)"";
5738 if (isbyref) /* only one level allowed by the spec */
5741 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5745 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5756 else if (*p != '*') /* '*' means unknown lower bound */
5762 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5774 return 0; /* missing assembly name */
5775 if (!assembly_name_to_aname (&info->assembly, p))
5782 if (info->assembly.name)
5785 *w = 0; /* terminate class name */
5786 if (!info->name || !*info->name)
5788 /* add other consistency checks */
5793 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5800 image = mono_defaults.corlib;
5803 klass = mono_class_from_name_case (image, info->name_space, info->name);
5805 klass = mono_class_from_name (image, info->name_space, info->name);
5808 for (mod = info->nested; mod; mod = mod->next) {
5811 mono_class_init (klass);
5812 nested = klass->nested_classes;
5815 klass = nested->data;
5817 if (g_strcasecmp (klass->name, mod->data) == 0)
5820 if (strcmp (klass->name, mod->data) == 0)
5824 nested = nested->next;
5831 mono_class_init (klass);
5832 for (mod = info->modifiers; mod; mod = mod->next) {
5833 modval = GPOINTER_TO_UINT (mod->data);
5834 if (!modval) { /* byref: must be last modifier */
5835 return &klass->this_arg;
5836 } else if (modval == -1) {
5837 klass = mono_ptr_class_get (&klass->byval_arg);
5838 } else { /* array rank */
5839 klass = mono_array_class_get (klass, modval);
5841 mono_class_init (klass);
5844 return &klass->byval_arg;
5848 * mono_reflection_get_type:
5849 * @image: a metadata context
5850 * @info: type description structure
5851 * @ignorecase: flag for case-insensitive string compares
5852 * @type_resolve: whenever type resolve was already tried
5854 * Build a MonoType from the type description in @info.
5859 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5862 MonoReflectionAssembly *assembly;
5866 type = mono_reflection_get_type_internal (image, info, ignorecase);
5869 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5872 /* FIXME: Enabling this causes regressions (#65577) */
5878 *type_resolve = TRUE;
5882 /* Reconstruct the type name */
5883 fullName = g_string_new ("");
5884 if (info->name_space && (info->name_space [0] != '\0'))
5885 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5887 g_string_printf (fullName, info->name);
5888 for (mod = info->nested; mod; mod = mod->next)
5889 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5891 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5892 if (assembly && (!image || (assembly->assembly->image == image))) {
5894 if (assembly->assembly->dynamic) {
5895 /* Enumerate all modules */
5896 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5900 if (abuilder->modules) {
5901 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5902 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5903 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5909 if (!type && abuilder->loaded_modules) {
5910 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5911 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5912 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5919 type = mono_reflection_get_type_internal (assembly->assembly->image,
5922 g_string_free (fullName, TRUE);
5927 * mono_reflection_type_from_name:
5929 * @image: a metadata context (can be NULL).
5931 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5932 * it defaults to get the type from @image or, if @image is NULL or loading
5933 * from it fails, uses corlib.
5937 mono_reflection_type_from_name (char *name, MonoImage *image)
5940 MonoTypeNameParse info;
5941 MonoAssembly *assembly;
5943 gboolean type_resolve = FALSE;
5945 /* Make a copy since parse_type modifies its argument */
5946 tmp = g_strdup (name);
5948 /*g_print ("requested type %s\n", str);*/
5949 if (!mono_reflection_parse_type (tmp, &info)) {
5951 g_list_free (info.modifiers);
5952 g_list_free (info.nested);
5956 if (info.assembly.name) {
5957 assembly = mono_assembly_loaded (&info.assembly);
5959 /* then we must load the assembly ourselve - see #60439 */
5960 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5963 g_list_free (info.modifiers);
5964 g_list_free (info.nested);
5968 image = assembly->image;
5969 } else if (image == NULL) {
5970 image = mono_defaults.corlib;
5973 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5974 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5975 image = mono_defaults.corlib;
5976 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5980 g_list_free (info.modifiers);
5981 g_list_free (info.nested);
5986 * mono_reflection_get_token:
5988 * Return the metadata token of OBJ which should be an object
5989 * representing a metadata element.
5992 mono_reflection_get_token (MonoObject *obj)
5997 klass = obj->vtable->klass;
5999 if (strcmp (klass->name, "MethodBuilder") == 0) {
6000 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6002 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6003 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6004 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6006 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6007 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6008 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6009 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6010 if (tb->generic_params) {
6011 g_assert_not_reached ();
6013 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6015 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6016 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6017 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6018 } else if (strcmp (klass->name, "MonoType") == 0) {
6019 MonoReflectionType *tb = (MonoReflectionType *)obj;
6020 token = mono_class_from_mono_type (tb->type)->type_token;
6021 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6022 strcmp (klass->name, "MonoMethod") == 0) {
6023 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6024 if (m->method->signature->is_inflated) {
6025 g_assert_not_reached ();
6026 } else if (m->method->signature->generic_param_count) {
6027 g_assert_not_reached ();
6028 } else if (m->method->klass->generic_inst) {
6029 g_assert_not_reached ();
6031 token = m->method->token;
6033 } else if (strcmp (klass->name, "MonoField") == 0) {
6034 MonoReflectionField *f = (MonoReflectionField*)obj;
6036 token = mono_class_get_field_token (f->field);
6037 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6038 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6040 token = mono_class_get_property_token (p->property);
6041 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6042 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6044 token = mono_class_get_event_token (p->event);
6045 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6046 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6048 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6049 } else if (strcmp (klass->name, "Module") == 0) {
6050 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6053 } else if (strcmp (klass->name, "Assembly") == 0) {
6054 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6056 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6057 MonoException *ex = mono_get_exception_not_implemented (msg);
6059 mono_raise_exception (ex);
6066 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6068 int slen, type = t->type;
6073 case MONO_TYPE_BOOLEAN: {
6074 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6079 case MONO_TYPE_CHAR:
6081 case MONO_TYPE_I2: {
6082 guint16 *val = g_malloc (sizeof (guint16));
6087 #if SIZEOF_VOID_P == 4
6093 case MONO_TYPE_I4: {
6094 guint32 *val = g_malloc (sizeof (guint32));
6099 #if SIZEOF_VOID_P == 8
6100 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6105 case MONO_TYPE_I8: {
6106 guint64 *val = g_malloc (sizeof (guint64));
6111 case MONO_TYPE_VALUETYPE:
6112 if (t->data.klass->enumtype) {
6113 type = t->data.klass->enum_basetype->type;
6116 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6119 case MONO_TYPE_STRING:
6120 if (*p == (char)0xFF) {
6124 slen = mono_metadata_decode_value (p, &p);
6126 return mono_string_new_len (mono_domain_get (), p, slen);
6127 case MONO_TYPE_CLASS: {
6130 if (*p == (char)0xFF) {
6135 slen = mono_metadata_decode_value (p, &p);
6136 n = g_memdup (p, slen + 1);
6138 t = mono_reflection_type_from_name (n, image);
6140 g_warning ("Cannot load type '%s'", n);
6144 return mono_type_get_object (mono_domain_get (), t);
6148 case MONO_TYPE_OBJECT: {
6151 MonoClass *subc = NULL;
6156 } else if (subt == 0x0E) {
6157 type = MONO_TYPE_STRING;
6159 } else if (subt == 0x55) {
6162 slen = mono_metadata_decode_value (p, &p);
6163 n = g_memdup (p, slen + 1);
6165 t = mono_reflection_type_from_name (n, image);
6167 g_warning ("Cannot load type '%s'", n);
6170 subc = mono_class_from_mono_type (t);
6171 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6172 MonoType simple_type = {{0}};
6173 simple_type.type = subt;
6174 subc = mono_class_from_mono_type (&simple_type);
6176 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6178 val = load_cattr_value (image, &subc->byval_arg, p, end);
6179 obj = mono_object_new (mono_domain_get (), subc);
6180 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6184 case MONO_TYPE_SZARRAY: {
6186 guint32 i, alen, basetype;
6189 if (alen == 0xffffffff) {
6193 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6194 basetype = t->data.klass->byval_arg.type;
6199 case MONO_TYPE_BOOLEAN:
6200 for (i = 0; i < alen; i++) {
6201 MonoBoolean val = *p++;
6202 mono_array_set (arr, MonoBoolean, i, val);
6205 case MONO_TYPE_CHAR:
6208 for (i = 0; i < alen; i++) {
6209 guint16 val = read16 (p);
6210 mono_array_set (arr, guint16, i, val);
6217 for (i = 0; i < alen; i++) {
6218 guint32 val = read32 (p);
6219 mono_array_set (arr, guint32, i, val);
6226 for (i = 0; i < alen; i++) {
6227 guint64 val = read64 (p);
6228 mono_array_set (arr, guint64, i, val);
6232 case MONO_TYPE_CLASS:
6233 case MONO_TYPE_OBJECT:
6234 case MONO_TYPE_STRING:
6235 for (i = 0; i < alen; i++) {
6236 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6237 mono_array_set (arr, gpointer, i, item);
6241 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6247 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6253 type_is_reference (MonoType *type)
6255 switch (type->type) {
6256 case MONO_TYPE_BOOLEAN:
6257 case MONO_TYPE_CHAR:
6270 case MONO_TYPE_VALUETYPE:
6278 free_param_data (MonoMethodSignature *sig, void **params) {
6280 for (i = 0; i < sig->param_count; ++i) {
6281 if (!type_is_reference (sig->params [i]))
6282 g_free (params [i]);
6287 * Find the method index in the metadata methodDef table.
6288 * Later put these three helper methods in metadata and export them.
6291 find_method_index (MonoMethod *method) {
6292 MonoClass *klass = method->klass;
6295 for (i = 0; i < klass->method.count; ++i) {
6296 if (method == klass->methods [i])
6297 return klass->method.first + 1 + i;
6303 * Find the field index in the metadata FieldDef table.
6306 find_field_index (MonoClass *klass, MonoClassField *field) {
6309 for (i = 0; i < klass->field.count; ++i) {
6310 if (field == &klass->fields [i])
6311 return klass->field.first + 1 + i;
6317 * Find the property index in the metadata Property table.
6320 find_property_index (MonoClass *klass, MonoProperty *property) {
6323 for (i = 0; i < klass->property.count; ++i) {
6324 if (property == &klass->properties [i])
6325 return klass->property.first + 1 + i;
6331 * Find the event index in the metadata Event table.
6334 find_event_index (MonoClass *klass, MonoEvent *event) {
6337 for (i = 0; i < klass->event.count; ++i) {
6338 if (event == &klass->events [i])
6339 return klass->event.first + 1 + i;
6345 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6347 const char *p = data;
6349 guint32 i, j, num_named;
6353 mono_class_init (method->klass);
6356 attr = mono_object_new (mono_domain_get (), method->klass);
6357 mono_runtime_invoke (method, attr, NULL, NULL);
6361 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6364 /*g_print ("got attr %s\n", method->klass->name);*/
6366 params = g_new (void*, method->signature->param_count);
6370 for (i = 0; i < method->signature->param_count; ++i) {
6371 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6375 attr = mono_object_new (mono_domain_get (), method->klass);
6376 mono_runtime_invoke (method, attr, params, NULL);
6377 free_param_data (method->signature, params);
6379 num_named = read16 (named);
6381 for (j = 0; j < num_named; j++) {
6383 char *name, named_type, data_type;
6384 named_type = *named++;
6385 data_type = *named++; /* type of data */
6386 if (data_type == 0x55) {
6389 type_len = mono_metadata_decode_blob_size (named, &named);
6390 type_name = g_malloc (type_len + 1);
6391 memcpy (type_name, named, type_len);
6392 type_name [type_len] = 0;
6394 /* FIXME: lookup the type and check type consistency */
6395 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6396 /* this seems to be the type of the element of the array */
6397 /* g_print ("skipping 0x%02x after prop\n", *named); */
6400 name_len = mono_metadata_decode_blob_size (named, &named);
6401 name = g_malloc (name_len + 1);
6402 memcpy (name, named, name_len);
6403 name [name_len] = 0;
6405 if (named_type == 0x53) {
6406 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6407 void *val = load_cattr_value (image, field->type, named, &named);
6408 mono_field_set_value (attr, field, val);
6409 if (!type_is_reference (field->type))
6411 } else if (named_type == 0x54) {
6414 MonoType *prop_type;
6416 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6417 /* can we have more that 1 arg in a custom attr named property? */
6418 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6419 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6420 mono_property_set_value (prop, attr, pparams, NULL);
6421 if (!type_is_reference (prop_type))
6422 g_free (pparams [0]);
6431 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6438 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6439 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6440 for (i = 0; i < cinfo->num_attrs; ++i) {
6441 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6442 mono_array_set (result, gpointer, i, attr);
6448 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6450 guint32 mtoken, i, len;
6451 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6453 MonoCustomAttrInfo *ainfo;
6454 GList *tmp, *list = NULL;
6457 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6459 i = mono_metadata_custom_attrs_from_index (image, idx);
6463 while (i < ca->rows) {
6464 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6466 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6469 len = g_list_length (list);
6472 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6473 ainfo->num_attrs = len;
6474 ainfo->image = image;
6475 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6476 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6477 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6478 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6479 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6480 mtoken |= MONO_TOKEN_METHOD_DEF;
6482 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6483 mtoken |= MONO_TOKEN_MEMBER_REF;
6486 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6489 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6490 if (!ainfo->attrs [i].ctor)
6491 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6492 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6493 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6494 ainfo->attrs [i].data = data;
6502 mono_custom_attrs_from_method (MonoMethod *method)
6504 MonoCustomAttrInfo *cinfo;
6507 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6509 idx = find_method_index (method);
6510 idx <<= MONO_CUSTOM_ATTR_BITS;
6511 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6512 return mono_custom_attrs_from_index (method->klass->image, idx);
6516 mono_custom_attrs_from_class (MonoClass *klass)
6518 MonoCustomAttrInfo *cinfo;
6521 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6523 idx = mono_metadata_token_index (klass->type_token);
6524 idx <<= MONO_CUSTOM_ATTR_BITS;
6525 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6526 return mono_custom_attrs_from_index (klass->image, idx);
6530 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6532 MonoCustomAttrInfo *cinfo;
6535 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6537 idx = 1; /* there is only one assembly */
6538 idx <<= MONO_CUSTOM_ATTR_BITS;
6539 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6540 return mono_custom_attrs_from_index (assembly->image, idx);
6543 static MonoCustomAttrInfo*
6544 mono_custom_attrs_from_module (MonoImage *image)
6546 MonoCustomAttrInfo *cinfo;
6549 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6551 idx = 1; /* there is only one module */
6552 idx <<= MONO_CUSTOM_ATTR_BITS;
6553 idx |= MONO_CUSTOM_ATTR_MODULE;
6554 return mono_custom_attrs_from_index (image, idx);
6558 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6560 MonoCustomAttrInfo *cinfo;
6563 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6565 idx = find_property_index (klass, property);
6566 idx <<= MONO_CUSTOM_ATTR_BITS;
6567 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6568 return mono_custom_attrs_from_index (klass->image, idx);
6572 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6574 MonoCustomAttrInfo *cinfo;
6577 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6579 idx = find_event_index (klass, event);
6580 idx <<= MONO_CUSTOM_ATTR_BITS;
6581 idx |= MONO_CUSTOM_ATTR_EVENT;
6582 return mono_custom_attrs_from_index (klass->image, idx);
6586 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6588 MonoCustomAttrInfo *cinfo;
6591 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6593 idx = find_field_index (klass, field);
6594 idx <<= MONO_CUSTOM_ATTR_BITS;
6595 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6596 return mono_custom_attrs_from_index (klass->image, idx);
6600 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6603 guint32 i, idx, method_index;
6604 guint32 param_list, param_last, param_pos, found;
6606 MonoReflectionMethodAux *aux;
6608 if (method->klass->image->dynamic) {
6609 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6610 if (!aux || !aux->param_cattr)
6612 return aux->param_cattr [param];
6615 image = method->klass->image;
6616 method_index = find_method_index (method);
6617 ca = &image->tables [MONO_TABLE_METHOD];
6619 if (method->klass->generic_inst || method->klass->gen_params ||
6620 method->signature->generic_param_count) {
6621 /* FIXME FIXME FIXME */
6625 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6626 if (method_index == ca->rows) {
6627 ca = &image->tables [MONO_TABLE_PARAM];
6628 param_last = ca->rows + 1;
6630 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6631 ca = &image->tables [MONO_TABLE_PARAM];
6634 for (i = param_list; i < param_last; ++i) {
6635 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6636 if (param_pos == param) {
6644 idx <<= MONO_CUSTOM_ATTR_BITS;
6645 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6646 return mono_custom_attrs_from_index (image, idx);
6650 * mono_reflection_get_custom_attrs:
6651 * @obj: a reflection object handle
6653 * Return an array with all the custom attributes defined of the
6654 * reflection handle @obj. The objects are fully build.
6657 mono_reflection_get_custom_attrs (MonoObject *obj)
6661 MonoCustomAttrInfo *cinfo = NULL;
6663 MONO_ARCH_SAVE_REGS;
6665 klass = obj->vtable->klass;
6666 if (klass == mono_defaults.monotype_class) {
6667 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6668 klass = mono_class_from_mono_type (rtype->type);
6669 cinfo = mono_custom_attrs_from_class (klass);
6670 } else if (strcmp ("Assembly", klass->name) == 0) {
6671 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6672 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6673 } else if (strcmp ("Module", klass->name) == 0) {
6674 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6675 cinfo = mono_custom_attrs_from_module (module->image);
6676 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6677 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6678 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6679 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6680 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6681 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6682 } else if (strcmp ("MonoField", klass->name) == 0) {
6683 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6684 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6685 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6686 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6687 cinfo = mono_custom_attrs_from_method (rmethod->method);
6688 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6689 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6690 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6691 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6692 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6693 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6694 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6695 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6696 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6697 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6698 } else { /* handle other types here... */
6699 g_error ("get custom attrs not yet supported for %s", klass->name);
6703 result = mono_custom_attrs_construct (cinfo);
6705 mono_custom_attrs_free (cinfo);
6707 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6708 result = mono_array_new (mono_domain_get (), klass, 0);
6714 static MonoMethodSignature*
6715 parameters_to_signature (MonoArray *parameters) {
6716 MonoMethodSignature *sig;
6719 count = parameters? mono_array_length (parameters): 0;
6721 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6722 sig->param_count = count;
6723 sig->sentinelpos = -1; /* FIXME */
6724 for (i = 0; i < count; ++i) {
6725 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6726 sig->params [i] = pt->type;
6731 static MonoMethodSignature*
6732 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6733 MonoMethodSignature *sig;
6735 sig = parameters_to_signature (ctor->parameters);
6736 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6737 sig->ret = &mono_defaults.void_class->byval_arg;
6741 static MonoMethodSignature*
6742 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6743 MonoMethodSignature *sig;
6745 sig = parameters_to_signature (method->parameters);
6746 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6747 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6748 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6752 static MonoMethodSignature*
6753 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6754 MonoMethodSignature *sig;
6756 sig = parameters_to_signature (method->parameters);
6757 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6758 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6759 sig->generic_param_count = 0;
6764 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6766 MonoClass *klass = mono_object_class (prop);
6767 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6768 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6769 *name = mono_string_to_utf8 (pb->name);
6770 *type = pb->type->type;
6772 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6773 *name = g_strdup (p->property->name);
6774 if (p->property->get)
6775 *type = p->property->get->signature->ret;
6777 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6782 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6784 MonoClass *klass = mono_object_class (field);
6785 if (strcmp (klass->name, "FieldBuilder") == 0) {
6786 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6787 *name = mono_string_to_utf8 (fb->name);
6788 *type = fb->type->type;
6790 MonoReflectionField *f = (MonoReflectionField *)field;
6791 *name = g_strdup (f->field->name);
6792 *type = f->field->type;
6797 * Encode a value in a custom attribute stream of bytes.
6798 * The value to encode is either supplied as an object in argument val
6799 * (valuetypes are boxed), or as a pointer to the data in the
6801 * @type represents the type of the value
6802 * @buffer is the start of the buffer
6803 * @p the current position in the buffer
6804 * @buflen contains the size of the buffer and is used to return the new buffer size
6805 * if this needs to be realloced.
6806 * @retbuffer and @retp return the start and the position of the buffer
6809 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6811 MonoTypeEnum simple_type;
6813 if ((p-buffer) + 10 >= *buflen) {
6816 newbuf = g_realloc (buffer, *buflen);
6817 p = newbuf + (p-buffer);
6821 argval = ((char*)arg + sizeof (MonoObject));
6822 simple_type = type->type;
6824 switch (simple_type) {
6825 case MONO_TYPE_BOOLEAN:
6830 case MONO_TYPE_CHAR:
6833 swap_with_size (p, argval, 2, 1);
6839 swap_with_size (p, argval, 4, 1);
6845 swap_with_size (p, argval, 8, 1);
6848 case MONO_TYPE_VALUETYPE:
6849 if (type->data.klass->enumtype) {
6850 simple_type = type->data.klass->enum_basetype->type;
6853 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6856 case MONO_TYPE_STRING: {
6863 str = mono_string_to_utf8 ((MonoString*)arg);
6864 slen = strlen (str);
6865 if ((p-buffer) + 10 + slen >= *buflen) {
6869 newbuf = g_realloc (buffer, *buflen);
6870 p = newbuf + (p-buffer);
6873 mono_metadata_encode_value (slen, p, &p);
6874 memcpy (p, str, slen);
6879 case MONO_TYPE_CLASS: {
6887 k = mono_object_class (arg);
6888 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6889 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6890 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6892 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6893 slen = strlen (str);
6894 if ((p-buffer) + 10 + slen >= *buflen) {
6898 newbuf = g_realloc (buffer, *buflen);
6899 p = newbuf + (p-buffer);
6902 mono_metadata_encode_value (slen, p, &p);
6903 memcpy (p, str, slen);
6908 case MONO_TYPE_SZARRAY: {
6910 MonoClass *eclass, *arg_eclass;
6913 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6916 len = mono_array_length ((MonoArray*)arg);
6918 *p++ = (len >> 8) & 0xff;
6919 *p++ = (len >> 16) & 0xff;
6920 *p++ = (len >> 24) & 0xff;
6922 *retbuffer = buffer;
6923 eclass = type->data.klass;
6924 arg_eclass = mono_object_class (arg)->element_class;
6925 if (eclass->valuetype && arg_eclass->valuetype) {
6926 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6927 int elsize = mono_class_array_element_size (eclass);
6928 for (i = 0; i < len; ++i) {
6929 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6933 for (i = 0; i < len; ++i) {
6934 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6939 /* it may be a boxed value or a Type */
6940 case MONO_TYPE_OBJECT: {
6941 MonoClass *klass = mono_object_class (arg);
6945 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6948 } else if (klass->enumtype) {
6950 } else if (klass == mono_defaults.string_class) {
6951 simple_type = MONO_TYPE_STRING;
6954 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6955 *p++ = simple_type = klass->byval_arg.type;
6958 g_error ("unhandled type in custom attr");
6960 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6961 slen = strlen (str);
6962 if ((p-buffer) + 10 + slen >= *buflen) {
6966 newbuf = g_realloc (buffer, *buflen);
6967 p = newbuf + (p-buffer);
6970 mono_metadata_encode_value (slen, p, &p);
6971 memcpy (p, str, slen);
6974 simple_type = klass->enum_basetype->type;
6978 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6981 *retbuffer = buffer;
6985 * mono_reflection_get_custom_attrs_blob:
6986 * @ctor: custom attribute constructor
6987 * @ctorArgs: arguments o the constructor
6993 * Creates the blob of data that needs to be saved in the metadata and that represents
6994 * the custom attributed described by @ctor, @ctorArgs etc.
6995 * Returns: a Byte array representing the blob of data.
6998 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7001 MonoMethodSignature *sig;
7006 MONO_ARCH_SAVE_REGS;
7008 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7009 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7011 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7013 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7015 p = buffer = g_malloc (buflen);
7016 /* write the prolog */
7019 for (i = 0; i < sig->param_count; ++i) {
7020 arg = mono_array_get (ctorArgs, MonoObject*, i);
7021 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7025 i += mono_array_length (properties);
7027 i += mono_array_length (fields);
7029 *p++ = (i >> 8) & 0xff;
7032 for (i = 0; i < mono_array_length (properties); ++i) {
7037 prop = mono_array_get (properties, gpointer, i);
7038 get_prop_name_and_type (prop, &pname, &ptype);
7039 *p++ = 0x54; /* PROPERTY signature */
7041 /* Preallocate a large enough buffer */
7042 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7043 char *str = type_get_qualified_name (ptype, NULL);
7049 len += strlen (pname);
7051 if ((p-buffer) + 20 + len >= buflen) {
7055 newbuf = g_realloc (buffer, buflen);
7056 p = newbuf + (p-buffer);
7060 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7061 char *str = type_get_qualified_name (ptype, NULL);
7062 int slen = strlen (str);
7066 * This seems to be optional...
7069 mono_metadata_encode_value (slen, p, &p);
7070 memcpy (p, str, slen);
7074 mono_metadata_encode_value (ptype->type, p, &p);
7075 if (ptype->type == MONO_TYPE_SZARRAY)
7076 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7078 len = strlen (pname);
7079 mono_metadata_encode_value (len, p, &p);
7080 memcpy (p, pname, len);
7082 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7089 for (i = 0; i < mono_array_length (fields); ++i) {
7094 field = mono_array_get (fields, gpointer, i);
7095 get_field_name_and_type (field, &fname, &ftype);
7096 *p++ = 0x53; /* FIELD signature */
7097 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7098 char *str = type_get_qualified_name (ftype, NULL);
7099 int slen = strlen (str);
7100 if ((p-buffer) + 10 + slen >= buflen) {
7104 newbuf = g_realloc (buffer, buflen);
7105 p = newbuf + (p-buffer);
7110 * This seems to be optional...
7113 mono_metadata_encode_value (slen, p, &p);
7114 memcpy (p, str, slen);
7118 mono_metadata_encode_value (ftype->type, p, &p);
7119 if (ftype->type == MONO_TYPE_SZARRAY)
7120 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7122 len = strlen (fname);
7123 mono_metadata_encode_value (len, p, &p);
7124 memcpy (p, fname, len);
7126 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7131 g_assert (p - buffer <= buflen);
7132 buflen = p - buffer;
7133 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7134 p = mono_array_addr (result, char, 0);
7135 memcpy (p, buffer, buflen);
7137 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7143 * mono_reflection_setup_internal_class:
7144 * @tb: a TypeBuilder object
7146 * Creates a MonoClass that represents the TypeBuilder.
7147 * This is a trick that lets us simplify a lot of reflection code
7148 * (and will allow us to support Build and Run assemblies easier).
7151 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7153 MonoClass *klass, *parent;
7155 MONO_ARCH_SAVE_REGS;
7158 /* check so we can compile corlib correctly */
7159 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7160 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7161 parent = tb->parent->type->data.klass;
7163 parent = my_mono_class_from_mono_type (tb->parent->type);
7169 /* the type has already being created: it means we just have to change the parent */
7170 if (tb->type.type) {
7171 klass = mono_class_from_mono_type (tb->type.type);
7172 klass->parent = NULL;
7173 /* fool mono_class_setup_parent */
7174 g_free (klass->supertypes);
7175 klass->supertypes = NULL;
7176 mono_class_setup_parent (klass, parent);
7177 mono_class_setup_mono_type (klass);
7181 klass = g_new0 (MonoClass, 1);
7183 klass->image = &tb->module->dynamic_image->image;
7185 klass->inited = 1; /* we lie to the runtime */
7186 klass->name = mono_string_to_utf8 (tb->name);
7187 klass->name_space = mono_string_to_utf8 (tb->nspace);
7188 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7189 klass->flags = tb->attrs;
7191 klass->element_class = klass;
7192 klass->reflection_info = tb; /* need to pin. */
7194 /* Put into cache so mono_class_get () will find it */
7195 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7197 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7198 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7200 if (parent != NULL) {
7201 mono_class_setup_parent (klass, parent);
7202 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7203 const char *old_n = klass->name;
7204 /* trick to get relative numbering right when compiling corlib */
7205 klass->name = "BuildingObject";
7206 mono_class_setup_parent (klass, mono_defaults.object_class);
7207 klass->name = old_n;
7210 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7211 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7212 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7213 klass->instance_size = sizeof (MonoObject);
7214 klass->size_inited = 1;
7215 mono_class_setup_vtable (klass, NULL, 0);
7218 mono_class_setup_mono_type (klass);
7220 mono_class_setup_supertypes (klass);
7223 * FIXME: handle interfaces.
7226 tb->type.type = &klass->byval_arg;
7228 if (tb->nesting_type) {
7229 g_assert (tb->nesting_type->type);
7230 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7233 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7237 * mono_reflection_setup_generic_class:
7238 * @tb: a TypeBuilder object
7240 * Setup the generic class after all generic parameters have been added.
7243 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7248 MONO_ARCH_SAVE_REGS;
7250 klass = my_mono_class_from_mono_type (tb->type.type);
7252 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7254 if (klass->gen_params || (count == 0))
7257 klass->num_gen_params = count;
7258 klass->gen_params = g_new0 (MonoGenericParam, count);
7260 for (i = 0; i < count; i++) {
7261 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7262 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7267 * mono_reflection_create_internal_class:
7268 * @tb: a TypeBuilder object
7270 * Actually create the MonoClass that is associated with the TypeBuilder.
7273 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7277 MONO_ARCH_SAVE_REGS;
7279 klass = my_mono_class_from_mono_type (tb->type.type);
7281 if (klass->enumtype && klass->enum_basetype == NULL) {
7282 MonoReflectionFieldBuilder *fb;
7285 g_assert (tb->fields != NULL);
7286 g_assert (mono_array_length (tb->fields) >= 1);
7288 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7290 klass->enum_basetype = fb->type->type;
7291 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7292 if (!klass->element_class)
7293 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7296 * get the element_class from the current corlib.
7298 ec = default_class_from_mono_type (klass->enum_basetype);
7299 klass->instance_size = ec->instance_size;
7300 klass->size_inited = 1;
7302 * this is almost safe to do with enums and it's needed to be able
7303 * to create objects of the enum type (for use in SetConstant).
7305 /* FIXME: Does this mean enums can't have method overrides ? */
7306 mono_class_setup_vtable (klass, NULL, 0);
7310 static MonoMarshalSpec*
7311 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7312 MonoReflectionMarshal *minfo)
7314 MonoMarshalSpec *res;
7316 res = g_new0 (MonoMarshalSpec, 1);
7317 res->native = minfo->type;
7319 switch (minfo->type) {
7320 case MONO_NATIVE_LPARRAY:
7321 res->data.array_data.elem_type = minfo->eltype;
7322 res->data.array_data.param_num = 0; /* Not yet */
7323 res->data.array_data.num_elem = minfo->count;
7326 case MONO_NATIVE_BYVALTSTR:
7327 case MONO_NATIVE_BYVALARRAY:
7328 res->data.array_data.num_elem = minfo->count;
7331 case MONO_NATIVE_CUSTOM:
7332 if (minfo->marshaltyperef)
7333 res->data.custom_data.custom_name =
7334 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7336 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7346 MonoReflectionMarshal*
7347 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7348 MonoMarshalSpec *spec)
7350 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7351 MonoReflectionMarshal *minfo;
7354 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7355 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7356 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7357 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7360 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7361 minfo->type = spec->native;
7363 switch (minfo->type) {
7364 case MONO_NATIVE_LPARRAY:
7365 minfo->eltype = spec->data.array_data.elem_type;
7366 minfo->count = spec->data.array_data.num_elem;
7369 case MONO_NATIVE_BYVALTSTR:
7370 case MONO_NATIVE_BYVALARRAY:
7371 minfo->count = spec->data.array_data.num_elem;
7374 case MONO_NATIVE_CUSTOM:
7375 if (spec->data.custom_data.custom_name) {
7376 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7378 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7380 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7382 if (spec->data.custom_data.cookie)
7383 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7394 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7395 ReflectionMethodBuilder *rmb,
7396 MonoMethodSignature *sig)
7399 MonoMethodNormal *pm;
7400 MonoMarshalSpec **specs;
7401 MonoReflectionMethodAux *method_aux;
7404 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7405 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7406 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7408 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7410 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7412 pm = (MonoMethodNormal*)m;
7415 m->flags = rmb->attrs;
7416 m->iflags = rmb->iattrs;
7417 m->name = mono_string_to_utf8 (rmb->name);
7421 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7423 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7424 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7427 m->signature->pinvoke = 1;
7428 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7429 m->signature->pinvoke = 1;
7431 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7433 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7434 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7436 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7438 if (klass->image->dynamic)
7439 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7442 } else if (!m->klass->dummy &&
7443 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7444 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7445 MonoMethodHeader *header;
7447 gint32 max_stack, i;
7448 gint32 num_locals = 0;
7449 gint32 num_clauses = 0;
7453 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7454 code_size = rmb->ilgen->code_len;
7455 max_stack = rmb->ilgen->max_stack;
7456 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7457 if (rmb->ilgen->ex_handlers)
7458 num_clauses = method_count_clauses (rmb->ilgen);
7461 code = mono_array_addr (rmb->code, guint8, 0);
7462 code_size = mono_array_length (rmb->code);
7463 /* we probably need to run a verifier on the code... */
7473 header = g_malloc0 (sizeof (MonoMethodHeader) +
7474 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7475 header->code_size = code_size;
7476 header->code = g_malloc (code_size);
7477 memcpy ((char*)header->code, code, code_size);
7478 header->max_stack = max_stack;
7479 header->init_locals = rmb->init_locals;
7480 header->num_locals = num_locals;
7482 for (i = 0; i < num_locals; ++i) {
7483 MonoReflectionLocalBuilder *lb =
7484 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7486 header->locals [i] = g_new0 (MonoType, 1);
7487 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7490 header->num_clauses = num_clauses;
7492 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7493 rmb->ilgen, num_clauses);
7496 pm->header = header;
7499 if (rmb->generic_params) {
7500 int count = mono_array_length (rmb->generic_params);
7501 pm->gen_params = g_new0 (MonoGenericParam, count);
7502 for (i = 0; i < count; i++) {
7503 MonoReflectionGenericParam *gp =
7504 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7506 pm->gen_params [i] = *gp->type.type->data.generic_param;
7511 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7514 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7516 for (i = 0; i < rmb->nrefs; ++i)
7517 mw->data = g_list_append (mw->data, rmb->refs [i]);
7522 /* Parameter names */
7525 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7526 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7527 for (i = 0; i <= m->signature->param_count; ++i) {
7528 MonoReflectionParamBuilder *pb;
7529 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7531 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7533 if (!method_aux->param_cattr)
7534 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7535 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7541 /* Parameter marshalling */
7544 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7545 MonoReflectionParamBuilder *pb;
7546 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7547 if (pb->marshal_info) {
7549 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7550 specs [pb->position] =
7551 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7555 if (specs != NULL) {
7557 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7558 method_aux->param_marshall = specs;
7561 if (klass->image->dynamic && method_aux)
7562 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7568 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7570 ReflectionMethodBuilder rmb;
7571 MonoMethodSignature *sig;
7573 sig = ctor_builder_to_signature (mb);
7575 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7577 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7578 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7580 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7581 /* ilgen is no longer needed */
7589 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7591 ReflectionMethodBuilder rmb;
7592 MonoMethodSignature *sig;
7594 sig = method_builder_to_signature (mb);
7596 reflection_methodbuilder_from_method_builder (&rmb, mb);
7598 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7599 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7601 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7602 /* ilgen is no longer needed */
7608 static MonoClassField*
7609 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7611 MonoClassField *field;
7618 field = g_new0 (MonoClassField, 1);
7620 field->name = mono_string_to_utf8 (fb->name);
7622 /* FIXME: handle type modifiers */
7623 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7624 field->type->attrs = fb->attrs;
7626 field->type = fb->type->type;
7628 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7629 field->data = mono_array_addr (fb->rva_data, char, 0);
7630 if (fb->offset != -1)
7631 field->offset = fb->offset;
7632 field->parent = klass;
7634 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7636 if (fb->def_value) {
7637 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7638 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7639 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7640 /* Copy the data from the blob since it might get realloc-ed */
7641 p = assembly->blob.data + idx;
7642 len = mono_metadata_decode_blob_size (p, &p2);
7644 field->data = g_malloc (len);
7645 memcpy ((gpointer)field->data, p, len);
7652 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7655 MonoReflectionTypeBuilder *tb = NULL;
7656 MonoGenericInst *ginst, *cached;
7661 klass = mono_class_from_mono_type (type->type);
7662 if (!klass->gen_params && !klass->generic_inst &&
7663 !(klass->nested_in && klass->nested_in->gen_params))
7666 mono_loader_lock ();
7668 domain = mono_object_domain (type);
7670 ginst = g_new0 (MonoGenericInst, 1);
7672 if (!klass->generic_inst) {
7673 ginst->type_argc = type_argc;
7674 ginst->type_argv = types;
7676 for (i = 0; i < ginst->type_argc; ++i) {
7677 if (!ginst->is_open)
7678 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7681 ginst->generic_type = &klass->byval_arg;
7683 MonoGenericInst *kginst = klass->generic_inst;
7685 ginst->type_argc = kginst->type_argc;
7686 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7688 for (i = 0; i < ginst->type_argc; i++) {
7689 MonoType *t = kginst->type_argv [i];
7691 if (t->type == MONO_TYPE_VAR)
7692 t = types [t->data.generic_param->num];
7694 if (!ginst->is_open)
7695 ginst->is_open = mono_class_is_open_constructed_type (t);
7697 ginst->type_argv [i] = t;
7700 ginst->generic_type = kginst->generic_type;
7703 geninst = g_new0 (MonoType, 1);
7704 geninst->type = MONO_TYPE_GENERICINST;
7706 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7709 mono_loader_unlock ();
7710 geninst->data.generic_inst = cached;
7714 geninst->data.generic_inst = ginst;
7716 ginst->context = g_new0 (MonoGenericContext, 1);
7717 ginst->context->ginst = ginst;
7719 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7720 tb = (MonoReflectionTypeBuilder *) type;
7722 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7723 ginst->is_dynamic = TRUE;
7724 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7725 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7726 MonoReflectionType *rgt = rgi->generic_type;
7728 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7729 tb = (MonoReflectionTypeBuilder *) rgt;
7731 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7732 ginst->is_dynamic = TRUE;
7734 icount = klass->interface_count;
7737 ginst->ifaces = g_new0 (MonoType *, icount);
7738 ginst->count_ifaces = icount;
7740 for (i = 0; i < icount; i++) {
7741 MonoReflectionType *itype;
7744 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7746 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7747 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7748 if (!ginst->ifaces [i])
7749 ginst->ifaces [i] = itype->type;
7752 mono_class_create_generic (ginst);
7754 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7756 mono_loader_unlock ();
7762 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7764 MonoClass *klass, *pklass = NULL;
7765 MonoReflectionType *parent = NULL;
7767 MonoReflectionTypeBuilder *tb = NULL;
7768 MonoGenericInst *ginst;
7771 domain = mono_object_domain (type);
7772 klass = mono_class_from_mono_type (type->type);
7774 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7775 tb = (MonoReflectionTypeBuilder *) type;
7778 parent = tb->parent;
7779 pklass = mono_class_from_mono_type (parent->type);
7782 pklass = klass->parent;
7784 parent = mono_type_get_object (domain, &pklass->byval_arg);
7787 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7791 ginst = geninst->data.generic_inst;
7793 if (pklass && pklass->generic_inst)
7794 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7799 MonoReflectionMethod*
7800 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7802 MonoMethod *method, *inflated;
7803 MonoReflectionMethodBuilder *mb = NULL;
7804 MonoGenericMethod *gmethod;
7805 MonoGenericContext *context;
7808 MONO_ARCH_SAVE_REGS;
7809 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7810 MonoReflectionTypeBuilder *tb;
7813 mb = (MonoReflectionMethodBuilder *) rmethod;
7814 tb = (MonoReflectionTypeBuilder *) mb->type;
7815 klass = mono_class_from_mono_type (tb->type.type);
7817 method = methodbuilder_to_mono_method (klass, mb);
7819 method = rmethod->method;
7822 count = method->signature->generic_param_count;
7823 if (count != mono_array_length (types))
7826 gmethod = g_new0 (MonoGenericMethod, 1);
7827 gmethod->mtype_argc = count;
7828 gmethod->mtype_argv = g_new0 (MonoType *, count);
7829 for (i = 0; i < count; i++) {
7830 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7831 gmethod->mtype_argv [i] = garg->type;
7834 gmethod->reflection_info = rmethod;
7836 context = g_new0 (MonoGenericContext, 1);
7837 context->ginst = method->klass->generic_inst;
7838 context->gmethod = gmethod;
7840 inflated = mono_class_inflate_generic_method (method, context, NULL);
7842 return mono_method_get_object (
7843 mono_object_domain (rmethod), inflated, NULL);
7847 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7849 MonoGenericMethod *gmethod;
7850 MonoGenericInst *ginst;
7851 MonoGenericContext *context;
7854 ginst = type->type.type->data.generic_inst;
7856 gmethod = g_new0 (MonoGenericMethod, 1);
7857 gmethod->reflection_info = obj;
7859 gmethod->mtype_argc = method->signature->generic_param_count;
7860 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7862 for (i = 0; i < gmethod->mtype_argc; i++) {
7863 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7864 MonoGenericParam *gparam = &mn->gen_params [i];
7866 g_assert (gparam->pklass);
7867 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7870 context = g_new0 (MonoGenericContext, 1);
7871 context->ginst = ginst;
7872 context->gmethod = gmethod;
7874 return mono_class_inflate_generic_method (method, context, ginst->klass);
7878 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7883 klass = mono_class_from_mono_type (type->type.type);
7885 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7886 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7887 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7888 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7889 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7890 method = ((MonoReflectionMethod *) obj)->method;
7892 method = NULL; /* prevent compiler warning */
7893 g_assert_not_reached ();
7896 return inflate_mono_method (type, method, obj);
7900 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
7901 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7903 MonoGenericInst *ginst;
7904 MonoDynamicGenericInst *dginst;
7905 MonoClass *klass, *gklass, *pklass;
7908 MONO_ARCH_SAVE_REGS;
7910 klass = mono_class_from_mono_type (type->type.type);
7911 ginst = type->type.type->data.generic_inst;
7913 if (ginst->initialized)
7916 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7918 gklass = mono_class_from_mono_type (ginst->generic_type);
7919 mono_class_init (gklass);
7922 pklass = mono_class_from_mono_type (ginst->parent);
7924 pklass = gklass->parent;
7926 mono_class_setup_parent (klass, pklass);
7928 dginst->count_methods = methods ? mono_array_length (methods) : 0;
7929 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7930 dginst->count_fields = fields ? mono_array_length (fields) : 0;
7931 dginst->count_properties = properties ? mono_array_length (properties) : 0;
7932 dginst->count_events = events ? mono_array_length (events) : 0;
7934 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7935 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7936 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7937 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7938 dginst->events = g_new0 (MonoEvent, dginst->count_events);
7940 for (i = 0; i < dginst->count_methods; i++) {
7941 MonoObject *obj = mono_array_get (methods, gpointer, i);
7943 dginst->methods [i] = inflate_method (type, obj);
7946 for (i = 0; i < dginst->count_ctors; i++) {
7947 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7949 dginst->ctors [i] = inflate_method (type, obj);
7952 for (i = 0; i < dginst->count_fields; i++) {
7953 MonoObject *obj = mono_array_get (fields, gpointer, i);
7954 MonoClassField *field;
7955 MonoInflatedField *ifield;
7957 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7958 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7959 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7960 field = ((MonoReflectionField *) obj)->field;
7962 field = NULL; /* prevent compiler warning */
7963 g_assert_not_reached ();
7966 ifield = g_new0 (MonoInflatedField, 1);
7967 ifield->generic_type = field->type;
7968 ifield->reflection_info = obj;
7970 dginst->fields [i] = *field;
7971 dginst->fields [i].generic_info = ifield;
7972 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7975 for (i = 0; i < dginst->count_properties; i++) {
7976 MonoObject *obj = mono_array_get (properties, gpointer, i);
7977 MonoProperty *property = &dginst->properties [i];
7979 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7980 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7982 property->parent = klass;
7983 property->attrs = pb->attrs;
7984 property->name = mono_string_to_utf8 (pb->name);
7986 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7988 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7989 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7990 *property = *((MonoReflectionProperty *) obj)->property;
7993 property->get = inflate_mono_method (type, property->get, NULL);
7995 property->set = inflate_mono_method (type, property->set, NULL);
7997 g_assert_not_reached ();
8000 for (i = 0; i < dginst->count_events; i++) {
8001 MonoObject *obj = mono_array_get (events, gpointer, i);
8002 MonoEvent *event = &dginst->events [i];
8004 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8005 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8007 event->parent = klass;
8008 event->attrs = eb->attrs;
8009 event->name = mono_string_to_utf8 (eb->name);
8011 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8012 if (eb->remove_method)
8013 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8014 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8015 *event = *((MonoReflectionEvent *) obj)->event;
8018 event->add = inflate_mono_method (type, event->add, NULL);
8020 event->remove = inflate_mono_method (type, event->remove, NULL);
8022 g_assert_not_reached ();
8025 ginst->initialized = TRUE;
8029 ensure_runtime_vtable (MonoClass *klass)
8031 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8032 int i, num, j, onum;
8033 MonoMethod **overrides;
8035 if (!tb || klass->wastypebuilder)
8038 ensure_runtime_vtable (klass->parent);
8040 num = tb->ctors? mono_array_length (tb->ctors): 0;
8041 num += tb->num_methods;
8042 klass->method.count = num;
8043 klass->methods = g_new (MonoMethod*, num);
8044 num = tb->ctors? mono_array_length (tb->ctors): 0;
8045 for (i = 0; i < num; ++i)
8046 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8047 num = tb->num_methods;
8049 for (i = 0; i < num; ++i)
8050 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8052 klass->wastypebuilder = TRUE;
8053 if (tb->interfaces) {
8054 klass->interface_count = mono_array_length (tb->interfaces);
8055 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8056 for (i = 0; i < klass->interface_count; ++i) {
8057 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8058 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8062 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8063 for (i = 0; i < klass->method.count; ++i)
8064 klass->methods [i]->slot = i;
8069 for (i = 0; i < tb->num_methods; ++i) {
8070 MonoReflectionMethodBuilder *mb =
8071 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8072 if (mb->override_method)
8077 overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8081 for (i = 0; i < tb->num_methods; ++i) {
8082 MonoReflectionMethodBuilder *mb =
8083 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8084 if (mb->override_method) {
8085 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8086 overrides [onum * 2] =
8087 mb->override_method->method;
8088 overrides [onum * 2 + 1] =
8091 g_assert (mb->mhandle);
8098 mono_class_setup_vtable (klass, overrides, onum);
8102 typebuilder_setup_fields (MonoClass *klass)
8104 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8105 MonoReflectionFieldBuilder *fb;
8106 MonoClassField *field;
8111 klass->field.count = tb->num_fields;
8112 klass->field.first = 0;
8113 klass->field.last = klass->field.count;
8115 if (!klass->field.count)
8118 klass->fields = g_new0 (MonoClassField, klass->field.count);
8120 for (i = 0; i < klass->field.count; ++i) {
8121 fb = mono_array_get (tb->fields, gpointer, i);
8122 field = &klass->fields [i];
8123 field->name = mono_string_to_utf8 (fb->name);
8125 /* FIXME: handle type modifiers */
8126 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8127 field->type->attrs = fb->attrs;
8129 field->type = fb->type->type;
8131 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8132 field->data = mono_array_addr (fb->rva_data, char, 0);
8133 if (fb->offset != -1)
8134 field->offset = fb->offset;
8135 field->parent = klass;
8137 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8139 if (fb->def_value) {
8140 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8141 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8142 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8143 /* Copy the data from the blob since it might get realloc-ed */
8144 p = assembly->blob.data + idx;
8145 len = mono_metadata_decode_blob_size (p, &p2);
8147 field->data = g_malloc (len);
8148 memcpy ((gpointer)field->data, p, len);
8151 mono_class_layout_fields (klass);
8155 typebuilder_setup_properties (MonoClass *klass)
8157 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8158 MonoReflectionPropertyBuilder *pb;
8161 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8162 klass->property.first = 0;
8163 klass->property.last = klass->property.count;
8165 klass->properties = g_new0 (MonoProperty, klass->property.count);
8166 for (i = 0; i < klass->property.count; ++i) {
8167 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8168 klass->properties [i].parent = klass;
8169 klass->properties [i].attrs = pb->attrs;
8170 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8172 klass->properties [i].get = pb->get_method->mhandle;
8174 klass->properties [i].set = pb->set_method->mhandle;
8178 MonoReflectionEvent *
8179 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8181 MonoEvent *event = g_new0 (MonoEvent, 1);
8185 klass = my_mono_class_from_mono_type (tb->type.type);
8187 event->parent = klass;
8188 event->attrs = eb->attrs;
8189 event->name = mono_string_to_utf8 (eb->name);
8191 event->add = eb->add_method->mhandle;
8192 if (eb->remove_method)
8193 event->remove = eb->remove_method->mhandle;
8194 if (eb->raise_method)
8195 event->raise = eb->raise_method->mhandle;
8197 if (eb->other_methods) {
8198 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8199 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8200 MonoReflectionMethodBuilder *mb =
8201 mono_array_get (eb->other_methods,
8202 MonoReflectionMethodBuilder*, j);
8203 event->other [j] = mb->mhandle;
8207 return mono_event_get_object (mono_object_domain (tb), klass, event);
8211 typebuilder_setup_events (MonoClass *klass)
8213 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8214 MonoReflectionEventBuilder *eb;
8217 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8218 klass->event.first = 0;
8219 klass->event.last = klass->event.count;
8221 klass->events = g_new0 (MonoEvent, klass->event.count);
8222 for (i = 0; i < klass->event.count; ++i) {
8223 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8224 klass->events [i].parent = klass;
8225 klass->events [i].attrs = eb->attrs;
8226 klass->events [i].name = mono_string_to_utf8 (eb->name);
8228 klass->events [i].add = eb->add_method->mhandle;
8229 if (eb->remove_method)
8230 klass->events [i].remove = eb->remove_method->mhandle;
8231 if (eb->raise_method)
8232 klass->events [i].raise = eb->raise_method->mhandle;
8234 if (eb->other_methods) {
8235 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8236 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8237 MonoReflectionMethodBuilder *mb =
8238 mono_array_get (eb->other_methods,
8239 MonoReflectionMethodBuilder*, j);
8240 klass->events [i].other [j] = mb->mhandle;
8247 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8250 MonoReflectionType* res;
8253 MONO_ARCH_SAVE_REGS;
8255 klass = my_mono_class_from_mono_type (tb->type.type);
8257 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8260 * Fields to set in klass:
8261 * the various flags: delegate/unicode/contextbound etc.
8263 klass->flags = tb->attrs;
8265 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8266 /* No need to fully construct the type */
8267 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8269 /* enums are done right away */
8270 if (!klass->enumtype)
8271 ensure_runtime_vtable (klass);
8274 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8275 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8276 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8280 /* fields and object layout */
8281 if (klass->parent) {
8282 if (!klass->parent->size_inited)
8283 mono_class_init (klass->parent);
8284 klass->instance_size += klass->parent->instance_size;
8285 klass->class_size += klass->parent->class_size;
8286 klass->min_align = klass->parent->min_align;
8288 klass->instance_size = sizeof (MonoObject);
8289 klass->min_align = 1;
8292 /* FIXME: handle packing_size and instance_size */
8293 typebuilder_setup_fields (klass);
8295 typebuilder_setup_properties (klass);
8297 typebuilder_setup_events (klass);
8299 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8300 /* with enums res == tb: need to fix that. */
8301 if (!klass->enumtype)
8302 g_assert (res != (MonoReflectionType*)tb);
8307 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8309 MonoGenericParam *param;
8312 MONO_ARCH_SAVE_REGS;
8314 param = g_new0 (MonoGenericParam, 1);
8316 param->method = NULL;
8317 param->name = mono_string_to_utf8 (gparam->name);
8318 param->num = gparam->index;
8320 image = &gparam->tbuilder->module->dynamic_image->image;
8321 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8323 param->pklass->reflection_info = gparam;
8325 gparam->type.type = g_new0 (MonoType, 1);
8326 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8327 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8328 gparam->type.type->data.generic_param = param;
8332 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8334 MonoDynamicImage *assembly = sig->module->dynamic_image;
8335 guint32 na = mono_array_length (sig->arguments);
8340 MONO_ARCH_SAVE_REGS;
8342 p = buf = g_malloc (10 + na * 10);
8344 mono_metadata_encode_value (0x07, p, &p);
8345 mono_metadata_encode_value (na, p, &p);
8346 for (i = 0; i < na; ++i) {
8347 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8348 encode_reflection_type (assembly, type, p, &p);
8352 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8353 p = mono_array_addr (result, char, 0);
8354 memcpy (p, buf, buflen);
8361 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8363 MonoDynamicImage *assembly = sig->module->dynamic_image;
8364 guint32 na = mono_array_length (sig->arguments);
8369 MONO_ARCH_SAVE_REGS;
8371 p = buf = g_malloc (10 + na * 10);
8373 mono_metadata_encode_value (0x06, p, &p);
8374 for (i = 0; i < na; ++i) {
8375 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8376 encode_reflection_type (assembly, type, p, &p);
8380 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8381 p = mono_array_addr (result, char, 0);
8382 memcpy (p, buf, buflen);
8389 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8391 ReflectionMethodBuilder rmb;
8392 MonoMethodSignature *sig;
8395 sig = dynamic_method_to_signature (mb);
8397 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8400 * Resolve references.
8402 rmb.nrefs = mb->nrefs;
8403 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8404 for (i = 0; i < mb->nrefs; ++i) {
8405 gpointer ref = resolve_object (mb->module->image,
8406 mono_array_get (mb->refs, MonoObject*, i));
8409 mono_raise_exception (mono_get_exception_type_load (NULL));
8416 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8420 /* ilgen is no longer needed */
8425 * mono_reflection_lookup_dynamic_token:
8427 * Finish the Builder object pointed to by TOKEN and return the corresponding
8428 * runtime structure.
8431 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8433 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8436 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8439 return resolve_object (image, obj);
8443 resolve_object (MonoImage *image, MonoObject *obj)
8445 gpointer result = NULL;
8447 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8448 result = mono_string_intern ((MonoString*)obj);
8450 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8451 MonoReflectionType *tb = (MonoReflectionType*)obj;
8452 result = mono_class_from_mono_type (tb->type);
8454 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8455 result = ((MonoReflectionMethod*)obj)->method;
8457 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8458 result = ((MonoReflectionMethod*)obj)->method;
8460 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8461 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8462 result = mb->mhandle;
8464 /* Type is not yet created */
8465 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8467 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8470 * Hopefully this has been filled in by calling CreateType() on the
8474 * TODO: This won't work if the application finishes another
8475 * TypeBuilder instance instead of this one.
8477 result = mb->mhandle;
8479 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8480 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8482 result = cb->mhandle;
8484 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8486 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8487 result = cb->mhandle;
8489 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8490 result = ((MonoReflectionField*)obj)->field;
8492 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8493 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8494 result = fb->handle;
8497 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8499 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8500 result = fb->handle;
8502 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8506 klass = tb->type.type->data.klass;
8507 if (klass->wastypebuilder) {
8508 /* Already created */
8512 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8513 result = tb->type.type->data.klass;
8516 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8517 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8518 MonoMethodSignature *sig;
8521 if (helper->arguments)
8522 nargs = mono_array_length (helper->arguments);
8526 sig = mono_metadata_signature_alloc (image, nargs);
8527 sig->explicit_this = helper->call_conv & 64;
8528 sig->hasthis = helper->call_conv & 32;
8530 if (helper->call_conv == 0) /* unmanaged */
8531 sig->call_convention = helper->unmanaged_call_conv - 1;
8533 if (helper->call_conv & 0x02)
8534 sig->call_convention = MONO_CALL_VARARG;
8536 sig->call_convention = MONO_CALL_DEFAULT;
8538 sig->param_count = nargs;
8539 /* TODO: Copy type ? */
8540 sig->ret = helper->return_type->type;
8541 for (i = 0; i < nargs; ++i) {
8542 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8543 sig->params [i] = rt->type;
8548 g_print (obj->vtable->klass->name);
8549 g_assert_not_reached ();