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;
4567 static const unsigned char msheader[] = {
4568 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4569 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4572 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4573 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4574 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4575 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4578 assemblyb = mb->assemblyb;
4580 mono_image_basic_init (assemblyb);
4581 assembly = mb->dynamic_image;
4583 assembly->pe_kind = assemblyb->pe_kind;
4584 assembly->machine = assemblyb->machine;
4585 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4586 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4588 /* already created */
4589 if (assembly->pefile.index)
4592 mono_image_build_metadata (mb);
4594 if (mb->is_main && assemblyb->resources) {
4595 int len = mono_array_length (assemblyb->resources);
4596 for (i = 0; i < len; ++i)
4597 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4600 if (mb->resources) {
4601 int len = mono_array_length (mb->resources);
4602 for (i = 0; i < len; ++i)
4603 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4606 build_compressed_metadata (assembly);
4609 assembly_add_win32_resources (assembly, assemblyb);
4611 nsections = calc_section_size (assembly);
4613 pefile = &assembly->pefile;
4615 /* The DOS header and stub */
4616 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4617 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4619 /* the dotnet header */
4620 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4622 /* the section tables */
4623 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4625 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4626 virtual_offset = VIRT_ALIGN;
4629 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4630 if (!assembly->sections [i].size)
4633 file_offset += FILE_ALIGN - 1;
4634 file_offset &= ~(FILE_ALIGN - 1);
4635 virtual_offset += VIRT_ALIGN - 1;
4636 virtual_offset &= ~(VIRT_ALIGN - 1);
4638 assembly->sections [i].offset = file_offset;
4639 assembly->sections [i].rva = virtual_offset;
4641 file_offset += assembly->sections [i].size;
4642 virtual_offset += assembly->sections [i].size;
4643 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4646 file_offset += FILE_ALIGN - 1;
4647 file_offset &= ~(FILE_ALIGN - 1);
4648 mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4650 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4652 /* back-patch info */
4653 msdos = (MonoMSDOSHeader*)pefile->data;
4654 msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4655 msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4656 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4658 header = (MonoDotNetHeader*)(pefile->data + header_start);
4659 header->pesig [0] = 'P';
4660 header->pesig [1] = 'E';
4662 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4663 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4664 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4665 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4666 if (assemblyb->pekind == 1) {
4668 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4671 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4674 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4676 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4677 header->pe.pe_major = 6;
4678 header->pe.pe_minor = 0;
4679 size = assembly->sections [MONO_SECTION_TEXT].size;
4680 size += FILE_ALIGN - 1;
4681 size &= ~(FILE_ALIGN - 1);
4682 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4683 size = assembly->sections [MONO_SECTION_RSRC].size;
4684 size += FILE_ALIGN - 1;
4685 size &= ~(FILE_ALIGN - 1);
4686 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4687 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4688 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4689 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4690 /* pe_rva_entry_point always at the beginning of the text section */
4691 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4693 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4694 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4695 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4696 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4697 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4698 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4699 size = section_start;
4700 size += FILE_ALIGN - 1;
4701 size &= ~(FILE_ALIGN - 1);
4702 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4704 size += VIRT_ALIGN - 1;
4705 size &= ~(VIRT_ALIGN - 1);
4706 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4709 // Translate the PEFileKind value to the value expected by the Windows loader
4715 // PEFileKinds.Dll == 1
4716 // PEFileKinds.ConsoleApplication == 2
4717 // PEFileKinds.WindowApplication == 3
4720 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4721 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4723 if (assemblyb->pekind == 3)
4728 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4730 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4731 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4732 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4733 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4734 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4735 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4737 /* fill data directory entries */
4739 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4740 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4742 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4743 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4745 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4746 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4747 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4748 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4749 /* patch entrypoint name */
4750 if (assemblyb->pekind == 1)
4751 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4753 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4754 /* patch imported function RVA name */
4755 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4756 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4758 /* the import table */
4759 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4760 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4761 /* patch imported dll RVA name and other entries in the dir */
4762 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4763 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4764 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4765 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4766 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4767 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4769 p = (assembly->code.data + assembly->ilt_offset);
4770 value = (assembly->text_rva + assembly->imp_names_offset);
4771 *p++ = (value) & 0xff;
4772 *p++ = (value >> 8) & (0xff);
4773 *p++ = (value >> 16) & (0xff);
4774 *p++ = (value >> 24) & (0xff);
4776 /* the CLI header info */
4777 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4778 cli_header->ch_size = GUINT32_FROM_LE (72);
4779 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4780 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4781 if (assemblyb->entry_point) {
4782 guint32 table_idx = 0;
4783 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4784 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4785 table_idx = methodb->table_idx;
4787 table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4789 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4791 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4793 /* The embedded managed resources */
4794 text_offset = assembly->text_rva + assembly->code.index;
4795 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4796 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4797 text_offset += assembly->resources.index;
4798 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4799 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4800 text_offset += assembly->meta_size;
4801 if (assembly->strong_name_size) {
4802 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4803 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4804 text_offset += assembly->strong_name_size;
4807 /* write the section tables and section content */
4808 section = (MonoSectionTable*)(pefile->data + section_start);
4809 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4810 static const char *section_names [] = {
4811 ".text", ".rsrc", ".reloc"
4813 if (!assembly->sections [i].size)
4815 strcpy (section->st_name, section_names [i]);
4816 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4817 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4818 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4819 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4820 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4821 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4822 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4824 case MONO_SECTION_TEXT:
4825 /* patch entry point */
4826 p = (assembly->code.data + 2);
4827 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4828 *p++ = (value) & 0xff;
4829 *p++ = (value >> 8) & 0xff;
4830 *p++ = (value >> 16) & 0xff;
4831 *p++ = (value >> 24) & 0xff;
4833 text_offset = assembly->sections [i].offset;
4834 memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4835 text_offset += assembly->code.index;
4836 memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4837 text_offset += assembly->resources.index;
4838 memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4839 text_offset += assembly->meta_size;
4840 memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4842 g_free (assembly->image.raw_metadata);
4844 case MONO_SECTION_RELOC:
4845 rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4846 *rva = GUINT32_FROM_LE (assembly->text_rva);
4848 *rva = GUINT32_FROM_LE (12);
4850 data16 = (guint16*)rva;
4852 * the entrypoint is always at the start of the text section
4853 * 3 is IMAGE_REL_BASED_HIGHLOW
4854 * 2 is patch_size_rva - text_rva
4856 *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4858 *data16 = 0; /* terminate */
4860 case MONO_SECTION_RSRC:
4861 if (assembly->win32_res) {
4862 text_offset = assembly->sections [i].offset;
4864 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4865 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4867 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4871 g_assert_not_reached ();
4876 /* check that the file is properly padded */
4878 if (!WriteFile (file, pefile->data, pefile->index , NULL, NULL))
4879 g_error ("WriteFile returned %d\n", GetLastError ());
4881 mono_dynamic_stream_reset (pefile);
4884 MonoReflectionModule *
4885 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4889 MonoImageOpenStatus status;
4890 MonoDynamicAssembly *assembly;
4891 guint32 module_count;
4892 MonoImage **new_modules;
4894 name = mono_string_to_utf8 (fileName);
4896 image = mono_image_open (name, &status);
4899 if (status == MONO_IMAGE_ERROR_ERRNO)
4900 exc = mono_get_exception_file_not_found (fileName);
4902 exc = mono_get_exception_bad_image_format (name);
4904 mono_raise_exception (exc);
4909 assembly = ab->dynamic_assembly;
4910 image->assembly = (MonoAssembly*)assembly;
4912 module_count = image->assembly->image->module_count;
4913 new_modules = g_new0 (MonoImage *, module_count + 1);
4915 if (image->assembly->image->modules)
4916 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4917 new_modules [module_count] = image;
4919 g_free (image->assembly->image->modules);
4920 image->assembly->image->modules = new_modules;
4921 image->assembly->image->module_count ++;
4923 mono_assembly_load_references (image, &status);
4925 mono_image_close (image);
4926 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4929 return mono_module_get_object (mono_domain_get (), image);
4933 * We need to return always the same object for MethodInfo, FieldInfo etc..
4934 * but we need to consider the reflected type.
4935 * type uses a different hash, since it uses custom hash/equal functions.
4940 MonoClass *refclass;
4944 reflected_equal (gconstpointer a, gconstpointer b) {
4945 const ReflectedEntry *ea = a;
4946 const ReflectedEntry *eb = b;
4948 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4952 reflected_hash (gconstpointer a) {
4953 const ReflectedEntry *ea = a;
4954 return GPOINTER_TO_UINT (ea->item);
4957 #define CHECK_OBJECT(t,p,k) \
4963 mono_domain_lock (domain); \
4964 if (!domain->refobject_hash) \
4965 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
4966 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
4967 mono_domain_unlock (domain); \
4973 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4975 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4978 #define CACHE_OBJECT(p,o,k) \
4980 ReflectedEntry *e = ALLOC_REFENTRY; \
4982 e->refclass = (k); \
4983 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4984 mono_domain_unlock (domain); \
4988 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4990 /* this is done only once */
4991 mono_domain_lock (domain);
4992 CACHE_OBJECT (assembly, res, NULL);
4996 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4998 /* this is done only once */
4999 mono_domain_lock (domain);
5000 CACHE_OBJECT (module, res, NULL);
5004 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5006 MonoDynamicImage *image = moduleb->dynamic_image;
5007 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5010 * FIXME: we already created an image in mono_image_basic_init (), but
5011 * we don't know which module it belongs to, since that is only
5012 * determined at assembly save time.
5014 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5015 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5017 moduleb->module.image = &image->image;
5018 moduleb->dynamic_image = image;
5019 register_module (mono_object_domain (moduleb), moduleb, image);
5024 * mono_assembly_get_object:
5025 * @domain: an app domain
5026 * @assembly: an assembly
5028 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5030 MonoReflectionAssembly*
5031 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5033 static MonoClass *System_Reflection_Assembly;
5034 MonoReflectionAssembly *res;
5036 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5037 if (!System_Reflection_Assembly)
5038 System_Reflection_Assembly = mono_class_from_name (
5039 mono_defaults.corlib, "System.Reflection", "Assembly");
5040 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5041 res->assembly = assembly;
5042 CACHE_OBJECT (assembly, res, NULL);
5048 MonoReflectionModule*
5049 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5051 static MonoClass *System_Reflection_Module;
5052 MonoReflectionModule *res;
5055 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5056 if (!System_Reflection_Module)
5057 System_Reflection_Module = mono_class_from_name (
5058 mono_defaults.corlib, "System.Reflection", "Module");
5059 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5062 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5064 res->fqname = mono_string_new (domain, image->name);
5065 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5066 res->scopename = mono_string_new (domain, image->module_name);
5070 if (image->assembly->image == image) {
5071 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5074 g_assert (image->assembly->image->modules);
5076 for (i = 0; i < image->assembly->image->module_count; i++) {
5077 if (image->assembly->image->modules [i] == image)
5078 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5080 g_assert (res->token);
5083 mono_image_addref (image);
5085 CACHE_OBJECT (image, res, NULL);
5089 MonoReflectionModule*
5090 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5092 static MonoClass *System_Reflection_Module;
5093 MonoReflectionModule *res;
5094 MonoTableInfo *table;
5095 guint32 cols [MONO_FILE_SIZE];
5097 guint32 i, name_idx;
5100 if (!System_Reflection_Module)
5101 System_Reflection_Module = mono_class_from_name (
5102 mono_defaults.corlib, "System.Reflection", "Module");
5103 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5105 table = &image->tables [MONO_TABLE_FILE];
5106 g_assert (table_index < table->rows);
5107 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5110 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5111 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5113 /* Check whenever the row has a corresponding row in the moduleref table */
5114 table = &image->tables [MONO_TABLE_MODULEREF];
5115 for (i = 0; i < table->rows; ++i) {
5116 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5117 val = mono_metadata_string_heap (image, name_idx);
5118 if (strcmp (val, name) == 0)
5119 res->image = image->modules [i];
5122 res->fqname = mono_string_new (domain, name);
5123 res->name = mono_string_new (domain, name);
5124 res->scopename = mono_string_new (domain, name);
5125 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5126 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5132 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5134 if ((t1->type != t2->type) ||
5135 (t1->byref != t2->byref))
5139 case MONO_TYPE_VOID:
5140 case MONO_TYPE_BOOLEAN:
5141 case MONO_TYPE_CHAR:
5152 case MONO_TYPE_STRING:
5155 case MONO_TYPE_OBJECT:
5156 case MONO_TYPE_TYPEDBYREF:
5158 case MONO_TYPE_VALUETYPE:
5159 case MONO_TYPE_CLASS:
5160 case MONO_TYPE_SZARRAY:
5161 return t1->data.klass == t2->data.klass;
5163 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5164 case MONO_TYPE_ARRAY:
5165 if (t1->data.array->rank != t2->data.array->rank)
5167 return t1->data.array->eklass == t2->data.array->eklass;
5168 case MONO_TYPE_GENERICINST: {
5170 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5172 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5174 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5175 if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5181 case MONO_TYPE_MVAR:
5182 return t1->data.generic_param == t2->data.generic_param;
5184 g_error ("implement type compare for %0x!", t1->type);
5192 mymono_metadata_type_hash (MonoType *t1)
5198 hash |= t1->byref << 6; /* do not collide with t1->type values */
5200 case MONO_TYPE_VALUETYPE:
5201 case MONO_TYPE_CLASS:
5202 case MONO_TYPE_SZARRAY:
5203 /* check if the distribution is good enough */
5204 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5206 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5211 static MonoReflectionGenericInst*
5212 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5214 static MonoClass *System_Reflection_MonoGenericInst;
5215 MonoReflectionGenericInst *res;
5216 MonoGenericInst *ginst;
5219 if (!System_Reflection_MonoGenericInst) {
5220 System_Reflection_MonoGenericInst = mono_class_from_name (
5221 mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5222 g_assert (System_Reflection_MonoGenericInst);
5225 ginst = geninst->data.generic_inst;
5226 gklass = mono_class_from_mono_type (ginst->generic_type);
5228 mono_class_init (ginst->klass);
5230 res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5232 res->type.type = geninst;
5233 if (gklass->wastypebuilder && gklass->reflection_info)
5234 res->generic_type = gklass->reflection_info;
5236 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5242 * mono_type_get_object:
5243 * @domain: an app domain
5246 * Return an System.MonoType object representing the type @type.
5249 mono_type_get_object (MonoDomain *domain, MonoType *type)
5251 MonoReflectionType *res;
5252 MonoClass *klass = mono_class_from_mono_type (type);
5254 mono_domain_lock (domain);
5255 if (!domain->type_hash)
5256 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5257 (GCompareFunc)mymono_metadata_type_equal);
5258 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5259 mono_domain_unlock (domain);
5262 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5263 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5264 mono_g_hash_table_insert (domain->type_hash, type, res);
5265 mono_domain_unlock (domain);
5268 if (klass->reflection_info && !klass->wastypebuilder) {
5269 /* g_assert_not_reached (); */
5270 /* should this be considered an error condition? */
5272 mono_domain_unlock (domain);
5273 return klass->reflection_info;
5276 mono_class_init (klass);
5277 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5279 mono_g_hash_table_insert (domain->type_hash, type, res);
5280 mono_domain_unlock (domain);
5285 * mono_method_get_object:
5286 * @domain: an app domain
5288 * @refclass: the reflected type (can be NULL)
5290 * Return an System.Reflection.MonoMethod object representing the method @method.
5292 MonoReflectionMethod*
5293 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5296 * We use the same C representation for methods and constructors, but the type
5297 * name in C# is different.
5301 MonoReflectionMethod *ret;
5304 refclass = method->klass;
5306 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5307 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5308 cname = "MonoCMethod";
5310 cname = "MonoMethod";
5311 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5313 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5314 ret->method = method;
5315 ret->name = mono_string_new (domain, method->name);
5316 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5317 CACHE_OBJECT (method, ret, refclass);
5322 * mono_field_get_object:
5323 * @domain: an app domain
5327 * Return an System.Reflection.MonoField object representing the field @field
5330 MonoReflectionField*
5331 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5333 MonoReflectionField *res;
5336 CHECK_OBJECT (MonoReflectionField *, field, klass);
5337 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5338 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5341 res->name = mono_string_new (domain, field->name);
5342 if (field->generic_info)
5343 res->attrs = field->generic_info->generic_type->attrs;
5345 res->attrs = field->type->attrs;
5346 res->type = mono_type_get_object (domain, field->type);
5347 CACHE_OBJECT (field, res, klass);
5352 * mono_property_get_object:
5353 * @domain: an app domain
5355 * @property: a property
5357 * Return an System.Reflection.MonoProperty object representing the property @property
5360 MonoReflectionProperty*
5361 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5363 MonoReflectionProperty *res;
5366 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5367 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5368 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5370 res->property = property;
5371 CACHE_OBJECT (property, res, klass);
5376 * mono_event_get_object:
5377 * @domain: an app domain
5381 * Return an System.Reflection.MonoEvent object representing the event @event
5384 MonoReflectionEvent*
5385 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5387 MonoReflectionEvent *res;
5390 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5391 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5392 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5395 CACHE_OBJECT (event, res, klass);
5400 * mono_param_get_objects:
5401 * @domain: an app domain
5404 * Return an System.Reflection.ParameterInfo array object representing the parameters
5405 * in the method @method.
5408 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5410 static MonoClass *System_Reflection_ParameterInfo;
5411 MonoArray *res = NULL;
5412 MonoReflectionMethod *member = NULL;
5413 MonoReflectionParameter *param = NULL;
5414 char **names, **blobs = NULL;
5415 MonoObject *dbnull = mono_get_dbnull_object (domain);
5416 MonoMarshalSpec **mspecs;
5419 if (!System_Reflection_ParameterInfo)
5420 System_Reflection_ParameterInfo = mono_class_from_name (
5421 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5423 if (!method->signature->param_count)
5424 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5426 /* Note: the cache is based on the address of the signature into the method
5427 * since we already cache MethodInfos with the method as keys.
5429 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5431 member = mono_method_get_object (domain, method, NULL);
5432 names = g_new (char *, method->signature->param_count);
5433 mono_method_get_param_names (method, (const char **) names);
5435 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5436 mono_method_get_marshal_info (method, mspecs);
5438 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5439 for (i = 0; i < method->signature->param_count; ++i) {
5440 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5441 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5442 param->MemberImpl = (MonoObject*)member;
5443 param->NameImpl = mono_string_new (domain, names [i]);
5444 param->PositionImpl = i;
5445 param->AttrsImpl = method->signature->params [i]->attrs;
5447 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5448 param->DefaultValueImpl = dbnull;
5450 MonoType *type = param->ClassImpl->type;
5453 blobs = g_new0 (char *, method->signature->param_count);
5454 get_default_param_value_blobs (method, blobs);
5457 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5459 if (!param->DefaultValueImpl) {
5460 param->DefaultValueImpl = dbnull;
5465 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5467 mono_array_set (res, gpointer, i, param);
5472 for (i = method->signature->param_count; i >= 0; i--)
5474 mono_metadata_free_marshal_spec (mspecs [i]);
5477 CACHE_OBJECT (&(method->signature), res, NULL);
5482 * mono_method_body_get_object:
5483 * @domain: an app domain
5486 * Return an System.Reflection.MethodBody object representing the method @method.
5488 MonoReflectionMethodBody*
5489 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5491 static MonoClass *System_Reflection_MethodBody = NULL;
5492 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5493 MonoReflectionMethodBody *ret;
5494 MonoMethodNormal *mn;
5495 MonoMethodHeader *header;
5498 if (!System_Reflection_MethodBody)
5499 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5500 if (!System_Reflection_LocalVariableInfo)
5501 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5503 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5505 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5506 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
5508 mn = (MonoMethodNormal *)method;
5509 header = mono_method_get_header (method);
5511 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5512 /* FIXME: Other fields */
5513 ret->init_locals = header->init_locals;
5514 ret->max_stack = header->max_stack;
5515 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5516 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5517 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5518 for (i = 0; i < header->num_locals; ++i) {
5519 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5520 info->local_type = mono_type_get_object (domain, header->locals [i]);
5521 info->is_pinned = header->locals [i]->pinned;
5522 info->local_index = 0;
5525 CACHE_OBJECT (method, ret, NULL);
5530 mono_get_dbnull_object (MonoDomain *domain)
5534 static MonoClassField *dbnull_value_field = NULL;
5536 if (!dbnull_value_field) {
5537 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5538 mono_class_init (klass);
5539 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5540 g_assert (dbnull_value_field);
5542 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5549 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5551 guint32 param_index, i, lastp, crow = 0;
5552 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5555 MonoClass *klass = method->klass;
5556 MonoImage *image = klass->image;
5557 MonoMethodSignature *methodsig = method->signature;
5559 MonoTableInfo *constt;
5560 MonoTableInfo *methodt;
5561 MonoTableInfo *paramt;
5563 if (!methodsig->param_count)
5566 if (klass->generic_inst) {
5567 return; /* FIXME - ??? */
5570 mono_class_init (klass);
5572 if (klass->image->dynamic) {
5573 MonoReflectionMethodAux *aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5574 if (aux && aux->param_defaults)
5575 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5579 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5580 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5581 constt = &image->tables [MONO_TABLE_CONSTANT];
5583 for (i = 0; i < klass->method.count; ++i) {
5584 if (method == klass->methods [i]) {
5585 idx = klass->method.first + i;
5590 g_assert (idx != -1);
5592 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5593 if (idx + 1 < methodt->rows)
5594 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5596 lastp = paramt->rows + 1;
5598 for (i = param_index; i < lastp; ++i) {
5601 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5602 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5604 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5607 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5612 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5613 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5620 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5629 klass = mono_class_from_mono_type (type);
5630 if (klass->valuetype) {
5631 object = mono_object_new (domain, klass);
5632 retval = ((gchar *) object + sizeof (MonoObject));
5637 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5644 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5648 memset (assembly, 0, sizeof (MonoAssemblyName));
5650 assembly->culture = "";
5651 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5653 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5656 while (*p == ' ' || *p == ',') {
5665 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5667 assembly->major = strtoul (p, &s, 10);
5668 if (s == p || *s != '.')
5671 assembly->minor = strtoul (p, &s, 10);
5672 if (s == p || *s != '.')
5675 assembly->build = strtoul (p, &s, 10);
5676 if (s == p || *s != '.')
5679 assembly->revision = strtoul (p, &s, 10);
5683 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5685 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5686 assembly->culture = "";
5689 assembly->culture = p;
5690 while (*p && *p != ',') {
5694 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5696 if (strncmp (p, "null", 4) == 0) {
5701 while (*p && *p != ',') {
5704 len = (p - start + 1);
5705 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5706 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5707 g_strlcpy (assembly->public_key_token, start, len);
5710 while (*p && *p != ',')
5714 while (*p == ' ' || *p == ',') {
5728 * mono_reflection_parse_type:
5731 * Parse a type name as accepted by the GetType () method and output the info
5732 * extracted in the info structure.
5733 * the name param will be mangled, so, make a copy before passing it to this function.
5734 * The fields in info will be valid until the memory pointed to by name is valid.
5735 * Returns 0 on parse error.
5736 * See also mono_type_get_name () below.
5739 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5741 char *start, *p, *w, *last_point, *startn;
5742 int in_modifiers = 0;
5743 int isbyref = 0, rank;
5745 start = p = w = name;
5747 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5748 info->name = info->name_space = NULL;
5749 info->nested = NULL;
5750 info->modifiers = NULL;
5752 /* last_point separates the namespace from the name */
5758 *p = 0; /* NULL terminate the name */
5760 info->nested = g_list_append (info->nested, startn);
5761 /* we have parsed the nesting namespace + name */
5765 info->name_space = start;
5767 info->name = last_point + 1;
5769 info->name_space = (char *)"";
5795 info->name_space = start;
5797 info->name = last_point + 1;
5799 info->name_space = (char *)"";
5806 if (isbyref) /* only one level allowed by the spec */
5809 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5813 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5824 else if (*p != '*') /* '*' means unknown lower bound */
5830 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5842 return 0; /* missing assembly name */
5843 if (!assembly_name_to_aname (&info->assembly, p))
5850 if (info->assembly.name)
5853 *w = 0; /* terminate class name */
5854 if (!info->name || !*info->name)
5856 /* add other consistency checks */
5861 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5868 image = mono_defaults.corlib;
5871 klass = mono_class_from_name_case (image, info->name_space, info->name);
5873 klass = mono_class_from_name (image, info->name_space, info->name);
5876 for (mod = info->nested; mod; mod = mod->next) {
5879 mono_class_init (klass);
5880 nested = klass->nested_classes;
5883 klass = nested->data;
5885 if (g_strcasecmp (klass->name, mod->data) == 0)
5888 if (strcmp (klass->name, mod->data) == 0)
5892 nested = nested->next;
5899 mono_class_init (klass);
5900 for (mod = info->modifiers; mod; mod = mod->next) {
5901 modval = GPOINTER_TO_UINT (mod->data);
5902 if (!modval) { /* byref: must be last modifier */
5903 return &klass->this_arg;
5904 } else if (modval == -1) {
5905 klass = mono_ptr_class_get (&klass->byval_arg);
5906 } else { /* array rank */
5907 klass = mono_array_class_get (klass, modval);
5909 mono_class_init (klass);
5912 return &klass->byval_arg;
5916 * mono_reflection_get_type:
5917 * @image: a metadata context
5918 * @info: type description structure
5919 * @ignorecase: flag for case-insensitive string compares
5920 * @type_resolve: whenever type resolve was already tried
5922 * Build a MonoType from the type description in @info.
5927 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5930 MonoReflectionAssembly *assembly;
5934 type = mono_reflection_get_type_internal (image, info, ignorecase);
5937 if (!mono_domain_has_type_resolve (mono_domain_get ()))
5944 *type_resolve = TRUE;
5947 /* Reconstruct the type name */
5948 fullName = g_string_new ("");
5949 if (info->name_space && (info->name_space [0] != '\0'))
5950 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5952 g_string_printf (fullName, info->name);
5953 for (mod = info->nested; mod; mod = mod->next)
5954 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5956 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5958 if (assembly->assembly->dynamic) {
5959 /* Enumerate all modules */
5960 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5964 if (abuilder->modules) {
5965 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5966 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5967 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5973 if (!type && abuilder->loaded_modules) {
5974 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5975 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5976 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5983 type = mono_reflection_get_type_internal (assembly->assembly->image,
5986 g_string_free (fullName, TRUE);
5991 * mono_reflection_type_from_name:
5993 * @image: a metadata context (can be NULL).
5995 * Retrieves a MonoType from its @name. If the name is not fully qualified,
5996 * it defaults to get the type from @image or, if @image is NULL or loading
5997 * from it fails, uses corlib.
6001 mono_reflection_type_from_name (char *name, MonoImage *image)
6004 MonoTypeNameParse info;
6005 MonoAssembly *assembly;
6007 gboolean type_resolve = FALSE;
6009 /* Make a copy since parse_type modifies its argument */
6010 tmp = g_strdup (name);
6012 /*g_print ("requested type %s\n", str);*/
6013 if (!mono_reflection_parse_type (tmp, &info)) {
6015 g_list_free (info.modifiers);
6016 g_list_free (info.nested);
6020 if (info.assembly.name) {
6021 assembly = mono_assembly_loaded (&info.assembly);
6023 /* then we must load the assembly ourselve - see #60439 */
6024 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6027 g_list_free (info.modifiers);
6028 g_list_free (info.nested);
6032 image = assembly->image;
6033 } else if (image == NULL) {
6034 image = mono_defaults.corlib;
6037 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6038 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6039 image = mono_defaults.corlib;
6040 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6044 g_list_free (info.modifiers);
6045 g_list_free (info.nested);
6050 * mono_reflection_get_token:
6052 * Return the metadata token of OBJ which should be an object
6053 * representing a metadata element.
6056 mono_reflection_get_token (MonoObject *obj)
6061 klass = obj->vtable->klass;
6063 if (strcmp (klass->name, "MethodBuilder") == 0) {
6064 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6066 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6067 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6068 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6070 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6071 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6072 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6073 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6074 if (tb->generic_params) {
6075 g_assert_not_reached ();
6077 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6079 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6080 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6081 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6082 } else if (strcmp (klass->name, "MonoType") == 0) {
6083 MonoReflectionType *tb = (MonoReflectionType *)obj;
6084 token = mono_class_from_mono_type (tb->type)->type_token;
6085 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6086 strcmp (klass->name, "MonoMethod") == 0) {
6087 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6088 if (m->method->signature->is_inflated) {
6089 g_assert_not_reached ();
6090 } else if (m->method->signature->generic_param_count) {
6091 g_assert_not_reached ();
6092 } else if (m->method->klass->generic_inst) {
6093 g_assert_not_reached ();
6095 token = m->method->token;
6097 } else if (strcmp (klass->name, "MonoField") == 0) {
6098 MonoReflectionField *f = (MonoReflectionField*)obj;
6100 token = mono_class_get_field_token (f->field);
6101 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6102 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6104 token = mono_class_get_property_token (p->property);
6105 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6106 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6108 token = mono_class_get_event_token (p->event);
6109 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6110 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6112 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6113 } else if (strcmp (klass->name, "Module") == 0) {
6114 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6117 } else if (strcmp (klass->name, "Assembly") == 0) {
6118 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6120 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6121 MonoException *ex = mono_get_exception_not_implemented (msg);
6123 mono_raise_exception (ex);
6130 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6132 int slen, type = t->type;
6137 case MONO_TYPE_BOOLEAN: {
6138 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6143 case MONO_TYPE_CHAR:
6145 case MONO_TYPE_I2: {
6146 guint16 *val = g_malloc (sizeof (guint16));
6151 #if SIZEOF_VOID_P == 4
6157 case MONO_TYPE_I4: {
6158 guint32 *val = g_malloc (sizeof (guint32));
6163 #if SIZEOF_VOID_P == 8
6164 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6169 case MONO_TYPE_I8: {
6170 guint64 *val = g_malloc (sizeof (guint64));
6175 case MONO_TYPE_VALUETYPE:
6176 if (t->data.klass->enumtype) {
6177 type = t->data.klass->enum_basetype->type;
6180 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6183 case MONO_TYPE_STRING:
6184 if (*p == (char)0xFF) {
6188 slen = mono_metadata_decode_value (p, &p);
6190 return mono_string_new_len (mono_domain_get (), p, slen);
6191 case MONO_TYPE_CLASS: {
6194 if (*p == (char)0xFF) {
6199 slen = mono_metadata_decode_value (p, &p);
6200 n = g_memdup (p, slen + 1);
6202 t = mono_reflection_type_from_name (n, image);
6204 g_warning ("Cannot load type '%s'", n);
6208 return mono_type_get_object (mono_domain_get (), t);
6212 case MONO_TYPE_OBJECT: {
6215 MonoClass *subc = NULL;
6220 } else if (subt == 0x0E) {
6221 type = MONO_TYPE_STRING;
6223 } else if (subt == 0x55) {
6226 slen = mono_metadata_decode_value (p, &p);
6227 n = g_memdup (p, slen + 1);
6229 t = mono_reflection_type_from_name (n, image);
6231 g_warning ("Cannot load type '%s'", n);
6234 subc = mono_class_from_mono_type (t);
6235 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6236 MonoType simple_type = {{0}};
6237 simple_type.type = subt;
6238 subc = mono_class_from_mono_type (&simple_type);
6240 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6242 val = load_cattr_value (image, &subc->byval_arg, p, end);
6243 obj = mono_object_new (mono_domain_get (), subc);
6244 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6248 case MONO_TYPE_SZARRAY: {
6250 guint32 i, alen, basetype;
6253 if (alen == 0xffffffff) {
6257 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6258 basetype = t->data.klass->byval_arg.type;
6263 case MONO_TYPE_BOOLEAN:
6264 for (i = 0; i < alen; i++) {
6265 MonoBoolean val = *p++;
6266 mono_array_set (arr, MonoBoolean, i, val);
6269 case MONO_TYPE_CHAR:
6272 for (i = 0; i < alen; i++) {
6273 guint16 val = read16 (p);
6274 mono_array_set (arr, guint16, i, val);
6281 for (i = 0; i < alen; i++) {
6282 guint32 val = read32 (p);
6283 mono_array_set (arr, guint32, i, val);
6290 for (i = 0; i < alen; i++) {
6291 guint64 val = read64 (p);
6292 mono_array_set (arr, guint64, i, val);
6296 case MONO_TYPE_CLASS:
6297 case MONO_TYPE_OBJECT:
6298 case MONO_TYPE_STRING:
6299 for (i = 0; i < alen; i++) {
6300 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6301 mono_array_set (arr, gpointer, i, item);
6305 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6311 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6317 type_is_reference (MonoType *type)
6319 switch (type->type) {
6320 case MONO_TYPE_BOOLEAN:
6321 case MONO_TYPE_CHAR:
6334 case MONO_TYPE_VALUETYPE:
6342 free_param_data (MonoMethodSignature *sig, void **params) {
6344 for (i = 0; i < sig->param_count; ++i) {
6345 if (!type_is_reference (sig->params [i]))
6346 g_free (params [i]);
6351 * Find the method index in the metadata methodDef table.
6352 * Later put these three helper methods in metadata and export them.
6355 find_method_index (MonoMethod *method) {
6356 MonoClass *klass = method->klass;
6359 for (i = 0; i < klass->method.count; ++i) {
6360 if (method == klass->methods [i])
6361 return klass->method.first + 1 + i;
6367 * Find the field index in the metadata FieldDef table.
6370 find_field_index (MonoClass *klass, MonoClassField *field) {
6373 for (i = 0; i < klass->field.count; ++i) {
6374 if (field == &klass->fields [i])
6375 return klass->field.first + 1 + i;
6381 * Find the property index in the metadata Property table.
6384 find_property_index (MonoClass *klass, MonoProperty *property) {
6387 for (i = 0; i < klass->property.count; ++i) {
6388 if (property == &klass->properties [i])
6389 return klass->property.first + 1 + i;
6395 * Find the event index in the metadata Event table.
6398 find_event_index (MonoClass *klass, MonoEvent *event) {
6401 for (i = 0; i < klass->event.count; ++i) {
6402 if (event == &klass->events [i])
6403 return klass->event.first + 1 + i;
6409 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6411 const char *p = data;
6413 guint32 i, j, num_named;
6417 mono_class_init (method->klass);
6420 attr = mono_object_new (mono_domain_get (), method->klass);
6421 mono_runtime_invoke (method, attr, NULL, NULL);
6425 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6428 /*g_print ("got attr %s\n", method->klass->name);*/
6430 params = g_new (void*, method->signature->param_count);
6434 for (i = 0; i < method->signature->param_count; ++i) {
6435 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6439 attr = mono_object_new (mono_domain_get (), method->klass);
6440 mono_runtime_invoke (method, attr, params, NULL);
6441 free_param_data (method->signature, params);
6443 num_named = read16 (named);
6445 for (j = 0; j < num_named; j++) {
6447 char *name, named_type, data_type;
6448 named_type = *named++;
6449 data_type = *named++; /* type of data */
6450 if (data_type == 0x55) {
6453 type_len = mono_metadata_decode_blob_size (named, &named);
6454 type_name = g_malloc (type_len + 1);
6455 memcpy (type_name, named, type_len);
6456 type_name [type_len] = 0;
6458 /* FIXME: lookup the type and check type consistency */
6459 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6460 /* this seems to be the type of the element of the array */
6461 /* g_print ("skipping 0x%02x after prop\n", *named); */
6464 name_len = mono_metadata_decode_blob_size (named, &named);
6465 name = g_malloc (name_len + 1);
6466 memcpy (name, named, name_len);
6467 name [name_len] = 0;
6469 if (named_type == 0x53) {
6470 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6471 void *val = load_cattr_value (image, field->type, named, &named);
6472 mono_field_set_value (attr, field, val);
6473 if (!type_is_reference (field->type))
6475 } else if (named_type == 0x54) {
6478 MonoType *prop_type;
6480 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6481 /* can we have more that 1 arg in a custom attr named property? */
6482 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6483 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6484 mono_property_set_value (prop, attr, pparams, NULL);
6485 if (!type_is_reference (prop_type))
6486 g_free (pparams [0]);
6495 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6502 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6503 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6504 for (i = 0; i < cinfo->num_attrs; ++i) {
6505 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6506 mono_array_set (result, gpointer, i, attr);
6512 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6514 guint32 mtoken, i, len;
6515 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6517 MonoCustomAttrInfo *ainfo;
6518 GList *tmp, *list = NULL;
6521 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6523 i = mono_metadata_custom_attrs_from_index (image, idx);
6527 while (i < ca->rows) {
6528 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6530 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6533 len = g_list_length (list);
6536 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6537 ainfo->num_attrs = len;
6538 ainfo->image = image;
6539 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6540 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6541 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6542 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6543 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6544 mtoken |= MONO_TOKEN_METHOD_DEF;
6546 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6547 mtoken |= MONO_TOKEN_MEMBER_REF;
6550 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6553 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6554 if (!ainfo->attrs [i].ctor)
6555 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6556 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6557 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6558 ainfo->attrs [i].data = data;
6566 mono_custom_attrs_from_method (MonoMethod *method)
6568 MonoCustomAttrInfo *cinfo;
6571 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6573 idx = find_method_index (method);
6574 idx <<= MONO_CUSTOM_ATTR_BITS;
6575 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6576 return mono_custom_attrs_from_index (method->klass->image, idx);
6580 mono_custom_attrs_from_class (MonoClass *klass)
6582 MonoCustomAttrInfo *cinfo;
6585 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6587 idx = mono_metadata_token_index (klass->type_token);
6588 idx <<= MONO_CUSTOM_ATTR_BITS;
6589 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6590 return mono_custom_attrs_from_index (klass->image, idx);
6594 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6596 MonoCustomAttrInfo *cinfo;
6599 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6601 idx = 1; /* there is only one assembly */
6602 idx <<= MONO_CUSTOM_ATTR_BITS;
6603 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6604 return mono_custom_attrs_from_index (assembly->image, idx);
6607 static MonoCustomAttrInfo*
6608 mono_custom_attrs_from_module (MonoImage *image)
6610 MonoCustomAttrInfo *cinfo;
6613 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6615 idx = 1; /* there is only one module */
6616 idx <<= MONO_CUSTOM_ATTR_BITS;
6617 idx |= MONO_CUSTOM_ATTR_MODULE;
6618 return mono_custom_attrs_from_index (image, idx);
6622 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6624 MonoCustomAttrInfo *cinfo;
6627 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6629 idx = find_property_index (klass, property);
6630 idx <<= MONO_CUSTOM_ATTR_BITS;
6631 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6632 return mono_custom_attrs_from_index (klass->image, idx);
6636 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6638 MonoCustomAttrInfo *cinfo;
6641 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6643 idx = find_event_index (klass, event);
6644 idx <<= MONO_CUSTOM_ATTR_BITS;
6645 idx |= MONO_CUSTOM_ATTR_EVENT;
6646 return mono_custom_attrs_from_index (klass->image, idx);
6650 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6652 MonoCustomAttrInfo *cinfo;
6655 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6657 idx = find_field_index (klass, field);
6658 idx <<= MONO_CUSTOM_ATTR_BITS;
6659 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6660 return mono_custom_attrs_from_index (klass->image, idx);
6664 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6667 guint32 i, idx, method_index;
6668 guint32 param_list, param_last, param_pos, found;
6670 MonoReflectionMethodAux *aux;
6672 if (method->klass->image->dynamic) {
6673 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6674 if (!aux || !aux->param_cattr)
6676 return aux->param_cattr [param];
6679 image = method->klass->image;
6680 method_index = find_method_index (method);
6681 ca = &image->tables [MONO_TABLE_METHOD];
6683 if (method->klass->generic_inst || method->klass->generic_container ||
6684 method->signature->generic_param_count) {
6685 /* FIXME FIXME FIXME */
6689 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6690 if (method_index == ca->rows) {
6691 ca = &image->tables [MONO_TABLE_PARAM];
6692 param_last = ca->rows + 1;
6694 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6695 ca = &image->tables [MONO_TABLE_PARAM];
6698 for (i = param_list; i < param_last; ++i) {
6699 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6700 if (param_pos == param) {
6708 idx <<= MONO_CUSTOM_ATTR_BITS;
6709 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6710 return mono_custom_attrs_from_index (image, idx);
6714 * mono_reflection_get_custom_attrs:
6715 * @obj: a reflection object handle
6717 * Return an array with all the custom attributes defined of the
6718 * reflection handle @obj. The objects are fully build.
6721 mono_reflection_get_custom_attrs (MonoObject *obj)
6725 MonoCustomAttrInfo *cinfo = NULL;
6727 MONO_ARCH_SAVE_REGS;
6729 klass = obj->vtable->klass;
6730 if (klass == mono_defaults.monotype_class) {
6731 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6732 klass = mono_class_from_mono_type (rtype->type);
6733 cinfo = mono_custom_attrs_from_class (klass);
6734 } else if (strcmp ("Assembly", klass->name) == 0) {
6735 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6736 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6737 } else if (strcmp ("Module", klass->name) == 0) {
6738 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6739 cinfo = mono_custom_attrs_from_module (module->image);
6740 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6741 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6742 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6743 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6744 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6745 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6746 } else if (strcmp ("MonoField", klass->name) == 0) {
6747 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6748 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6749 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6750 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6751 cinfo = mono_custom_attrs_from_method (rmethod->method);
6752 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6753 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6754 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6755 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6756 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6757 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6758 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6759 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6760 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6761 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6762 } else { /* handle other types here... */
6763 g_error ("get custom attrs not yet supported for %s", klass->name);
6767 result = mono_custom_attrs_construct (cinfo);
6769 mono_custom_attrs_free (cinfo);
6771 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6772 result = mono_array_new (mono_domain_get (), klass, 0);
6778 static MonoMethodSignature*
6779 parameters_to_signature (MonoArray *parameters) {
6780 MonoMethodSignature *sig;
6783 count = parameters? mono_array_length (parameters): 0;
6785 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6786 sig->param_count = count;
6787 sig->sentinelpos = -1; /* FIXME */
6788 for (i = 0; i < count; ++i) {
6789 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6790 sig->params [i] = pt->type;
6795 static MonoMethodSignature*
6796 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6797 MonoMethodSignature *sig;
6799 sig = parameters_to_signature (ctor->parameters);
6800 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6801 sig->ret = &mono_defaults.void_class->byval_arg;
6805 static MonoMethodSignature*
6806 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6807 MonoMethodSignature *sig;
6809 sig = parameters_to_signature (method->parameters);
6810 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6811 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6812 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6816 static MonoMethodSignature*
6817 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6818 MonoMethodSignature *sig;
6820 sig = parameters_to_signature (method->parameters);
6821 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6822 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6823 sig->generic_param_count = 0;
6828 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6830 MonoClass *klass = mono_object_class (prop);
6831 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6832 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6833 *name = mono_string_to_utf8 (pb->name);
6834 *type = pb->type->type;
6836 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6837 *name = g_strdup (p->property->name);
6838 if (p->property->get)
6839 *type = p->property->get->signature->ret;
6841 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6846 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6848 MonoClass *klass = mono_object_class (field);
6849 if (strcmp (klass->name, "FieldBuilder") == 0) {
6850 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6851 *name = mono_string_to_utf8 (fb->name);
6852 *type = fb->type->type;
6854 MonoReflectionField *f = (MonoReflectionField *)field;
6855 *name = g_strdup (f->field->name);
6856 *type = f->field->type;
6861 * Encode a value in a custom attribute stream of bytes.
6862 * The value to encode is either supplied as an object in argument val
6863 * (valuetypes are boxed), or as a pointer to the data in the
6865 * @type represents the type of the value
6866 * @buffer is the start of the buffer
6867 * @p the current position in the buffer
6868 * @buflen contains the size of the buffer and is used to return the new buffer size
6869 * if this needs to be realloced.
6870 * @retbuffer and @retp return the start and the position of the buffer
6873 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6875 MonoTypeEnum simple_type;
6877 if ((p-buffer) + 10 >= *buflen) {
6880 newbuf = g_realloc (buffer, *buflen);
6881 p = newbuf + (p-buffer);
6885 argval = ((char*)arg + sizeof (MonoObject));
6886 simple_type = type->type;
6888 switch (simple_type) {
6889 case MONO_TYPE_BOOLEAN:
6894 case MONO_TYPE_CHAR:
6897 swap_with_size (p, argval, 2, 1);
6903 swap_with_size (p, argval, 4, 1);
6909 swap_with_size (p, argval, 8, 1);
6912 case MONO_TYPE_VALUETYPE:
6913 if (type->data.klass->enumtype) {
6914 simple_type = type->data.klass->enum_basetype->type;
6917 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6920 case MONO_TYPE_STRING: {
6927 str = mono_string_to_utf8 ((MonoString*)arg);
6928 slen = strlen (str);
6929 if ((p-buffer) + 10 + slen >= *buflen) {
6933 newbuf = g_realloc (buffer, *buflen);
6934 p = newbuf + (p-buffer);
6937 mono_metadata_encode_value (slen, p, &p);
6938 memcpy (p, str, slen);
6943 case MONO_TYPE_CLASS: {
6951 k = mono_object_class (arg);
6952 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6953 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6954 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6956 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6957 slen = strlen (str);
6958 if ((p-buffer) + 10 + slen >= *buflen) {
6962 newbuf = g_realloc (buffer, *buflen);
6963 p = newbuf + (p-buffer);
6966 mono_metadata_encode_value (slen, p, &p);
6967 memcpy (p, str, slen);
6972 case MONO_TYPE_SZARRAY: {
6974 MonoClass *eclass, *arg_eclass;
6977 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6980 len = mono_array_length ((MonoArray*)arg);
6982 *p++ = (len >> 8) & 0xff;
6983 *p++ = (len >> 16) & 0xff;
6984 *p++ = (len >> 24) & 0xff;
6986 *retbuffer = buffer;
6987 eclass = type->data.klass;
6988 arg_eclass = mono_object_class (arg)->element_class;
6989 if (eclass->valuetype && arg_eclass->valuetype) {
6990 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6991 int elsize = mono_class_array_element_size (eclass);
6992 for (i = 0; i < len; ++i) {
6993 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6997 for (i = 0; i < len; ++i) {
6998 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7003 /* it may be a boxed value or a Type */
7004 case MONO_TYPE_OBJECT: {
7005 MonoClass *klass = mono_object_class (arg);
7009 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7012 } else if (klass->enumtype) {
7014 } else if (klass == mono_defaults.string_class) {
7015 simple_type = MONO_TYPE_STRING;
7018 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7019 *p++ = simple_type = klass->byval_arg.type;
7022 g_error ("unhandled type in custom attr");
7024 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7025 slen = strlen (str);
7026 if ((p-buffer) + 10 + slen >= *buflen) {
7030 newbuf = g_realloc (buffer, *buflen);
7031 p = newbuf + (p-buffer);
7034 mono_metadata_encode_value (slen, p, &p);
7035 memcpy (p, str, slen);
7038 simple_type = klass->enum_basetype->type;
7042 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7045 *retbuffer = buffer;
7049 * mono_reflection_get_custom_attrs_blob:
7050 * @ctor: custom attribute constructor
7051 * @ctorArgs: arguments o the constructor
7057 * Creates the blob of data that needs to be saved in the metadata and that represents
7058 * the custom attributed described by @ctor, @ctorArgs etc.
7059 * Returns: a Byte array representing the blob of data.
7062 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7065 MonoMethodSignature *sig;
7070 MONO_ARCH_SAVE_REGS;
7072 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7073 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7075 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7077 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7079 p = buffer = g_malloc (buflen);
7080 /* write the prolog */
7083 for (i = 0; i < sig->param_count; ++i) {
7084 arg = mono_array_get (ctorArgs, MonoObject*, i);
7085 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7089 i += mono_array_length (properties);
7091 i += mono_array_length (fields);
7093 *p++ = (i >> 8) & 0xff;
7096 for (i = 0; i < mono_array_length (properties); ++i) {
7101 prop = mono_array_get (properties, gpointer, i);
7102 get_prop_name_and_type (prop, &pname, &ptype);
7103 *p++ = 0x54; /* PROPERTY signature */
7105 /* Preallocate a large enough buffer */
7106 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7107 char *str = type_get_qualified_name (ptype, NULL);
7113 len += strlen (pname);
7115 if ((p-buffer) + 20 + len >= buflen) {
7119 newbuf = g_realloc (buffer, buflen);
7120 p = newbuf + (p-buffer);
7124 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7125 char *str = type_get_qualified_name (ptype, NULL);
7126 int slen = strlen (str);
7130 * This seems to be optional...
7133 mono_metadata_encode_value (slen, p, &p);
7134 memcpy (p, str, slen);
7138 mono_metadata_encode_value (ptype->type, p, &p);
7139 if (ptype->type == MONO_TYPE_SZARRAY)
7140 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7142 len = strlen (pname);
7143 mono_metadata_encode_value (len, p, &p);
7144 memcpy (p, pname, len);
7146 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7153 for (i = 0; i < mono_array_length (fields); ++i) {
7158 field = mono_array_get (fields, gpointer, i);
7159 get_field_name_and_type (field, &fname, &ftype);
7160 *p++ = 0x53; /* FIELD signature */
7161 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7162 char *str = type_get_qualified_name (ftype, NULL);
7163 int slen = strlen (str);
7164 if ((p-buffer) + 10 + slen >= buflen) {
7168 newbuf = g_realloc (buffer, buflen);
7169 p = newbuf + (p-buffer);
7174 * This seems to be optional...
7177 mono_metadata_encode_value (slen, p, &p);
7178 memcpy (p, str, slen);
7182 mono_metadata_encode_value (ftype->type, p, &p);
7183 if (ftype->type == MONO_TYPE_SZARRAY)
7184 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7186 len = strlen (fname);
7187 mono_metadata_encode_value (len, p, &p);
7188 memcpy (p, fname, len);
7190 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7195 g_assert (p - buffer <= buflen);
7196 buflen = p - buffer;
7197 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7198 p = mono_array_addr (result, char, 0);
7199 memcpy (p, buffer, buflen);
7201 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7207 * mono_reflection_setup_internal_class:
7208 * @tb: a TypeBuilder object
7210 * Creates a MonoClass that represents the TypeBuilder.
7211 * This is a trick that lets us simplify a lot of reflection code
7212 * (and will allow us to support Build and Run assemblies easier).
7215 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7217 MonoClass *klass, *parent;
7219 MONO_ARCH_SAVE_REGS;
7222 /* check so we can compile corlib correctly */
7223 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7224 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7225 parent = tb->parent->type->data.klass;
7227 parent = my_mono_class_from_mono_type (tb->parent->type);
7233 /* the type has already being created: it means we just have to change the parent */
7234 if (tb->type.type) {
7235 klass = mono_class_from_mono_type (tb->type.type);
7236 klass->parent = NULL;
7237 /* fool mono_class_setup_parent */
7238 g_free (klass->supertypes);
7239 klass->supertypes = NULL;
7240 mono_class_setup_parent (klass, parent);
7241 mono_class_setup_mono_type (klass);
7245 klass = g_new0 (MonoClass, 1);
7247 klass->image = &tb->module->dynamic_image->image;
7249 klass->inited = 1; /* we lie to the runtime */
7250 klass->name = mono_string_to_utf8 (tb->name);
7251 klass->name_space = mono_string_to_utf8 (tb->nspace);
7252 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7253 klass->flags = tb->attrs;
7255 klass->element_class = klass;
7256 klass->reflection_info = tb; /* need to pin. */
7258 /* Put into cache so mono_class_get () will find it */
7259 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7261 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7262 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7264 if (parent != NULL) {
7265 mono_class_setup_parent (klass, parent);
7266 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7267 const char *old_n = klass->name;
7268 /* trick to get relative numbering right when compiling corlib */
7269 klass->name = "BuildingObject";
7270 mono_class_setup_parent (klass, mono_defaults.object_class);
7271 klass->name = old_n;
7274 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7275 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7276 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7277 klass->instance_size = sizeof (MonoObject);
7278 klass->size_inited = 1;
7279 mono_class_setup_vtable (klass, NULL, 0);
7282 mono_class_setup_mono_type (klass);
7284 mono_class_setup_supertypes (klass);
7287 * FIXME: handle interfaces.
7290 tb->type.type = &klass->byval_arg;
7292 if (tb->nesting_type) {
7293 g_assert (tb->nesting_type->type);
7294 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7297 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7301 * mono_reflection_setup_generic_class:
7302 * @tb: a TypeBuilder object
7304 * Setup the generic class before adding the first generic parameter.
7307 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7311 MONO_ARCH_SAVE_REGS;
7313 klass = my_mono_class_from_mono_type (tb->type.type);
7314 if (tb->generic_container)
7317 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7318 tb->generic_container->klass = klass;
7320 tb->generic_container->context = g_new0 (MonoGenericContext, 1);
7321 tb->generic_container->context->container = tb->generic_container;
7325 * mono_reflection_create_generic_class:
7326 * @tb: a TypeBuilder object
7328 * Creates the generic class after all generic parameters have been added.
7331 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7336 MONO_ARCH_SAVE_REGS;
7338 klass = my_mono_class_from_mono_type (tb->type.type);
7340 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7342 if (klass->generic_container || (count == 0))
7345 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7347 klass->generic_container = tb->generic_container;
7349 klass->generic_container->type_argc = count;
7350 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7352 for (i = 0; i < count; i++) {
7353 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7354 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7355 g_assert (klass->generic_container->type_params [i].owner);
7360 * mono_reflection_create_internal_class:
7361 * @tb: a TypeBuilder object
7363 * Actually create the MonoClass that is associated with the TypeBuilder.
7366 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7370 MONO_ARCH_SAVE_REGS;
7372 klass = my_mono_class_from_mono_type (tb->type.type);
7374 if (klass->enumtype && klass->enum_basetype == NULL) {
7375 MonoReflectionFieldBuilder *fb;
7378 g_assert (tb->fields != NULL);
7379 g_assert (mono_array_length (tb->fields) >= 1);
7381 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7383 klass->enum_basetype = fb->type->type;
7384 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7385 if (!klass->element_class)
7386 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7389 * get the element_class from the current corlib.
7391 ec = default_class_from_mono_type (klass->enum_basetype);
7392 klass->instance_size = ec->instance_size;
7393 klass->size_inited = 1;
7395 * this is almost safe to do with enums and it's needed to be able
7396 * to create objects of the enum type (for use in SetConstant).
7398 /* FIXME: Does this mean enums can't have method overrides ? */
7399 mono_class_setup_vtable (klass, NULL, 0);
7403 static MonoMarshalSpec*
7404 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7405 MonoReflectionMarshal *minfo)
7407 MonoMarshalSpec *res;
7409 res = g_new0 (MonoMarshalSpec, 1);
7410 res->native = minfo->type;
7412 switch (minfo->type) {
7413 case MONO_NATIVE_LPARRAY:
7414 res->data.array_data.elem_type = minfo->eltype;
7415 res->data.array_data.param_num = 0; /* Not yet */
7416 res->data.array_data.num_elem = minfo->count;
7419 case MONO_NATIVE_BYVALTSTR:
7420 case MONO_NATIVE_BYVALARRAY:
7421 res->data.array_data.num_elem = minfo->count;
7424 case MONO_NATIVE_CUSTOM:
7425 if (minfo->marshaltyperef)
7426 res->data.custom_data.custom_name =
7427 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7429 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7439 MonoReflectionMarshal*
7440 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7441 MonoMarshalSpec *spec)
7443 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7444 MonoReflectionMarshal *minfo;
7447 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7448 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7449 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7450 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7453 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7454 minfo->type = spec->native;
7456 switch (minfo->type) {
7457 case MONO_NATIVE_LPARRAY:
7458 minfo->eltype = spec->data.array_data.elem_type;
7459 minfo->count = spec->data.array_data.num_elem;
7462 case MONO_NATIVE_BYVALTSTR:
7463 case MONO_NATIVE_BYVALARRAY:
7464 minfo->count = spec->data.array_data.num_elem;
7467 case MONO_NATIVE_CUSTOM:
7468 if (spec->data.custom_data.custom_name) {
7469 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7471 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7473 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7475 if (spec->data.custom_data.cookie)
7476 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7487 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7488 ReflectionMethodBuilder *rmb,
7489 MonoMethodSignature *sig)
7492 MonoMethodNormal *pm;
7493 MonoMarshalSpec **specs;
7494 MonoReflectionMethodAux *method_aux;
7497 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7498 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7499 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7501 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7503 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7505 pm = (MonoMethodNormal*)m;
7508 m->flags = rmb->attrs;
7509 m->iflags = rmb->iattrs;
7510 m->name = mono_string_to_utf8 (rmb->name);
7514 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7516 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7517 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7520 m->signature->pinvoke = 1;
7521 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7522 m->signature->pinvoke = 1;
7524 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7526 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7527 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7529 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7531 if (klass->image->dynamic)
7532 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7535 } else if (!m->klass->dummy &&
7536 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7537 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7538 MonoMethodHeader *header;
7540 gint32 max_stack, i;
7541 gint32 num_locals = 0;
7542 gint32 num_clauses = 0;
7546 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7547 code_size = rmb->ilgen->code_len;
7548 max_stack = rmb->ilgen->max_stack;
7549 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7550 if (rmb->ilgen->ex_handlers)
7551 num_clauses = method_count_clauses (rmb->ilgen);
7554 code = mono_array_addr (rmb->code, guint8, 0);
7555 code_size = mono_array_length (rmb->code);
7556 /* we probably need to run a verifier on the code... */
7566 header = g_malloc0 (sizeof (MonoMethodHeader) +
7567 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7568 header->code_size = code_size;
7569 header->code = g_malloc (code_size);
7570 memcpy ((char*)header->code, code, code_size);
7571 header->max_stack = max_stack;
7572 header->init_locals = rmb->init_locals;
7573 header->num_locals = num_locals;
7575 for (i = 0; i < num_locals; ++i) {
7576 MonoReflectionLocalBuilder *lb =
7577 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7579 header->locals [i] = g_new0 (MonoType, 1);
7580 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7583 header->num_clauses = num_clauses;
7585 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7586 rmb->ilgen, num_clauses);
7589 pm->header = header;
7592 if (rmb->generic_params) {
7593 int count = mono_array_length (rmb->generic_params);
7594 MonoGenericContainer *container;
7596 pm->generic_container = container = g_new0 (MonoGenericContainer, 1);
7597 container->type_argc = count;
7598 container->type_params = g_new0 (MonoGenericParam, count);
7600 for (i = 0; i < count; i++) {
7601 MonoReflectionGenericParam *gp =
7602 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7604 container->type_params [i] = *gp->type.type->data.generic_param;
7609 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7612 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7614 for (i = 0; i < rmb->nrefs; ++i)
7615 mw->data = g_list_append (mw->data, rmb->refs [i]);
7620 /* Parameter info */
7623 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7624 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7625 for (i = 0; i <= m->signature->param_count; ++i) {
7626 MonoReflectionParamBuilder *pb;
7627 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7629 m->signature->params [i - 1]->attrs = pb->attrs;
7631 if (pb->def_value) {
7632 MonoDynamicImage *assembly;
7633 guint32 idx, def_type, len;
7637 if (!method_aux->param_defaults)
7638 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7639 assembly = (MonoDynamicImage*)klass->image;
7640 idx = encode_constant (assembly, pb->def_value, &def_type);
7641 /* Copy the data from the blob since it might get realloc-ed */
7642 p = assembly->blob.data + idx;
7643 len = mono_metadata_decode_blob_size (p, &p2);
7645 method_aux->param_defaults [i] = g_malloc (len);
7646 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7650 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7652 if (!method_aux->param_cattr)
7653 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7654 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7660 /* Parameter marshalling */
7663 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7664 MonoReflectionParamBuilder *pb;
7665 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7666 if (pb->marshal_info) {
7668 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7669 specs [pb->position] =
7670 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7674 if (specs != NULL) {
7676 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7677 method_aux->param_marshall = specs;
7680 if (klass->image->dynamic && method_aux)
7681 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7687 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7689 ReflectionMethodBuilder rmb;
7690 MonoMethodSignature *sig;
7692 sig = ctor_builder_to_signature (mb);
7694 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7696 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7697 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7699 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7700 /* ilgen is no longer needed */
7708 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7710 ReflectionMethodBuilder rmb;
7711 MonoMethodSignature *sig;
7713 sig = method_builder_to_signature (mb);
7715 reflection_methodbuilder_from_method_builder (&rmb, mb);
7717 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7718 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7720 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7721 /* ilgen is no longer needed */
7727 static MonoClassField*
7728 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7730 MonoClassField *field;
7737 field = g_new0 (MonoClassField, 1);
7739 field->name = mono_string_to_utf8 (fb->name);
7741 /* FIXME: handle type modifiers */
7742 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7743 field->type->attrs = fb->attrs;
7745 field->type = fb->type->type;
7747 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7748 field->data = mono_array_addr (fb->rva_data, char, 0);
7749 if (fb->offset != -1)
7750 field->offset = fb->offset;
7751 field->parent = klass;
7753 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7755 if (fb->def_value) {
7756 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7757 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7758 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7759 /* Copy the data from the blob since it might get realloc-ed */
7760 p = assembly->blob.data + idx;
7761 len = mono_metadata_decode_blob_size (p, &p2);
7763 field->data = g_malloc (len);
7764 memcpy ((gpointer)field->data, p, len);
7771 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7773 MonoClass *klass, *gklass;
7774 MonoReflectionTypeBuilder *tb = NULL;
7775 MonoGenericInst *ginst, *cached;
7780 klass = mono_class_from_mono_type (type->type);
7781 if (!klass->generic_container && !klass->generic_inst &&
7782 !(klass->nested_in && klass->nested_in->generic_container))
7785 mono_loader_lock ();
7787 domain = mono_object_domain (type);
7789 ginst = g_new0 (MonoGenericInst, 1);
7791 ginst->type_argc = type_argc;
7792 ginst->type_argv = types;
7794 for (i = 0; i < ginst->type_argc; ++i) {
7795 if (!ginst->is_open)
7796 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7799 ginst->generic_type = &klass->byval_arg;
7801 if (klass->generic_inst) {
7802 MonoGenericInst *kginst = klass->generic_inst;
7803 MonoGenericInst *oginst = ginst;
7805 oginst->context = g_new0 (MonoGenericContext, 1);
7806 oginst->context->ginst = oginst;
7808 ginst = g_new0 (MonoGenericInst, 1);
7810 ginst->type_argc = kginst->type_argc;
7811 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7813 for (i = 0; i < ginst->type_argc; i++) {
7814 MonoType *t = kginst->type_argv [i];
7816 t = mono_class_inflate_generic_type (t, oginst->context);
7818 if (!ginst->is_open)
7819 ginst->is_open = mono_class_is_open_constructed_type (t);
7821 ginst->type_argv [i] = t;
7824 ginst->generic_type = kginst->generic_type;
7827 geninst = g_new0 (MonoType, 1);
7828 geninst->type = MONO_TYPE_GENERICINST;
7830 cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7833 mono_loader_unlock ();
7834 geninst->data.generic_inst = cached;
7838 gklass = mono_class_from_mono_type (ginst->generic_type);
7839 g_assert ((ginst->container = gklass->generic_container) != NULL);
7841 geninst->data.generic_inst = ginst;
7843 ginst->context = g_new0 (MonoGenericContext, 1);
7844 ginst->context->ginst = ginst;
7846 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7847 tb = (MonoReflectionTypeBuilder *) type;
7849 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7850 ginst->is_dynamic = TRUE;
7851 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7852 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7853 MonoReflectionType *rgt = rgi->generic_type;
7855 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7856 tb = (MonoReflectionTypeBuilder *) rgt;
7858 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7859 ginst->is_dynamic = TRUE;
7861 icount = klass->interface_count;
7864 ginst->ifaces = g_new0 (MonoType *, icount);
7865 ginst->count_ifaces = icount;
7867 for (i = 0; i < icount; i++) {
7868 MonoReflectionType *itype;
7871 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7873 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7874 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7875 if (!ginst->ifaces [i])
7876 ginst->ifaces [i] = itype->type;
7879 mono_class_create_generic (ginst);
7880 mono_class_create_generic_2 (ginst);
7882 g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7884 mono_loader_unlock ();
7890 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7892 MonoClass *klass, *pklass = NULL;
7893 MonoReflectionType *parent = NULL;
7895 MonoReflectionTypeBuilder *tb = NULL;
7896 MonoGenericInst *ginst;
7899 domain = mono_object_domain (type);
7900 klass = mono_class_from_mono_type (type->type);
7902 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7903 tb = (MonoReflectionTypeBuilder *) type;
7906 parent = tb->parent;
7907 pklass = mono_class_from_mono_type (parent->type);
7910 pklass = klass->parent;
7912 parent = mono_type_get_object (domain, &pklass->byval_arg);
7913 else if (klass->generic_inst && klass->generic_inst->parent) {
7914 parent = mono_type_get_object (domain, klass->generic_inst->parent);
7915 pklass = mono_class_from_mono_type (klass->generic_inst->parent);
7919 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7923 ginst = geninst->data.generic_inst;
7925 if (pklass && pklass->generic_inst)
7926 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7931 MonoReflectionMethod*
7932 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7934 MonoMethod *method, *inflated;
7935 MonoReflectionMethodBuilder *mb = NULL;
7936 MonoGenericMethod *gmethod;
7937 MonoGenericContext *context;
7940 MONO_ARCH_SAVE_REGS;
7941 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7942 MonoReflectionTypeBuilder *tb;
7945 mb = (MonoReflectionMethodBuilder *) rmethod;
7946 tb = (MonoReflectionTypeBuilder *) mb->type;
7947 klass = mono_class_from_mono_type (tb->type.type);
7949 method = methodbuilder_to_mono_method (klass, mb);
7951 method = rmethod->method;
7954 count = method->signature->generic_param_count;
7955 if (count != mono_array_length (types))
7958 gmethod = g_new0 (MonoGenericMethod, 1);
7959 gmethod->mtype_argc = count;
7960 gmethod->mtype_argv = g_new0 (MonoType *, count);
7961 for (i = 0; i < count; i++) {
7962 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7963 gmethod->mtype_argv [i] = garg->type;
7966 gmethod->reflection_info = rmethod;
7968 context = g_new0 (MonoGenericContext, 1);
7969 context->ginst = method->klass->generic_inst;
7970 context->gmethod = gmethod;
7972 inflated = mono_class_inflate_generic_method (method, context, NULL);
7974 return mono_method_get_object (
7975 mono_object_domain (rmethod), inflated, NULL);
7979 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7981 MonoGenericMethod *gmethod;
7982 MonoGenericInst *ginst;
7983 MonoGenericContext *context;
7986 ginst = type->type.type->data.generic_inst;
7988 gmethod = g_new0 (MonoGenericMethod, 1);
7989 gmethod->reflection_info = obj;
7991 gmethod->mtype_argc = method->signature->generic_param_count;
7992 gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7994 for (i = 0; i < gmethod->mtype_argc; i++) {
7995 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7996 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
7998 g_assert (gparam->pklass);
7999 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
8002 context = g_new0 (MonoGenericContext, 1);
8003 context->ginst = ginst;
8004 context->gmethod = gmethod;
8006 return mono_class_inflate_generic_method (method, context, ginst->klass);
8010 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
8015 klass = mono_class_from_mono_type (type->type.type);
8017 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8018 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8019 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8020 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8021 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8022 method = ((MonoReflectionMethod *) obj)->method;
8024 method = NULL; /* prevent compiler warning */
8025 g_assert_not_reached ();
8028 return inflate_mono_method (type, method, obj);
8032 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods,
8033 MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
8035 MonoGenericInst *ginst;
8036 MonoDynamicGenericInst *dginst;
8037 MonoClass *klass, *gklass, *pklass;
8040 MONO_ARCH_SAVE_REGS;
8042 klass = mono_class_from_mono_type (type->type.type);
8043 ginst = type->type.type->data.generic_inst;
8045 if (ginst->initialized)
8048 dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
8050 gklass = mono_class_from_mono_type (ginst->generic_type);
8051 mono_class_init (gklass);
8054 pklass = mono_class_from_mono_type (ginst->parent);
8056 pklass = gklass->parent;
8058 mono_class_setup_parent (klass, pklass);
8060 dginst->count_methods = methods ? mono_array_length (methods) : 0;
8061 dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
8062 dginst->count_fields = fields ? mono_array_length (fields) : 0;
8063 dginst->count_properties = properties ? mono_array_length (properties) : 0;
8064 dginst->count_events = events ? mono_array_length (events) : 0;
8066 dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
8067 dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
8068 dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
8069 dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
8070 dginst->events = g_new0 (MonoEvent, dginst->count_events);
8072 for (i = 0; i < dginst->count_methods; i++) {
8073 MonoObject *obj = mono_array_get (methods, gpointer, i);
8075 dginst->methods [i] = inflate_method (type, obj);
8078 for (i = 0; i < dginst->count_ctors; i++) {
8079 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8081 dginst->ctors [i] = inflate_method (type, obj);
8084 for (i = 0; i < dginst->count_fields; i++) {
8085 MonoObject *obj = mono_array_get (fields, gpointer, i);
8086 MonoClassField *field;
8087 MonoInflatedField *ifield;
8089 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8090 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8091 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8092 field = ((MonoReflectionField *) obj)->field;
8094 field = NULL; /* prevent compiler warning */
8095 g_assert_not_reached ();
8098 ifield = g_new0 (MonoInflatedField, 1);
8099 ifield->generic_type = field->type;
8100 ifield->reflection_info = obj;
8102 dginst->fields [i] = *field;
8103 dginst->fields [i].generic_info = ifield;
8104 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
8107 for (i = 0; i < dginst->count_properties; i++) {
8108 MonoObject *obj = mono_array_get (properties, gpointer, i);
8109 MonoProperty *property = &dginst->properties [i];
8111 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8112 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8114 property->parent = klass;
8115 property->attrs = pb->attrs;
8116 property->name = mono_string_to_utf8 (pb->name);
8118 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8120 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8121 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8122 *property = *((MonoReflectionProperty *) obj)->property;
8125 property->get = inflate_mono_method (type, property->get, NULL);
8127 property->set = inflate_mono_method (type, property->set, NULL);
8129 g_assert_not_reached ();
8132 for (i = 0; i < dginst->count_events; i++) {
8133 MonoObject *obj = mono_array_get (events, gpointer, i);
8134 MonoEvent *event = &dginst->events [i];
8136 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8137 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8139 event->parent = klass;
8140 event->attrs = eb->attrs;
8141 event->name = mono_string_to_utf8 (eb->name);
8143 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8144 if (eb->remove_method)
8145 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8146 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8147 *event = *((MonoReflectionEvent *) obj)->event;
8150 event->add = inflate_mono_method (type, event->add, NULL);
8152 event->remove = inflate_mono_method (type, event->remove, NULL);
8154 g_assert_not_reached ();
8157 ginst->initialized = TRUE;
8161 ensure_runtime_vtable (MonoClass *klass)
8163 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8164 int i, num, j, onum;
8165 MonoMethod **overrides;
8167 if (!tb || klass->wastypebuilder)
8170 ensure_runtime_vtable (klass->parent);
8172 num = tb->ctors? mono_array_length (tb->ctors): 0;
8173 num += tb->num_methods;
8174 klass->method.count = num;
8175 klass->methods = g_new (MonoMethod*, num);
8176 num = tb->ctors? mono_array_length (tb->ctors): 0;
8177 for (i = 0; i < num; ++i)
8178 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8179 num = tb->num_methods;
8181 for (i = 0; i < num; ++i)
8182 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8184 if (tb->interfaces) {
8185 klass->interface_count = mono_array_length (tb->interfaces);
8186 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8187 for (i = 0; i < klass->interface_count; ++i) {
8188 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8189 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8193 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8194 for (i = 0; i < klass->method.count; ++i)
8195 klass->methods [i]->slot = i;
8200 for (i = 0; i < tb->num_methods; ++i) {
8201 MonoReflectionMethodBuilder *mb =
8202 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8203 if (mb->override_method)
8208 overrides = g_new0 (MonoMethod*, onum * 2);
8212 for (i = 0; i < tb->num_methods; ++i) {
8213 MonoReflectionMethodBuilder *mb =
8214 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8215 if (mb->override_method) {
8216 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8217 overrides [onum * 2] =
8218 mb->override_method->method;
8219 overrides [onum * 2 + 1] =
8222 g_assert (mb->mhandle);
8229 mono_class_setup_vtable (klass, overrides, onum);
8234 typebuilder_setup_fields (MonoClass *klass)
8236 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8237 MonoReflectionFieldBuilder *fb;
8238 MonoClassField *field;
8243 klass->field.count = tb->num_fields;
8244 klass->field.first = 0;
8245 klass->field.last = klass->field.count;
8247 if (!klass->field.count)
8250 klass->fields = g_new0 (MonoClassField, klass->field.count);
8252 for (i = 0; i < klass->field.count; ++i) {
8253 fb = mono_array_get (tb->fields, gpointer, i);
8254 field = &klass->fields [i];
8255 field->name = mono_string_to_utf8 (fb->name);
8257 /* FIXME: handle type modifiers */
8258 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8259 field->type->attrs = fb->attrs;
8261 field->type = fb->type->type;
8263 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8264 field->data = mono_array_addr (fb->rva_data, char, 0);
8265 if (fb->offset != -1)
8266 field->offset = fb->offset;
8267 field->parent = klass;
8269 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8271 if (fb->def_value) {
8272 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8273 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8274 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8275 /* Copy the data from the blob since it might get realloc-ed */
8276 p = assembly->blob.data + idx;
8277 len = mono_metadata_decode_blob_size (p, &p2);
8279 field->data = g_malloc (len);
8280 memcpy ((gpointer)field->data, p, len);
8283 mono_class_layout_fields (klass);
8287 typebuilder_setup_properties (MonoClass *klass)
8289 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8290 MonoReflectionPropertyBuilder *pb;
8293 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8294 klass->property.first = 0;
8295 klass->property.last = klass->property.count;
8297 klass->properties = g_new0 (MonoProperty, klass->property.count);
8298 for (i = 0; i < klass->property.count; ++i) {
8299 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8300 klass->properties [i].parent = klass;
8301 klass->properties [i].attrs = pb->attrs;
8302 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8304 klass->properties [i].get = pb->get_method->mhandle;
8306 klass->properties [i].set = pb->set_method->mhandle;
8310 MonoReflectionEvent *
8311 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8313 MonoEvent *event = g_new0 (MonoEvent, 1);
8317 klass = my_mono_class_from_mono_type (tb->type.type);
8319 event->parent = klass;
8320 event->attrs = eb->attrs;
8321 event->name = mono_string_to_utf8 (eb->name);
8323 event->add = eb->add_method->mhandle;
8324 if (eb->remove_method)
8325 event->remove = eb->remove_method->mhandle;
8326 if (eb->raise_method)
8327 event->raise = eb->raise_method->mhandle;
8329 if (eb->other_methods) {
8330 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8331 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8332 MonoReflectionMethodBuilder *mb =
8333 mono_array_get (eb->other_methods,
8334 MonoReflectionMethodBuilder*, j);
8335 event->other [j] = mb->mhandle;
8339 return mono_event_get_object (mono_object_domain (tb), klass, event);
8343 typebuilder_setup_events (MonoClass *klass)
8345 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8346 MonoReflectionEventBuilder *eb;
8349 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8350 klass->event.first = 0;
8351 klass->event.last = klass->event.count;
8353 klass->events = g_new0 (MonoEvent, klass->event.count);
8354 for (i = 0; i < klass->event.count; ++i) {
8355 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8356 klass->events [i].parent = klass;
8357 klass->events [i].attrs = eb->attrs;
8358 klass->events [i].name = mono_string_to_utf8 (eb->name);
8360 klass->events [i].add = eb->add_method->mhandle;
8361 if (eb->remove_method)
8362 klass->events [i].remove = eb->remove_method->mhandle;
8363 if (eb->raise_method)
8364 klass->events [i].raise = eb->raise_method->mhandle;
8366 if (eb->other_methods) {
8367 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8368 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8369 MonoReflectionMethodBuilder *mb =
8370 mono_array_get (eb->other_methods,
8371 MonoReflectionMethodBuilder*, j);
8372 klass->events [i].other [j] = mb->mhandle;
8379 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8382 MonoReflectionType* res;
8385 MONO_ARCH_SAVE_REGS;
8387 klass = my_mono_class_from_mono_type (tb->type.type);
8389 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8392 * Fields to set in klass:
8393 * the various flags: delegate/unicode/contextbound etc.
8395 klass->flags = tb->attrs;
8397 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8398 /* No need to fully construct the type */
8399 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8401 /* enums are done right away */
8402 if (!klass->enumtype)
8403 ensure_runtime_vtable (klass);
8406 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8407 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8408 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8412 /* fields and object layout */
8413 if (klass->parent) {
8414 if (!klass->parent->size_inited)
8415 mono_class_init (klass->parent);
8416 klass->instance_size += klass->parent->instance_size;
8417 klass->class_size += klass->parent->class_size;
8418 klass->min_align = klass->parent->min_align;
8420 klass->instance_size = sizeof (MonoObject);
8421 klass->min_align = 1;
8424 /* FIXME: handle packing_size and instance_size */
8425 typebuilder_setup_fields (klass);
8427 typebuilder_setup_properties (klass);
8429 typebuilder_setup_events (klass);
8431 klass->wastypebuilder = TRUE;
8433 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8434 g_assert (res != (MonoReflectionType*)tb);
8439 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8441 MonoGenericParam *param;
8444 MONO_ARCH_SAVE_REGS;
8446 param = g_new0 (MonoGenericParam, 1);
8448 if (gparam->mbuilder) {
8449 if (!gparam->mbuilder->generic_container)
8450 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8451 param->owner = gparam->mbuilder->generic_container;
8452 } else if (gparam->tbuilder) {
8453 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8454 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8459 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8460 if (gparam->index >= count)
8463 container = nesting->generic_container;
8464 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8467 g_assert (container);
8468 param->owner = container;
8471 param->method = NULL;
8472 param->name = mono_string_to_utf8 (gparam->name);
8473 param->num = gparam->index;
8475 image = &gparam->tbuilder->module->dynamic_image->image;
8476 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8478 param->pklass->reflection_info = gparam;
8480 gparam->type.type = g_new0 (MonoType, 1);
8481 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8482 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8483 gparam->type.type->data.generic_param = param;
8487 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8489 MonoDynamicImage *assembly = sig->module->dynamic_image;
8490 guint32 na = mono_array_length (sig->arguments);
8495 MONO_ARCH_SAVE_REGS;
8497 p = buf = g_malloc (10 + na * 10);
8499 mono_metadata_encode_value (0x07, p, &p);
8500 mono_metadata_encode_value (na, p, &p);
8501 for (i = 0; i < na; ++i) {
8502 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8503 encode_reflection_type (assembly, type, p, &p);
8507 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8508 p = mono_array_addr (result, char, 0);
8509 memcpy (p, buf, buflen);
8516 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8518 MonoDynamicImage *assembly = sig->module->dynamic_image;
8519 guint32 na = mono_array_length (sig->arguments);
8524 MONO_ARCH_SAVE_REGS;
8526 p = buf = g_malloc (10 + na * 10);
8528 mono_metadata_encode_value (0x06, p, &p);
8529 for (i = 0; i < na; ++i) {
8530 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8531 encode_reflection_type (assembly, type, p, &p);
8535 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8536 p = mono_array_addr (result, char, 0);
8537 memcpy (p, buf, buflen);
8544 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8546 ReflectionMethodBuilder rmb;
8547 MonoMethodSignature *sig;
8550 sig = dynamic_method_to_signature (mb);
8552 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8555 * Resolve references.
8557 rmb.nrefs = mb->nrefs;
8558 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8559 for (i = 0; i < mb->nrefs; ++i) {
8560 gpointer ref = resolve_object (mb->module->image,
8561 mono_array_get (mb->refs, MonoObject*, i));
8564 mono_raise_exception (mono_get_exception_type_load (NULL));
8571 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8575 /* ilgen is no longer needed */
8580 * mono_reflection_lookup_dynamic_token:
8582 * Finish the Builder object pointed to by TOKEN and return the corresponding
8583 * runtime structure.
8586 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8588 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8591 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8594 return resolve_object (image, obj);
8598 resolve_object (MonoImage *image, MonoObject *obj)
8600 gpointer result = NULL;
8602 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8603 result = mono_string_intern ((MonoString*)obj);
8605 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8606 MonoReflectionType *tb = (MonoReflectionType*)obj;
8607 result = mono_class_from_mono_type (tb->type);
8609 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8610 result = ((MonoReflectionMethod*)obj)->method;
8612 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8613 result = ((MonoReflectionMethod*)obj)->method;
8615 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8616 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8617 result = mb->mhandle;
8619 /* Type is not yet created */
8620 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8622 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8625 * Hopefully this has been filled in by calling CreateType() on the
8629 * TODO: This won't work if the application finishes another
8630 * TypeBuilder instance instead of this one.
8632 result = mb->mhandle;
8634 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8635 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8637 result = cb->mhandle;
8639 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8641 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8642 result = cb->mhandle;
8644 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8645 result = ((MonoReflectionField*)obj)->field;
8647 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8648 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8649 result = fb->handle;
8652 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8654 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8655 result = fb->handle;
8657 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8658 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8661 klass = tb->type.type->data.klass;
8662 if (klass->wastypebuilder) {
8663 /* Already created */
8667 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8668 result = tb->type.type->data.klass;
8671 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8672 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8673 MonoMethodSignature *sig;
8676 if (helper->arguments)
8677 nargs = mono_array_length (helper->arguments);
8681 sig = mono_metadata_signature_alloc (image, nargs);
8682 sig->explicit_this = helper->call_conv & 64;
8683 sig->hasthis = helper->call_conv & 32;
8685 if (helper->call_conv == 0) /* unmanaged */
8686 sig->call_convention = helper->unmanaged_call_conv - 1;
8688 if (helper->call_conv & 0x02)
8689 sig->call_convention = MONO_CALL_VARARG;
8691 sig->call_convention = MONO_CALL_DEFAULT;
8693 sig->param_count = nargs;
8694 /* TODO: Copy type ? */
8695 sig->ret = helper->return_type->type;
8696 for (i = 0; i < nargs; ++i) {
8697 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8698 sig->params [i] = rt->type;
8703 g_print (obj->vtable->klass->name);
8704 g_assert_not_reached ();