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,
125 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
126 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
127 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
128 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
129 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
130 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
131 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
132 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
133 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
134 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
135 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
136 static void ensure_runtime_vtable (MonoClass *klass);
137 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
138 static void encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
139 static guint32 type_get_signature_size (MonoType *type);
140 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
141 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
145 alloc_table (MonoDynamicTable *table, guint nrows)
148 g_assert (table->columns);
149 if (nrows + 1 >= table->alloc_rows) {
150 while (nrows + 1 >= table->alloc_rows) {
151 if (table->alloc_rows == 0)
152 table->alloc_rows = 16;
154 table->alloc_rows *= 2;
157 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
162 make_room_in_stream (MonoDynamicStream *stream, int size)
164 if (size <= stream->alloc_size)
167 while (stream->alloc_size <= size) {
168 if (stream->alloc_size < 4096)
169 stream->alloc_size = 4096;
171 stream->alloc_size *= 2;
174 stream->data = g_realloc (stream->data, stream->alloc_size);
178 mono_dynamic_stream_reset (MonoDynamicStream* stream)
180 stream->alloc_size = stream->index = stream->offset = 0;
181 g_free (stream->data);
183 g_hash_table_destroy (stream->hash);
187 string_heap_insert (MonoDynamicStream *sh, const char *str)
191 gpointer oldkey, oldval;
193 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
194 return GPOINTER_TO_UINT (oldval);
196 len = strlen (str) + 1;
199 make_room_in_stream (sh, idx + len);
202 * We strdup the string even if we already copy them in sh->data
203 * so that the string pointers in the hash remain valid even if
204 * we need to realloc sh->data. We may want to avoid that later.
206 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
207 memcpy (sh->data + idx, str, len);
213 string_heap_init (MonoDynamicStream *sh)
216 sh->alloc_size = 4096;
217 sh->data = g_malloc (4096);
218 sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
219 string_heap_insert (sh, "");
222 #if 0 /* never used */
224 string_heap_free (MonoDynamicStream *sh)
227 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
228 g_hash_table_destroy (sh->hash);
233 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
237 make_room_in_stream (stream, stream->index + len);
238 memcpy (stream->data + stream->index, data, len);
240 stream->index += len;
242 * align index? Not without adding an additional param that controls it since
243 * we may store a blob value in pieces.
249 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
253 make_room_in_stream (stream, stream->index + len);
254 memset (stream->data + stream->index, 0, len);
256 stream->index += len;
261 stream_data_align (MonoDynamicStream *stream)
264 guint32 count = stream->index % 4;
266 /* we assume the stream data will be aligned */
268 mono_image_add_stream_data (stream, buf, 4 - count);
272 mono_blob_entry_hash (const char* str)
276 len = mono_metadata_decode_blob_size (str, &str);
280 for (str += 1; str < end; str++)
281 h = (h << 5) - h + *str;
289 mono_blob_entry_equal (const char *str1, const char *str2) {
293 len = mono_metadata_decode_blob_size (str1, &end1);
294 len2 = mono_metadata_decode_blob_size (str2, &end2);
297 return memcmp (end1, end2, len) == 0;
301 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
305 gpointer oldkey, oldval;
307 copy = g_malloc (s1+s2);
308 memcpy (copy, b1, s1);
309 memcpy (copy + s1, b2, s2);
310 if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
312 idx = GPOINTER_TO_UINT (oldval);
314 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
315 mono_image_add_stream_data (&assembly->blob, b2, s2);
316 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
322 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
323 * dest may be misaligned.
326 swap_with_size (char *dest, const char* val, int len, int nelem) {
327 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
330 for (elem = 0; elem < nelem; ++elem) {
356 g_assert_not_reached ();
362 memcpy (dest, val, len * nelem);
367 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
371 guint32 idx = 0, len;
373 len = str->length * 2;
374 mono_metadata_encode_value (len, b, &b);
375 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
377 char *swapped = g_malloc (2 * mono_string_length (str));
378 const char *p = (const char*)mono_string_chars (str);
380 swap_with_size (swapped, p, 2, mono_string_length (str));
381 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
385 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
390 /* modified version needed to handle building corlib */
392 my_mono_class_from_mono_type (MonoType *type) {
393 switch (type->type) {
394 case MONO_TYPE_ARRAY:
396 case MONO_TYPE_SZARRAY:
397 case MONO_TYPE_GENERICINST:
398 return mono_class_from_mono_type (type);
401 g_assert (type->data.generic_param->pklass);
402 return type->data.generic_param->pklass;
404 /* should be always valid when we reach this case... */
405 return type->data.klass;
410 default_class_from_mono_type (MonoType *type)
412 switch (type->type) {
413 case MONO_TYPE_OBJECT:
414 return mono_defaults.object_class;
416 return mono_defaults.void_class;
417 case MONO_TYPE_BOOLEAN:
418 return mono_defaults.boolean_class;
420 return mono_defaults.char_class;
422 return mono_defaults.sbyte_class;
424 return mono_defaults.byte_class;
426 return mono_defaults.int16_class;
428 return mono_defaults.uint16_class;
430 return mono_defaults.int32_class;
432 return mono_defaults.uint32_class;
434 return mono_defaults.int_class;
436 return mono_defaults.uint_class;
438 return mono_defaults.int64_class;
440 return mono_defaults.uint64_class;
442 return mono_defaults.single_class;
444 return mono_defaults.double_class;
445 case MONO_TYPE_STRING:
446 return mono_defaults.string_class;
448 g_warning ("implement me 0x%02x\n", type->type);
449 g_assert_not_reached ();
456 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
461 g_assert_not_reached ();
465 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
466 encode_type (assembly, ginst->generic_type, p, &p);
467 mono_metadata_encode_value (ginst->type_argc, p, &p);
468 for (i = 0; i < ginst->type_argc; ++i)
469 encode_type (assembly, ginst->type_argv [i], p, &p);
475 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
478 g_assert_not_reached ();
483 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
487 case MONO_TYPE_BOOLEAN:
501 case MONO_TYPE_STRING:
502 case MONO_TYPE_OBJECT:
503 case MONO_TYPE_TYPEDBYREF:
504 mono_metadata_encode_value (type->type, p, &p);
507 mono_metadata_encode_value (type->type, p, &p);
508 encode_type (assembly, type->data.type, p, &p);
510 case MONO_TYPE_SZARRAY:
511 mono_metadata_encode_value (type->type, p, &p);
512 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
514 case MONO_TYPE_VALUETYPE:
515 case MONO_TYPE_CLASS: {
516 MonoClass *k = mono_class_from_mono_type (type);
517 mono_metadata_encode_value (type->type, p, &p);
519 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
520 * otherwise two typerefs could point to the same type, leading to
521 * verification errors.
523 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
526 case MONO_TYPE_ARRAY:
527 mono_metadata_encode_value (type->type, p, &p);
528 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
529 mono_metadata_encode_value (type->data.array->rank, p, &p);
530 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
531 mono_metadata_encode_value (0, p, &p);
533 case MONO_TYPE_GENERICINST:
534 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
538 mono_metadata_encode_value (type->type, p, &p);
539 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
542 g_error ("need to encode type %x", type->type);
548 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
551 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
555 encode_type (assembly, type->type, p, endbuf);
559 g_assert_not_reached ();
564 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
569 for (i = 0; i < mono_array_length (modreq); ++i) {
570 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
571 *p = MONO_TYPE_CMOD_REQD;
573 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
577 for (i = 0; i < mono_array_length (modopt); ++i) {
578 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
579 *p = MONO_TYPE_CMOD_OPT;
581 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
588 generic_inst_get_signature_size (MonoGenericInst *ginst)
594 g_assert_not_reached ();
597 size += 1 + type_get_signature_size (ginst->generic_type);
599 for (i = 0; i < ginst->type_argc; ++i)
600 size += type_get_signature_size (ginst->type_argv [i]);
606 type_get_signature_size (MonoType *type)
611 g_assert_not_reached ();
619 case MONO_TYPE_BOOLEAN:
633 case MONO_TYPE_STRING:
634 case MONO_TYPE_OBJECT:
635 case MONO_TYPE_TYPEDBYREF:
638 return size + 1 + type_get_signature_size (type->data.type);
639 case MONO_TYPE_SZARRAY:
640 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
641 case MONO_TYPE_VALUETYPE:
642 case MONO_TYPE_CLASS:
644 case MONO_TYPE_ARRAY:
645 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
646 case MONO_TYPE_GENERICINST:
647 return size + generic_inst_get_signature_size (type->data.generic_inst);
652 g_error ("need to encode type %x", type->type);
658 method_get_signature_size (MonoMethodSignature *sig)
663 size = type_get_signature_size (sig->ret);
664 for (i = 0; i < sig->param_count; i++)
665 size += type_get_signature_size (sig->params [i]);
667 if (sig->generic_param_count)
669 if (sig->sentinelpos >= 0)
676 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
681 guint32 nparams = sig->param_count;
682 guint32 size = 11 + method_get_signature_size (sig);
690 p = buf = g_malloc (size);
692 * FIXME: vararg, explicit_this, differenc call_conv values...
694 *p = sig->call_convention;
696 *p |= 0x20; /* hasthis */
697 if (sig->generic_param_count)
698 *p |= 0x10; /* generic */
700 if (sig->generic_param_count)
701 mono_metadata_encode_value (sig->generic_param_count, p, &p);
702 mono_metadata_encode_value (nparams, p, &p);
703 encode_type (assembly, sig->ret, p, &p);
704 for (i = 0; i < nparams; ++i) {
705 if (i == sig->sentinelpos)
706 *p++ = MONO_TYPE_SENTINEL;
707 encode_type (assembly, sig->params [i], p, &p);
710 g_assert (p - buf < size);
711 mono_metadata_encode_value (p-buf, b, &b);
712 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
718 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
721 * FIXME: reuse code from method_encode_signature().
726 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
727 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
728 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
729 guint32 size = 21 + nparams * 20 + notypes * 20;
734 p = buf = g_malloc (size);
735 /* LAMESPEC: all the call conv spec is foobared */
736 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
737 if (mb->call_conv & 2)
738 *p |= 0x5; /* vararg */
739 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
740 *p |= 0x20; /* hasthis */
742 *p |= 0x10; /* generic */
745 mono_metadata_encode_value (ngparams, p, &p);
746 mono_metadata_encode_value (nparams + notypes, p, &p);
747 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
748 encode_reflection_type (assembly, mb->rtype, p, &p);
749 for (i = 0; i < nparams; ++i) {
750 MonoArray *modreq = NULL;
751 MonoArray *modopt = NULL;
752 MonoReflectionType *pt;
754 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
755 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
756 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
757 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
758 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
759 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
760 encode_reflection_type (assembly, pt, p, &p);
763 *p++ = MONO_TYPE_SENTINEL;
764 for (i = 0; i < notypes; ++i) {
765 MonoReflectionType *pt;
767 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
768 encode_reflection_type (assembly, pt, p, &p);
772 g_assert (p - buf < size);
773 mono_metadata_encode_value (p-buf, b, &b);
774 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
780 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
782 MonoDynamicTable *table;
785 guint32 idx, sig_idx, size;
786 guint nl = mono_array_length (ilgen->locals);
793 p = buf = g_malloc (size);
794 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
795 idx = table->next_idx ++;
797 alloc_table (table, table->rows);
798 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
800 mono_metadata_encode_value (0x07, p, &p);
801 mono_metadata_encode_value (nl, p, &p);
802 for (i = 0; i < nl; ++i) {
803 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
806 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
808 encode_reflection_type (assembly, lb->type, p, &p);
810 g_assert (p - buf < size);
811 mono_metadata_encode_value (p-buf, b, &b);
812 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
815 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
821 method_count_clauses (MonoReflectionILGen *ilgen)
823 guint32 num_clauses = 0;
826 MonoILExceptionInfo *ex_info;
827 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
828 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
829 if (ex_info->handlers)
830 num_clauses += mono_array_length (ex_info->handlers);
838 static MonoExceptionClause*
839 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
841 MonoExceptionClause *clauses;
842 MonoExceptionClause *clause;
843 MonoILExceptionInfo *ex_info;
844 MonoILExceptionBlock *ex_block;
845 guint32 finally_start;
846 int i, j, clause_index;;
848 clauses = g_new0 (MonoExceptionClause, num_clauses);
851 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
852 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
853 finally_start = ex_info->start + ex_info->len;
854 g_assert (ex_info->handlers);
855 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
856 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
857 clause = &(clauses [clause_index]);
859 clause->flags = ex_block->type;
860 clause->try_offset = ex_info->start;
862 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
863 clause->try_len = finally_start - ex_info->start;
865 clause->try_len = ex_info->len;
866 clause->handler_offset = ex_block->start;
867 clause->handler_len = ex_block->len;
868 if (ex_block->extype) {
869 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
871 /* FIXME: handle filters */
872 clause->data.filter_offset = 0;
874 finally_start = ex_block->start + ex_block->len;
884 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
890 gint32 num_locals = 0;
891 gint32 num_exception = 0;
894 char fat_header [12];
897 guint32 local_sig = 0;
898 guint32 header_size = 12;
901 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
902 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
906 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
908 code = mb->ilgen->code;
909 code_size = mb->ilgen->code_len;
910 max_stack = mb->ilgen->max_stack;
911 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
912 if (mb->ilgen->ex_handlers)
913 num_exception = method_count_clauses (mb->ilgen);
917 char *name = mono_string_to_utf8 (mb->name);
918 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
919 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
922 mono_raise_exception (exception);
925 code_size = mono_array_length (code);
926 max_stack = 8; /* we probably need to run a verifier on the code... */
929 stream_data_align (&assembly->code);
931 /* check for exceptions, maxstack, locals */
932 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
934 if (code_size < 64 && !(code_size & 1)) {
935 flags = (code_size << 2) | 0x2;
936 } else if (code_size < 32 && (code_size & 1)) {
937 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
941 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
942 /* add to the fixup todo list */
943 if (mb->ilgen && mb->ilgen->num_token_fixups)
944 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
945 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
946 return assembly->text_rva + idx;
950 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
952 * FIXME: need to set also the header size in fat_flags.
953 * (and more sects and init locals flags)
957 fat_flags |= METHOD_HEADER_MORE_SECTS;
959 fat_flags |= METHOD_HEADER_INIT_LOCALS;
960 fat_header [0] = fat_flags;
961 fat_header [1] = (header_size / 4 ) << 4;
962 shortp = (guint16*)(fat_header + 2);
963 *shortp = GUINT16_TO_LE (max_stack);
964 intp = (guint32*)(fat_header + 4);
965 *intp = GUINT32_TO_LE (code_size);
966 intp = (guint32*)(fat_header + 8);
967 *intp = GUINT32_TO_LE (local_sig);
968 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
969 /* add to the fixup todo list */
970 if (mb->ilgen && mb->ilgen->num_token_fixups)
971 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
973 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
975 unsigned char sheader [4];
976 MonoILExceptionInfo * ex_info;
977 MonoILExceptionBlock * ex_block;
980 stream_data_align (&assembly->code);
981 /* always use fat format for now */
982 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
983 num_exception *= 6 * sizeof (guint32);
984 num_exception += 4; /* include the size of the header */
985 sheader [1] = num_exception & 0xff;
986 sheader [2] = (num_exception >> 8) & 0xff;
987 sheader [3] = (num_exception >> 16) & 0xff;
988 mono_image_add_stream_data (&assembly->code, sheader, 4);
989 /* fat header, so we are already aligned */
991 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
992 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
993 if (ex_info->handlers) {
994 int finally_start = ex_info->start + ex_info->len;
995 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
997 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
999 val = GUINT32_TO_LE (ex_block->type);
1000 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1002 val = GUINT32_TO_LE (ex_info->start);
1003 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1004 /* need fault, too, probably */
1005 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1006 val = GUINT32_TO_LE (finally_start - ex_info->start);
1008 val = GUINT32_TO_LE (ex_info->len);
1009 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1010 /* handler offset */
1011 val = GUINT32_TO_LE (ex_block->start);
1012 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1014 val = GUINT32_TO_LE (ex_block->len);
1015 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1016 finally_start = ex_block->start + ex_block->len;
1017 if (ex_block->extype) {
1018 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1020 /* FIXME: handle filters */
1023 val = GUINT32_TO_LE (val);
1024 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1025 /*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",
1026 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);*/
1029 g_error ("No clauses for ex info block %d", i);
1033 return assembly->text_rva + idx;
1037 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1040 MonoDynamicTable *table;
1043 table = &assembly->tables [table_idx];
1045 g_assert (col < table->columns);
1047 values = table->values + table->columns;
1048 for (i = 1; i <= table->rows; ++i) {
1049 if (values [col] == token)
1051 values += table->columns;
1056 static GHashTable *dynamic_custom_attrs = NULL;
1058 static MonoCustomAttrInfo*
1059 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1062 MonoCustomAttrInfo *ainfo;
1063 MonoReflectionCustomAttr *cattr;
1067 /* FIXME: check in assembly the Run flag is set */
1069 count = mono_array_length (cattrs);
1071 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1073 ainfo->image = image;
1074 ainfo->num_attrs = count;
1075 for (i = 0; i < count; ++i) {
1076 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1077 ainfo->attrs [i].ctor = cattr->ctor->method;
1078 /* FIXME: might want to memdup the data here */
1079 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1080 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1087 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1089 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1094 if (!dynamic_custom_attrs)
1095 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1097 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1098 ainfo->cached = TRUE;
1102 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1104 /* they are cached, so we don't free them */
1105 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1111 * idx is the table index of the object
1112 * type is one of MONO_CUSTOM_ATTR_*
1115 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1117 MonoDynamicTable *table;
1118 MonoReflectionCustomAttr *cattr;
1120 guint32 count, i, token;
1122 char *p = blob_size;
1124 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1127 count = mono_array_length (cattrs);
1128 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1129 table->rows += count;
1130 alloc_table (table, table->rows);
1131 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1132 idx <<= MONO_CUSTOM_ATTR_BITS;
1134 for (i = 0; i < count; ++i) {
1135 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1136 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1137 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1138 type = mono_metadata_token_index (token);
1139 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1140 switch (mono_metadata_token_table (token)) {
1141 case MONO_TABLE_METHOD:
1142 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1144 case MONO_TABLE_MEMBERREF:
1145 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1148 g_warning ("got wrong token in custom attr");
1151 values [MONO_CUSTOM_ATTR_TYPE] = type;
1153 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1154 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1155 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1156 values += MONO_CUSTOM_ATTR_SIZE;
1162 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1164 MonoDynamicTable *table;
1166 guint32 count, i, idx;
1167 MonoReflectionPermissionSet *perm;
1172 count = mono_array_length (permissions);
1173 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1174 table->rows += count;
1175 alloc_table (table, table->rows);
1177 for (i = 0; i < mono_array_length (permissions); ++i) {
1178 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1180 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1182 idx = mono_metadata_token_index (parent_token);
1183 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1184 switch (mono_metadata_token_table (parent_token)) {
1185 case MONO_TABLE_TYPEDEF:
1186 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1188 case MONO_TABLE_METHOD:
1189 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1191 case MONO_TABLE_ASSEMBLY:
1192 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1195 g_assert_not_reached ();
1198 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1199 values [MONO_DECL_SECURITY_PARENT] = idx;
1200 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1207 * Fill in the MethodDef and ParamDef tables for a method.
1208 * This is used for both normal methods and constructors.
1211 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1213 MonoDynamicTable *table;
1218 /* room in this table is already allocated */
1219 table = &assembly->tables [MONO_TABLE_METHOD];
1220 *mb->table_idx = table->next_idx ++;
1221 mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1222 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1223 name = mono_string_to_utf8 (mb->name);
1224 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1226 values [MONO_METHOD_FLAGS] = mb->attrs;
1227 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1228 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1229 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1231 table = &assembly->tables [MONO_TABLE_PARAM];
1232 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1234 mono_image_add_decl_security (assembly,
1235 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1238 MonoDynamicTable *mtable;
1241 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1242 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1245 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1246 if (mono_array_get (mb->pinfo, gpointer, i))
1249 table->rows += count;
1250 alloc_table (table, table->rows);
1251 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1252 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1253 MonoReflectionParamBuilder *pb;
1254 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1255 values [MONO_PARAM_FLAGS] = pb->attrs;
1256 values [MONO_PARAM_SEQUENCE] = i;
1257 if (pb->name != NULL) {
1258 name = mono_string_to_utf8 (pb->name);
1259 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1262 values [MONO_PARAM_NAME] = 0;
1264 values += MONO_PARAM_SIZE;
1265 if (pb->marshal_info) {
1267 alloc_table (mtable, mtable->rows);
1268 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1269 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1270 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1272 pb->table_idx = table->next_idx++;
1273 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1274 guint32 field_type = 0;
1275 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1277 alloc_table (mtable, mtable->rows);
1278 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1279 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1280 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1281 mvalues [MONO_CONSTANT_TYPE] = field_type;
1282 mvalues [MONO_CONSTANT_PADDING] = 0;
1290 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1292 rmb->ilgen = mb->ilgen;
1293 rmb->rtype = mb->rtype;
1294 rmb->parameters = mb->parameters;
1295 rmb->generic_params = mb->generic_params;
1296 rmb->opt_types = NULL;
1297 rmb->pinfo = mb->pinfo;
1298 rmb->attrs = mb->attrs;
1299 rmb->iattrs = mb->iattrs;
1300 rmb->call_conv = mb->call_conv;
1301 rmb->code = mb->code;
1302 rmb->type = mb->type;
1303 rmb->name = mb->name;
1304 rmb->table_idx = &mb->table_idx;
1305 rmb->init_locals = mb->init_locals;
1306 rmb->return_modreq = mb->return_modreq;
1307 rmb->return_modopt = mb->return_modopt;
1308 rmb->param_modreq = mb->param_modreq;
1309 rmb->param_modopt = mb->param_modopt;
1310 rmb->permissions = mb->permissions;
1311 rmb->mhandle = mb->mhandle;
1316 rmb->charset = rmb->charset & 0xf;
1317 rmb->lasterr = rmb->charset & 0x40;
1318 rmb->native_cc = rmb->native_cc;
1319 rmb->dllentry = mb->dllentry;
1325 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1327 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1329 rmb->ilgen = mb->ilgen;
1330 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1331 rmb->parameters = mb->parameters;
1332 rmb->generic_params = NULL;
1333 rmb->opt_types = NULL;
1334 rmb->pinfo = mb->pinfo;
1335 rmb->attrs = mb->attrs;
1336 rmb->iattrs = mb->iattrs;
1337 rmb->call_conv = mb->call_conv;
1339 rmb->type = mb->type;
1340 rmb->name = mono_string_new (mono_domain_get (), name);
1341 rmb->table_idx = &mb->table_idx;
1342 rmb->init_locals = mb->init_locals;
1343 rmb->return_modreq = NULL;
1344 rmb->return_modopt = NULL;
1345 rmb->param_modreq = mb->param_modreq;
1346 rmb->param_modopt = mb->param_modopt;
1347 rmb->permissions = mb->permissions;
1348 rmb->mhandle = mb->mhandle;
1354 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1356 rmb->ilgen = mb->ilgen;
1357 rmb->rtype = mb->rtype;
1358 rmb->parameters = mb->parameters;
1359 rmb->generic_params = NULL;
1360 rmb->opt_types = NULL;
1362 rmb->attrs = mb->attrs;
1364 rmb->call_conv = mb->call_conv;
1367 rmb->name = mb->name;
1368 rmb->table_idx = NULL;
1369 rmb->init_locals = mb->init_locals;
1370 rmb->return_modreq = NULL;
1371 rmb->return_modopt = NULL;
1372 rmb->param_modreq = NULL;
1373 rmb->param_modopt = NULL;
1374 rmb->permissions = NULL;
1375 rmb->mhandle = mb->mhandle;
1381 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1383 MonoDynamicTable *table;
1386 ReflectionMethodBuilder rmb;
1389 reflection_methodbuilder_from_method_builder (&rmb, mb);
1391 mono_image_basic_method (&rmb, assembly);
1393 if (mb->dll) { /* It's a P/Invoke method */
1395 int charset = mb->charset & 0xf;
1396 int lasterr = mb->charset & 0x40;
1397 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1399 alloc_table (table, table->rows);
1400 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1401 /* map CharSet values to on-disk values */
1403 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1404 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1405 name = mono_string_to_utf8 (mb->dllentry);
1406 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1408 name = mono_string_to_utf8 (mb->dll);
1409 moduleref = string_heap_insert (&assembly->sheap, name);
1411 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1412 table = &assembly->tables [MONO_TABLE_MODULEREF];
1414 alloc_table (table, table->rows);
1415 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1416 values [MONO_IMPLMAP_SCOPE] = table->rows;
1420 if (mb->override_method) {
1421 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1423 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1425 alloc_table (table, table->rows);
1426 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1427 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1428 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1430 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1431 switch (mono_metadata_token_table (tok)) {
1432 case MONO_TABLE_MEMBERREF:
1433 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1435 case MONO_TABLE_METHOD:
1436 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1439 g_assert_not_reached ();
1441 values [MONO_METHODIMPL_DECLARATION] = tok;
1444 if (mb->generic_params) {
1445 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1446 table->rows += mono_array_length (mb->generic_params);
1447 alloc_table (table, table->rows);
1448 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1449 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1451 mono_image_get_generic_param_info (
1452 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1459 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1461 ReflectionMethodBuilder rmb;
1463 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1465 mono_image_basic_method (&rmb, assembly);
1469 type_get_fully_qualified_name (MonoType *type) {
1470 char *name, *result;
1474 name = mono_type_get_name (type);
1475 klass = my_mono_class_from_mono_type (type);
1476 ta = klass->image->assembly;
1478 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1479 name, ta->aname.name,
1480 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1481 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1482 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1488 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1492 klass = my_mono_class_from_mono_type (type);
1494 return mono_type_get_name (type);
1495 ta = klass->image->assembly;
1496 if (ta == ass || klass->image == mono_defaults.corlib)
1497 return mono_type_get_name (type);
1499 return type_get_fully_qualified_name (type);
1503 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1505 char blob_size [64];
1506 char *b = blob_size;
1511 if (!assembly->save)
1514 p = buf = g_malloc (64);
1516 mono_metadata_encode_value (0x06, p, &p);
1517 /* encode custom attributes before the type */
1518 encode_type (assembly, type, p, &p);
1519 g_assert (p-buf < 64);
1520 mono_metadata_encode_value (p-buf, b, &b);
1521 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1527 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1529 char blob_size [64];
1530 char *b = blob_size;
1535 p = buf = g_malloc (64);
1537 mono_metadata_encode_value (0x06, p, &p);
1538 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1539 /* encode custom attributes before the type */
1540 encode_reflection_type (assembly, fb->type, p, &p);
1541 g_assert (p-buf < 64);
1542 mono_metadata_encode_value (p-buf, b, &b);
1543 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1549 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1550 char blob_size [64];
1551 char *b = blob_size;
1554 guint32 idx = 0, len = 0, dummy = 0;
1556 p = buf = g_malloc (64);
1558 *ret_type = MONO_TYPE_CLASS;
1560 box_val = (char*)&dummy;
1562 box_val = ((char*)val) + sizeof (MonoObject);
1563 *ret_type = val->vtable->klass->byval_arg.type;
1566 switch (*ret_type) {
1567 case MONO_TYPE_BOOLEAN:
1572 case MONO_TYPE_CHAR:
1587 case MONO_TYPE_VALUETYPE:
1588 if (val->vtable->klass->enumtype) {
1589 *ret_type = val->vtable->klass->enum_basetype->type;
1592 g_error ("we can't encode valuetypes");
1593 case MONO_TYPE_CLASS:
1595 case MONO_TYPE_STRING: {
1596 MonoString *str = (MonoString*)val;
1597 /* there is no signature */
1598 len = str->length * 2;
1599 mono_metadata_encode_value (len, b, &b);
1600 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1602 char *swapped = g_malloc (2 * mono_string_length (str));
1603 const char *p = (const char*)mono_string_chars (str);
1605 swap_with_size (swapped, p, 2, mono_string_length (str));
1606 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1610 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1617 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1620 /* there is no signature */
1621 mono_metadata_encode_value (len, b, &b);
1622 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1623 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1624 swap_with_size (blob_size, box_val, len, 1);
1625 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1627 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1635 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1636 char blob_size [64];
1637 char *b = blob_size;
1638 char *p, *buf, *str;
1639 guint32 idx, len, bufsize = 256;
1641 p = buf = g_malloc (bufsize);
1643 switch (minfo->type) {
1644 case MONO_NATIVE_BYVALTSTR:
1645 case MONO_NATIVE_BYVALARRAY:
1646 mono_metadata_encode_value (minfo->type, p, &p);
1647 mono_metadata_encode_value (minfo->count, p, &p);
1649 case MONO_NATIVE_LPARRAY:
1650 mono_metadata_encode_value (minfo->type, p, &p);
1651 if (minfo->eltype || (minfo->count > 0)) {
1652 mono_metadata_encode_value (minfo->eltype, p, &p);
1653 if (minfo->count > 0) {
1654 mono_metadata_encode_value (0, p, &p);
1655 mono_metadata_encode_value (minfo->count, p, &p);
1659 case MONO_NATIVE_CUSTOM:
1660 mono_metadata_encode_value (minfo->type, p, &p);
1662 str = mono_string_to_utf8 (minfo->guid);
1664 mono_metadata_encode_value (len, p, &p);
1665 memcpy (p, str, len);
1669 mono_metadata_encode_value (0, p, &p);
1671 if (minfo->marshaltype) {
1672 str = mono_string_to_utf8 (minfo->marshaltype);
1674 mono_metadata_encode_value (len, p, &p);
1675 if (p + len >= buf + bufsize) {
1678 buf = g_realloc (buf, bufsize);
1681 memcpy (p, str, len);
1685 mono_metadata_encode_value (0, p, &p);
1687 if (minfo->marshaltyperef) {
1688 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1690 mono_metadata_encode_value (len, p, &p);
1691 if (p + len >= buf + bufsize) {
1694 buf = g_realloc (buf, bufsize);
1697 memcpy (p, str, len);
1701 mono_metadata_encode_value (0, p, &p);
1703 if (minfo->mcookie) {
1704 str = mono_string_to_utf8 (minfo->mcookie);
1706 mono_metadata_encode_value (len, p, &p);
1707 if (p + len >= buf + bufsize) {
1710 buf = g_realloc (buf, bufsize);
1713 memcpy (p, str, len);
1717 mono_metadata_encode_value (0, p, &p);
1721 mono_metadata_encode_value (minfo->type, p, &p);
1725 mono_metadata_encode_value (len, b, &b);
1726 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1732 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1734 MonoDynamicTable *table;
1738 /* maybe this fixup should be done in the C# code */
1739 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1740 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1741 table = &assembly->tables [MONO_TABLE_FIELD];
1742 fb->table_idx = table->next_idx ++;
1743 mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1744 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1745 name = mono_string_to_utf8 (fb->name);
1746 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1748 values [MONO_FIELD_FLAGS] = fb->attrs;
1749 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1751 if (fb->offset != -1) {
1752 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1754 alloc_table (table, table->rows);
1755 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1756 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1757 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1759 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1760 guint32 field_type = 0;
1761 table = &assembly->tables [MONO_TABLE_CONSTANT];
1763 alloc_table (table, table->rows);
1764 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1765 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1766 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1767 values [MONO_CONSTANT_TYPE] = field_type;
1768 values [MONO_CONSTANT_PADDING] = 0;
1770 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1772 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1774 alloc_table (table, table->rows);
1775 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1776 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1778 * We store it in the code section because it's simpler for now.
1781 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1783 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1784 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1786 if (fb->marshal_info) {
1787 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1789 alloc_table (table, table->rows);
1790 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1791 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1792 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1797 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1801 char *b = blob_size;
1802 guint32 nparams = 0;
1803 MonoReflectionMethodBuilder *mb = fb->get_method;
1804 MonoReflectionMethodBuilder *smb = fb->set_method;
1805 guint32 idx, i, size;
1807 if (mb && mb->parameters)
1808 nparams = mono_array_length (mb->parameters);
1809 if (!mb && smb && smb->parameters)
1810 nparams = mono_array_length (smb->parameters) - 1;
1811 size = 24 + nparams * 10;
1812 buf = p = g_malloc (size);
1815 mono_metadata_encode_value (nparams, p, &p);
1817 encode_reflection_type (assembly, mb->rtype, p, &p);
1818 for (i = 0; i < nparams; ++i) {
1819 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1820 encode_reflection_type (assembly, pt, p, &p);
1823 /* the property type is the last param */
1824 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1825 for (i = 0; i < nparams; ++i) {
1826 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1827 encode_reflection_type (assembly, pt, p, &p);
1831 g_assert (p - buf < size);
1832 mono_metadata_encode_value (p-buf, b, &b);
1833 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1839 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1841 MonoDynamicTable *table;
1844 guint num_methods = 0;
1848 * we need to set things in the following tables:
1849 * PROPERTYMAP (info already filled in _get_type_info ())
1850 * PROPERTY (rows already preallocated in _get_type_info ())
1851 * METHOD (method info already done with the generic method code)
1854 table = &assembly->tables [MONO_TABLE_PROPERTY];
1855 pb->table_idx = table->next_idx ++;
1856 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1857 name = mono_string_to_utf8 (pb->name);
1858 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1860 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1861 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1863 /* FIXME: we still don't handle 'other' methods */
1864 if (pb->get_method) num_methods ++;
1865 if (pb->set_method) num_methods ++;
1867 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1868 table->rows += num_methods;
1869 alloc_table (table, table->rows);
1871 if (pb->get_method) {
1872 semaidx = table->next_idx ++;
1873 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1874 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1875 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1876 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1878 if (pb->set_method) {
1879 semaidx = table->next_idx ++;
1880 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1881 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1882 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1883 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1888 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1890 MonoDynamicTable *table;
1893 guint num_methods = 0;
1897 * we need to set things in the following tables:
1898 * EVENTMAP (info already filled in _get_type_info ())
1899 * EVENT (rows already preallocated in _get_type_info ())
1900 * METHOD (method info already done with the generic method code)
1903 table = &assembly->tables [MONO_TABLE_EVENT];
1904 eb->table_idx = table->next_idx ++;
1905 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1906 name = mono_string_to_utf8 (eb->name);
1907 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1909 values [MONO_EVENT_FLAGS] = eb->attrs;
1910 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1913 * FIXME: we still don't handle 'other' methods
1915 if (eb->add_method) num_methods ++;
1916 if (eb->remove_method) num_methods ++;
1917 if (eb->raise_method) num_methods ++;
1919 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1920 table->rows += num_methods;
1921 alloc_table (table, table->rows);
1923 if (eb->add_method) {
1924 semaidx = table->next_idx ++;
1925 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1926 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1927 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1928 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1930 if (eb->remove_method) {
1931 semaidx = table->next_idx ++;
1932 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1933 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1934 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1935 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1937 if (eb->raise_method) {
1938 semaidx = table->next_idx ++;
1939 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1940 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1941 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1942 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1947 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1949 static MonoClass *NewConstraintAttr;
1950 static MonoMethod *NewConstraintAttr_ctor;
1951 MonoDynamicTable *table;
1953 guint32 token, type;
1954 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1957 if (!NewConstraintAttr)
1958 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1959 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1960 g_assert (NewConstraintAttr);
1962 if (!NewConstraintAttr_ctor) {
1965 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1966 MonoMethod *m = NewConstraintAttr->methods [i];
1968 if (strcmp (m->name, ".ctor"))
1971 NewConstraintAttr_ctor = m;
1975 g_assert (NewConstraintAttr_ctor);
1978 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1980 alloc_table (table, table->rows);
1982 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1983 owner <<= MONO_CUSTOM_ATTR_BITS;
1984 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1985 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1987 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1989 type = mono_metadata_token_index (token);
1990 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1991 switch (mono_metadata_token_table (token)) {
1992 case MONO_TABLE_METHOD:
1993 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1995 case MONO_TABLE_MEMBERREF:
1996 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1999 g_warning ("got wrong token in custom attr");
2002 values [MONO_CUSTOM_ATTR_TYPE] = type;
2004 buf = p = g_malloc (1);
2005 mono_metadata_encode_value (4, p, &p);
2006 g_assert (p-buf == 1);
2008 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2010 values += MONO_CUSTOM_ATTR_SIZE;
2015 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2017 MonoDynamicTable *table;
2018 guint32 num_constraints, i;
2022 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2023 num_constraints = gparam->iface_constraints ?
2024 mono_array_length (gparam->iface_constraints) : 0;
2025 table->rows += num_constraints;
2026 if (gparam->base_type)
2028 alloc_table (table, table->rows);
2030 if (gparam->base_type) {
2031 table_idx = table->next_idx ++;
2032 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2034 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2035 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2036 assembly, gparam->base_type->type);
2039 for (i = 0; i < num_constraints; i++) {
2040 MonoReflectionType *constraint = mono_array_get (
2041 gparam->iface_constraints, gpointer, i);
2043 table_idx = table->next_idx ++;
2044 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2046 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2047 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2048 assembly, constraint->type);
2051 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2052 encode_new_constraint (assembly, owner);
2056 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2058 GenericParamTableEntry *entry;
2061 * The GenericParam table must be sorted according to the `owner' field.
2062 * We need to do this sorting prior to writing the GenericParamConstraint
2063 * table, since we have to use the final GenericParam table indices there
2064 * and they must also be sorted.
2067 entry = g_new0 (GenericParamTableEntry, 1);
2068 entry->owner = owner;
2069 entry->gparam = gparam;
2071 g_ptr_array_add (assembly->gen_params, entry);
2075 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2077 MonoDynamicTable *table;
2078 MonoGenericParam *param;
2082 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2083 table_idx = table->next_idx ++;
2084 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2086 param = entry->gparam->type.type->data.generic_param;
2088 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2089 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2090 values [MONO_GENERICPARAM_NUMBER] = param->num;
2091 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2092 values [MONO_GENERICPARAM_KIND] = 0;
2094 encode_constraints (entry->gparam, table_idx, assembly);
2098 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2100 MonoDynamicTable *table;
2103 guint32 cols [MONO_ASSEMBLY_SIZE];
2107 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2110 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2111 table = &assembly->tables [MONO_TABLE_MODULEREF];
2112 token = table->next_idx ++;
2114 alloc_table (table, table->rows);
2115 values = table->values + token * MONO_MODULEREF_SIZE;
2116 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2118 token <<= MONO_RESOLTION_SCOPE_BITS;
2119 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2120 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2125 if (image->assembly->dynamic)
2127 memset (cols, 0, sizeof (cols));
2129 /* image->assembly->image is the manifest module */
2130 image = image->assembly->image;
2131 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2134 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2135 token = table->next_idx ++;
2137 alloc_table (table, table->rows);
2138 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2139 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2140 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2141 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2142 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2143 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2144 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2145 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2146 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2148 if (strcmp ("", image->assembly->aname.culture)) {
2149 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2150 image->assembly->aname.culture);
2153 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2154 guchar pubtoken [9];
2156 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2157 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2159 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2161 token <<= MONO_RESOLTION_SCOPE_BITS;
2162 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2163 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2168 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2170 MonoDynamicTable *table;
2176 char *b = blob_size;
2178 switch (type->type) {
2179 case MONO_TYPE_FNPTR:
2181 case MONO_TYPE_SZARRAY:
2182 case MONO_TYPE_ARRAY:
2184 case MONO_TYPE_MVAR:
2185 case MONO_TYPE_GENERICINST:
2186 encode_type (assembly, type, p, &p);
2188 case MONO_TYPE_CLASS:
2189 case MONO_TYPE_VALUETYPE: {
2190 MonoClass *k = mono_class_from_mono_type (type);
2191 if (!k || !k->generic_inst)
2193 encode_generic_inst (assembly, k->generic_inst, p, &p);
2200 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2201 if (assembly->save) {
2202 g_assert (p-sig < 128);
2203 mono_metadata_encode_value (p-sig, b, &b);
2204 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2205 alloc_table (table, table->rows + 1);
2206 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2207 values [MONO_TYPESPEC_SIGNATURE] = token;
2210 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2211 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2217 * Despite the name, we handle also TypeSpec (with the above helper).
2220 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2222 MonoDynamicTable *table;
2224 guint32 token, scope, enclosing;
2227 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2230 token = create_typespec (assembly, type);
2233 klass = my_mono_class_from_mono_type (type);
2235 klass = mono_class_from_mono_type (type);
2238 * If it's in the same module and not a generic type parameter:
2240 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2241 (type->type != MONO_TYPE_MVAR)) {
2242 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2243 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2244 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2248 if (klass->nested_in) {
2249 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2250 /* get the typeref idx of the enclosing type */
2251 enclosing >>= MONO_TYPEDEFORREF_BITS;
2252 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2254 scope = resolution_scope_from_image (assembly, klass->image);
2256 table = &assembly->tables [MONO_TABLE_TYPEREF];
2257 if (assembly->save) {
2258 alloc_table (table, table->rows + 1);
2259 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2260 values [MONO_TYPEREF_SCOPE] = scope;
2261 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2262 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2264 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2265 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2267 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2272 * Insert a memberef row into the metadata: the token that point to the memberref
2273 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2274 * mono_image_get_fieldref_token()).
2275 * The sig param is an index to an already built signature.
2278 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2280 MonoDynamicTable *table;
2282 guint32 token, pclass;
2285 parent = mono_image_typedef_or_ref (assembly, type);
2286 switch (parent & MONO_TYPEDEFORREF_MASK) {
2287 case MONO_TYPEDEFORREF_TYPEREF:
2288 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2290 case MONO_TYPEDEFORREF_TYPESPEC:
2291 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2293 case MONO_TYPEDEFORREF_TYPEDEF:
2294 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2297 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2300 /* extract the index */
2301 parent >>= MONO_TYPEDEFORREF_BITS;
2303 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2305 if (assembly->save) {
2306 alloc_table (table, table->rows + 1);
2307 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2308 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2309 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2310 values [MONO_MEMBERREF_SIGNATURE] = sig;
2313 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2320 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2323 MonoMethodSignature *sig;
2325 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2330 * A methodref signature can't contain an unmanaged calling convention.
2332 sig = mono_metadata_signature_dup (method->signature);
2333 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2334 sig->call_convention = MONO_CALL_DEFAULT;
2335 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2336 method->name, method_encode_signature (assembly, sig));
2338 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2343 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2344 const gchar *name, guint32 sig)
2346 MonoDynamicTable *table;
2350 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2352 if (assembly->save) {
2353 alloc_table (table, table->rows + 1);
2354 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2355 values [MONO_MEMBERREF_CLASS] = original;
2356 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2357 values [MONO_MEMBERREF_SIGNATURE] = sig;
2360 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2367 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2370 ReflectionMethodBuilder rmb;
2372 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2376 reflection_methodbuilder_from_method_builder (&rmb, mb);
2378 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2379 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2380 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2385 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2388 ReflectionMethodBuilder rmb;
2390 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2394 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2396 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2397 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2398 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2403 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2408 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2411 g_assert (f->field->parent);
2412 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2413 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2414 f->field->name, fieldref_encode_signature (assembly, type));
2415 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2420 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2425 guint32 nparams = gmethod->mtype_argc;
2426 guint32 size = 10 + nparams * 10;
2429 char *b = blob_size;
2431 if (!assembly->save)
2434 p = buf = g_malloc (size);
2436 * FIXME: vararg, explicit_this, differenc call_conv values...
2438 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2439 mono_metadata_encode_value (nparams, p, &p);
2441 for (i = 0; i < nparams; i++)
2442 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2445 g_assert (p - buf < size);
2446 mono_metadata_encode_value (p-buf, b, &b);
2447 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2453 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2455 MonoDynamicTable *table;
2457 guint32 token, mtoken = 0, sig;
2458 MonoMethodInflated *imethod;
2459 MonoMethod *declaring;
2461 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2463 g_assert (method->signature->is_inflated);
2464 imethod = (MonoMethodInflated *) method;
2465 declaring = imethod->declaring;
2467 sig = method_encode_signature (assembly, declaring->signature);
2468 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2470 if (!declaring->signature->generic_param_count)
2473 switch (mono_metadata_token_table (mtoken)) {
2474 case MONO_TABLE_MEMBERREF:
2475 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2477 case MONO_TABLE_METHOD:
2478 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2481 g_assert_not_reached ();
2484 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2486 if (assembly->save) {
2487 alloc_table (table, table->rows + 1);
2488 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2489 values [MONO_METHODSPEC_METHOD] = mtoken;
2490 values [MONO_METHODSPEC_SIGNATURE] = sig;
2493 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2500 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2502 MonoMethodInflated *imethod;
2505 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2509 g_assert (m->signature->is_inflated);
2510 imethod = (MonoMethodInflated *) m;
2512 if (imethod->declaring->signature->generic_param_count) {
2513 token = method_encode_methodspec (assembly, m);
2515 guint32 sig = method_encode_signature (
2516 assembly, imethod->declaring->signature);
2517 token = mono_image_get_memberref_token (
2518 assembly, &m->klass->byval_arg, m->name, sig);
2521 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2526 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2528 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2531 sig = method_encode_signature (assembly, imethod->declaring->signature);
2532 token = mono_image_get_memberref_token (
2533 assembly, &m->klass->byval_arg, m->name, sig);
2539 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2541 MonoDynamicTable *table;
2548 char *b = blob_size;
2552 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2553 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2554 * Because of this, we must not insert it into the `typeref' hash table.
2557 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2561 g_assert (tb->generic_params);
2562 klass = mono_class_from_mono_type (tb->type.type);
2564 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2565 encode_type (assembly, &klass->byval_arg, p, &p);
2567 count = mono_array_length (tb->generic_params);
2568 mono_metadata_encode_value (count, p, &p);
2569 for (i = 0; i < count; i++) {
2570 MonoReflectionGenericParam *gparam;
2572 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2574 encode_type (assembly, gparam->type.type, p, &p);
2577 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2578 if (assembly->save) {
2579 g_assert (p-sig < 128);
2580 mono_metadata_encode_value (p-sig, b, &b);
2581 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2582 alloc_table (table, table->rows + 1);
2583 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2584 values [MONO_TYPESPEC_SIGNATURE] = token;
2587 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2588 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2594 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2596 MonoDynamicTable *table;
2599 guint32 token, pclass, parent, sig;
2602 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2606 klass = mono_class_from_mono_type (fb->typeb->type);
2607 name = mono_string_to_utf8 (fb->name);
2609 sig = fieldref_encode_signature (assembly, fb->type->type);
2611 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2612 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2614 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2615 parent >>= MONO_TYPEDEFORREF_BITS;
2617 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2619 if (assembly->save) {
2620 alloc_table (table, table->rows + 1);
2621 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2622 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2623 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2624 values [MONO_MEMBERREF_SIGNATURE] = sig;
2627 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2629 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2634 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2642 char *b = blob_size;
2644 if (!assembly->save)
2648 g_assert (helper->type == 2);
2650 if (helper->arguments)
2651 nargs = mono_array_length (helper->arguments);
2655 size = 10 + (nargs * 10);
2657 p = buf = g_malloc (size);
2659 /* Encode calling convention */
2660 /* Change Any to Standard */
2661 if ((helper->call_conv & 0x03) == 0x03)
2662 helper->call_conv = 0x01;
2663 /* explicit_this implies has_this */
2664 if (helper->call_conv & 0x40)
2665 helper->call_conv &= 0x20;
2667 if (helper->call_conv == 0) { /* Unmanaged */
2668 *p = helper->unmanaged_call_conv - 1;
2671 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2672 if (helper->call_conv & 0x02) /* varargs */
2677 mono_metadata_encode_value (nargs, p, &p);
2678 encode_reflection_type (assembly, helper->return_type, p, &p);
2679 for (i = 0; i < nargs; ++i) {
2680 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2681 encode_reflection_type (assembly, pt, p, &p);
2684 g_assert (p - buf < size);
2685 mono_metadata_encode_value (p-buf, b, &b);
2686 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2693 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2696 MonoDynamicTable *table;
2699 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2700 idx = table->next_idx ++;
2702 alloc_table (table, table->rows);
2703 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2705 values [MONO_STAND_ALONE_SIGNATURE] =
2706 mono_reflection_encode_sighelper (assembly, helper);
2712 reflection_cc_to_file (int call_conv) {
2713 switch (call_conv & 0x3) {
2715 case 1: return MONO_CALL_DEFAULT;
2716 case 2: return MONO_CALL_VARARG;
2718 g_assert_not_reached ();
2725 MonoMethodSignature *sig;
2731 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2736 MonoMethodSignature *sig;
2739 name = mono_string_to_utf8 (m->name);
2740 nparams = mono_array_length (m->parameters);
2741 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2743 sig->sentinelpos = -1;
2744 sig->call_convention = reflection_cc_to_file (m->call_conv);
2745 sig->param_count = nparams;
2746 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2747 for (i = 0; i < nparams; ++i) {
2748 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2749 sig->params [i] = t->type;
2752 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2754 if (strcmp (name, am->name) == 0 &&
2755 mono_metadata_type_equal (am->parent, m->parent->type) &&
2756 mono_metadata_signature_equal (am->sig, sig)) {
2759 m->table_idx = am->token & 0xffffff;
2763 am = g_new0 (ArrayMethod, 1);
2766 am->parent = m->parent->type;
2767 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2768 method_encode_signature (assembly, sig));
2769 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2770 m->table_idx = am->token & 0xffffff;
2775 * Insert into the metadata tables all the info about the TypeBuilder tb.
2776 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2779 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2781 MonoDynamicTable *table;
2783 int i, is_object = 0, is_system = 0;
2786 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2787 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2788 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2789 n = mono_string_to_utf8 (tb->name);
2790 if (strcmp (n, "Object") == 0)
2792 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2794 n = mono_string_to_utf8 (tb->nspace);
2795 if (strcmp (n, "System") == 0)
2797 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2799 if (tb->parent && !(is_system && is_object) &&
2800 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2801 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2803 values [MONO_TYPEDEF_EXTENDS] = 0;
2805 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2806 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2809 * if we have explicitlayout or sequentiallayouts, output data in the
2810 * ClassLayout table.
2812 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2813 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2814 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2816 alloc_table (table, table->rows);
2817 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2818 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2819 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2820 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2823 /* handle interfaces */
2824 if (tb->interfaces) {
2825 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2827 table->rows += mono_array_length (tb->interfaces);
2828 alloc_table (table, table->rows);
2829 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2830 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2831 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2832 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2833 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2834 values += MONO_INTERFACEIMPL_SIZE;
2840 table = &assembly->tables [MONO_TABLE_FIELD];
2841 table->rows += tb->num_fields;
2842 alloc_table (table, table->rows);
2843 for (i = 0; i < tb->num_fields; ++i)
2844 mono_image_get_field_info (
2845 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2848 /* handle constructors */
2850 table = &assembly->tables [MONO_TABLE_METHOD];
2851 table->rows += mono_array_length (tb->ctors);
2852 alloc_table (table, table->rows);
2853 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2854 mono_image_get_ctor_info (domain,
2855 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2858 /* handle methods */
2860 table = &assembly->tables [MONO_TABLE_METHOD];
2861 table->rows += tb->num_methods;
2862 alloc_table (table, table->rows);
2863 for (i = 0; i < tb->num_methods; ++i)
2864 mono_image_get_method_info (
2865 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2868 /* Do the same with properties etc.. */
2869 if (tb->events && mono_array_length (tb->events)) {
2870 table = &assembly->tables [MONO_TABLE_EVENT];
2871 table->rows += mono_array_length (tb->events);
2872 alloc_table (table, table->rows);
2873 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2875 alloc_table (table, table->rows);
2876 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2877 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2878 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2879 for (i = 0; i < mono_array_length (tb->events); ++i)
2880 mono_image_get_event_info (
2881 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2883 if (tb->properties && mono_array_length (tb->properties)) {
2884 table = &assembly->tables [MONO_TABLE_PROPERTY];
2885 table->rows += mono_array_length (tb->properties);
2886 alloc_table (table, table->rows);
2887 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2889 alloc_table (table, table->rows);
2890 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2891 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2892 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2893 for (i = 0; i < mono_array_length (tb->properties); ++i)
2894 mono_image_get_property_info (
2895 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2898 /* handle generic parameters */
2899 if (tb->generic_params) {
2900 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2901 table->rows += mono_array_length (tb->generic_params);
2902 alloc_table (table, table->rows);
2903 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2904 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2906 mono_image_get_generic_param_info (
2907 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2911 mono_image_add_decl_security (assembly,
2912 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2915 MonoDynamicTable *ntable;
2917 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2918 ntable->rows += mono_array_length (tb->subtypes);
2919 alloc_table (ntable, ntable->rows);
2920 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2922 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2923 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2925 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2926 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2927 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2928 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2929 mono_string_to_utf8 (tb->name), tb->table_idx,
2930 ntable->next_idx, ntable->rows);*/
2931 values += MONO_NESTED_CLASS_SIZE;
2938 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2942 g_ptr_array_add (types, type);
2944 if (!type->subtypes)
2947 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2948 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2949 collect_types (types, subtype);
2954 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2956 if ((*type1)->table_idx < (*type2)->table_idx)
2959 if ((*type1)->table_idx > (*type2)->table_idx)
2966 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2971 for (i = 0; i < mono_array_length (pinfo); ++i) {
2972 MonoReflectionParamBuilder *pb;
2973 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2976 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2981 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2984 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2986 for (i = 0; i < tb->num_fields; ++i) {
2987 MonoReflectionFieldBuilder* fb;
2988 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2989 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2993 for (i = 0; i < mono_array_length (tb->events); ++i) {
2994 MonoReflectionEventBuilder* eb;
2995 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2996 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2999 if (tb->properties) {
3000 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3001 MonoReflectionPropertyBuilder* pb;
3002 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3003 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3007 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3008 MonoReflectionCtorBuilder* cb;
3009 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3010 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3011 params_add_cattrs (assembly, cb->pinfo);
3016 for (i = 0; i < tb->num_methods; ++i) {
3017 MonoReflectionMethodBuilder* mb;
3018 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3019 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3020 params_add_cattrs (assembly, mb->pinfo);
3025 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3026 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3031 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3034 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3036 /* no types in the module */
3040 for (i = 0; i < mb->num_types; ++i)
3041 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3045 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3047 MonoDynamicTable *table;
3051 char *b = blob_size;
3054 table = &assembly->tables [MONO_TABLE_FILE];
3056 alloc_table (table, table->rows);
3057 values = table->values + table->next_idx * MONO_FILE_SIZE;
3058 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3059 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3060 if (module->image->dynamic) {
3061 /* This depends on the fact that the main module is emitted last */
3062 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3063 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3066 path = g_strdup (module->image->name);
3068 mono_sha1_get_digest_from_file (path, hash);
3071 mono_metadata_encode_value (20, b, &b);
3072 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3073 mono_image_add_stream_data (&assembly->blob, hash, 20);
3078 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3080 MonoDynamicTable *table;
3084 table = &assembly->tables [MONO_TABLE_MODULE];
3085 mb->table_idx = table->next_idx ++;
3086 name = mono_string_to_utf8 (mb->module.name);
3087 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3089 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3092 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3093 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3094 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3098 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3099 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3101 MonoDynamicTable *table;
3105 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3106 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3109 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3111 alloc_table (table, table->rows);
3112 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3114 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3115 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3116 if (klass->nested_in)
3117 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3119 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3120 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3121 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3123 res = table->next_idx;
3127 /* Emit nested types */
3128 if (klass->nested_classes) {
3131 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3132 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3139 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3140 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3145 klass = mono_class_from_mono_type (tb->type.type);
3147 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3149 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3150 parent_index, assembly);
3154 * We need to do this ourselves since klass->nested_classes is not set up.
3157 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3158 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3163 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3164 guint32 module_index, MonoDynamicImage *assembly)
3166 MonoImage *image = module->image;
3170 t = &image->tables [MONO_TABLE_TYPEDEF];
3172 for (i = 0; i < t->rows; ++i) {
3173 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3175 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3176 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3180 #define align_pointer(base,p)\
3182 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3184 (p) += 4 - (__diff & 3);\
3188 compare_semantics (const void *a, const void *b)
3190 const guint32 *a_values = a;
3191 const guint32 *b_values = b;
3192 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3195 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3199 compare_custom_attrs (const void *a, const void *b)
3201 const guint32 *a_values = a;
3202 const guint32 *b_values = b;
3204 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3208 compare_field_marshal (const void *a, const void *b)
3210 const guint32 *a_values = a;
3211 const guint32 *b_values = b;
3213 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3217 compare_nested (const void *a, const void *b)
3219 const guint32 *a_values = a;
3220 const guint32 *b_values = b;
3222 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3226 compare_genericparam (const void *a, const void *b)
3228 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3229 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3231 return (*a_entry)->owner - (*b_entry)->owner;
3235 compare_declsecurity_attrs (const void *a, const void *b)
3237 const guint32 *a_values = a;
3238 const guint32 *b_values = b;
3240 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3244 pad_heap (MonoDynamicStream *sh)
3246 if (sh->index & 3) {
3247 int sz = 4 - (sh->index & 3);
3248 memset (sh->data + sh->index, 0, sz);
3255 MonoDynamicStream *stream;
3259 * build_compressed_metadata() fills in the blob of data that represents the
3260 * raw metadata as it will be saved in the PE file. The five streams are output
3261 * and the metadata tables are comnpressed from the guint32 array representation,
3262 * to the compressed on-disk format.
3265 build_compressed_metadata (MonoDynamicImage *assembly)
3267 MonoDynamicTable *table;
3269 guint64 valid_mask = 0;
3270 guint64 sorted_mask;
3271 guint32 heapt_size = 0;
3272 guint32 meta_size = 256; /* allow for header and other stuff */
3273 guint32 table_offset;
3274 guint32 ntables = 0;
3280 struct StreamDesc stream_desc [5];
3282 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3283 for (i = 0; i < assembly->gen_params->len; i++){
3284 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3285 write_generic_param_entry (assembly, entry);
3288 stream_desc [0].name = "#~";
3289 stream_desc [0].stream = &assembly->tstream;
3290 stream_desc [1].name = "#Strings";
3291 stream_desc [1].stream = &assembly->sheap;
3292 stream_desc [2].name = "#US";
3293 stream_desc [2].stream = &assembly->us;
3294 stream_desc [3].name = "#Blob";
3295 stream_desc [3].stream = &assembly->blob;
3296 stream_desc [4].name = "#GUID";
3297 stream_desc [4].stream = &assembly->guid;
3299 /* tables that are sorted */
3300 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3301 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3302 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3303 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3304 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3305 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3307 /* Compute table sizes */
3308 /* the MonoImage has already been created in mono_image_basic_init() */
3309 meta = &assembly->image;
3311 /* sizes should be multiple of 4 */
3312 pad_heap (&assembly->blob);
3313 pad_heap (&assembly->guid);
3314 pad_heap (&assembly->sheap);
3315 pad_heap (&assembly->us);
3317 /* Setup the info used by compute_sizes () */
3318 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3319 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3320 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3322 meta_size += assembly->blob.index;
3323 meta_size += assembly->guid.index;
3324 meta_size += assembly->sheap.index;
3325 meta_size += assembly->us.index;
3327 for (i=0; i < 64; ++i)
3328 meta->tables [i].rows = assembly->tables [i].rows;
3330 for (i = 0; i < 64; i++){
3331 if (meta->tables [i].rows == 0)
3333 valid_mask |= (guint64)1 << i;
3335 meta->tables [i].row_size = mono_metadata_compute_size (
3336 meta, i, &meta->tables [i].size_bitfield);
3337 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3339 heapt_size += 24; /* #~ header size */
3340 heapt_size += ntables * 4;
3341 /* make multiple of 4 */
3344 meta_size += heapt_size;
3345 meta->raw_metadata = g_malloc0 (meta_size);
3346 p = meta->raw_metadata;
3347 /* the metadata signature */
3348 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3349 /* version numbers and 4 bytes reserved */
3350 int16val = (guint16*)p;
3351 *int16val++ = GUINT16_TO_LE (1);
3352 *int16val = GUINT16_TO_LE (1);
3354 /* version string */
3355 int32val = (guint32*)p;
3356 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3358 memcpy (p, meta->version, strlen (meta->version));
3359 p += GUINT32_FROM_LE (*int32val);
3360 align_pointer (meta->raw_metadata, p);
3361 int16val = (guint16*)p;
3362 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3363 *int16val = GUINT16_TO_LE (5); /* number of streams */
3367 * write the stream info.
3369 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3370 table_offset += 3; table_offset &= ~3;
3372 assembly->tstream.index = heapt_size;
3373 for (i = 0; i < 5; ++i) {
3374 int32val = (guint32*)p;
3375 stream_desc [i].stream->offset = table_offset;
3376 *int32val++ = GUINT32_TO_LE (table_offset);
3377 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3378 table_offset += GUINT32_FROM_LE (*int32val);
3379 table_offset += 3; table_offset &= ~3;
3381 strcpy (p, stream_desc [i].name);
3382 p += strlen (stream_desc [i].name) + 1;
3383 align_pointer (meta->raw_metadata, p);
3386 * now copy the data, the table stream header and contents goes first.
3388 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3389 p = meta->raw_metadata + assembly->tstream.offset;
3390 int32val = (guint32*)p;
3391 *int32val = GUINT32_TO_LE (0); /* reserved */
3394 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3395 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3396 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3397 *p++ = 1; /* version */
3400 *p++ = 1; /* version */
3404 if (meta->idx_string_wide)
3406 if (meta->idx_guid_wide)
3408 if (meta->idx_blob_wide)
3411 *p++ = 1; /* reserved */
3412 int64val = (guint64*)p;
3413 *int64val++ = GUINT64_TO_LE (valid_mask);
3414 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3416 int32val = (guint32*)p;
3417 for (i = 0; i < 64; i++){
3418 if (meta->tables [i].rows == 0)
3420 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3422 p = (unsigned char*)int32val;
3424 /* sort the tables that still need sorting */
3425 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3427 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3428 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3430 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3431 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3433 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3434 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3436 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3437 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3438 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3440 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3442 /* compress the tables */
3443 for (i = 0; i < 64; i++){
3446 guint32 bitfield = meta->tables [i].size_bitfield;
3447 if (!meta->tables [i].rows)
3449 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3450 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3451 meta->tables [i].base = p;
3452 for (row = 1; row <= meta->tables [i].rows; ++row) {
3453 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3454 for (col = 0; col < assembly->tables [i].columns; ++col) {
3455 switch (mono_metadata_table_size (bitfield, col)) {
3457 *p++ = values [col];
3460 *p++ = values [col] & 0xff;
3461 *p++ = (values [col] >> 8) & 0xff;
3464 *p++ = values [col] & 0xff;
3465 *p++ = (values [col] >> 8) & 0xff;
3466 *p++ = (values [col] >> 16) & 0xff;
3467 *p++ = (values [col] >> 24) & 0xff;
3470 g_assert_not_reached ();
3474 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3477 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3478 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3479 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3480 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3481 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3483 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3487 * Some tables in metadata need to be sorted according to some criteria, but
3488 * when methods and fields are first created with reflection, they may be assigned a token
3489 * that doesn't correspond to the final token they will get assigned after the sorting.
3490 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3491 * with the reflection objects that represent them. Once all the tables are set up, the
3492 * reflection objects will contains the correct table index. fixup_method() will fixup the
3493 * tokens for the method with ILGenerator @ilgen.
3496 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3497 guint32 code_idx = GPOINTER_TO_UINT (value);
3498 MonoReflectionILTokenInfo *iltoken;
3499 MonoReflectionFieldBuilder *field;
3500 MonoReflectionCtorBuilder *ctor;
3501 MonoReflectionMethodBuilder *method;
3502 MonoReflectionTypeBuilder *tb;
3503 MonoReflectionArrayMethod *am;
3505 unsigned char *target;
3507 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3508 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3509 target = assembly->code.data + code_idx + iltoken->code_pos;
3510 switch (target [3]) {
3511 case MONO_TABLE_FIELD:
3512 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3513 field = (MonoReflectionFieldBuilder *)iltoken->member;
3514 idx = field->table_idx;
3515 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3516 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3517 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3519 g_assert_not_reached ();
3522 case MONO_TABLE_METHOD:
3523 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3524 method = (MonoReflectionMethodBuilder *)iltoken->member;
3525 idx = method->table_idx;
3526 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3527 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3528 idx = ctor->table_idx;
3529 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3530 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3531 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3532 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3534 g_assert_not_reached ();
3537 case MONO_TABLE_TYPEDEF:
3538 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3539 g_assert_not_reached ();
3540 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3541 idx = tb->table_idx;
3543 case MONO_TABLE_MEMBERREF:
3544 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3545 am = (MonoReflectionArrayMethod*)iltoken->member;
3546 idx = am->table_idx;
3547 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3548 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3549 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3550 g_assert (m->klass->generic_inst);
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3554 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3555 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3556 g_assert (f->generic_info);
3558 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3561 g_assert_not_reached ();
3564 case MONO_TABLE_METHODSPEC:
3565 if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3566 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3567 g_assert (m->signature->generic_param_count);
3570 g_assert_not_reached ();
3574 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3576 target [0] = idx & 0xff;
3577 target [1] = (idx >> 8) & 0xff;
3578 target [2] = (idx >> 16) & 0xff;
3585 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3586 * value is not known when the table is emitted.
3589 fixup_cattrs (MonoDynamicImage *assembly)
3591 MonoDynamicTable *table;
3593 guint32 type, i, idx, token;
3596 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3598 for (i = 0; i < table->rows; ++i) {
3599 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3601 type = values [MONO_CUSTOM_ATTR_TYPE];
3602 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3603 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3604 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3605 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3608 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3609 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3610 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3611 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3618 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3620 MonoDynamicTable *table;
3624 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3626 alloc_table (table, table->rows);
3627 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3628 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3629 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3630 name = mono_string_to_utf8 (rsrc->name);
3631 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3633 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3638 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3640 MonoDynamicTable *table;
3644 char *b = blob_size;
3646 guint32 idx, offset;
3648 if (rsrc->filename) {
3649 name = mono_string_to_utf8 (rsrc->filename);
3650 sname = g_path_get_basename (name);
3652 table = &assembly->tables [MONO_TABLE_FILE];
3654 alloc_table (table, table->rows);
3655 values = table->values + table->next_idx * MONO_FILE_SIZE;
3656 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3657 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3660 mono_sha1_get_digest_from_file (name, hash);
3661 mono_metadata_encode_value (20, b, &b);
3662 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3663 mono_image_add_stream_data (&assembly->blob, hash, 20);
3665 idx = table->next_idx++;
3667 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3670 offset = mono_array_length (rsrc->data);
3671 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3672 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3673 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3674 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3678 * The entry should be emitted into the MANIFESTRESOURCE table of
3679 * the main module, but that needs to reference the FILE table
3680 * which isn't emitted yet.
3687 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3691 set_version_from_string (MonoString *version, guint32 *values)
3693 gchar *ver, *p, *str;
3696 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3697 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3698 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3699 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3702 ver = str = mono_string_to_utf8 (version);
3703 for (i = 0; i < 4; ++i) {
3704 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3710 /* handle Revision and Build */
3720 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3724 char *b = blob_size;
3729 len = mono_array_length (pkey);
3730 mono_metadata_encode_value (len, b, &b);
3731 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3732 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3734 /* need to get the actual value from the key type... */
3735 assembly->strong_name_size = 128;
3736 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3742 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3744 MonoDynamicTable *table;
3745 MonoDynamicImage *assembly;
3746 MonoReflectionAssemblyBuilder *assemblyb;
3751 guint32 module_index;
3753 assemblyb = moduleb->assemblyb;
3754 assembly = moduleb->dynamic_image;
3755 domain = mono_object_domain (assemblyb);
3757 /* Emit ASSEMBLY table */
3758 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3759 alloc_table (table, 1);
3760 values = table->values + MONO_ASSEMBLY_SIZE;
3761 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3762 name = mono_string_to_utf8 (assemblyb->name);
3763 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3765 if (assemblyb->culture) {
3766 name = mono_string_to_utf8 (assemblyb->culture);
3767 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3770 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3772 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3773 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3774 set_version_from_string (assemblyb->version, values);
3776 /* Emit FILE + EXPORTED_TYPE table */
3778 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3780 MonoReflectionModuleBuilder *file_module =
3781 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3782 if (file_module != moduleb) {
3783 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3785 if (file_module->types) {
3786 for (j = 0; j < file_module->num_types; ++j) {
3787 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3788 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3793 if (assemblyb->loaded_modules) {
3794 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3795 MonoReflectionModule *file_module =
3796 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3797 mono_image_fill_file_table (domain, file_module, assembly);
3799 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3803 /* Emit MANIFESTRESOURCE table */
3805 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3807 MonoReflectionModuleBuilder *file_module =
3808 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3809 /* The table for the main module is emitted later */
3810 if (file_module != moduleb) {
3812 if (file_module->resources) {
3813 int len = mono_array_length (file_module->resources);
3814 for (j = 0; j < len; ++j) {
3815 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3816 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3824 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3825 * for the modulebuilder @moduleb.
3826 * At the end of the process, method and field tokens are fixed up and the
3827 * on-disk compressed metadata representation is created.
3830 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3832 MonoDynamicTable *table;
3833 MonoDynamicImage *assembly;
3834 MonoReflectionAssemblyBuilder *assemblyb;
3839 assemblyb = moduleb->assemblyb;
3840 assembly = moduleb->dynamic_image;
3841 domain = mono_object_domain (assemblyb);
3843 if (assembly->text_rva)
3846 assembly->text_rva = START_TEXT_RVA;
3848 if (moduleb->is_main) {
3849 mono_image_emit_manifest (moduleb);
3852 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3853 table->rows = 1; /* .<Module> */
3855 alloc_table (table, table->rows);
3857 * Set the first entry.
3859 values = table->values + table->columns;
3860 values [MONO_TYPEDEF_FLAGS] = 0;
3861 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3862 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3863 values [MONO_TYPEDEF_EXTENDS] = 0;
3864 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3865 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3868 * handle global methods
3869 * FIXME: test what to do when global methods are defined in multiple modules.
3871 if (moduleb->global_methods) {
3872 table = &assembly->tables [MONO_TABLE_METHOD];
3873 table->rows += mono_array_length (moduleb->global_methods);
3874 alloc_table (table, table->rows);
3875 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3876 mono_image_get_method_info (
3877 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3879 if (moduleb->global_fields) {
3880 table = &assembly->tables [MONO_TABLE_FIELD];
3881 table->rows += mono_array_length (moduleb->global_fields);
3882 alloc_table (table, table->rows);
3883 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3884 mono_image_get_field_info (
3885 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3888 table = &assembly->tables [MONO_TABLE_MODULE];
3889 alloc_table (table, 1);
3890 mono_image_fill_module_table (domain, moduleb, assembly);
3894 /* Collect all types into a list sorted by their table_idx */
3895 GPtrArray *types = g_ptr_array_new ();
3898 for (i = 0; i < moduleb->num_types; ++i) {
3899 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3900 collect_types (types, type);
3903 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3904 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3905 table->rows += types->len;
3906 alloc_table (table, table->rows);
3908 for (i = 0; i < types->len; ++i) {
3909 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3910 mono_image_get_type_info (domain, type, assembly);
3912 g_ptr_array_free (types, TRUE);
3916 * table->rows is already set above and in mono_image_fill_module_table.
3918 /* add all the custom attributes at the end, once all the indexes are stable */
3919 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3921 /* CAS assembly permissions */
3922 if (assemblyb->permissions_minimum)
3923 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3924 if (assemblyb->permissions_optional)
3925 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3926 if (assemblyb->permissions_refused)
3927 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3929 module_add_cattrs (assembly, moduleb);
3932 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3933 fixup_cattrs (assembly);
3937 * mono_image_insert_string:
3938 * @module: module builder object
3941 * Insert @str into the user string stream of @module.
3944 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3946 MonoDynamicImage *assembly;
3951 MONO_ARCH_SAVE_REGS;
3953 if (!module->dynamic_image)
3954 mono_image_module_basic_init (module);
3956 assembly = module->dynamic_image;
3958 if (assembly->save) {
3959 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3960 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3961 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3963 char *swapped = g_malloc (2 * mono_string_length (str));
3964 const char *p = (const char*)mono_string_chars (str);
3966 swap_with_size (swapped, p, 2, mono_string_length (str));
3967 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3971 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3973 mono_image_add_stream_data (&assembly->us, "", 1);
3975 idx = assembly->us.index ++;
3978 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3980 return MONO_TOKEN_STRING | idx;
3984 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3989 klass = obj->vtable->klass;
3990 if (strcmp (klass->name, "MonoMethod") == 0) {
3991 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3992 MonoMethodSignature *sig, *old;
3993 guint32 sig_token, parent;
3996 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3998 nargs = mono_array_length (opt_param_types);
3999 old = method->signature;
4000 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4002 sig->hasthis = old->hasthis;
4003 sig->explicit_this = old->explicit_this;
4004 sig->call_convention = old->call_convention;
4005 sig->generic_param_count = old->generic_param_count;
4006 sig->param_count = old->param_count + nargs;
4007 sig->sentinelpos = old->param_count;
4008 sig->ret = old->ret;
4010 for (i = 0; i < old->param_count; i++)
4011 sig->params [i] = old->params [i];
4013 for (i = 0; i < nargs; i++) {
4014 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4015 sig->params [old->param_count + i] = rt->type;
4018 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4019 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4020 parent >>= MONO_TYPEDEFORREF_BITS;
4022 parent <<= MONO_MEMBERREF_PARENT_BITS;
4023 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4025 sig_token = method_encode_signature (assembly, sig);
4026 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4027 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4028 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4029 ReflectionMethodBuilder rmb;
4030 guint32 parent, sig;
4032 reflection_methodbuilder_from_method_builder (&rmb, mb);
4033 rmb.opt_types = opt_param_types;
4035 sig = method_builder_encode_signature (assembly, &rmb);
4037 parent = mono_image_create_token (assembly, obj, TRUE);
4038 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4040 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4041 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4043 token = mono_image_get_varargs_method_token (
4044 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4046 g_error ("requested method token for %s\n", klass->name);
4053 * mono_image_create_token:
4054 * @assembly: a dynamic assembly
4057 * Get a token to insert in the IL code stream for the given MemberInfo.
4058 * @obj can be one of:
4059 * ConstructorBuilder
4069 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4074 klass = obj->vtable->klass;
4075 if (strcmp (klass->name, "MethodBuilder") == 0) {
4076 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4078 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4079 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4081 token = mono_image_get_methodbuilder_token (assembly, mb);
4082 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4083 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4084 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4086 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4087 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4089 token = mono_image_get_ctorbuilder_token (assembly, mb);
4090 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4091 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4092 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4093 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4094 if (tb->generic_params) {
4095 token = mono_image_get_generic_field_token (assembly, fb);
4097 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4099 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4100 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4101 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4102 } else if (strcmp (klass->name, "MonoType") == 0 ||
4103 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4104 MonoReflectionType *tb = (MonoReflectionType *)obj;
4105 token = mono_metadata_token_from_dor (
4106 mono_image_typedef_or_ref (assembly, tb->type));
4107 } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4108 MonoReflectionType *tb = (MonoReflectionType *)obj;
4109 token = mono_metadata_token_from_dor (
4110 mono_image_typedef_or_ref (assembly, tb->type));
4111 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4112 strcmp (klass->name, "MonoMethod") == 0) {
4113 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4114 if (m->method->signature->is_inflated) {
4115 if (create_methodspec)
4116 token = mono_image_get_methodspec_token (assembly, m->method);
4118 token = mono_image_get_inflated_method_token (assembly, m->method);
4119 } else if ((m->method->klass->image == &assembly->image) &&
4120 !m->method->klass->generic_inst) {
4121 static guint32 method_table_idx = 0xffffff;
4122 if (m->method->klass->wastypebuilder) {
4123 /* we use the same token as the one that was assigned
4124 * to the Methodbuilder.
4125 * FIXME: do the equivalent for Fields.
4127 token = m->method->token;
4130 * Each token should have a unique index, but the indexes are
4131 * assigned by managed code, so we don't know about them. An
4132 * easy solution is to count backwards...
4134 method_table_idx --;
4135 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4138 token = mono_image_get_methodref_token (assembly, m->method);
4140 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4141 } else if (strcmp (klass->name, "MonoField") == 0) {
4142 MonoReflectionField *f = (MonoReflectionField *)obj;
4143 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4144 static guint32 field_table_idx = 0xffffff;
4146 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4148 token = mono_image_get_fieldref_token (assembly, f);
4150 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4151 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4152 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4153 token = mono_image_get_array_token (assembly, m);
4154 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4155 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4156 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4158 g_error ("requested token for %s\n", klass->name);
4161 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4167 guint32 import_lookup_table;
4171 guint32 import_address_table_rva;
4179 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4181 static MonoDynamicImage*
4182 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4184 static const guchar entrycode [16] = {0xff, 0x25, 0};
4185 MonoDynamicImage *image;
4188 const char *version = mono_get_runtime_version ();
4191 image = GC_MALLOC (sizeof (MonoDynamicImage));
4193 image = g_new0 (MonoDynamicImage, 1);
4196 /* keep in sync with image.c */
4197 image->image.name = assembly_name;
4198 image->image.assembly_name = image->image.name; /* they may be different */
4199 image->image.module_name = module_name;
4200 image->image.version = g_strdup (version);
4201 image->image.dynamic = TRUE;
4203 image->image.references = g_new0 (MonoAssembly*, 1);
4204 image->image.references [0] = NULL;
4206 mono_image_init (&image->image);
4208 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4209 image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4210 image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4211 image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4212 image->handleref = g_hash_table_new (NULL, NULL);
4213 image->tokens = mono_g_hash_table_new (NULL, NULL);
4214 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4215 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4216 image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4217 image->gen_params = g_ptr_array_new ();
4219 string_heap_init (&image->sheap);
4220 mono_image_add_stream_data (&image->us, "", 1);
4221 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4222 /* import tables... */
4223 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4224 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4225 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4226 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4227 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4228 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4229 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4230 stream_data_align (&image->code);
4232 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4234 for (i=0; i < 64; ++i) {
4235 image->tables [i].next_idx = 1;
4236 image->tables [i].columns = table_sizes [i];
4239 image->image.assembly = (MonoAssembly*)assembly;
4240 image->run = assembly->run;
4241 image->save = assembly->save;
4242 image->pe_kind = 0x1; /* ILOnly */
4243 image->machine = 0x14c; /* I386 */
4249 * mono_image_basic_init:
4250 * @assembly: an assembly builder object
4252 * Create the MonoImage that represents the assembly builder and setup some
4253 * of the helper hash table and the basic metadata streams.
4256 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4258 MonoDynamicAssembly *assembly;
4259 MonoDynamicImage *image;
4261 MONO_ARCH_SAVE_REGS;
4263 if (assemblyb->dynamic_assembly)
4267 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4269 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4272 assembly->assembly.dynamic = TRUE;
4273 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4274 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4275 if (assemblyb->culture)
4276 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4278 assembly->assembly.aname.culture = g_strdup ("");
4280 assembly->run = assemblyb->access != 2;
4281 assembly->save = assemblyb->access != 1;
4283 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4284 image->initial_image = TRUE;
4285 assembly->assembly.aname.name = image->image.name;
4286 assembly->assembly.image = &image->image;
4288 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4289 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4293 calc_section_size (MonoDynamicImage *assembly)
4297 /* alignment constraints */
4298 assembly->code.index += 3;
4299 assembly->code.index &= ~3;
4300 assembly->meta_size += 3;
4301 assembly->meta_size &= ~3;
4302 assembly->resources.index += 3;
4303 assembly->resources.index &= ~3;
4305 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4306 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4309 if (assembly->win32_res) {
4310 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4312 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4313 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4317 assembly->sections [MONO_SECTION_RELOC].size = 12;
4318 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4328 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4332 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4334 ResTreeNode *t1 = (ResTreeNode*)a;
4335 ResTreeNode *t2 = (ResTreeNode*)b;
4337 return t1->id - t2->id;
4341 * resource_tree_create:
4343 * Organize the resources into a resource tree.
4345 static ResTreeNode *
4346 resource_tree_create (MonoArray *win32_resources)
4348 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4352 tree = g_new0 (ResTreeNode, 1);
4354 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4355 MonoReflectionWin32Resource *win32_res =
4356 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4360 lang_node = g_new0 (ResTreeNode, 1);
4361 lang_node->id = win32_res->lang_id;
4362 lang_node->win32_res = win32_res;
4364 /* Create type node if neccesary */
4366 for (l = tree->children; l; l = l->next)
4367 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4368 type_node = (ResTreeNode*)l->data;
4373 type_node = g_new0 (ResTreeNode, 1);
4374 type_node->id = win32_res->res_type;
4377 * The resource types have to be sorted otherwise
4378 * Windows Explorer can't display the version information.
4380 tree->children = g_slist_insert_sorted (tree->children,
4381 type_node, resource_tree_compare_by_id);
4384 /* Create res node if neccesary */
4386 for (l = type_node->children; l; l = l->next)
4387 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4388 res_node = (ResTreeNode*)l->data;
4393 res_node = g_new0 (ResTreeNode, 1);
4394 res_node->id = win32_res->res_id;
4395 type_node->children = g_slist_append (type_node->children, res_node);
4398 res_node->children = g_slist_append (res_node->children, lang_node);
4405 * resource_tree_encode:
4407 * Encode the resource tree into the format used in the PE file.
4410 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4413 MonoPEResourceDir dir;
4414 MonoPEResourceDirEntry dir_entry;
4415 MonoPEResourceDataEntry data_entry;
4419 * For the format of the resource directory, see the article
4420 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4424 memset (&dir, 0, sizeof (dir));
4425 memset (&dir_entry, 0, sizeof (dir_entry));
4426 memset (&data_entry, 0, sizeof (data_entry));
4428 g_assert (sizeof (dir) == 16);
4429 g_assert (sizeof (dir_entry) == 8);
4430 g_assert (sizeof (data_entry) == 16);
4432 node->offset = p - begin;
4434 /* IMAGE_RESOURCE_DIRECTORY */
4435 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4437 memcpy (p, &dir, sizeof (dir));
4440 /* Reserve space for entries */
4442 p += sizeof (dir_entry) * dir.res_id_entries;
4444 /* Write children */
4445 for (l = node->children; l; l = l->next) {
4446 ResTreeNode *child = (ResTreeNode*)l->data;
4448 if (child->win32_res) {
4450 child->offset = p - begin;
4452 /* IMAGE_RESOURCE_DATA_ENTRY */
4453 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4454 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4456 memcpy (p, &data_entry, sizeof (data_entry));
4457 p += sizeof (data_entry);
4459 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4460 p += data_entry.rde_size;
4462 resource_tree_encode (child, begin, p, &p);
4466 /* IMAGE_RESOURCE_ENTRY */
4467 for (l = node->children; l; l = l->next) {
4468 ResTreeNode *child = (ResTreeNode*)l->data;
4469 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4471 dir_entry.is_dir = child->win32_res ? 0 : 1;
4472 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4474 memcpy (entries, &dir_entry, sizeof (dir_entry));
4475 entries += sizeof (dir_entry);
4482 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4487 MonoReflectionWin32Resource *win32_res;
4490 if (!assemblyb->win32_resources)
4494 * Resources are stored in a three level tree inside the PE file.
4495 * - level one contains a node for each type of resource
4496 * - level two contains a node for each resource
4497 * - level three contains a node for each instance of a resource for a
4498 * specific language.
4501 tree = resource_tree_create (assemblyb->win32_resources);
4503 /* Estimate the size of the encoded tree */
4505 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4506 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4507 size += mono_array_length (win32_res->res_data);
4509 /* Directory structure */
4510 size += mono_array_length (assemblyb->win32_resources) * 256;
4511 p = buf = g_malloc (size);
4513 resource_tree_encode (tree, p, p, &p);
4515 g_assert (p - buf < size);
4517 assembly->win32_res = g_malloc (p - buf);
4518 assembly->win32_res_size = p - buf;
4519 memcpy (assembly->win32_res, buf, p - buf);
4525 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4527 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4530 p += sizeof (MonoPEResourceDir);
4531 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4532 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4533 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4534 if (dir_entry->is_dir) {
4535 fixup_resource_directory (res_section, child, rva);
4537 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4538 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4541 p += sizeof (MonoPEResourceDirEntry);
4546 * mono_image_create_pefile:
4547 * @mb: a module builder object
4549 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4550 * assembly->pefile where it can be easily retrieved later in chunks.
4553 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4554 MonoMSDOSHeader *msdos;
4555 MonoDotNetHeader *header;
4556 MonoSectionTable *section;
4557 MonoCLIHeader *cli_header;
4558 guint32 size, image_size, virtual_base, text_offset;
4559 guint32 header_start, section_start, file_offset, virtual_offset;
4560 MonoDynamicImage *assembly;
4561 MonoReflectionAssemblyBuilder *assemblyb;
4562 MonoDynamicStream *pefile;
4564 guint32 *rva, value;
4568 static const unsigned char msheader[] = {
4569 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4570 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4573 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4574 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4575 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4576 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4579 assemblyb = mb->assemblyb;
4581 mono_image_basic_init (assemblyb);
4582 assembly = mb->dynamic_image;
4584 assembly->pe_kind = assemblyb->pe_kind;
4585 assembly->machine = assemblyb->machine;
4586 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4587 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4589 /* already created */
4590 if (assembly->pefile.index)
4593 mono_image_build_metadata (mb);
4595 if (mb->is_main && assemblyb->resources) {
4596 int len = mono_array_length (assemblyb->resources);
4597 for (i = 0; i < len; ++i)
4598 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4601 if (mb->resources) {
4602 int len = mono_array_length (mb->resources);
4603 for (i = 0; i < len; ++i)
4604 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4607 build_compressed_metadata (assembly);
4610 assembly_add_win32_resources (assembly, assemblyb);
4612 nsections = calc_section_size (assembly);
4614 pefile = &assembly->pefile;
4616 /* The DOS header and stub */
4617 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4618 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4620 /* the dotnet header */
4621 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4623 /* the section tables */
4624 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4626 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4627 virtual_offset = VIRT_ALIGN;
4630 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4631 if (!assembly->sections [i].size)
4634 file_offset += FILE_ALIGN - 1;
4635 file_offset &= ~(FILE_ALIGN - 1);
4636 virtual_offset += VIRT_ALIGN - 1;
4637 virtual_offset &= ~(VIRT_ALIGN - 1);
4639 assembly->sections [i].offset = file_offset;
4640 assembly->sections [i].rva = virtual_offset;
4642 file_offset += assembly->sections [i].size;
4643 virtual_offset += assembly->sections [i].size;
4644 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4647 file_offset += FILE_ALIGN - 1;
4648 file_offset &= ~(FILE_ALIGN - 1);
4649 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4651 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4653 /* back-patch info */
4654 msdos = (MonoMSDOSHeader*)pefile->data;
4655 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4656 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4657 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4659 header = (MonoDotNetHeader*)(pefile->data + header_start);
4660 header->pesig [0] = 'P';
4661 header->pesig [1] = 'E';
4663 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4664 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4665 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4666 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4667 if (assemblyb->pekind == 1) {
4669 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4672 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4675 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4677 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4678 header->pe.pe_major = 6;
4679 header->pe.pe_minor = 0;
4680 size = assembly->sections [MONO_SECTION_TEXT].size;
4681 size += FILE_ALIGN - 1;
4682 size &= ~(FILE_ALIGN - 1);
4683 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4684 size = assembly->sections [MONO_SECTION_RSRC].size;
4685 size += FILE_ALIGN - 1;
4686 size &= ~(FILE_ALIGN - 1);
4687 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4688 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4689 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4690 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4691 /* pe_rva_entry_point always at the beginning of the text section */
4692 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4694 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4695 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4696 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4697 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4698 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4699 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4700 size = section_start;
4701 size += FILE_ALIGN - 1;
4702 size &= ~(FILE_ALIGN - 1);
4703 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4705 size += VIRT_ALIGN - 1;
4706 size &= ~(VIRT_ALIGN - 1);
4707 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4710 // Translate the PEFileKind value to the value expected by the Windows loader
4716 // PEFileKinds.Dll == 1
4717 // PEFileKinds.ConsoleApplication == 2
4718 // PEFileKinds.WindowApplication == 3
4721 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4722 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4724 if (assemblyb->pekind == 3)
4729 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4731 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4732 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4733 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4734 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4735 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4736 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4738 /* fill data directory entries */
4740 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4741 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4743 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4744 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4746 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4747 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4748 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4749 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4750 /* patch entrypoint name */
4751 if (assemblyb->pekind == 1)
4752 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4754 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4755 /* patch imported function RVA name */
4756 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4757 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4759 /* the import table */
4760 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4761 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4762 /* patch imported dll RVA name and other entries in the dir */
4763 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4764 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4765 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4766 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4767 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4768 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4770 p = (assembly->code.data + assembly->ilt_offset);
4771 value = (assembly->text_rva + assembly->imp_names_offset);
4772 *p++ = (value) & 0xff;
4773 *p++ = (value >> 8) & (0xff);
4774 *p++ = (value >> 16) & (0xff);
4775 *p++ = (value >> 24) & (0xff);
4777 /* the CLI header info */
4778 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4779 cli_header->ch_size = GUINT32_FROM_LE (72);
4780 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4781 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4782 if (assemblyb->entry_point) {
4783 guint32 table_idx = 0;
4784 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4785 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4786 table_idx = methodb->table_idx;
4788 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4790 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4792 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4794 /* The embedded managed resources */
4795 text_offset = assembly->text_rva + assembly->code.index;
4796 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4797 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4798 text_offset += assembly->resources.index;
4799 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4800 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4801 text_offset += assembly->meta_size;
4802 if (assembly->strong_name_size) {
4803 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4804 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4805 text_offset += assembly->strong_name_size;
4808 /* write the section tables and section content */
4809 section = (MonoSectionTable*)(pefile->data + section_start);
4810 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4811 static const char *section_names [] = {
4812 ".text", ".rsrc", ".reloc"
4814 if (!assembly->sections [i].size)
4816 strcpy (section->st_name, section_names [i]);
4817 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4818 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4819 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4820 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4821 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4822 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4823 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4825 case MONO_SECTION_TEXT:
4826 /* patch entry point */
4827 p = (assembly->code.data + 2);
4828 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4829 *p++ = (value) & 0xff;
4830 *p++ = (value >> 8) & 0xff;
4831 *p++ = (value >> 16) & 0xff;
4832 *p++ = (value >> 24) & 0xff;
4834 text_offset = assembly->sections [i].offset;
4835 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4836 text_offset += assembly->code.index;
4837 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4838 text_offset += assembly->resources.index;
4839 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4840 text_offset += assembly->meta_size;
4841 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4843 g_free (assembly->image.raw_metadata);
4845 case MONO_SECTION_RELOC:
4846 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4847 *rva = GUINT32_FROM_LE (assembly->text_rva);
4849 *rva = GUINT32_FROM_LE (12);
4851 data16 = (guint16*)rva;
4853 * the entrypoint is always at the start of the text section
4854 * 3 is IMAGE_REL_BASED_HIGHLOW
4855 * 2 is patch_size_rva - text_rva
4857 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4859 *data16 = 0; /* terminate */
4861 case MONO_SECTION_RSRC:
4862 if (assembly->win32_res) {
4863 text_offset = assembly->sections [i].offset;
4865 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4866 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4868 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4872 g_assert_not_reached ();
4877 /* check that the file is properly padded */
4879 if (!WriteFile (file, pefile->data, pefile->index , &dummy, NULL))
4880 g_error ("WriteFile returned %d\n", GetLastError ());
4882 mono_dynamic_stream_reset (pefile);
4883 mono_dynamic_stream_reset (&assembly->code);
4884 mono_dynamic_stream_reset (&assembly->us);
4885 mono_dynamic_stream_reset (&assembly->blob);
4886 mono_dynamic_stream_reset (&assembly->guid);
4887 mono_dynamic_stream_reset (&assembly->sheap);
4890 MonoReflectionModule *
4891 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4895 MonoImageOpenStatus status;
4896 MonoDynamicAssembly *assembly;
4897 guint32 module_count;
4898 MonoImage **new_modules;
4900 name = mono_string_to_utf8 (fileName);
4902 image = mono_image_open (name, &status);
4905 if (status == MONO_IMAGE_ERROR_ERRNO)
4906 exc = mono_get_exception_file_not_found (fileName);
4908 exc = mono_get_exception_bad_image_format (name);
4910 mono_raise_exception (exc);
4915 assembly = ab->dynamic_assembly;
4916 image->assembly = (MonoAssembly*)assembly;
4918 module_count = image->assembly->image->module_count;
4919 new_modules = g_new0 (MonoImage *, module_count + 1);
4921 if (image->assembly->image->modules)
4922 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4923 new_modules [module_count] = image;
4925 g_free (image->assembly->image->modules);
4926 image->assembly->image->modules = new_modules;
4927 image->assembly->image->module_count ++;
4929 mono_assembly_load_references (image, &status);
4931 mono_image_close (image);
4932 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4935 return mono_module_get_object (mono_domain_get (), image);
4939 * We need to return always the same object for MethodInfo, FieldInfo etc..
4940 * but we need to consider the reflected type.
4941 * type uses a different hash, since it uses custom hash/equal functions.
4946 MonoClass *refclass;
4950 reflected_equal (gconstpointer a, gconstpointer b) {
4951 const ReflectedEntry *ea = a;
4952 const ReflectedEntry *eb = b;
4954 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4958 reflected_hash (gconstpointer a) {
4959 const ReflectedEntry *ea = a;
4960 return GPOINTER_TO_UINT (ea->item);
4963 #define CHECK_OBJECT(t,p,k) \
4969 mono_domain_lock (domain); \
4970 if (!domain->refobject_hash) \
4971 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4972 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4973 mono_domain_unlock (domain); \
4979 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4981 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4984 #define CACHE_OBJECT(p,o,k) \
4986 ReflectedEntry *e = ALLOC_REFENTRY; \
4988 e->refclass = (k); \
4989 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4990 mono_domain_unlock (domain); \
4994 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4996 /* this is done only once */
4997 mono_domain_lock (domain);
4998 CACHE_OBJECT (assembly, res, NULL);
5002 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5004 /* this is done only once */
5005 mono_domain_lock (domain);
5006 CACHE_OBJECT (module, res, NULL);
5010 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5012 MonoDynamicImage *image = moduleb->dynamic_image;
5013 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5016 * FIXME: we already created an image in mono_image_basic_init (), but
5017 * we don't know which module it belongs to, since that is only
5018 * determined at assembly save time.
5020 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5021 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5023 moduleb->module.image = &image->image;
5024 moduleb->dynamic_image = image;
5025 register_module (mono_object_domain (moduleb), moduleb, image);
5030 * mono_assembly_get_object:
5031 * @domain: an app domain
5032 * @assembly: an assembly
5034 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5036 MonoReflectionAssembly*
5037 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5039 static MonoClass *System_Reflection_Assembly;
5040 MonoReflectionAssembly *res;
5042 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5043 if (!System_Reflection_Assembly)
5044 System_Reflection_Assembly = mono_class_from_name (
5045 mono_defaults.corlib, "System.Reflection", "Assembly");
5046 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5047 res->assembly = assembly;
5048 CACHE_OBJECT (assembly, res, NULL);
5054 MonoReflectionModule*
5055 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5057 static MonoClass *System_Reflection_Module;
5058 MonoReflectionModule *res;
5061 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5062 if (!System_Reflection_Module)
5063 System_Reflection_Module = mono_class_from_name (
5064 mono_defaults.corlib, "System.Reflection", "Module");
5065 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5068 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5070 res->fqname = mono_string_new (domain, image->name);
5071 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5072 res->scopename = mono_string_new (domain, image->module_name);
5076 if (image->assembly->image == image) {
5077 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5080 g_assert (image->assembly->image->modules);
5082 for (i = 0; i < image->assembly->image->module_count; i++) {
5083 if (image->assembly->image->modules [i] == image)
5084 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5086 g_assert (res->token);
5089 mono_image_addref (image);
5091 CACHE_OBJECT (image, res, NULL);
5095 MonoReflectionModule*
5096 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5098 static MonoClass *System_Reflection_Module;
5099 MonoReflectionModule *res;
5100 MonoTableInfo *table;
5101 guint32 cols [MONO_FILE_SIZE];
5103 guint32 i, name_idx;
5106 if (!System_Reflection_Module)
5107 System_Reflection_Module = mono_class_from_name (
5108 mono_defaults.corlib, "System.Reflection", "Module");
5109 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5111 table = &image->tables [MONO_TABLE_FILE];
5112 g_assert (table_index < table->rows);
5113 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5116 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5117 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5119 /* Check whenever the row has a corresponding row in the moduleref table */
5120 table = &image->tables [MONO_TABLE_MODULEREF];
5121 for (i = 0; i < table->rows; ++i) {
5122 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5123 val = mono_metadata_string_heap (image, name_idx);
5124 if (strcmp (val, name) == 0)
5125 res->image = image->modules [i];
5128 res->fqname = mono_string_new (domain, name);
5129 res->name = mono_string_new (domain, name);
5130 res->scopename = mono_string_new (domain, name);
5131 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5132 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5138 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5140 if ((t1->type != t2->type) ||
5141 (t1->byref != t2->byref))
5145 case MONO_TYPE_VOID:
5146 case MONO_TYPE_BOOLEAN:
5147 case MONO_TYPE_CHAR:
5158 case MONO_TYPE_STRING:
5161 case MONO_TYPE_OBJECT:
5162 case MONO_TYPE_TYPEDBYREF:
5164 case MONO_TYPE_VALUETYPE:
5165 case MONO_TYPE_CLASS:
5166 case MONO_TYPE_SZARRAY:
5167 return t1->data.klass == t2->data.klass;
5169 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5170 case MONO_TYPE_ARRAY:
5171 if (t1->data.array->rank != t2->data.array->rank)
5173 return t1->data.array->eklass == t2->data.array->eklass;
5174 case MONO_TYPE_GENERICINST: {
5176 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5178 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5180 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5181 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5187 case MONO_TYPE_MVAR:
5188 return t1->data.generic_param == t2->data.generic_param;
5190 g_error ("implement type compare for %0x!", t1->type);
5198 mymono_metadata_type_hash (MonoType *t1)
5204 hash |= t1->byref << 6; /* do not collide with t1->type values */
5206 case MONO_TYPE_VALUETYPE:
5207 case MONO_TYPE_CLASS:
5208 case MONO_TYPE_SZARRAY:
5209 /* check if the distribution is good enough */
5210 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5212 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5217 static MonoReflectionGenericInst*
5218 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5220 static MonoClass *System_Reflection_MonoGenericInst;
5221 MonoReflectionGenericInst *res;
5222 MonoGenericInst *ginst;
5225 if (!System_Reflection_MonoGenericInst) {
5226 System_Reflection_MonoGenericInst = mono_class_from_name (
5227 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5228 g_assert (System_Reflection_MonoGenericInst);
5231 ginst = geninst->data.generic_inst;
5232 gklass = mono_class_from_mono_type (ginst->generic_type);
5234 mono_class_init (ginst->klass);
5236 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5238 res->type.type = geninst;
5239 if (gklass->wastypebuilder && gklass->reflection_info)
5240 res->generic_type = gklass->reflection_info;
5242 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5248 * mono_type_get_object:
5249 * @domain: an app domain
5252 * Return an System.MonoType object representing the type @type.
5255 mono_type_get_object (MonoDomain *domain, MonoType *type)
5257 MonoReflectionType *res;
5258 MonoClass *klass = mono_class_from_mono_type (type);
5260 mono_domain_lock (domain);
5261 if (!domain->type_hash)
5262 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5263 (GCompareFunc)mymono_metadata_type_equal);
5264 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5265 mono_domain_unlock (domain);
5268 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5269 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5270 mono_g_hash_table_insert (domain->type_hash, type, res);
5271 mono_domain_unlock (domain);
5274 if (klass->reflection_info && !klass->wastypebuilder) {
5275 /* g_assert_not_reached (); */
5276 /* should this be considered an error condition? */
5278 mono_domain_unlock (domain);
5279 return klass->reflection_info;
5282 mono_class_init (klass);
5283 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5285 mono_g_hash_table_insert (domain->type_hash, type, res);
5286 mono_domain_unlock (domain);
5291 * mono_method_get_object:
5292 * @domain: an app domain
5294 * @refclass: the reflected type (can be NULL)
5296 * Return an System.Reflection.MonoMethod object representing the method @method.
5298 MonoReflectionMethod*
5299 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5302 * We use the same C representation for methods and constructors, but the type
5303 * name in C# is different.
5307 MonoReflectionMethod *ret;
5310 refclass = method->klass;
5312 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5313 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5314 cname = "MonoCMethod";
5316 cname = "MonoMethod";
5317 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5319 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5320 ret->method = method;
5321 ret->name = mono_string_new (domain, method->name);
5322 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5323 CACHE_OBJECT (method, ret, refclass);
5328 * mono_field_get_object:
5329 * @domain: an app domain
5333 * Return an System.Reflection.MonoField object representing the field @field
5336 MonoReflectionField*
5337 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5339 MonoReflectionField *res;
5342 CHECK_OBJECT (MonoReflectionField *, field, klass);
5343 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5344 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5347 res->name = mono_string_new (domain, field->name);
5348 if (field->generic_info)
5349 res->attrs = field->generic_info->generic_type->attrs;
5351 res->attrs = field->type->attrs;
5352 res->type = mono_type_get_object (domain, field->type);
5353 CACHE_OBJECT (field, res, klass);
5358 * mono_property_get_object:
5359 * @domain: an app domain
5361 * @property: a property
5363 * Return an System.Reflection.MonoProperty object representing the property @property
5366 MonoReflectionProperty*
5367 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5369 MonoReflectionProperty *res;
5372 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5373 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5374 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5376 res->property = property;
5377 CACHE_OBJECT (property, res, klass);
5382 * mono_event_get_object:
5383 * @domain: an app domain
5387 * Return an System.Reflection.MonoEvent object representing the event @event
5390 MonoReflectionEvent*
5391 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5393 MonoReflectionEvent *res;
5396 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5397 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5398 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5401 CACHE_OBJECT (event, res, klass);
5406 * mono_param_get_objects:
5407 * @domain: an app domain
5410 * Return an System.Reflection.ParameterInfo array object representing the parameters
5411 * in the method @method.
5414 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5416 static MonoClass *System_Reflection_ParameterInfo;
5417 MonoArray *res = NULL;
5418 MonoReflectionMethod *member = NULL;
5419 MonoReflectionParameter *param = NULL;
5420 char **names, **blobs = NULL;
5421 MonoObject *dbnull = mono_get_dbnull_object (domain);
5422 MonoMarshalSpec **mspecs;
5425 if (!System_Reflection_ParameterInfo)
5426 System_Reflection_ParameterInfo = mono_class_from_name (
5427 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5429 if (!method->signature->param_count)
5430 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5432 /* Note: the cache is based on the address of the signature into the method
5433 * since we already cache MethodInfos with the method as keys.
5435 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5437 member = mono_method_get_object (domain, method, NULL);
5438 names = g_new (char *, method->signature->param_count);
5439 mono_method_get_param_names (method, (const char **) names);
5441 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5442 mono_method_get_marshal_info (method, mspecs);
5444 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5445 for (i = 0; i < method->signature->param_count; ++i) {
5446 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5447 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5448 param->MemberImpl = (MonoObject*)member;
5449 param->NameImpl = mono_string_new (domain, names [i]);
5450 param->PositionImpl = i;
5451 param->AttrsImpl = method->signature->params [i]->attrs;
5453 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5454 param->DefaultValueImpl = dbnull;
5456 MonoType *type = param->ClassImpl->type;
5459 blobs = g_new0 (char *, method->signature->param_count);
5460 get_default_param_value_blobs (method, blobs);
5463 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5465 if (!param->DefaultValueImpl) {
5466 param->DefaultValueImpl = dbnull;
5471 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5473 mono_array_set (res, gpointer, i, param);
5478 for (i = method->signature->param_count; i >= 0; i--)
5480 mono_metadata_free_marshal_spec (mspecs [i]);
5483 CACHE_OBJECT (&(method->signature), res, NULL);
5488 * mono_method_body_get_object:
5489 * @domain: an app domain
5492 * Return an System.Reflection.MethodBody object representing the method @method.
5494 MonoReflectionMethodBody*
5495 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5497 static MonoClass *System_Reflection_MethodBody = NULL;
5498 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5499 MonoReflectionMethodBody *ret;
5500 MonoMethodNormal *mn;
5501 MonoMethodHeader *header;
5504 if (!System_Reflection_MethodBody)
5505 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5506 if (!System_Reflection_LocalVariableInfo)
5507 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5509 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5511 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5512 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5514 mn = (MonoMethodNormal *)method;
5515 header = mono_method_get_header (method);
5517 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5518 /* FIXME: Other fields */
5519 ret->init_locals = header->init_locals;
5520 ret->max_stack = header->max_stack;
5521 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5522 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5523 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5524 for (i = 0; i < header->num_locals; ++i) {
5525 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5526 info->local_type = mono_type_get_object (domain, header->locals [i]);
5527 info->is_pinned = header->locals [i]->pinned;
5528 info->local_index = 0;
5531 CACHE_OBJECT (method, ret, NULL);
5536 mono_get_dbnull_object (MonoDomain *domain)
5540 static MonoClassField *dbnull_value_field = NULL;
5542 if (!dbnull_value_field) {
5543 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5544 mono_class_init (klass);
5545 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5546 g_assert (dbnull_value_field);
5548 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5555 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5557 guint32 param_index, i, lastp, crow = 0;
5558 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5561 MonoClass *klass = method->klass;
5562 MonoImage *image = klass->image;
5563 MonoMethodSignature *methodsig = method->signature;
5565 MonoTableInfo *constt;
5566 MonoTableInfo *methodt;
5567 MonoTableInfo *paramt;
5569 if (!methodsig->param_count)
5572 if (klass->generic_inst) {
5573 return; /* FIXME - ??? */
5576 mono_class_init (klass);
5578 if (klass->image->dynamic) {
5579 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5580 if (aux && aux->param_defaults)
5581 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5585 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5586 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5587 constt = &image->tables [MONO_TABLE_CONSTANT];
5589 for (i = 0; i < klass->method.count; ++i) {
5590 if (method == klass->methods [i]) {
5591 idx = klass->method.first + i;
5596 g_assert (idx != -1);
5598 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5599 if (idx + 1 < methodt->rows)
5600 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5602 lastp = paramt->rows + 1;
5604 for (i = param_index; i < lastp; ++i) {
5607 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5608 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5610 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5613 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5618 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5619 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5626 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5635 klass = mono_class_from_mono_type (type);
5636 if (klass->valuetype) {
5637 object = mono_object_new (domain, klass);
5638 retval = ((gchar *) object + sizeof (MonoObject));
5643 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5650 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5654 memset (assembly, 0, sizeof (MonoAssemblyName));
5656 assembly->culture = "";
5657 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5659 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5662 while (*p == ' ' || *p == ',') {
5671 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5673 assembly->major = strtoul (p, &s, 10);
5674 if (s == p || *s != '.')
5677 assembly->minor = strtoul (p, &s, 10);
5678 if (s == p || *s != '.')
5681 assembly->build = strtoul (p, &s, 10);
5682 if (s == p || *s != '.')
5685 assembly->revision = strtoul (p, &s, 10);
5689 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5691 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5692 assembly->culture = "";
5695 assembly->culture = p;
5696 while (*p && *p != ',') {
5700 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5702 if (strncmp (p, "null", 4) == 0) {
5707 while (*p && *p != ',') {
5710 len = (p - start + 1);
5711 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5712 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5713 g_strlcpy (assembly->public_key_token, start, len);
5716 while (*p && *p != ',')
5720 while (*p == ' ' || *p == ',') {
5734 * mono_reflection_parse_type:
5737 * Parse a type name as accepted by the GetType () method and output the info
5738 * extracted in the info structure.
5739 * the name param will be mangled, so, make a copy before passing it to this function.
5740 * The fields in info will be valid until the memory pointed to by name is valid.
5741 * Returns 0 on parse error.
5742 * See also mono_type_get_name () below.
5745 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5747 char *start, *p, *w, *last_point, *startn;
5748 int in_modifiers = 0;
5749 int isbyref = 0, rank;
5751 start = p = w = name;
5753 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5754 info->name = info->name_space = NULL;
5755 info->nested = NULL;
5756 info->modifiers = NULL;
5758 /* last_point separates the namespace from the name */
5764 *p = 0; /* NULL terminate the name */
5766 info->nested = g_list_append (info->nested, startn);
5767 /* we have parsed the nesting namespace + name */
5771 info->name_space = start;
5773 info->name = last_point + 1;
5775 info->name_space = (char *)"";
5801 info->name_space = start;
5803 info->name = last_point + 1;
5805 info->name_space = (char *)"";
5812 if (isbyref) /* only one level allowed by the spec */
5815 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5819 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5830 else if (*p != '*') /* '*' means unknown lower bound */
5836 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5848 return 0; /* missing assembly name */
5849 if (!assembly_name_to_aname (&info->assembly, p))
5856 if (info->assembly.name)
5859 *w = 0; /* terminate class name */
5860 if (!info->name || !*info->name)
5862 /* add other consistency checks */
5867 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5874 image = mono_defaults.corlib;
5877 klass = mono_class_from_name_case (image, info->name_space, info->name);
5879 klass = mono_class_from_name (image, info->name_space, info->name);
5882 for (mod = info->nested; mod; mod = mod->next) {
5885 mono_class_init (klass);
5886 nested = klass->nested_classes;
5889 klass = nested->data;
5891 if (g_strcasecmp (klass->name, mod->data) == 0)
5894 if (strcmp (klass->name, mod->data) == 0)
5898 nested = nested->next;
5905 mono_class_init (klass);
5906 for (mod = info->modifiers; mod; mod = mod->next) {
5907 modval = GPOINTER_TO_UINT (mod->data);
5908 if (!modval) { /* byref: must be last modifier */
5909 return &klass->this_arg;
5910 } else if (modval == -1) {
5911 klass = mono_ptr_class_get (&klass->byval_arg);
5912 } else { /* array rank */
5913 klass = mono_array_class_get (klass, modval);
5915 mono_class_init (klass);
5918 return &klass->byval_arg;
5922 * mono_reflection_get_type:
5923 * @image: a metadata context
5924 * @info: type description structure
5925 * @ignorecase: flag for case-insensitive string compares
5926 * @type_resolve: whenever type resolve was already tried
5928 * Build a MonoType from the type description in @info.
5933 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5936 MonoReflectionAssembly *assembly;
5940 type = mono_reflection_get_type_internal (image, info, ignorecase);
5943 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5950 *type_resolve = TRUE;
5953 /* Reconstruct the type name */
5954 fullName = g_string_new ("");
5955 if (info->name_space && (info->name_space [0] != '\0'))
5956 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5958 g_string_printf (fullName, info->name);
5959 for (mod = info->nested; mod; mod = mod->next)
5960 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5962 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5964 if (assembly->assembly->dynamic) {
5965 /* Enumerate all modules */
5966 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5970 if (abuilder->modules) {
5971 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5972 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5973 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5979 if (!type && abuilder->loaded_modules) {
5980 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5981 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5982 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5989 type = mono_reflection_get_type_internal (assembly->assembly->image,
5992 g_string_free (fullName, TRUE);
5997 * mono_reflection_type_from_name:
5999 * @image: a metadata context (can be NULL).
6001 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6002 * it defaults to get the type from @image or, if @image is NULL or loading
6003 * from it fails, uses corlib.
6007 mono_reflection_type_from_name (char *name, MonoImage *image)
6010 MonoTypeNameParse info;
6011 MonoAssembly *assembly;
6013 gboolean type_resolve = FALSE;
6015 /* Make a copy since parse_type modifies its argument */
6016 tmp = g_strdup (name);
6018 /*g_print ("requested type %s\n", str);*/
6019 if (!mono_reflection_parse_type (tmp, &info)) {
6021 g_list_free (info.modifiers);
6022 g_list_free (info.nested);
6026 if (info.assembly.name) {
6027 assembly = mono_assembly_loaded (&info.assembly);
6029 /* then we must load the assembly ourselve - see #60439 */
6030 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6033 g_list_free (info.modifiers);
6034 g_list_free (info.nested);
6038 image = assembly->image;
6039 } else if (image == NULL) {
6040 image = mono_defaults.corlib;
6043 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6044 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6045 image = mono_defaults.corlib;
6046 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6050 g_list_free (info.modifiers);
6051 g_list_free (info.nested);
6056 * mono_reflection_get_token:
6058 * Return the metadata token of OBJ which should be an object
6059 * representing a metadata element.
6062 mono_reflection_get_token (MonoObject *obj)
6067 klass = obj->vtable->klass;
6069 if (strcmp (klass->name, "MethodBuilder") == 0) {
6070 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6072 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6073 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6074 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6076 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6077 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6078 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6079 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6080 if (tb->generic_params) {
6081 g_assert_not_reached ();
6083 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6085 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6086 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6087 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6088 } else if (strcmp (klass->name, "MonoType") == 0) {
6089 MonoReflectionType *tb = (MonoReflectionType *)obj;
6090 token = mono_class_from_mono_type (tb->type)->type_token;
6091 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6092 strcmp (klass->name, "MonoMethod") == 0) {
6093 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6094 if (m->method->signature->is_inflated) {
6095 g_assert_not_reached ();
6096 } else if (m->method->signature->generic_param_count) {
6097 g_assert_not_reached ();
6098 } else if (m->method->klass->generic_inst) {
6099 g_assert_not_reached ();
6101 token = m->method->token;
6103 } else if (strcmp (klass->name, "MonoField") == 0) {
6104 MonoReflectionField *f = (MonoReflectionField*)obj;
6106 token = mono_class_get_field_token (f->field);
6107 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6108 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6110 token = mono_class_get_property_token (p->property);
6111 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6112 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6114 token = mono_class_get_event_token (p->event);
6115 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6116 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6118 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6119 } else if (strcmp (klass->name, "Module") == 0) {
6120 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6123 } else if (strcmp (klass->name, "Assembly") == 0) {
6124 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6126 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6127 MonoException *ex = mono_get_exception_not_implemented (msg);
6129 mono_raise_exception (ex);
6136 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6138 int slen, type = t->type;
6143 case MONO_TYPE_BOOLEAN: {
6144 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6149 case MONO_TYPE_CHAR:
6151 case MONO_TYPE_I2: {
6152 guint16 *val = g_malloc (sizeof (guint16));
6157 #if SIZEOF_VOID_P == 4
6163 case MONO_TYPE_I4: {
6164 guint32 *val = g_malloc (sizeof (guint32));
6169 #if SIZEOF_VOID_P == 8
6170 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6175 case MONO_TYPE_I8: {
6176 guint64 *val = g_malloc (sizeof (guint64));
6181 case MONO_TYPE_VALUETYPE:
6182 if (t->data.klass->enumtype) {
6183 type = t->data.klass->enum_basetype->type;
6186 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6189 case MONO_TYPE_STRING:
6190 if (*p == (char)0xFF) {
6194 slen = mono_metadata_decode_value (p, &p);
6196 return mono_string_new_len (mono_domain_get (), p, slen);
6197 case MONO_TYPE_CLASS: {
6200 if (*p == (char)0xFF) {
6205 slen = mono_metadata_decode_value (p, &p);
6206 n = g_memdup (p, slen + 1);
6208 t = mono_reflection_type_from_name (n, image);
6210 g_warning ("Cannot load type '%s'", n);
6214 return mono_type_get_object (mono_domain_get (), t);
6218 case MONO_TYPE_OBJECT: {
6221 MonoClass *subc = NULL;
6226 } else if (subt == 0x0E) {
6227 type = MONO_TYPE_STRING;
6229 } else if (subt == 0x55) {
6232 slen = mono_metadata_decode_value (p, &p);
6233 n = g_memdup (p, slen + 1);
6235 t = mono_reflection_type_from_name (n, image);
6237 g_warning ("Cannot load type '%s'", n);
6240 subc = mono_class_from_mono_type (t);
6241 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6242 MonoType simple_type = {{0}};
6243 simple_type.type = subt;
6244 subc = mono_class_from_mono_type (&simple_type);
6246 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6248 val = load_cattr_value (image, &subc->byval_arg, p, end);
6249 obj = mono_object_new (mono_domain_get (), subc);
6250 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6254 case MONO_TYPE_SZARRAY: {
6256 guint32 i, alen, basetype;
6259 if (alen == 0xffffffff) {
6263 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6264 basetype = t->data.klass->byval_arg.type;
6269 case MONO_TYPE_BOOLEAN:
6270 for (i = 0; i < alen; i++) {
6271 MonoBoolean val = *p++;
6272 mono_array_set (arr, MonoBoolean, i, val);
6275 case MONO_TYPE_CHAR:
6278 for (i = 0; i < alen; i++) {
6279 guint16 val = read16 (p);
6280 mono_array_set (arr, guint16, i, val);
6287 for (i = 0; i < alen; i++) {
6288 guint32 val = read32 (p);
6289 mono_array_set (arr, guint32, i, val);
6296 for (i = 0; i < alen; i++) {
6297 guint64 val = read64 (p);
6298 mono_array_set (arr, guint64, i, val);
6302 case MONO_TYPE_CLASS:
6303 case MONO_TYPE_OBJECT:
6304 case MONO_TYPE_STRING:
6305 for (i = 0; i < alen; i++) {
6306 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6307 mono_array_set (arr, gpointer, i, item);
6311 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6317 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6323 type_is_reference (MonoType *type)
6325 switch (type->type) {
6326 case MONO_TYPE_BOOLEAN:
6327 case MONO_TYPE_CHAR:
6340 case MONO_TYPE_VALUETYPE:
6348 free_param_data (MonoMethodSignature *sig, void **params) {
6350 for (i = 0; i < sig->param_count; ++i) {
6351 if (!type_is_reference (sig->params [i]))
6352 g_free (params [i]);
6357 * Find the method index in the metadata methodDef table.
6358 * Later put these three helper methods in metadata and export them.
6361 find_method_index (MonoMethod *method) {
6362 MonoClass *klass = method->klass;
6365 for (i = 0; i < klass->method.count; ++i) {
6366 if (method == klass->methods [i])
6367 return klass->method.first + 1 + i;
6373 * Find the field index in the metadata FieldDef table.
6376 find_field_index (MonoClass *klass, MonoClassField *field) {
6379 for (i = 0; i < klass->field.count; ++i) {
6380 if (field == &klass->fields [i])
6381 return klass->field.first + 1 + i;
6387 * Find the property index in the metadata Property table.
6390 find_property_index (MonoClass *klass, MonoProperty *property) {
6393 for (i = 0; i < klass->property.count; ++i) {
6394 if (property == &klass->properties [i])
6395 return klass->property.first + 1 + i;
6401 * Find the event index in the metadata Event table.
6404 find_event_index (MonoClass *klass, MonoEvent *event) {
6407 for (i = 0; i < klass->event.count; ++i) {
6408 if (event == &klass->events [i])
6409 return klass->event.first + 1 + i;
6415 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6417 const char *p = data;
6419 guint32 i, j, num_named;
6423 mono_class_init (method->klass);
6426 attr = mono_object_new (mono_domain_get (), method->klass);
6427 mono_runtime_invoke (method, attr, NULL, NULL);
6431 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6434 /*g_print ("got attr %s\n", method->klass->name);*/
6436 params = g_new (void*, method->signature->param_count);
6440 for (i = 0; i < method->signature->param_count; ++i) {
6441 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6445 attr = mono_object_new (mono_domain_get (), method->klass);
6446 mono_runtime_invoke (method, attr, params, NULL);
6447 free_param_data (method->signature, params);
6449 num_named = read16 (named);
6451 for (j = 0; j < num_named; j++) {
6453 char *name, named_type, data_type;
6454 named_type = *named++;
6455 data_type = *named++; /* type of data */
6456 if (data_type == 0x55) {
6459 type_len = mono_metadata_decode_blob_size (named, &named);
6460 type_name = g_malloc (type_len + 1);
6461 memcpy (type_name, named, type_len);
6462 type_name [type_len] = 0;
6464 /* FIXME: lookup the type and check type consistency */
6465 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6466 /* this seems to be the type of the element of the array */
6467 /* g_print ("skipping 0x%02x after prop\n", *named); */
6470 name_len = mono_metadata_decode_blob_size (named, &named);
6471 name = g_malloc (name_len + 1);
6472 memcpy (name, named, name_len);
6473 name [name_len] = 0;
6475 if (named_type == 0x53) {
6476 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6477 void *val = load_cattr_value (image, field->type, named, &named);
6478 mono_field_set_value (attr, field, val);
6479 if (!type_is_reference (field->type))
6481 } else if (named_type == 0x54) {
6484 MonoType *prop_type;
6486 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6487 /* can we have more that 1 arg in a custom attr named property? */
6488 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6489 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6490 mono_property_set_value (prop, attr, pparams, NULL);
6491 if (!type_is_reference (prop_type))
6492 g_free (pparams [0]);
6501 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6508 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6509 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6510 for (i = 0; i < cinfo->num_attrs; ++i) {
6511 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6512 mono_array_set (result, gpointer, i, attr);
6518 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6520 guint32 mtoken, i, len;
6521 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6523 MonoCustomAttrInfo *ainfo;
6524 GList *tmp, *list = NULL;
6527 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6529 i = mono_metadata_custom_attrs_from_index (image, idx);
6533 while (i < ca->rows) {
6534 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6536 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6539 len = g_list_length (list);
6542 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6543 ainfo->num_attrs = len;
6544 ainfo->image = image;
6545 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6546 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6547 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6548 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6549 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6550 mtoken |= MONO_TOKEN_METHOD_DEF;
6552 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6553 mtoken |= MONO_TOKEN_MEMBER_REF;
6556 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6559 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6560 if (!ainfo->attrs [i].ctor)
6561 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6562 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6563 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6564 ainfo->attrs [i].data = data;
6572 mono_custom_attrs_from_method (MonoMethod *method)
6574 MonoCustomAttrInfo *cinfo;
6577 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6579 idx = find_method_index (method);
6580 idx <<= MONO_CUSTOM_ATTR_BITS;
6581 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6582 return mono_custom_attrs_from_index (method->klass->image, idx);
6586 mono_custom_attrs_from_class (MonoClass *klass)
6588 MonoCustomAttrInfo *cinfo;
6591 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6593 idx = mono_metadata_token_index (klass->type_token);
6594 idx <<= MONO_CUSTOM_ATTR_BITS;
6595 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6596 return mono_custom_attrs_from_index (klass->image, idx);
6600 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6602 MonoCustomAttrInfo *cinfo;
6605 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6607 idx = 1; /* there is only one assembly */
6608 idx <<= MONO_CUSTOM_ATTR_BITS;
6609 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6610 return mono_custom_attrs_from_index (assembly->image, idx);
6613 static MonoCustomAttrInfo*
6614 mono_custom_attrs_from_module (MonoImage *image)
6616 MonoCustomAttrInfo *cinfo;
6619 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6621 idx = 1; /* there is only one module */
6622 idx <<= MONO_CUSTOM_ATTR_BITS;
6623 idx |= MONO_CUSTOM_ATTR_MODULE;
6624 return mono_custom_attrs_from_index (image, idx);
6628 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6630 MonoCustomAttrInfo *cinfo;
6633 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6635 idx = find_property_index (klass, property);
6636 idx <<= MONO_CUSTOM_ATTR_BITS;
6637 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6638 return mono_custom_attrs_from_index (klass->image, idx);
6642 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6644 MonoCustomAttrInfo *cinfo;
6647 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6649 idx = find_event_index (klass, event);
6650 idx <<= MONO_CUSTOM_ATTR_BITS;
6651 idx |= MONO_CUSTOM_ATTR_EVENT;
6652 return mono_custom_attrs_from_index (klass->image, idx);
6656 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6658 MonoCustomAttrInfo *cinfo;
6661 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6663 idx = find_field_index (klass, field);
6664 idx <<= MONO_CUSTOM_ATTR_BITS;
6665 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6666 return mono_custom_attrs_from_index (klass->image, idx);
6670 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6673 guint32 i, idx, method_index;
6674 guint32 param_list, param_last, param_pos, found;
6676 MonoReflectionMethodAux *aux;
6678 if (method->klass->image->dynamic) {
6679 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6680 if (!aux || !aux->param_cattr)
6682 return aux->param_cattr [param];
6685 image = method->klass->image;
6686 method_index = find_method_index (method);
6687 ca = &image->tables [MONO_TABLE_METHOD];
6689 if (method->klass->generic_inst || method->klass->generic_container ||
6690 method->signature->generic_param_count) {
6691 /* FIXME FIXME FIXME */
6695 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6696 if (method_index == ca->rows) {
6697 ca = &image->tables [MONO_TABLE_PARAM];
6698 param_last = ca->rows + 1;
6700 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6701 ca = &image->tables [MONO_TABLE_PARAM];
6704 for (i = param_list; i < param_last; ++i) {
6705 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6706 if (param_pos == param) {
6714 idx <<= MONO_CUSTOM_ATTR_BITS;
6715 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6716 return mono_custom_attrs_from_index (image, idx);
6720 * mono_reflection_get_custom_attrs:
6721 * @obj: a reflection object handle
6723 * Return an array with all the custom attributes defined of the
6724 * reflection handle @obj. The objects are fully build.
6727 mono_reflection_get_custom_attrs (MonoObject *obj)
6731 MonoCustomAttrInfo *cinfo = NULL;
6733 MONO_ARCH_SAVE_REGS;
6735 klass = obj->vtable->klass;
6736 if (klass == mono_defaults.monotype_class) {
6737 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6738 klass = mono_class_from_mono_type (rtype->type);
6739 cinfo = mono_custom_attrs_from_class (klass);
6740 } else if (strcmp ("Assembly", klass->name) == 0) {
6741 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6742 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6743 } else if (strcmp ("Module", klass->name) == 0) {
6744 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6745 cinfo = mono_custom_attrs_from_module (module->image);
6746 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6747 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6748 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6749 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6750 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6751 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6752 } else if (strcmp ("MonoField", klass->name) == 0) {
6753 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6754 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6755 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6756 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6757 cinfo = mono_custom_attrs_from_method (rmethod->method);
6758 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6759 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6760 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6761 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6762 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6763 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6764 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6765 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6766 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6767 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6768 } else { /* handle other types here... */
6769 g_error ("get custom attrs not yet supported for %s", klass->name);
6773 result = mono_custom_attrs_construct (cinfo);
6775 mono_custom_attrs_free (cinfo);
6777 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6778 result = mono_array_new (mono_domain_get (), klass, 0);
6784 static MonoMethodSignature*
6785 parameters_to_signature (MonoArray *parameters) {
6786 MonoMethodSignature *sig;
6789 count = parameters? mono_array_length (parameters): 0;
6791 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6792 sig->param_count = count;
6793 sig->sentinelpos = -1; /* FIXME */
6794 for (i = 0; i < count; ++i) {
6795 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6796 sig->params [i] = pt->type;
6801 static MonoMethodSignature*
6802 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6803 MonoMethodSignature *sig;
6805 sig = parameters_to_signature (ctor->parameters);
6806 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6807 sig->ret = &mono_defaults.void_class->byval_arg;
6811 static MonoMethodSignature*
6812 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6813 MonoMethodSignature *sig;
6815 sig = parameters_to_signature (method->parameters);
6816 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6817 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6818 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6822 static MonoMethodSignature*
6823 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6824 MonoMethodSignature *sig;
6826 sig = parameters_to_signature (method->parameters);
6827 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6828 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6829 sig->generic_param_count = 0;
6834 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6836 MonoClass *klass = mono_object_class (prop);
6837 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6838 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6839 *name = mono_string_to_utf8 (pb->name);
6840 *type = pb->type->type;
6842 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6843 *name = g_strdup (p->property->name);
6844 if (p->property->get)
6845 *type = p->property->get->signature->ret;
6847 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6852 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6854 MonoClass *klass = mono_object_class (field);
6855 if (strcmp (klass->name, "FieldBuilder") == 0) {
6856 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6857 *name = mono_string_to_utf8 (fb->name);
6858 *type = fb->type->type;
6860 MonoReflectionField *f = (MonoReflectionField *)field;
6861 *name = g_strdup (f->field->name);
6862 *type = f->field->type;
6867 * Encode a value in a custom attribute stream of bytes.
6868 * The value to encode is either supplied as an object in argument val
6869 * (valuetypes are boxed), or as a pointer to the data in the
6871 * @type represents the type of the value
6872 * @buffer is the start of the buffer
6873 * @p the current position in the buffer
6874 * @buflen contains the size of the buffer and is used to return the new buffer size
6875 * if this needs to be realloced.
6876 * @retbuffer and @retp return the start and the position of the buffer
6879 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6881 MonoTypeEnum simple_type;
6883 if ((p-buffer) + 10 >= *buflen) {
6886 newbuf = g_realloc (buffer, *buflen);
6887 p = newbuf + (p-buffer);
6891 argval = ((char*)arg + sizeof (MonoObject));
6892 simple_type = type->type;
6894 switch (simple_type) {
6895 case MONO_TYPE_BOOLEAN:
6900 case MONO_TYPE_CHAR:
6903 swap_with_size (p, argval, 2, 1);
6909 swap_with_size (p, argval, 4, 1);
6915 swap_with_size (p, argval, 8, 1);
6918 case MONO_TYPE_VALUETYPE:
6919 if (type->data.klass->enumtype) {
6920 simple_type = type->data.klass->enum_basetype->type;
6923 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6926 case MONO_TYPE_STRING: {
6933 str = mono_string_to_utf8 ((MonoString*)arg);
6934 slen = strlen (str);
6935 if ((p-buffer) + 10 + slen >= *buflen) {
6939 newbuf = g_realloc (buffer, *buflen);
6940 p = newbuf + (p-buffer);
6943 mono_metadata_encode_value (slen, p, &p);
6944 memcpy (p, str, slen);
6949 case MONO_TYPE_CLASS: {
6957 k = mono_object_class (arg);
6958 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6959 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6960 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6962 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6963 slen = strlen (str);
6964 if ((p-buffer) + 10 + slen >= *buflen) {
6968 newbuf = g_realloc (buffer, *buflen);
6969 p = newbuf + (p-buffer);
6972 mono_metadata_encode_value (slen, p, &p);
6973 memcpy (p, str, slen);
6978 case MONO_TYPE_SZARRAY: {
6980 MonoClass *eclass, *arg_eclass;
6983 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6986 len = mono_array_length ((MonoArray*)arg);
6988 *p++ = (len >> 8) & 0xff;
6989 *p++ = (len >> 16) & 0xff;
6990 *p++ = (len >> 24) & 0xff;
6992 *retbuffer = buffer;
6993 eclass = type->data.klass;
6994 arg_eclass = mono_object_class (arg)->element_class;
6995 if (eclass->valuetype && arg_eclass->valuetype) {
6996 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6997 int elsize = mono_class_array_element_size (eclass);
6998 for (i = 0; i < len; ++i) {
6999 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7003 for (i = 0; i < len; ++i) {
7004 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7009 /* it may be a boxed value or a Type */
7010 case MONO_TYPE_OBJECT: {
7011 MonoClass *klass = mono_object_class (arg);
7015 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7018 } else if (klass->enumtype) {
7020 } else if (klass == mono_defaults.string_class) {
7021 simple_type = MONO_TYPE_STRING;
7024 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7025 *p++ = simple_type = klass->byval_arg.type;
7028 g_error ("unhandled type in custom attr");
7030 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7031 slen = strlen (str);
7032 if ((p-buffer) + 10 + slen >= *buflen) {
7036 newbuf = g_realloc (buffer, *buflen);
7037 p = newbuf + (p-buffer);
7040 mono_metadata_encode_value (slen, p, &p);
7041 memcpy (p, str, slen);
7044 simple_type = klass->enum_basetype->type;
7048 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7051 *retbuffer = buffer;
7055 * mono_reflection_get_custom_attrs_blob:
7056 * @ctor: custom attribute constructor
7057 * @ctorArgs: arguments o the constructor
7063 * Creates the blob of data that needs to be saved in the metadata and that represents
7064 * the custom attributed described by @ctor, @ctorArgs etc.
7065 * Returns: a Byte array representing the blob of data.
7068 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7071 MonoMethodSignature *sig;
7076 MONO_ARCH_SAVE_REGS;
7078 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7079 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7081 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7083 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7085 p = buffer = g_malloc (buflen);
7086 /* write the prolog */
7089 for (i = 0; i < sig->param_count; ++i) {
7090 arg = mono_array_get (ctorArgs, MonoObject*, i);
7091 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7095 i += mono_array_length (properties);
7097 i += mono_array_length (fields);
7099 *p++ = (i >> 8) & 0xff;
7102 for (i = 0; i < mono_array_length (properties); ++i) {
7107 prop = mono_array_get (properties, gpointer, i);
7108 get_prop_name_and_type (prop, &pname, &ptype);
7109 *p++ = 0x54; /* PROPERTY signature */
7111 /* Preallocate a large enough buffer */
7112 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7113 char *str = type_get_qualified_name (ptype, NULL);
7119 len += strlen (pname);
7121 if ((p-buffer) + 20 + len >= buflen) {
7125 newbuf = g_realloc (buffer, buflen);
7126 p = newbuf + (p-buffer);
7130 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7131 char *str = type_get_qualified_name (ptype, NULL);
7132 int slen = strlen (str);
7136 * This seems to be optional...
7139 mono_metadata_encode_value (slen, p, &p);
7140 memcpy (p, str, slen);
7144 mono_metadata_encode_value (ptype->type, p, &p);
7145 if (ptype->type == MONO_TYPE_SZARRAY)
7146 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7148 len = strlen (pname);
7149 mono_metadata_encode_value (len, p, &p);
7150 memcpy (p, pname, len);
7152 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7159 for (i = 0; i < mono_array_length (fields); ++i) {
7164 field = mono_array_get (fields, gpointer, i);
7165 get_field_name_and_type (field, &fname, &ftype);
7166 *p++ = 0x53; /* FIELD signature */
7167 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7168 char *str = type_get_qualified_name (ftype, NULL);
7169 int slen = strlen (str);
7170 if ((p-buffer) + 10 + slen >= buflen) {
7174 newbuf = g_realloc (buffer, buflen);
7175 p = newbuf + (p-buffer);
7180 * This seems to be optional...
7183 mono_metadata_encode_value (slen, p, &p);
7184 memcpy (p, str, slen);
7188 mono_metadata_encode_value (ftype->type, p, &p);
7189 if (ftype->type == MONO_TYPE_SZARRAY)
7190 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7192 len = strlen (fname);
7193 mono_metadata_encode_value (len, p, &p);
7194 memcpy (p, fname, len);
7196 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7201 g_assert (p - buffer <= buflen);
7202 buflen = p - buffer;
7203 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7204 p = mono_array_addr (result, char, 0);
7205 memcpy (p, buffer, buflen);
7207 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7213 * mono_reflection_setup_internal_class:
7214 * @tb: a TypeBuilder object
7216 * Creates a MonoClass that represents the TypeBuilder.
7217 * This is a trick that lets us simplify a lot of reflection code
7218 * (and will allow us to support Build and Run assemblies easier).
7221 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7223 MonoClass *klass, *parent;
7225 MONO_ARCH_SAVE_REGS;
7228 /* check so we can compile corlib correctly */
7229 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7230 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7231 parent = tb->parent->type->data.klass;
7233 parent = my_mono_class_from_mono_type (tb->parent->type);
7239 /* the type has already being created: it means we just have to change the parent */
7240 if (tb->type.type) {
7241 klass = mono_class_from_mono_type (tb->type.type);
7242 klass->parent = NULL;
7243 /* fool mono_class_setup_parent */
7244 g_free (klass->supertypes);
7245 klass->supertypes = NULL;
7246 mono_class_setup_parent (klass, parent);
7247 mono_class_setup_mono_type (klass);
7251 klass = g_new0 (MonoClass, 1);
7253 klass->image = &tb->module->dynamic_image->image;
7255 klass->inited = 1; /* we lie to the runtime */
7256 klass->name = mono_string_to_utf8 (tb->name);
7257 klass->name_space = mono_string_to_utf8 (tb->nspace);
7258 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7259 klass->flags = tb->attrs;
7261 klass->element_class = klass;
7262 klass->reflection_info = tb; /* need to pin. */
7264 /* Put into cache so mono_class_get () will find it */
7265 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7267 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7268 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7270 if (parent != NULL) {
7271 mono_class_setup_parent (klass, parent);
7272 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7273 const char *old_n = klass->name;
7274 /* trick to get relative numbering right when compiling corlib */
7275 klass->name = "BuildingObject";
7276 mono_class_setup_parent (klass, mono_defaults.object_class);
7277 klass->name = old_n;
7280 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7281 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7282 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7283 klass->instance_size = sizeof (MonoObject);
7284 klass->size_inited = 1;
7285 mono_class_setup_vtable (klass, NULL, 0);
7288 mono_class_setup_mono_type (klass);
7290 mono_class_setup_supertypes (klass);
7293 * FIXME: handle interfaces.
7296 tb->type.type = &klass->byval_arg;
7298 if (tb->nesting_type) {
7299 g_assert (tb->nesting_type->type);
7300 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7303 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7307 * mono_reflection_setup_generic_class:
7308 * @tb: a TypeBuilder object
7310 * Setup the generic class before adding the first generic parameter.
7313 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7317 MONO_ARCH_SAVE_REGS;
7319 klass = my_mono_class_from_mono_type (tb->type.type);
7320 if (tb->generic_container)
7323 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7324 tb->generic_container->klass = klass;
7326 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7327 tb->generic_container->context->container = tb->generic_container;
7331 * mono_reflection_create_generic_class:
7332 * @tb: a TypeBuilder object
7334 * Creates the generic class after all generic parameters have been added.
7337 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7342 MONO_ARCH_SAVE_REGS;
7344 klass = my_mono_class_from_mono_type (tb->type.type);
7346 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7348 if (klass->generic_container || (count == 0))
7351 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7353 klass->generic_container = tb->generic_container;
7355 klass->generic_container->type_argc = count;
7356 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7358 for (i = 0; i < count; i++) {
7359 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7360 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7361 g_assert (klass->generic_container->type_params [i].owner);
7366 * mono_reflection_create_internal_class:
7367 * @tb: a TypeBuilder object
7369 * Actually create the MonoClass that is associated with the TypeBuilder.
7372 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7376 MONO_ARCH_SAVE_REGS;
7378 klass = my_mono_class_from_mono_type (tb->type.type);
7380 if (klass->enumtype && klass->enum_basetype == NULL) {
7381 MonoReflectionFieldBuilder *fb;
7384 g_assert (tb->fields != NULL);
7385 g_assert (mono_array_length (tb->fields) >= 1);
7387 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7389 klass->enum_basetype = fb->type->type;
7390 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7391 if (!klass->element_class)
7392 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7395 * get the element_class from the current corlib.
7397 ec = default_class_from_mono_type (klass->enum_basetype);
7398 klass->instance_size = ec->instance_size;
7399 klass->size_inited = 1;
7401 * this is almost safe to do with enums and it's needed to be able
7402 * to create objects of the enum type (for use in SetConstant).
7404 /* FIXME: Does this mean enums can't have method overrides ? */
7405 mono_class_setup_vtable (klass, NULL, 0);
7409 static MonoMarshalSpec*
7410 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7411 MonoReflectionMarshal *minfo)
7413 MonoMarshalSpec *res;
7415 res = g_new0 (MonoMarshalSpec, 1);
7416 res->native = minfo->type;
7418 switch (minfo->type) {
7419 case MONO_NATIVE_LPARRAY:
7420 res->data.array_data.elem_type = minfo->eltype;
7421 res->data.array_data.param_num = 0; /* Not yet */
7422 res->data.array_data.num_elem = minfo->count;
7425 case MONO_NATIVE_BYVALTSTR:
7426 case MONO_NATIVE_BYVALARRAY:
7427 res->data.array_data.num_elem = minfo->count;
7430 case MONO_NATIVE_CUSTOM:
7431 if (minfo->marshaltyperef)
7432 res->data.custom_data.custom_name =
7433 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7435 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7445 MonoReflectionMarshal*
7446 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7447 MonoMarshalSpec *spec)
7449 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7450 MonoReflectionMarshal *minfo;
7453 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7454 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7455 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7456 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7459 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7460 minfo->type = spec->native;
7462 switch (minfo->type) {
7463 case MONO_NATIVE_LPARRAY:
7464 minfo->eltype = spec->data.array_data.elem_type;
7465 minfo->count = spec->data.array_data.num_elem;
7468 case MONO_NATIVE_BYVALTSTR:
7469 case MONO_NATIVE_BYVALARRAY:
7470 minfo->count = spec->data.array_data.num_elem;
7473 case MONO_NATIVE_CUSTOM:
7474 if (spec->data.custom_data.custom_name) {
7475 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7477 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7479 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7481 if (spec->data.custom_data.cookie)
7482 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7493 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7494 ReflectionMethodBuilder *rmb,
7495 MonoMethodSignature *sig)
7498 MonoMethodNormal *pm;
7499 MonoMarshalSpec **specs;
7500 MonoReflectionMethodAux *method_aux;
7503 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7504 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7505 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7507 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7509 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7511 pm = (MonoMethodNormal*)m;
7514 m->flags = rmb->attrs;
7515 m->iflags = rmb->iattrs;
7516 m->name = mono_string_to_utf8 (rmb->name);
7520 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7522 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7523 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7526 m->signature->pinvoke = 1;
7527 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7528 m->signature->pinvoke = 1;
7530 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7532 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7533 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7535 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7537 if (klass->image->dynamic)
7538 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7541 } else if (!m->klass->dummy &&
7542 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7543 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7544 MonoMethodHeader *header;
7546 gint32 max_stack, i;
7547 gint32 num_locals = 0;
7548 gint32 num_clauses = 0;
7552 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7553 code_size = rmb->ilgen->code_len;
7554 max_stack = rmb->ilgen->max_stack;
7555 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7556 if (rmb->ilgen->ex_handlers)
7557 num_clauses = method_count_clauses (rmb->ilgen);
7560 code = mono_array_addr (rmb->code, guint8, 0);
7561 code_size = mono_array_length (rmb->code);
7562 /* we probably need to run a verifier on the code... */
7572 header = g_malloc0 (sizeof (MonoMethodHeader) +
7573 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7574 header->code_size = code_size;
7575 header->code = g_malloc (code_size);
7576 memcpy ((char*)header->code, code, code_size);
7577 header->max_stack = max_stack;
7578 header->init_locals = rmb->init_locals;
7579 header->num_locals = num_locals;
7581 for (i = 0; i < num_locals; ++i) {
7582 MonoReflectionLocalBuilder *lb =
7583 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7585 header->locals [i] = g_new0 (MonoType, 1);
7586 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7589 header->num_clauses = num_clauses;
7591 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7592 rmb->ilgen, num_clauses);
7595 pm->header = header;
7598 if (rmb->generic_params) {
7599 int count = mono_array_length (rmb->generic_params);
7600 MonoGenericContainer *container;
7602 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7603 container->type_argc = count;
7604 container->type_params = g_new0 (MonoGenericParam, count);
7606 for (i = 0; i < count; i++) {
7607 MonoReflectionGenericParam *gp =
7608 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7610 container->type_params [i] = *gp->type.type->data.generic_param;
7615 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7618 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7620 for (i = 0; i < rmb->nrefs; ++i)
7621 mw->data = g_list_append (mw->data, rmb->refs [i]);
7626 /* Parameter info */
7629 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7630 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7631 for (i = 0; i <= m->signature->param_count; ++i) {
7632 MonoReflectionParamBuilder *pb;
7633 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7635 m->signature->params [i - 1]->attrs = pb->attrs;
7637 if (pb->def_value) {
7638 MonoDynamicImage *assembly;
7639 guint32 idx, def_type, len;
7643 if (!method_aux->param_defaults)
7644 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7645 assembly = (MonoDynamicImage*)klass->image;
7646 idx = encode_constant (assembly, pb->def_value, &def_type);
7647 /* Copy the data from the blob since it might get realloc-ed */
7648 p = assembly->blob.data + idx;
7649 len = mono_metadata_decode_blob_size (p, &p2);
7651 method_aux->param_defaults [i] = g_malloc (len);
7652 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7656 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7658 if (!method_aux->param_cattr)
7659 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7660 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7666 /* Parameter marshalling */
7669 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7670 MonoReflectionParamBuilder *pb;
7671 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7672 if (pb->marshal_info) {
7674 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7675 specs [pb->position] =
7676 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7680 if (specs != NULL) {
7682 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7683 method_aux->param_marshall = specs;
7686 if (klass->image->dynamic && method_aux)
7687 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7693 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7695 ReflectionMethodBuilder rmb;
7696 MonoMethodSignature *sig;
7698 sig = ctor_builder_to_signature (mb);
7700 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7702 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7703 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7705 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7706 /* ilgen is no longer needed */
7714 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7716 ReflectionMethodBuilder rmb;
7717 MonoMethodSignature *sig;
7719 sig = method_builder_to_signature (mb);
7721 reflection_methodbuilder_from_method_builder (&rmb, mb);
7723 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7724 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7726 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7727 /* ilgen is no longer needed */
7733 static MonoClassField*
7734 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7736 MonoClassField *field;
7743 field = g_new0 (MonoClassField, 1);
7745 field->name = mono_string_to_utf8 (fb->name);
7747 /* FIXME: handle type modifiers */
7748 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7749 field->type->attrs = fb->attrs;
7751 field->type = fb->type->type;
7753 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7754 field->data = mono_array_addr (fb->rva_data, char, 0);
7755 if (fb->offset != -1)
7756 field->offset = fb->offset;
7757 field->parent = klass;
7759 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7761 if (fb->def_value) {
7762 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7763 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7764 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7765 /* Copy the data from the blob since it might get realloc-ed */
7766 p = assembly->blob.data + idx;
7767 len = mono_metadata_decode_blob_size (p, &p2);
7769 field->data = g_malloc (len);
7770 memcpy ((gpointer)field->data, p, len);
7777 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7779 MonoClass *klass, *gklass;
7780 MonoReflectionTypeBuilder *tb = NULL;
7781 MonoGenericInst *ginst, *cached;
7786 klass = mono_class_from_mono_type (type->type);
7787 if (!klass->generic_container && !klass->generic_inst &&
7788 !(klass->nested_in && klass->nested_in->generic_container))
7791 mono_loader_lock ();
7793 domain = mono_object_domain (type);
7795 ginst = g_new0 (MonoGenericInst, 1);
7797 ginst->type_argc = type_argc;
7798 ginst->type_argv = types;
7800 for (i = 0; i < ginst->type_argc; ++i) {
7801 if (!ginst->is_open)
7802 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7805 ginst->generic_type = &klass->byval_arg;
7807 if (klass->generic_inst) {
7808 MonoGenericInst *kginst = klass->generic_inst;
7809 MonoGenericInst *oginst = ginst;
7811 oginst->context = g_new0 (MonoGenericContext, 1);
7812 oginst->context->ginst = oginst;
7814 ginst = g_new0 (MonoGenericInst, 1);
7816 ginst->type_argc = kginst->type_argc;
7817 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7819 for (i = 0; i < ginst->type_argc; i++) {
7820 MonoType *t = kginst->type_argv [i];
7822 t = mono_class_inflate_generic_type (t, oginst->context);
7824 if (!ginst->is_open)
7825 ginst->is_open = mono_class_is_open_constructed_type (t);
7827 ginst->type_argv [i] = t;
7830 ginst->generic_type = kginst->generic_type;
7833 geninst = g_new0 (MonoType, 1);
7834 geninst->type = MONO_TYPE_GENERICINST;
7836 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7839 mono_loader_unlock ();
7840 geninst->data.generic_inst = cached;
7844 gklass = mono_class_from_mono_type (ginst->generic_type);
7845 g_assert ((ginst->container = gklass->generic_container) != NULL);
7847 geninst->data.generic_inst = ginst;
7849 ginst->context = g_new0 (MonoGenericContext, 1);
7850 ginst->context->ginst = ginst;
7852 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7853 tb = (MonoReflectionTypeBuilder *) type;
7855 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7856 ginst->is_dynamic = TRUE;
7857 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7858 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7859 MonoReflectionType *rgt = rgi->generic_type;
7861 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7862 tb = (MonoReflectionTypeBuilder *) rgt;
7864 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7865 ginst->is_dynamic = TRUE;
7867 icount = klass->interface_count;
7870 ginst->ifaces = g_new0 (MonoType *, icount);
7871 ginst->count_ifaces = icount;
7873 for (i = 0; i < icount; i++) {
7874 MonoReflectionType *itype;
7877 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7879 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7880 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7881 if (!ginst->ifaces [i])
7882 ginst->ifaces [i] = itype->type;
7885 mono_class_create_generic (ginst);
7886 mono_class_create_generic_2 (ginst);
7888 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7890 mono_loader_unlock ();
7896 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7898 MonoClass *klass, *pklass = NULL;
7899 MonoReflectionType *parent = NULL;
7901 MonoReflectionTypeBuilder *tb = NULL;
7902 MonoGenericInst *ginst;
7905 domain = mono_object_domain (type);
7906 klass = mono_class_from_mono_type (type->type);
7908 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7909 tb = (MonoReflectionTypeBuilder *) type;
7912 parent = tb->parent;
7913 pklass = mono_class_from_mono_type (parent->type);
7916 pklass = klass->parent;
7918 parent = mono_type_get_object (domain, &pklass->byval_arg);
7919 else if (klass->generic_inst && klass->generic_inst->parent) {
7920 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7921 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7925 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7929 ginst = geninst->data.generic_inst;
7931 if (pklass && pklass->generic_inst)
7932 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7937 MonoReflectionMethod*
7938 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7940 MonoMethod *method, *inflated;
7941 MonoReflectionMethodBuilder *mb = NULL;
7942 MonoGenericMethod *gmethod;
7943 MonoGenericContext *context;
7946 MONO_ARCH_SAVE_REGS;
7947 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7948 MonoReflectionTypeBuilder *tb;
7951 mb = (MonoReflectionMethodBuilder *) rmethod;
7952 tb = (MonoReflectionTypeBuilder *) mb->type;
7953 klass = mono_class_from_mono_type (tb->type.type);
7955 method = methodbuilder_to_mono_method (klass, mb);
7957 method = rmethod->method;
7960 count = method->signature->generic_param_count;
7961 if (count != mono_array_length (types))
7964 gmethod = g_new0 (MonoGenericMethod, 1);
7965 gmethod->mtype_argc = count;
7966 gmethod->mtype_argv = g_new0 (MonoType *, count);
7967 for (i = 0; i < count; i++) {
7968 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7969 gmethod->mtype_argv [i] = garg->type;
7972 gmethod->reflection_info = rmethod;
7974 context = g_new0 (MonoGenericContext, 1);
7975 context->ginst = method->klass->generic_inst;
7976 context->gmethod = gmethod;
7978 inflated = mono_class_inflate_generic_method (method, context, NULL);
7980 return mono_method_get_object (
7981 mono_object_domain (rmethod), inflated, NULL);
7985 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7987 MonoGenericMethod *gmethod;
7988 MonoGenericInst *ginst;
7989 MonoGenericContext *context;
7992 ginst = type->type.type->data.generic_inst;
7994 gmethod = g_new0 (MonoGenericMethod, 1);
7995 gmethod->reflection_info = obj;
7997 gmethod->mtype_argc = method->signature->generic_param_count;
7998 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
8000 for (i = 0; i < gmethod->mtype_argc; i++) {
8001 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8002 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8004 g_assert (gparam->pklass);
8005 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8008 context = g_new0 (MonoGenericContext, 1);
8009 context->ginst = ginst;
8010 context->gmethod = gmethod;
8012 return mono_class_inflate_generic_method (method, context, ginst->klass);
8016 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8021 klass = mono_class_from_mono_type (type->type.type);
8023 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8024 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8025 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8026 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8027 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8028 method = ((MonoReflectionMethod *) obj)->method;
8030 method = NULL; /* prevent compiler warning */
8031 g_assert_not_reached ();
8034 return inflate_mono_method (type, method, obj);
8038 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8039 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8041 MonoGenericInst *ginst;
8042 MonoDynamicGenericInst *dginst;
8043 MonoClass *klass, *gklass, *pklass;
8046 MONO_ARCH_SAVE_REGS;
8048 klass = mono_class_from_mono_type (type->type.type);
8049 ginst = type->type.type->data.generic_inst;
8051 if (ginst->initialized)
8054 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8056 gklass = mono_class_from_mono_type (ginst->generic_type);
8057 mono_class_init (gklass);
8060 pklass = mono_class_from_mono_type (ginst->parent);
8062 pklass = gklass->parent;
8064 mono_class_setup_parent (klass, pklass);
8066 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8067 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8068 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8069 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8070 dginst->count_events = events ? mono_array_length (events) : 0;
8072 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8073 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8074 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8075 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8076 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8078 for (i = 0; i < dginst->count_methods; i++) {
8079 MonoObject *obj = mono_array_get (methods, gpointer, i);
8081 dginst->methods [i] = inflate_method (type, obj);
8084 for (i = 0; i < dginst->count_ctors; i++) {
8085 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8087 dginst->ctors [i] = inflate_method (type, obj);
8090 for (i = 0; i < dginst->count_fields; i++) {
8091 MonoObject *obj = mono_array_get (fields, gpointer, i);
8092 MonoClassField *field;
8093 MonoInflatedField *ifield;
8095 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8096 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8097 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8098 field = ((MonoReflectionField *) obj)->field;
8100 field = NULL; /* prevent compiler warning */
8101 g_assert_not_reached ();
8104 ifield = g_new0 (MonoInflatedField, 1);
8105 ifield->generic_type = field->type;
8106 ifield->reflection_info = obj;
8108 dginst->fields [i] = *field;
8109 dginst->fields [i].generic_info = ifield;
8110 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8113 for (i = 0; i < dginst->count_properties; i++) {
8114 MonoObject *obj = mono_array_get (properties, gpointer, i);
8115 MonoProperty *property = &dginst->properties [i];
8117 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8118 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8120 property->parent = klass;
8121 property->attrs = pb->attrs;
8122 property->name = mono_string_to_utf8 (pb->name);
8124 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8126 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8127 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8128 *property = *((MonoReflectionProperty *) obj)->property;
8131 property->get = inflate_mono_method (type, property->get, NULL);
8133 property->set = inflate_mono_method (type, property->set, NULL);
8135 g_assert_not_reached ();
8138 for (i = 0; i < dginst->count_events; i++) {
8139 MonoObject *obj = mono_array_get (events, gpointer, i);
8140 MonoEvent *event = &dginst->events [i];
8142 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8143 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8145 event->parent = klass;
8146 event->attrs = eb->attrs;
8147 event->name = mono_string_to_utf8 (eb->name);
8149 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8150 if (eb->remove_method)
8151 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8152 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8153 *event = *((MonoReflectionEvent *) obj)->event;
8156 event->add = inflate_mono_method (type, event->add, NULL);
8158 event->remove = inflate_mono_method (type, event->remove, NULL);
8160 g_assert_not_reached ();
8163 ginst->initialized = TRUE;
8167 ensure_runtime_vtable (MonoClass *klass)
8169 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8170 int i, num, j, onum;
8171 MonoMethod **overrides;
8173 if (!tb || klass->wastypebuilder)
8176 ensure_runtime_vtable (klass->parent);
8178 num = tb->ctors? mono_array_length (tb->ctors): 0;
8179 num += tb->num_methods;
8180 klass->method.count = num;
8181 klass->methods = g_new (MonoMethod*, num);
8182 num = tb->ctors? mono_array_length (tb->ctors): 0;
8183 for (i = 0; i < num; ++i)
8184 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8185 num = tb->num_methods;
8187 for (i = 0; i < num; ++i)
8188 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8190 if (tb->interfaces) {
8191 klass->interface_count = mono_array_length (tb->interfaces);
8192 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8193 for (i = 0; i < klass->interface_count; ++i) {
8194 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8195 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8199 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8200 for (i = 0; i < klass->method.count; ++i)
8201 klass->methods [i]->slot = i;
8206 for (i = 0; i < tb->num_methods; ++i) {
8207 MonoReflectionMethodBuilder *mb =
8208 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8209 if (mb->override_method)
8214 overrides = g_new0 (MonoMethod*, onum * 2);
8218 for (i = 0; i < tb->num_methods; ++i) {
8219 MonoReflectionMethodBuilder *mb =
8220 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8221 if (mb->override_method) {
8222 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8223 overrides [onum * 2] =
8224 mb->override_method->method;
8225 overrides [onum * 2 + 1] =
8228 g_assert (mb->mhandle);
8235 mono_class_setup_vtable (klass, overrides, onum);
8240 typebuilder_setup_fields (MonoClass *klass)
8242 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8243 MonoReflectionFieldBuilder *fb;
8244 MonoClassField *field;
8249 klass->field.count = tb->num_fields;
8250 klass->field.first = 0;
8251 klass->field.last = klass->field.count;
8253 if (!klass->field.count)
8256 klass->fields = g_new0 (MonoClassField, klass->field.count);
8258 for (i = 0; i < klass->field.count; ++i) {
8259 fb = mono_array_get (tb->fields, gpointer, i);
8260 field = &klass->fields [i];
8261 field->name = mono_string_to_utf8 (fb->name);
8263 /* FIXME: handle type modifiers */
8264 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8265 field->type->attrs = fb->attrs;
8267 field->type = fb->type->type;
8269 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8270 field->data = mono_array_addr (fb->rva_data, char, 0);
8271 if (fb->offset != -1)
8272 field->offset = fb->offset;
8273 field->parent = klass;
8275 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8277 if (fb->def_value) {
8278 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8279 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8280 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8281 /* Copy the data from the blob since it might get realloc-ed */
8282 p = assembly->blob.data + idx;
8283 len = mono_metadata_decode_blob_size (p, &p2);
8285 field->data = g_malloc (len);
8286 memcpy ((gpointer)field->data, p, len);
8289 mono_class_layout_fields (klass);
8293 typebuilder_setup_properties (MonoClass *klass)
8295 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8296 MonoReflectionPropertyBuilder *pb;
8299 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8300 klass->property.first = 0;
8301 klass->property.last = klass->property.count;
8303 klass->properties = g_new0 (MonoProperty, klass->property.count);
8304 for (i = 0; i < klass->property.count; ++i) {
8305 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8306 klass->properties [i].parent = klass;
8307 klass->properties [i].attrs = pb->attrs;
8308 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8310 klass->properties [i].get = pb->get_method->mhandle;
8312 klass->properties [i].set = pb->set_method->mhandle;
8316 MonoReflectionEvent *
8317 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8319 MonoEvent *event = g_new0 (MonoEvent, 1);
8323 klass = my_mono_class_from_mono_type (tb->type.type);
8325 event->parent = klass;
8326 event->attrs = eb->attrs;
8327 event->name = mono_string_to_utf8 (eb->name);
8329 event->add = eb->add_method->mhandle;
8330 if (eb->remove_method)
8331 event->remove = eb->remove_method->mhandle;
8332 if (eb->raise_method)
8333 event->raise = eb->raise_method->mhandle;
8335 if (eb->other_methods) {
8336 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8337 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8338 MonoReflectionMethodBuilder *mb =
8339 mono_array_get (eb->other_methods,
8340 MonoReflectionMethodBuilder*, j);
8341 event->other [j] = mb->mhandle;
8345 return mono_event_get_object (mono_object_domain (tb), klass, event);
8349 typebuilder_setup_events (MonoClass *klass)
8351 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8352 MonoReflectionEventBuilder *eb;
8355 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8356 klass->event.first = 0;
8357 klass->event.last = klass->event.count;
8359 klass->events = g_new0 (MonoEvent, klass->event.count);
8360 for (i = 0; i < klass->event.count; ++i) {
8361 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8362 klass->events [i].parent = klass;
8363 klass->events [i].attrs = eb->attrs;
8364 klass->events [i].name = mono_string_to_utf8 (eb->name);
8366 klass->events [i].add = eb->add_method->mhandle;
8367 if (eb->remove_method)
8368 klass->events [i].remove = eb->remove_method->mhandle;
8369 if (eb->raise_method)
8370 klass->events [i].raise = eb->raise_method->mhandle;
8372 if (eb->other_methods) {
8373 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8374 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8375 MonoReflectionMethodBuilder *mb =
8376 mono_array_get (eb->other_methods,
8377 MonoReflectionMethodBuilder*, j);
8378 klass->events [i].other [j] = mb->mhandle;
8385 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8388 MonoReflectionType* res;
8391 MONO_ARCH_SAVE_REGS;
8393 klass = my_mono_class_from_mono_type (tb->type.type);
8395 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8398 * Fields to set in klass:
8399 * the various flags: delegate/unicode/contextbound etc.
8401 klass->flags = tb->attrs;
8403 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8404 /* No need to fully construct the type */
8405 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8407 /* enums are done right away */
8408 if (!klass->enumtype)
8409 ensure_runtime_vtable (klass);
8412 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8413 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8414 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8418 /* fields and object layout */
8419 if (klass->parent) {
8420 if (!klass->parent->size_inited)
8421 mono_class_init (klass->parent);
8422 klass->instance_size += klass->parent->instance_size;
8423 klass->class_size += klass->parent->class_size;
8424 klass->min_align = klass->parent->min_align;
8426 klass->instance_size = sizeof (MonoObject);
8427 klass->min_align = 1;
8430 /* FIXME: handle packing_size and instance_size */
8431 typebuilder_setup_fields (klass);
8433 typebuilder_setup_properties (klass);
8435 typebuilder_setup_events (klass);
8437 klass->wastypebuilder = TRUE;
8439 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8440 g_assert (res != (MonoReflectionType*)tb);
8445 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8447 MonoGenericParam *param;
8450 MONO_ARCH_SAVE_REGS;
8452 param = g_new0 (MonoGenericParam, 1);
8454 if (gparam->mbuilder) {
8455 if (!gparam->mbuilder->generic_container)
8456 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8457 param->owner = gparam->mbuilder->generic_container;
8458 } else if (gparam->tbuilder) {
8459 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8460 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8465 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8466 if (gparam->index >= count)
8469 container = nesting->generic_container;
8470 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8473 g_assert (container);
8474 param->owner = container;
8477 param->method = NULL;
8478 param->name = mono_string_to_utf8 (gparam->name);
8479 param->num = gparam->index;
8481 image = &gparam->tbuilder->module->dynamic_image->image;
8482 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8484 param->pklass->reflection_info = gparam;
8486 gparam->type.type = g_new0 (MonoType, 1);
8487 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8488 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8489 gparam->type.type->data.generic_param = param;
8493 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8495 MonoDynamicImage *assembly = sig->module->dynamic_image;
8496 guint32 na = mono_array_length (sig->arguments);
8501 MONO_ARCH_SAVE_REGS;
8503 p = buf = g_malloc (10 + na * 10);
8505 mono_metadata_encode_value (0x07, p, &p);
8506 mono_metadata_encode_value (na, p, &p);
8507 for (i = 0; i < na; ++i) {
8508 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8509 encode_reflection_type (assembly, type, p, &p);
8513 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8514 p = mono_array_addr (result, char, 0);
8515 memcpy (p, buf, buflen);
8522 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8524 MonoDynamicImage *assembly = sig->module->dynamic_image;
8525 guint32 na = mono_array_length (sig->arguments);
8530 MONO_ARCH_SAVE_REGS;
8532 p = buf = g_malloc (10 + na * 10);
8534 mono_metadata_encode_value (0x06, p, &p);
8535 for (i = 0; i < na; ++i) {
8536 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8537 encode_reflection_type (assembly, type, p, &p);
8541 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8542 p = mono_array_addr (result, char, 0);
8543 memcpy (p, buf, buflen);
8550 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8552 ReflectionMethodBuilder rmb;
8553 MonoMethodSignature *sig;
8556 sig = dynamic_method_to_signature (mb);
8558 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8561 * Resolve references.
8563 rmb.nrefs = mb->nrefs;
8564 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8565 for (i = 0; i < mb->nrefs; ++i) {
8566 gpointer ref = resolve_object (mb->module->image,
8567 mono_array_get (mb->refs, MonoObject*, i));
8570 mono_raise_exception (mono_get_exception_type_load (NULL));
8577 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8581 /* ilgen is no longer needed */
8586 * mono_reflection_lookup_dynamic_token:
8588 * Finish the Builder object pointed to by TOKEN and return the corresponding
8589 * runtime structure.
8592 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8594 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8597 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8600 return resolve_object (image, obj);
8604 resolve_object (MonoImage *image, MonoObject *obj)
8606 gpointer result = NULL;
8608 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8609 result = mono_string_intern ((MonoString*)obj);
8611 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8612 MonoReflectionType *tb = (MonoReflectionType*)obj;
8613 result = mono_class_from_mono_type (tb->type);
8615 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8616 result = ((MonoReflectionMethod*)obj)->method;
8618 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8619 result = ((MonoReflectionMethod*)obj)->method;
8621 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8622 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8623 result = mb->mhandle;
8625 /* Type is not yet created */
8626 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8628 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8631 * Hopefully this has been filled in by calling CreateType() on the
8635 * TODO: This won't work if the application finishes another
8636 * TypeBuilder instance instead of this one.
8638 result = mb->mhandle;
8640 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8641 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8643 result = cb->mhandle;
8645 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8647 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8648 result = cb->mhandle;
8650 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8651 result = ((MonoReflectionField*)obj)->field;
8653 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8654 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8655 result = fb->handle;
8658 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8660 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8661 result = fb->handle;
8663 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8664 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8667 klass = tb->type.type->data.klass;
8668 if (klass->wastypebuilder) {
8669 /* Already created */
8673 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8674 result = tb->type.type->data.klass;
8677 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8678 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8679 MonoMethodSignature *sig;
8682 if (helper->arguments)
8683 nargs = mono_array_length (helper->arguments);
8687 sig = mono_metadata_signature_alloc (image, nargs);
8688 sig->explicit_this = helper->call_conv & 64;
8689 sig->hasthis = helper->call_conv & 32;
8691 if (helper->call_conv == 0) /* unmanaged */
8692 sig->call_convention = helper->unmanaged_call_conv - 1;
8694 if (helper->call_conv & 0x02)
8695 sig->call_convention = MONO_CALL_VARARG;
8697 sig->call_convention = MONO_CALL_DEFAULT;
8699 sig->param_count = nargs;
8700 /* TODO: Copy type ? */
8701 sig->ret = helper->return_type->type;
8702 for (i = 0; i < nargs; ++i) {
8703 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8704 sig->params [i] = rt->type;
8709 g_print (obj->vtable->klass->name);
8710 g_assert_not_reached ();