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;
46 MonoGenericContainer *generic_container;
52 guint32 *table_idx; /* note: it's a pointer */
56 MonoBoolean init_locals;
57 MonoArray *return_modreq;
58 MonoArray *return_modopt;
59 MonoArray *param_modreq;
60 MonoArray *param_modopt;
61 MonoArray *permissions;
66 int charset, lasterr, native_cc;
67 MonoString *dll, *dllentry;
68 } ReflectionMethodBuilder;
72 MonoReflectionGenericParam *gparam;
73 } GenericParamTableEntry;
75 const unsigned char table_sizes [MONO_TABLE_NUM] = {
85 MONO_INTERFACEIMPL_SIZE,
86 MONO_MEMBERREF_SIZE, /* 0x0A */
88 MONO_CUSTOM_ATTR_SIZE,
89 MONO_FIELD_MARSHAL_SIZE,
90 MONO_DECL_SECURITY_SIZE,
91 MONO_CLASS_LAYOUT_SIZE,
92 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
93 MONO_STAND_ALONE_SIGNATURE_SIZE,
97 MONO_PROPERTY_MAP_SIZE,
100 MONO_METHOD_SEMA_SIZE,
101 MONO_METHODIMPL_SIZE,
102 MONO_MODULEREF_SIZE, /* 0x1A */
108 MONO_ASSEMBLY_SIZE, /* 0x20 */
109 MONO_ASSEMBLY_PROCESSOR_SIZE,
110 MONO_ASSEMBLYOS_SIZE,
111 MONO_ASSEMBLYREF_SIZE,
112 MONO_ASSEMBLYREFPROC_SIZE,
113 MONO_ASSEMBLYREFOS_SIZE,
117 MONO_NESTED_CLASS_SIZE,
119 MONO_GENERICPARAM_SIZE, /* 0x2A */
120 MONO_METHODSPEC_SIZE,
121 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, "");
223 string_heap_free (MonoDynamicStream *sh)
226 g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
227 g_hash_table_destroy (sh->hash);
231 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
235 make_room_in_stream (stream, stream->index + len);
236 memcpy (stream->data + stream->index, data, len);
238 stream->index += len;
240 * align index? Not without adding an additional param that controls it since
241 * we may store a blob value in pieces.
247 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
251 make_room_in_stream (stream, stream->index + len);
252 memset (stream->data + stream->index, 0, len);
254 stream->index += len;
259 stream_data_align (MonoDynamicStream *stream)
262 guint32 count = stream->index % 4;
264 /* we assume the stream data will be aligned */
266 mono_image_add_stream_data (stream, buf, 4 - count);
270 mono_blob_entry_hash (const char* str)
274 len = mono_metadata_decode_blob_size (str, &str);
278 for (str += 1; str < end; str++)
279 h = (h << 5) - h + *str;
287 mono_blob_entry_equal (const char *str1, const char *str2) {
291 len = mono_metadata_decode_blob_size (str1, &end1);
292 len2 = mono_metadata_decode_blob_size (str2, &end2);
295 return memcmp (end1, end2, len) == 0;
299 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
303 gpointer oldkey, oldval;
305 copy = g_malloc (s1+s2);
306 memcpy (copy, b1, s1);
307 memcpy (copy + s1, b2, s2);
308 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
310 idx = GPOINTER_TO_UINT (oldval);
312 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
313 mono_image_add_stream_data (&assembly->blob, b2, s2);
314 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
320 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
321 * dest may be misaligned.
324 swap_with_size (char *dest, const char* val, int len, int nelem) {
325 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
328 for (elem = 0; elem < nelem; ++elem) {
354 g_assert_not_reached ();
360 memcpy (dest, val, len * nelem);
365 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
369 guint32 idx = 0, len;
371 len = str->length * 2;
372 mono_metadata_encode_value (len, b, &b);
373 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
375 char *swapped = g_malloc (2 * mono_string_length (str));
376 const char *p = (const char*)mono_string_chars (str);
378 swap_with_size (swapped, p, 2, mono_string_length (str));
379 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
383 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
388 /* modified version needed to handle building corlib */
390 my_mono_class_from_mono_type (MonoType *type) {
391 switch (type->type) {
392 case MONO_TYPE_ARRAY:
394 case MONO_TYPE_SZARRAY:
395 case MONO_TYPE_GENERICINST:
396 return mono_class_from_mono_type (type);
399 g_assert (type->data.generic_param->pklass);
400 return type->data.generic_param->pklass;
402 /* should be always valid when we reach this case... */
403 return type->data.klass;
408 default_class_from_mono_type (MonoType *type)
410 switch (type->type) {
411 case MONO_TYPE_OBJECT:
412 return mono_defaults.object_class;
414 return mono_defaults.void_class;
415 case MONO_TYPE_BOOLEAN:
416 return mono_defaults.boolean_class;
418 return mono_defaults.char_class;
420 return mono_defaults.sbyte_class;
422 return mono_defaults.byte_class;
424 return mono_defaults.int16_class;
426 return mono_defaults.uint16_class;
428 return mono_defaults.int32_class;
430 return mono_defaults.uint32_class;
432 return mono_defaults.int_class;
434 return mono_defaults.uint_class;
436 return mono_defaults.int64_class;
438 return mono_defaults.uint64_class;
440 return mono_defaults.single_class;
442 return mono_defaults.double_class;
443 case MONO_TYPE_STRING:
444 return mono_defaults.string_class;
446 g_warning ("implement me 0x%02x\n", type->type);
447 g_assert_not_reached ();
454 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
459 g_assert_not_reached ();
463 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
464 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
465 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
466 for (i = 0; i < gclass->inst->type_argc; ++i)
467 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
473 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
476 g_assert_not_reached ();
481 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
485 case MONO_TYPE_BOOLEAN:
499 case MONO_TYPE_STRING:
500 case MONO_TYPE_OBJECT:
501 case MONO_TYPE_TYPEDBYREF:
502 mono_metadata_encode_value (type->type, p, &p);
505 mono_metadata_encode_value (type->type, p, &p);
506 encode_type (assembly, type->data.type, p, &p);
508 case MONO_TYPE_SZARRAY:
509 mono_metadata_encode_value (type->type, p, &p);
510 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
512 case MONO_TYPE_VALUETYPE:
513 case MONO_TYPE_CLASS: {
514 MonoClass *k = mono_class_from_mono_type (type);
515 mono_metadata_encode_value (type->type, p, &p);
517 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
518 * otherwise two typerefs could point to the same type, leading to
519 * verification errors.
521 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
524 case MONO_TYPE_ARRAY:
525 mono_metadata_encode_value (type->type, p, &p);
526 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
527 mono_metadata_encode_value (type->data.array->rank, p, &p);
528 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
529 mono_metadata_encode_value (0, p, &p);
531 case MONO_TYPE_GENERICINST:
532 encode_generic_class (assembly, type->data.generic_class, p, &p);
536 mono_metadata_encode_value (type->type, p, &p);
537 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
540 g_error ("need to encode type %x", type->type);
546 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
549 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
553 encode_type (assembly, type->type, p, endbuf);
557 g_assert_not_reached ();
562 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
567 for (i = 0; i < mono_array_length (modreq); ++i) {
568 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
569 *p = MONO_TYPE_CMOD_REQD;
571 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
575 for (i = 0; i < mono_array_length (modopt); ++i) {
576 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
577 *p = MONO_TYPE_CMOD_OPT;
579 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
586 generic_class_get_signature_size (MonoGenericClass *gclass)
592 g_assert_not_reached ();
595 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
597 for (i = 0; i < gclass->inst->type_argc; ++i)
598 size += type_get_signature_size (gclass->inst->type_argv [i]);
604 type_get_signature_size (MonoType *type)
609 g_assert_not_reached ();
617 case MONO_TYPE_BOOLEAN:
631 case MONO_TYPE_STRING:
632 case MONO_TYPE_OBJECT:
633 case MONO_TYPE_TYPEDBYREF:
636 return size + 1 + type_get_signature_size (type->data.type);
637 case MONO_TYPE_SZARRAY:
638 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
639 case MONO_TYPE_VALUETYPE:
640 case MONO_TYPE_CLASS:
642 case MONO_TYPE_ARRAY:
643 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
644 case MONO_TYPE_GENERICINST:
645 return size + generic_class_get_signature_size (type->data.generic_class);
650 g_error ("need to encode type %x", type->type);
656 method_get_signature_size (MonoMethodSignature *sig)
661 size = type_get_signature_size (sig->ret);
662 for (i = 0; i < sig->param_count; i++)
663 size += type_get_signature_size (sig->params [i]);
665 if (sig->generic_param_count)
667 if (sig->sentinelpos >= 0)
674 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
679 guint32 nparams = sig->param_count;
680 guint32 size = 11 + method_get_signature_size (sig);
688 p = buf = g_malloc (size);
690 * FIXME: vararg, explicit_this, differenc call_conv values...
692 *p = sig->call_convention;
694 *p |= 0x20; /* hasthis */
695 if (sig->generic_param_count)
696 *p |= 0x10; /* generic */
698 if (sig->generic_param_count)
699 mono_metadata_encode_value (sig->generic_param_count, p, &p);
700 mono_metadata_encode_value (nparams, p, &p);
701 encode_type (assembly, sig->ret, p, &p);
702 for (i = 0; i < nparams; ++i) {
703 if (i == sig->sentinelpos)
704 *p++ = MONO_TYPE_SENTINEL;
705 encode_type (assembly, sig->params [i], p, &p);
708 g_assert (p - buf < size);
709 mono_metadata_encode_value (p-buf, b, &b);
710 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
716 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
719 * FIXME: reuse code from method_encode_signature().
724 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
725 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
726 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
727 guint32 size = 21 + nparams * 20 + notypes * 20;
732 p = buf = g_malloc (size);
733 /* LAMESPEC: all the call conv spec is foobared */
734 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
735 if (mb->call_conv & 2)
736 *p |= 0x5; /* vararg */
737 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
738 *p |= 0x20; /* hasthis */
740 *p |= 0x10; /* generic */
743 mono_metadata_encode_value (ngparams, p, &p);
744 mono_metadata_encode_value (nparams + notypes, p, &p);
745 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
746 encode_reflection_type (assembly, mb->rtype, p, &p);
747 for (i = 0; i < nparams; ++i) {
748 MonoArray *modreq = NULL;
749 MonoArray *modopt = NULL;
750 MonoReflectionType *pt;
752 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
753 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
754 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
755 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
756 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
757 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
758 encode_reflection_type (assembly, pt, p, &p);
761 *p++ = MONO_TYPE_SENTINEL;
762 for (i = 0; i < notypes; ++i) {
763 MonoReflectionType *pt;
765 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
766 encode_reflection_type (assembly, pt, p, &p);
770 g_assert (p - buf < size);
771 mono_metadata_encode_value (p-buf, b, &b);
772 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
778 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
780 MonoDynamicTable *table;
783 guint32 idx, sig_idx, size;
784 guint nl = mono_array_length (ilgen->locals);
791 p = buf = g_malloc (size);
792 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
793 idx = table->next_idx ++;
795 alloc_table (table, table->rows);
796 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
798 mono_metadata_encode_value (0x07, p, &p);
799 mono_metadata_encode_value (nl, p, &p);
800 for (i = 0; i < nl; ++i) {
801 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
804 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
806 encode_reflection_type (assembly, lb->type, p, &p);
808 g_assert (p - buf < size);
809 mono_metadata_encode_value (p-buf, b, &b);
810 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
813 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
819 method_count_clauses (MonoReflectionILGen *ilgen)
821 guint32 num_clauses = 0;
824 MonoILExceptionInfo *ex_info;
825 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
826 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
827 if (ex_info->handlers)
828 num_clauses += mono_array_length (ex_info->handlers);
836 static MonoExceptionClause*
837 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
839 MonoExceptionClause *clauses;
840 MonoExceptionClause *clause;
841 MonoILExceptionInfo *ex_info;
842 MonoILExceptionBlock *ex_block;
843 guint32 finally_start;
844 int i, j, clause_index;;
846 clauses = g_new0 (MonoExceptionClause, num_clauses);
849 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
850 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
851 finally_start = ex_info->start + ex_info->len;
852 g_assert (ex_info->handlers);
853 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
854 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
855 clause = &(clauses [clause_index]);
857 clause->flags = ex_block->type;
858 clause->try_offset = ex_info->start;
860 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
861 clause->try_len = finally_start - ex_info->start;
863 clause->try_len = ex_info->len;
864 clause->handler_offset = ex_block->start;
865 clause->handler_len = ex_block->len;
866 if (ex_block->extype) {
867 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
869 /* FIXME: handle filters */
870 clause->data.filter_offset = 0;
872 finally_start = ex_block->start + ex_block->len;
882 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
888 gint32 num_locals = 0;
889 gint32 num_exception = 0;
892 char fat_header [12];
895 guint32 local_sig = 0;
896 guint32 header_size = 12;
899 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
900 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
904 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
906 code = mb->ilgen->code;
907 code_size = mb->ilgen->code_len;
908 max_stack = mb->ilgen->max_stack;
909 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
910 if (mb->ilgen->ex_handlers)
911 num_exception = method_count_clauses (mb->ilgen);
915 char *name = mono_string_to_utf8 (mb->name);
916 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
917 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
920 mono_raise_exception (exception);
923 code_size = mono_array_length (code);
924 max_stack = 8; /* we probably need to run a verifier on the code... */
927 stream_data_align (&assembly->code);
929 /* check for exceptions, maxstack, locals */
930 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
932 if (code_size < 64 && !(code_size & 1)) {
933 flags = (code_size << 2) | 0x2;
934 } else if (code_size < 32 && (code_size & 1)) {
935 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
939 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
940 /* add to the fixup todo list */
941 if (mb->ilgen && mb->ilgen->num_token_fixups)
942 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
943 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
944 return assembly->text_rva + idx;
948 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
950 * FIXME: need to set also the header size in fat_flags.
951 * (and more sects and init locals flags)
955 fat_flags |= METHOD_HEADER_MORE_SECTS;
957 fat_flags |= METHOD_HEADER_INIT_LOCALS;
958 fat_header [0] = fat_flags;
959 fat_header [1] = (header_size / 4 ) << 4;
960 shortp = (guint16*)(fat_header + 2);
961 *shortp = GUINT16_TO_LE (max_stack);
962 intp = (guint32*)(fat_header + 4);
963 *intp = GUINT32_TO_LE (code_size);
964 intp = (guint32*)(fat_header + 8);
965 *intp = GUINT32_TO_LE (local_sig);
966 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
967 /* add to the fixup todo list */
968 if (mb->ilgen && mb->ilgen->num_token_fixups)
969 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
971 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
973 unsigned char sheader [4];
974 MonoILExceptionInfo * ex_info;
975 MonoILExceptionBlock * ex_block;
978 stream_data_align (&assembly->code);
979 /* always use fat format for now */
980 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
981 num_exception *= 6 * sizeof (guint32);
982 num_exception += 4; /* include the size of the header */
983 sheader [1] = num_exception & 0xff;
984 sheader [2] = (num_exception >> 8) & 0xff;
985 sheader [3] = (num_exception >> 16) & 0xff;
986 mono_image_add_stream_data (&assembly->code, sheader, 4);
987 /* fat header, so we are already aligned */
989 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
990 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
991 if (ex_info->handlers) {
992 int finally_start = ex_info->start + ex_info->len;
993 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
995 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
997 val = GUINT32_TO_LE (ex_block->type);
998 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1000 val = GUINT32_TO_LE (ex_info->start);
1001 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1002 /* need fault, too, probably */
1003 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1004 val = GUINT32_TO_LE (finally_start - ex_info->start);
1006 val = GUINT32_TO_LE (ex_info->len);
1007 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1008 /* handler offset */
1009 val = GUINT32_TO_LE (ex_block->start);
1010 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1012 val = GUINT32_TO_LE (ex_block->len);
1013 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1014 finally_start = ex_block->start + ex_block->len;
1015 if (ex_block->extype) {
1016 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1018 /* FIXME: handle filters */
1021 val = GUINT32_TO_LE (val);
1022 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1023 /*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",
1024 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);*/
1027 g_error ("No clauses for ex info block %d", i);
1031 return assembly->text_rva + idx;
1035 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1038 MonoDynamicTable *table;
1041 table = &assembly->tables [table_idx];
1043 g_assert (col < table->columns);
1045 values = table->values + table->columns;
1046 for (i = 1; i <= table->rows; ++i) {
1047 if (values [col] == token)
1049 values += table->columns;
1054 static GHashTable *dynamic_custom_attrs = NULL;
1056 static MonoCustomAttrInfo*
1057 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1060 MonoCustomAttrInfo *ainfo;
1061 MonoReflectionCustomAttr *cattr;
1065 /* FIXME: check in assembly the Run flag is set */
1067 count = mono_array_length (cattrs);
1069 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1071 ainfo->image = image;
1072 ainfo->num_attrs = count;
1073 for (i = 0; i < count; ++i) {
1074 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1075 ainfo->attrs [i].ctor = cattr->ctor->method;
1076 /* FIXME: might want to memdup the data here */
1077 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1078 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1085 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1087 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1092 if (!dynamic_custom_attrs)
1093 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1095 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1096 ainfo->cached = TRUE;
1100 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1102 /* they are cached, so we don't free them */
1103 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1109 * idx is the table index of the object
1110 * type is one of MONO_CUSTOM_ATTR_*
1113 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1115 MonoDynamicTable *table;
1116 MonoReflectionCustomAttr *cattr;
1118 guint32 count, i, token;
1120 char *p = blob_size;
1122 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1125 count = mono_array_length (cattrs);
1126 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1127 table->rows += count;
1128 alloc_table (table, table->rows);
1129 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1130 idx <<= MONO_CUSTOM_ATTR_BITS;
1132 for (i = 0; i < count; ++i) {
1133 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1134 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1135 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1136 type = mono_metadata_token_index (token);
1137 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1138 switch (mono_metadata_token_table (token)) {
1139 case MONO_TABLE_METHOD:
1140 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1142 case MONO_TABLE_MEMBERREF:
1143 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1146 g_warning ("got wrong token in custom attr");
1149 values [MONO_CUSTOM_ATTR_TYPE] = type;
1151 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1152 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1153 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1154 values += MONO_CUSTOM_ATTR_SIZE;
1160 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1162 MonoDynamicTable *table;
1164 guint32 count, i, idx;
1165 MonoReflectionPermissionSet *perm;
1170 count = mono_array_length (permissions);
1171 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1172 table->rows += count;
1173 alloc_table (table, table->rows);
1175 for (i = 0; i < mono_array_length (permissions); ++i) {
1176 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1178 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1180 idx = mono_metadata_token_index (parent_token);
1181 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1182 switch (mono_metadata_token_table (parent_token)) {
1183 case MONO_TABLE_TYPEDEF:
1184 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1186 case MONO_TABLE_METHOD:
1187 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1189 case MONO_TABLE_ASSEMBLY:
1190 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1193 g_assert_not_reached ();
1196 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1197 values [MONO_DECL_SECURITY_PARENT] = idx;
1198 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1205 * Fill in the MethodDef and ParamDef tables for a method.
1206 * This is used for both normal methods and constructors.
1209 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1211 MonoDynamicTable *table;
1216 /* room in this table is already allocated */
1217 table = &assembly->tables [MONO_TABLE_METHOD];
1218 *mb->table_idx = table->next_idx ++;
1219 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1220 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1221 name = mono_string_to_utf8 (mb->name);
1222 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1224 values [MONO_METHOD_FLAGS] = mb->attrs;
1225 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1226 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1227 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1229 table = &assembly->tables [MONO_TABLE_PARAM];
1230 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1232 mono_image_add_decl_security (assembly,
1233 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1236 MonoDynamicTable *mtable;
1239 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1240 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1243 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1244 if (mono_array_get (mb->pinfo, gpointer, i))
1247 table->rows += count;
1248 alloc_table (table, table->rows);
1249 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1250 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1251 MonoReflectionParamBuilder *pb;
1252 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1253 values [MONO_PARAM_FLAGS] = pb->attrs;
1254 values [MONO_PARAM_SEQUENCE] = i;
1255 if (pb->name != NULL) {
1256 name = mono_string_to_utf8 (pb->name);
1257 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1260 values [MONO_PARAM_NAME] = 0;
1262 values += MONO_PARAM_SIZE;
1263 if (pb->marshal_info) {
1265 alloc_table (mtable, mtable->rows);
1266 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1267 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1268 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1270 pb->table_idx = table->next_idx++;
1271 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1272 guint32 field_type = 0;
1273 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1275 alloc_table (mtable, mtable->rows);
1276 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1277 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1278 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1279 mvalues [MONO_CONSTANT_TYPE] = field_type;
1280 mvalues [MONO_CONSTANT_PADDING] = 0;
1288 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1290 rmb->ilgen = mb->ilgen;
1291 rmb->rtype = mb->rtype;
1292 rmb->parameters = mb->parameters;
1293 rmb->generic_params = mb->generic_params;
1294 rmb->generic_container = mb->generic_container;
1295 rmb->opt_types = NULL;
1296 rmb->pinfo = mb->pinfo;
1297 rmb->attrs = mb->attrs;
1298 rmb->iattrs = mb->iattrs;
1299 rmb->call_conv = mb->call_conv;
1300 rmb->code = mb->code;
1301 rmb->type = mb->type;
1302 rmb->name = mb->name;
1303 rmb->table_idx = &mb->table_idx;
1304 rmb->init_locals = mb->init_locals;
1305 rmb->return_modreq = mb->return_modreq;
1306 rmb->return_modopt = mb->return_modopt;
1307 rmb->param_modreq = mb->param_modreq;
1308 rmb->param_modopt = mb->param_modopt;
1309 rmb->permissions = mb->permissions;
1310 rmb->mhandle = mb->mhandle;
1315 rmb->charset = mb->charset & 0xf;
1316 rmb->lasterr = mb->charset & 0x40;
1317 rmb->native_cc = mb->native_cc;
1318 rmb->dllentry = mb->dllentry;
1324 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1326 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1328 rmb->ilgen = mb->ilgen;
1329 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1330 rmb->parameters = mb->parameters;
1331 rmb->generic_params = NULL;
1332 rmb->generic_container = 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->generic_container = NULL;
1361 rmb->opt_types = NULL;
1363 rmb->attrs = mb->attrs;
1365 rmb->call_conv = mb->call_conv;
1368 rmb->name = mb->name;
1369 rmb->table_idx = NULL;
1370 rmb->init_locals = mb->init_locals;
1371 rmb->return_modreq = NULL;
1372 rmb->return_modopt = NULL;
1373 rmb->param_modreq = NULL;
1374 rmb->param_modopt = NULL;
1375 rmb->permissions = NULL;
1376 rmb->mhandle = mb->mhandle;
1382 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1384 MonoDynamicTable *table;
1387 ReflectionMethodBuilder rmb;
1390 reflection_methodbuilder_from_method_builder (&rmb, mb);
1392 mono_image_basic_method (&rmb, assembly);
1394 if (mb->dll) { /* It's a P/Invoke method */
1396 int charset = mb->charset & 0xf;
1397 int lasterr = mb->charset & 0x40;
1398 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1400 alloc_table (table, table->rows);
1401 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1402 /* map CharSet values to on-disk values */
1404 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1405 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1406 name = mono_string_to_utf8 (mb->dllentry);
1407 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1409 name = mono_string_to_utf8 (mb->dll);
1410 moduleref = string_heap_insert (&assembly->sheap, name);
1412 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1413 table = &assembly->tables [MONO_TABLE_MODULEREF];
1415 alloc_table (table, table->rows);
1416 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1417 values [MONO_IMPLMAP_SCOPE] = table->rows;
1421 if (mb->override_method) {
1422 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1424 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1426 alloc_table (table, table->rows);
1427 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1428 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1429 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1431 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1432 switch (mono_metadata_token_table (tok)) {
1433 case MONO_TABLE_MEMBERREF:
1434 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1436 case MONO_TABLE_METHOD:
1437 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1440 g_assert_not_reached ();
1442 values [MONO_METHODIMPL_DECLARATION] = tok;
1445 if (mb->generic_params) {
1446 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1447 table->rows += mono_array_length (mb->generic_params);
1448 alloc_table (table, table->rows);
1449 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1450 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1452 mono_image_get_generic_param_info (
1453 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1460 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1462 ReflectionMethodBuilder rmb;
1464 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1466 mono_image_basic_method (&rmb, assembly);
1470 type_get_fully_qualified_name (MonoType *type) {
1471 char *name, *result;
1475 name = mono_type_get_name (type);
1476 klass = my_mono_class_from_mono_type (type);
1477 ta = klass->image->assembly;
1479 result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1480 name, ta->aname.name,
1481 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1482 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1483 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1489 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1493 klass = my_mono_class_from_mono_type (type);
1495 return mono_type_get_name (type);
1496 ta = klass->image->assembly;
1497 if (ta == ass || klass->image == mono_defaults.corlib)
1498 return mono_type_get_name (type);
1500 return type_get_fully_qualified_name (type);
1504 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1506 char blob_size [64];
1507 char *b = blob_size;
1512 if (!assembly->save)
1515 p = buf = g_malloc (64);
1517 mono_metadata_encode_value (0x06, p, &p);
1518 /* encode custom attributes before the type */
1519 encode_type (assembly, type, p, &p);
1520 g_assert (p-buf < 64);
1521 mono_metadata_encode_value (p-buf, b, &b);
1522 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1528 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1530 char blob_size [64];
1531 char *b = blob_size;
1536 p = buf = g_malloc (64);
1538 mono_metadata_encode_value (0x06, p, &p);
1539 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1540 /* encode custom attributes before the type */
1541 encode_reflection_type (assembly, fb->type, p, &p);
1542 g_assert (p-buf < 64);
1543 mono_metadata_encode_value (p-buf, b, &b);
1544 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1550 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1551 char blob_size [64];
1552 char *b = blob_size;
1555 guint32 idx = 0, len = 0, dummy = 0;
1557 p = buf = g_malloc (64);
1559 *ret_type = MONO_TYPE_CLASS;
1561 box_val = (char*)&dummy;
1563 box_val = ((char*)val) + sizeof (MonoObject);
1564 *ret_type = val->vtable->klass->byval_arg.type;
1567 switch (*ret_type) {
1568 case MONO_TYPE_BOOLEAN:
1573 case MONO_TYPE_CHAR:
1588 case MONO_TYPE_VALUETYPE:
1589 if (val->vtable->klass->enumtype) {
1590 *ret_type = val->vtable->klass->enum_basetype->type;
1593 g_error ("we can't encode valuetypes");
1594 case MONO_TYPE_CLASS:
1596 case MONO_TYPE_STRING: {
1597 MonoString *str = (MonoString*)val;
1598 /* there is no signature */
1599 len = str->length * 2;
1600 mono_metadata_encode_value (len, b, &b);
1601 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1603 char *swapped = g_malloc (2 * mono_string_length (str));
1604 const char *p = (const char*)mono_string_chars (str);
1606 swap_with_size (swapped, p, 2, mono_string_length (str));
1607 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1611 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1618 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1621 /* there is no signature */
1622 mono_metadata_encode_value (len, b, &b);
1623 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1624 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1625 swap_with_size (blob_size, box_val, len, 1);
1626 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1628 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1636 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1637 char blob_size [64];
1638 char *b = blob_size;
1639 char *p, *buf, *str;
1640 guint32 idx, len, bufsize = 256;
1642 p = buf = g_malloc (bufsize);
1644 switch (minfo->type) {
1645 case MONO_NATIVE_BYVALTSTR:
1646 case MONO_NATIVE_BYVALARRAY:
1647 mono_metadata_encode_value (minfo->type, p, &p);
1648 mono_metadata_encode_value (minfo->count, p, &p);
1650 case MONO_NATIVE_LPARRAY:
1651 mono_metadata_encode_value (minfo->type, p, &p);
1652 if (minfo->eltype || (minfo->count > 0)) {
1653 mono_metadata_encode_value (minfo->eltype, p, &p);
1654 if (minfo->count > 0) {
1655 mono_metadata_encode_value (0, p, &p);
1656 mono_metadata_encode_value (minfo->count, p, &p);
1660 case MONO_NATIVE_CUSTOM:
1661 mono_metadata_encode_value (minfo->type, p, &p);
1663 str = mono_string_to_utf8 (minfo->guid);
1665 mono_metadata_encode_value (len, p, &p);
1666 memcpy (p, str, len);
1670 mono_metadata_encode_value (0, p, &p);
1672 if (minfo->marshaltype) {
1673 str = mono_string_to_utf8 (minfo->marshaltype);
1675 mono_metadata_encode_value (len, p, &p);
1676 if (p + len >= buf + bufsize) {
1679 buf = g_realloc (buf, bufsize);
1682 memcpy (p, str, len);
1686 mono_metadata_encode_value (0, p, &p);
1688 if (minfo->marshaltyperef) {
1689 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1691 mono_metadata_encode_value (len, p, &p);
1692 if (p + len >= buf + bufsize) {
1695 buf = g_realloc (buf, bufsize);
1698 memcpy (p, str, len);
1702 mono_metadata_encode_value (0, p, &p);
1704 if (minfo->mcookie) {
1705 str = mono_string_to_utf8 (minfo->mcookie);
1707 mono_metadata_encode_value (len, p, &p);
1708 if (p + len >= buf + bufsize) {
1711 buf = g_realloc (buf, bufsize);
1714 memcpy (p, str, len);
1718 mono_metadata_encode_value (0, p, &p);
1722 mono_metadata_encode_value (minfo->type, p, &p);
1726 mono_metadata_encode_value (len, b, &b);
1727 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1733 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1735 MonoDynamicTable *table;
1739 /* maybe this fixup should be done in the C# code */
1740 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1741 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1742 table = &assembly->tables [MONO_TABLE_FIELD];
1743 fb->table_idx = table->next_idx ++;
1744 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1745 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1746 name = mono_string_to_utf8 (fb->name);
1747 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1749 values [MONO_FIELD_FLAGS] = fb->attrs;
1750 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1752 if (fb->offset != -1) {
1753 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1755 alloc_table (table, table->rows);
1756 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1757 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1758 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1760 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1761 guint32 field_type = 0;
1762 table = &assembly->tables [MONO_TABLE_CONSTANT];
1764 alloc_table (table, table->rows);
1765 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1766 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1767 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1768 values [MONO_CONSTANT_TYPE] = field_type;
1769 values [MONO_CONSTANT_PADDING] = 0;
1771 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1773 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1775 alloc_table (table, table->rows);
1776 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1777 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1779 * We store it in the code section because it's simpler for now.
1782 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1784 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1785 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1787 if (fb->marshal_info) {
1788 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1790 alloc_table (table, table->rows);
1791 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1792 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1793 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1798 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1802 char *b = blob_size;
1803 guint32 nparams = 0;
1804 MonoReflectionMethodBuilder *mb = fb->get_method;
1805 MonoReflectionMethodBuilder *smb = fb->set_method;
1806 guint32 idx, i, size;
1808 if (mb && mb->parameters)
1809 nparams = mono_array_length (mb->parameters);
1810 if (!mb && smb && smb->parameters)
1811 nparams = mono_array_length (smb->parameters) - 1;
1812 size = 24 + nparams * 10;
1813 buf = p = g_malloc (size);
1816 mono_metadata_encode_value (nparams, p, &p);
1818 encode_reflection_type (assembly, mb->rtype, p, &p);
1819 for (i = 0; i < nparams; ++i) {
1820 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1821 encode_reflection_type (assembly, pt, p, &p);
1824 /* the property type is the last param */
1825 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1826 for (i = 0; i < nparams; ++i) {
1827 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1828 encode_reflection_type (assembly, pt, p, &p);
1832 encode_reflection_type (assembly, fb->type, p, &p);
1836 g_assert (p - buf < size);
1837 mono_metadata_encode_value (p-buf, b, &b);
1838 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1844 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1846 MonoDynamicTable *table;
1849 guint num_methods = 0;
1853 * we need to set things in the following tables:
1854 * PROPERTYMAP (info already filled in _get_type_info ())
1855 * PROPERTY (rows already preallocated in _get_type_info ())
1856 * METHOD (method info already done with the generic method code)
1859 table = &assembly->tables [MONO_TABLE_PROPERTY];
1860 pb->table_idx = table->next_idx ++;
1861 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1862 name = mono_string_to_utf8 (pb->name);
1863 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1865 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1866 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1868 /* FIXME: we still don't handle 'other' methods */
1869 if (pb->get_method) num_methods ++;
1870 if (pb->set_method) num_methods ++;
1872 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1873 table->rows += num_methods;
1874 alloc_table (table, table->rows);
1876 if (pb->get_method) {
1877 semaidx = table->next_idx ++;
1878 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1879 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1880 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1881 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1883 if (pb->set_method) {
1884 semaidx = table->next_idx ++;
1885 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1886 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1887 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1888 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1893 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1895 MonoDynamicTable *table;
1898 guint num_methods = 0;
1902 * we need to set things in the following tables:
1903 * EVENTMAP (info already filled in _get_type_info ())
1904 * EVENT (rows already preallocated in _get_type_info ())
1905 * METHOD (method info already done with the generic method code)
1908 table = &assembly->tables [MONO_TABLE_EVENT];
1909 eb->table_idx = table->next_idx ++;
1910 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1911 name = mono_string_to_utf8 (eb->name);
1912 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1914 values [MONO_EVENT_FLAGS] = eb->attrs;
1915 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1918 * FIXME: we still don't handle 'other' methods
1920 if (eb->add_method) num_methods ++;
1921 if (eb->remove_method) num_methods ++;
1922 if (eb->raise_method) num_methods ++;
1924 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1925 table->rows += num_methods;
1926 alloc_table (table, table->rows);
1928 if (eb->add_method) {
1929 semaidx = table->next_idx ++;
1930 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1931 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1932 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1933 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1935 if (eb->remove_method) {
1936 semaidx = table->next_idx ++;
1937 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1938 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1939 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1940 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1942 if (eb->raise_method) {
1943 semaidx = table->next_idx ++;
1944 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1945 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1946 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1947 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1952 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1954 static MonoClass *NewConstraintAttr;
1955 static MonoMethod *NewConstraintAttr_ctor;
1956 MonoDynamicTable *table;
1958 guint32 token, type;
1959 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1962 if (!NewConstraintAttr)
1963 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1964 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1965 g_assert (NewConstraintAttr);
1967 if (!NewConstraintAttr_ctor) {
1970 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1971 MonoMethod *m = NewConstraintAttr->methods [i];
1973 if (strcmp (m->name, ".ctor"))
1976 NewConstraintAttr_ctor = m;
1980 g_assert (NewConstraintAttr_ctor);
1983 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1985 alloc_table (table, table->rows);
1987 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1988 owner <<= MONO_CUSTOM_ATTR_BITS;
1989 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1990 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1992 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1994 type = mono_metadata_token_index (token);
1995 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1996 switch (mono_metadata_token_table (token)) {
1997 case MONO_TABLE_METHOD:
1998 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
2000 case MONO_TABLE_MEMBERREF:
2001 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
2004 g_warning ("got wrong token in custom attr");
2007 values [MONO_CUSTOM_ATTR_TYPE] = type;
2009 buf = p = g_malloc (1);
2010 mono_metadata_encode_value (4, p, &p);
2011 g_assert (p-buf == 1);
2013 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2015 values += MONO_CUSTOM_ATTR_SIZE;
2020 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2022 MonoDynamicTable *table;
2023 guint32 num_constraints, i;
2027 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2028 num_constraints = gparam->iface_constraints ?
2029 mono_array_length (gparam->iface_constraints) : 0;
2030 table->rows += num_constraints;
2031 if (gparam->base_type)
2033 alloc_table (table, table->rows);
2035 if (gparam->base_type) {
2036 table_idx = table->next_idx ++;
2037 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2039 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2040 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2041 assembly, gparam->base_type->type);
2044 for (i = 0; i < num_constraints; i++) {
2045 MonoReflectionType *constraint = mono_array_get (
2046 gparam->iface_constraints, gpointer, i);
2048 table_idx = table->next_idx ++;
2049 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2051 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2052 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2053 assembly, constraint->type);
2056 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2057 encode_new_constraint (assembly, owner);
2061 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2063 GenericParamTableEntry *entry;
2066 * The GenericParam table must be sorted according to the `owner' field.
2067 * We need to do this sorting prior to writing the GenericParamConstraint
2068 * table, since we have to use the final GenericParam table indices there
2069 * and they must also be sorted.
2072 entry = g_new0 (GenericParamTableEntry, 1);
2073 entry->owner = owner;
2074 entry->gparam = gparam;
2076 g_ptr_array_add (assembly->gen_params, entry);
2080 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2082 MonoDynamicTable *table;
2083 MonoGenericParam *param;
2087 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2088 table_idx = table->next_idx ++;
2089 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2091 param = entry->gparam->type.type->data.generic_param;
2093 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2094 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2095 values [MONO_GENERICPARAM_NUMBER] = param->num;
2096 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2097 values [MONO_GENERICPARAM_KIND] = 0;
2099 encode_constraints (entry->gparam, table_idx, assembly);
2103 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2105 MonoDynamicTable *table;
2108 guint32 cols [MONO_ASSEMBLY_SIZE];
2112 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2115 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2116 table = &assembly->tables [MONO_TABLE_MODULEREF];
2117 token = table->next_idx ++;
2119 alloc_table (table, table->rows);
2120 values = table->values + token * MONO_MODULEREF_SIZE;
2121 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2123 token <<= MONO_RESOLTION_SCOPE_BITS;
2124 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2125 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2130 if (image->assembly->dynamic)
2132 memset (cols, 0, sizeof (cols));
2134 /* image->assembly->image is the manifest module */
2135 image = image->assembly->image;
2136 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2139 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2140 token = table->next_idx ++;
2142 alloc_table (table, table->rows);
2143 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2144 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2145 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2146 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2147 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2148 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2149 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2150 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2151 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2153 if (strcmp ("", image->assembly->aname.culture)) {
2154 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2155 image->assembly->aname.culture);
2158 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2159 guchar pubtoken [9];
2161 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2162 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2164 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2166 token <<= MONO_RESOLTION_SCOPE_BITS;
2167 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2168 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2173 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2175 MonoDynamicTable *table;
2181 char *b = blob_size;
2183 switch (type->type) {
2184 case MONO_TYPE_FNPTR:
2186 case MONO_TYPE_SZARRAY:
2187 case MONO_TYPE_ARRAY:
2189 case MONO_TYPE_MVAR:
2190 case MONO_TYPE_GENERICINST:
2191 encode_type (assembly, type, p, &p);
2193 case MONO_TYPE_CLASS:
2194 case MONO_TYPE_VALUETYPE: {
2195 MonoClass *k = mono_class_from_mono_type (type);
2196 if (!k || !k->generic_class)
2198 encode_generic_class (assembly, k->generic_class, p, &p);
2205 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2206 if (assembly->save) {
2207 g_assert (p-sig < 128);
2208 mono_metadata_encode_value (p-sig, b, &b);
2209 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2210 alloc_table (table, table->rows + 1);
2211 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2212 values [MONO_TYPESPEC_SIGNATURE] = token;
2215 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2216 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2222 * Despite the name, we handle also TypeSpec (with the above helper).
2225 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2227 MonoDynamicTable *table;
2229 guint32 token, scope, enclosing;
2232 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2235 token = create_typespec (assembly, type);
2238 klass = my_mono_class_from_mono_type (type);
2240 klass = mono_class_from_mono_type (type);
2243 * If it's in the same module and not a generic type parameter:
2245 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2246 (type->type != MONO_TYPE_MVAR)) {
2247 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2248 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2249 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2253 if (klass->nested_in) {
2254 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2255 /* get the typeref idx of the enclosing type */
2256 enclosing >>= MONO_TYPEDEFORREF_BITS;
2257 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2259 scope = resolution_scope_from_image (assembly, klass->image);
2261 table = &assembly->tables [MONO_TABLE_TYPEREF];
2262 if (assembly->save) {
2263 alloc_table (table, table->rows + 1);
2264 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2265 values [MONO_TYPEREF_SCOPE] = scope;
2266 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2267 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2269 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2270 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2272 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2277 * Insert a memberef row into the metadata: the token that point to the memberref
2278 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2279 * mono_image_get_fieldref_token()).
2280 * The sig param is an index to an already built signature.
2283 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2285 MonoDynamicTable *table;
2287 guint32 token, pclass;
2290 parent = mono_image_typedef_or_ref (assembly, type);
2291 switch (parent & MONO_TYPEDEFORREF_MASK) {
2292 case MONO_TYPEDEFORREF_TYPEREF:
2293 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2295 case MONO_TYPEDEFORREF_TYPESPEC:
2296 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2298 case MONO_TYPEDEFORREF_TYPEDEF:
2299 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2302 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2305 /* extract the index */
2306 parent >>= MONO_TYPEDEFORREF_BITS;
2308 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2310 if (assembly->save) {
2311 alloc_table (table, table->rows + 1);
2312 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2313 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2314 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2315 values [MONO_MEMBERREF_SIGNATURE] = sig;
2318 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2325 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2328 MonoMethodSignature *sig;
2330 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2335 * A methodref signature can't contain an unmanaged calling convention.
2337 sig = mono_metadata_signature_dup (method->signature);
2338 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2339 sig->call_convention = MONO_CALL_DEFAULT;
2340 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2341 method->name, method_encode_signature (assembly, sig));
2343 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2348 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2349 const gchar *name, guint32 sig)
2351 MonoDynamicTable *table;
2355 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2357 if (assembly->save) {
2358 alloc_table (table, table->rows + 1);
2359 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2360 values [MONO_MEMBERREF_CLASS] = original;
2361 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2362 values [MONO_MEMBERREF_SIGNATURE] = sig;
2365 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2372 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2375 ReflectionMethodBuilder rmb;
2377 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2381 reflection_methodbuilder_from_method_builder (&rmb, mb);
2383 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2384 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2385 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2390 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2393 ReflectionMethodBuilder rmb;
2395 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2399 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2401 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2402 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2403 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2408 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2413 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2416 g_assert (f->field->parent);
2417 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2418 token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg,
2419 f->field->name, fieldref_encode_signature (assembly, type));
2420 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2425 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2430 guint32 nparams = gmethod->inst->type_argc;
2431 guint32 size = 10 + nparams * 10;
2434 char *b = blob_size;
2436 if (!assembly->save)
2439 p = buf = g_malloc (size);
2441 * FIXME: vararg, explicit_this, differenc call_conv values...
2443 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2444 mono_metadata_encode_value (nparams, p, &p);
2446 for (i = 0; i < nparams; i++)
2447 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2450 g_assert (p - buf < size);
2451 mono_metadata_encode_value (p-buf, b, &b);
2452 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2458 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2460 MonoDynamicTable *table;
2462 guint32 token, mtoken = 0, sig;
2463 MonoMethodInflated *imethod;
2464 MonoMethod *declaring;
2466 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2468 g_assert (method->is_inflated);
2469 method = mono_get_inflated_method (method);
2470 imethod = (MonoMethodInflated *) method;
2471 declaring = imethod->declaring;
2473 sig = method_encode_signature (assembly, declaring->signature);
2474 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2476 if (!declaring->signature->generic_param_count)
2479 switch (mono_metadata_token_table (mtoken)) {
2480 case MONO_TABLE_MEMBERREF:
2481 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2483 case MONO_TABLE_METHOD:
2484 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2487 g_assert_not_reached ();
2490 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2492 if (assembly->save) {
2493 alloc_table (table, table->rows + 1);
2494 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2495 values [MONO_METHODSPEC_METHOD] = mtoken;
2496 values [MONO_METHODSPEC_SIGNATURE] = sig;
2499 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2506 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2508 MonoMethodInflated *imethod;
2511 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2515 g_assert (m->is_inflated);
2516 m = mono_get_inflated_method (m);
2517 imethod = (MonoMethodInflated *) m;
2519 if (imethod->declaring->signature->generic_param_count) {
2520 token = method_encode_methodspec (assembly, m);
2522 guint32 sig = method_encode_signature (
2523 assembly, imethod->declaring->signature);
2524 token = mono_image_get_memberref_token (
2525 assembly, &m->klass->byval_arg, m->name, sig);
2528 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2533 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2535 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2538 sig = method_encode_signature (assembly, imethod->declaring->signature);
2539 token = mono_image_get_memberref_token (
2540 assembly, &m->klass->byval_arg, m->name, sig);
2546 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2548 MonoDynamicTable *table;
2555 char *b = blob_size;
2559 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2560 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2561 * Because of this, we must not insert it into the `typeref' hash table.
2564 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2568 g_assert (tb->generic_params);
2569 klass = mono_class_from_mono_type (tb->type.type);
2571 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2572 encode_type (assembly, &klass->byval_arg, p, &p);
2574 count = mono_array_length (tb->generic_params);
2575 mono_metadata_encode_value (count, p, &p);
2576 for (i = 0; i < count; i++) {
2577 MonoReflectionGenericParam *gparam;
2579 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2581 encode_type (assembly, gparam->type.type, p, &p);
2584 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2585 if (assembly->save) {
2586 g_assert (p-sig < 128);
2587 mono_metadata_encode_value (p-sig, b, &b);
2588 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2589 alloc_table (table, table->rows + 1);
2590 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2591 values [MONO_TYPESPEC_SIGNATURE] = token;
2594 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2595 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2601 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2603 MonoDynamicTable *table;
2606 guint32 token, pclass, parent, sig;
2609 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2613 klass = mono_class_from_mono_type (fb->typeb->type);
2614 name = mono_string_to_utf8 (fb->name);
2616 sig = fieldref_encode_signature (assembly, fb->type->type);
2618 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2619 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2621 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2622 parent >>= MONO_TYPEDEFORREF_BITS;
2624 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2626 if (assembly->save) {
2627 alloc_table (table, table->rows + 1);
2628 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2629 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2630 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2631 values [MONO_MEMBERREF_SIGNATURE] = sig;
2634 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2636 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2641 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2649 char *b = blob_size;
2651 if (!assembly->save)
2655 g_assert (helper->type == 2);
2657 if (helper->arguments)
2658 nargs = mono_array_length (helper->arguments);
2662 size = 10 + (nargs * 10);
2664 p = buf = g_malloc (size);
2666 /* Encode calling convention */
2667 /* Change Any to Standard */
2668 if ((helper->call_conv & 0x03) == 0x03)
2669 helper->call_conv = 0x01;
2670 /* explicit_this implies has_this */
2671 if (helper->call_conv & 0x40)
2672 helper->call_conv &= 0x20;
2674 if (helper->call_conv == 0) { /* Unmanaged */
2675 *p = helper->unmanaged_call_conv - 1;
2678 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2679 if (helper->call_conv & 0x02) /* varargs */
2684 mono_metadata_encode_value (nargs, p, &p);
2685 encode_reflection_type (assembly, helper->return_type, p, &p);
2686 for (i = 0; i < nargs; ++i) {
2687 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2688 encode_reflection_type (assembly, pt, p, &p);
2691 g_assert (p - buf < size);
2692 mono_metadata_encode_value (p-buf, b, &b);
2693 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2700 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2703 MonoDynamicTable *table;
2706 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2707 idx = table->next_idx ++;
2709 alloc_table (table, table->rows);
2710 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2712 values [MONO_STAND_ALONE_SIGNATURE] =
2713 mono_reflection_encode_sighelper (assembly, helper);
2719 reflection_cc_to_file (int call_conv) {
2720 switch (call_conv & 0x3) {
2722 case 1: return MONO_CALL_DEFAULT;
2723 case 2: return MONO_CALL_VARARG;
2725 g_assert_not_reached ();
2732 MonoMethodSignature *sig;
2738 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2743 MonoMethodSignature *sig;
2746 name = mono_string_to_utf8 (m->name);
2747 nparams = mono_array_length (m->parameters);
2748 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2750 sig->sentinelpos = -1;
2751 sig->call_convention = reflection_cc_to_file (m->call_conv);
2752 sig->param_count = nparams;
2753 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2754 for (i = 0; i < nparams; ++i) {
2755 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2756 sig->params [i] = t->type;
2759 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2761 if (strcmp (name, am->name) == 0 &&
2762 mono_metadata_type_equal (am->parent, m->parent->type) &&
2763 mono_metadata_signature_equal (am->sig, sig)) {
2766 m->table_idx = am->token & 0xffffff;
2770 am = g_new0 (ArrayMethod, 1);
2773 am->parent = m->parent->type;
2774 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2775 method_encode_signature (assembly, sig));
2776 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2777 m->table_idx = am->token & 0xffffff;
2782 * Insert into the metadata tables all the info about the TypeBuilder tb.
2783 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2786 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2788 MonoDynamicTable *table;
2790 int i, is_object = 0, is_system = 0;
2793 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2794 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2795 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2796 n = mono_string_to_utf8 (tb->name);
2797 if (strcmp (n, "Object") == 0)
2799 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2801 n = mono_string_to_utf8 (tb->nspace);
2802 if (strcmp (n, "System") == 0)
2804 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2806 if (tb->parent && !(is_system && is_object) &&
2807 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2808 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2810 values [MONO_TYPEDEF_EXTENDS] = 0;
2812 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2813 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2816 * if we have explicitlayout or sequentiallayouts, output data in the
2817 * ClassLayout table.
2819 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2820 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2821 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2823 alloc_table (table, table->rows);
2824 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2825 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2826 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2827 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2830 /* handle interfaces */
2831 if (tb->interfaces) {
2832 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2834 table->rows += mono_array_length (tb->interfaces);
2835 alloc_table (table, table->rows);
2836 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2837 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2838 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2839 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2840 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2841 values += MONO_INTERFACEIMPL_SIZE;
2847 table = &assembly->tables [MONO_TABLE_FIELD];
2848 table->rows += tb->num_fields;
2849 alloc_table (table, table->rows);
2850 for (i = 0; i < tb->num_fields; ++i)
2851 mono_image_get_field_info (
2852 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2855 /* handle constructors */
2857 table = &assembly->tables [MONO_TABLE_METHOD];
2858 table->rows += mono_array_length (tb->ctors);
2859 alloc_table (table, table->rows);
2860 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2861 mono_image_get_ctor_info (domain,
2862 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2865 /* handle methods */
2867 table = &assembly->tables [MONO_TABLE_METHOD];
2868 table->rows += tb->num_methods;
2869 alloc_table (table, table->rows);
2870 for (i = 0; i < tb->num_methods; ++i)
2871 mono_image_get_method_info (
2872 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2875 /* Do the same with properties etc.. */
2876 if (tb->events && mono_array_length (tb->events)) {
2877 table = &assembly->tables [MONO_TABLE_EVENT];
2878 table->rows += mono_array_length (tb->events);
2879 alloc_table (table, table->rows);
2880 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2882 alloc_table (table, table->rows);
2883 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2884 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2885 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2886 for (i = 0; i < mono_array_length (tb->events); ++i)
2887 mono_image_get_event_info (
2888 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2890 if (tb->properties && mono_array_length (tb->properties)) {
2891 table = &assembly->tables [MONO_TABLE_PROPERTY];
2892 table->rows += mono_array_length (tb->properties);
2893 alloc_table (table, table->rows);
2894 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2896 alloc_table (table, table->rows);
2897 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2898 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2899 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2900 for (i = 0; i < mono_array_length (tb->properties); ++i)
2901 mono_image_get_property_info (
2902 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2905 /* handle generic parameters */
2906 if (tb->generic_params) {
2907 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2908 table->rows += mono_array_length (tb->generic_params);
2909 alloc_table (table, table->rows);
2910 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2911 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2913 mono_image_get_generic_param_info (
2914 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2918 mono_image_add_decl_security (assembly,
2919 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2922 MonoDynamicTable *ntable;
2924 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2925 ntable->rows += mono_array_length (tb->subtypes);
2926 alloc_table (ntable, ntable->rows);
2927 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2929 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2930 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2932 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2933 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2934 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2935 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2936 mono_string_to_utf8 (tb->name), tb->table_idx,
2937 ntable->next_idx, ntable->rows);*/
2938 values += MONO_NESTED_CLASS_SIZE;
2945 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2949 g_ptr_array_add (types, type);
2951 if (!type->subtypes)
2954 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2955 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2956 collect_types (types, subtype);
2961 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2963 if ((*type1)->table_idx < (*type2)->table_idx)
2966 if ((*type1)->table_idx > (*type2)->table_idx)
2973 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2978 for (i = 0; i < mono_array_length (pinfo); ++i) {
2979 MonoReflectionParamBuilder *pb;
2980 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2983 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2988 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2991 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2993 for (i = 0; i < tb->num_fields; ++i) {
2994 MonoReflectionFieldBuilder* fb;
2995 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2996 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3000 for (i = 0; i < mono_array_length (tb->events); ++i) {
3001 MonoReflectionEventBuilder* eb;
3002 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3003 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3006 if (tb->properties) {
3007 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3008 MonoReflectionPropertyBuilder* pb;
3009 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3010 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3014 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3015 MonoReflectionCtorBuilder* cb;
3016 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3017 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3018 params_add_cattrs (assembly, cb->pinfo);
3023 for (i = 0; i < tb->num_methods; ++i) {
3024 MonoReflectionMethodBuilder* mb;
3025 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3026 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3027 params_add_cattrs (assembly, mb->pinfo);
3032 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3033 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3038 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3041 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3043 /* no types in the module */
3047 for (i = 0; i < mb->num_types; ++i)
3048 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3052 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3054 MonoDynamicTable *table;
3058 char *b = blob_size;
3061 table = &assembly->tables [MONO_TABLE_FILE];
3063 alloc_table (table, table->rows);
3064 values = table->values + table->next_idx * MONO_FILE_SIZE;
3065 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3066 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3067 if (module->image->dynamic) {
3068 /* This depends on the fact that the main module is emitted last */
3069 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3070 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3073 path = g_strdup (module->image->name);
3075 mono_sha1_get_digest_from_file (path, hash);
3078 mono_metadata_encode_value (20, b, &b);
3079 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3080 mono_image_add_stream_data (&assembly->blob, hash, 20);
3085 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3087 MonoDynamicTable *table;
3091 table = &assembly->tables [MONO_TABLE_MODULE];
3092 mb->table_idx = table->next_idx ++;
3093 name = mono_string_to_utf8 (mb->module.name);
3094 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3096 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3099 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3100 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3101 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3105 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3106 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3108 MonoDynamicTable *table;
3112 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3113 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3116 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3118 alloc_table (table, table->rows);
3119 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3121 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3122 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3123 if (klass->nested_in)
3124 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3126 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3127 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3128 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3130 res = table->next_idx;
3134 /* Emit nested types */
3135 if (klass->nested_classes) {
3138 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3139 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3146 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3147 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3152 klass = mono_class_from_mono_type (tb->type.type);
3154 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3156 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3157 parent_index, assembly);
3161 * We need to do this ourselves since klass->nested_classes is not set up.
3164 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3165 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3170 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3171 guint32 module_index, MonoDynamicImage *assembly)
3173 MonoImage *image = module->image;
3177 t = &image->tables [MONO_TABLE_TYPEDEF];
3179 for (i = 0; i < t->rows; ++i) {
3180 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3182 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3183 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3187 #define align_pointer(base,p)\
3189 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3191 (p) += 4 - (__diff & 3);\
3195 compare_constants (const void *a, const void *b)
3197 const guint32 *a_values = a;
3198 const guint32 *b_values = b;
3199 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3203 compare_semantics (const void *a, const void *b)
3205 const guint32 *a_values = a;
3206 const guint32 *b_values = b;
3207 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3210 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3214 compare_custom_attrs (const void *a, const void *b)
3216 const guint32 *a_values = a;
3217 const guint32 *b_values = b;
3219 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3223 compare_field_marshal (const void *a, const void *b)
3225 const guint32 *a_values = a;
3226 const guint32 *b_values = b;
3228 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3232 compare_nested (const void *a, const void *b)
3234 const guint32 *a_values = a;
3235 const guint32 *b_values = b;
3237 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3241 compare_genericparam (const void *a, const void *b)
3243 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3244 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3246 if ((*b_entry)->owner == (*a_entry)->owner)
3248 (*a_entry)->gparam->type.type->data.generic_param->num -
3249 (*b_entry)->gparam->type.type->data.generic_param->num;
3251 return (*a_entry)->owner - (*b_entry)->owner;
3255 compare_declsecurity_attrs (const void *a, const void *b)
3257 const guint32 *a_values = a;
3258 const guint32 *b_values = b;
3260 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3264 pad_heap (MonoDynamicStream *sh)
3266 if (sh->index & 3) {
3267 int sz = 4 - (sh->index & 3);
3268 memset (sh->data + sh->index, 0, sz);
3275 MonoDynamicStream *stream;
3279 * build_compressed_metadata() fills in the blob of data that represents the
3280 * raw metadata as it will be saved in the PE file. The five streams are output
3281 * and the metadata tables are comnpressed from the guint32 array representation,
3282 * to the compressed on-disk format.
3285 build_compressed_metadata (MonoDynamicImage *assembly)
3287 MonoDynamicTable *table;
3289 guint64 valid_mask = 0;
3290 guint64 sorted_mask;
3291 guint32 heapt_size = 0;
3292 guint32 meta_size = 256; /* allow for header and other stuff */
3293 guint32 table_offset;
3294 guint32 ntables = 0;
3300 struct StreamDesc stream_desc [5];
3302 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3303 for (i = 0; i < assembly->gen_params->len; i++){
3304 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3305 write_generic_param_entry (assembly, entry);
3308 stream_desc [0].name = "#~";
3309 stream_desc [0].stream = &assembly->tstream;
3310 stream_desc [1].name = "#Strings";
3311 stream_desc [1].stream = &assembly->sheap;
3312 stream_desc [2].name = "#US";
3313 stream_desc [2].stream = &assembly->us;
3314 stream_desc [3].name = "#Blob";
3315 stream_desc [3].stream = &assembly->blob;
3316 stream_desc [4].name = "#GUID";
3317 stream_desc [4].stream = &assembly->guid;
3319 /* tables that are sorted */
3320 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3321 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3322 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3323 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3324 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3325 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3327 /* Compute table sizes */
3328 /* the MonoImage has already been created in mono_image_basic_init() */
3329 meta = &assembly->image;
3331 /* sizes should be multiple of 4 */
3332 pad_heap (&assembly->blob);
3333 pad_heap (&assembly->guid);
3334 pad_heap (&assembly->sheap);
3335 pad_heap (&assembly->us);
3337 /* Setup the info used by compute_sizes () */
3338 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3339 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3340 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3342 meta_size += assembly->blob.index;
3343 meta_size += assembly->guid.index;
3344 meta_size += assembly->sheap.index;
3345 meta_size += assembly->us.index;
3347 for (i=0; i < MONO_TABLE_NUM; ++i)
3348 meta->tables [i].rows = assembly->tables [i].rows;
3350 for (i = 0; i < MONO_TABLE_NUM; i++){
3351 if (meta->tables [i].rows == 0)
3353 valid_mask |= (guint64)1 << i;
3355 meta->tables [i].row_size = mono_metadata_compute_size (
3356 meta, i, &meta->tables [i].size_bitfield);
3357 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3359 heapt_size += 24; /* #~ header size */
3360 heapt_size += ntables * 4;
3361 /* make multiple of 4 */
3364 meta_size += heapt_size;
3365 meta->raw_metadata = g_malloc0 (meta_size);
3366 p = meta->raw_metadata;
3367 /* the metadata signature */
3368 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3369 /* version numbers and 4 bytes reserved */
3370 int16val = (guint16*)p;
3371 *int16val++ = GUINT16_TO_LE (1);
3372 *int16val = GUINT16_TO_LE (1);
3374 /* version string */
3375 int32val = (guint32*)p;
3376 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3378 memcpy (p, meta->version, strlen (meta->version));
3379 p += GUINT32_FROM_LE (*int32val);
3380 align_pointer (meta->raw_metadata, p);
3381 int16val = (guint16*)p;
3382 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3383 *int16val = GUINT16_TO_LE (5); /* number of streams */
3387 * write the stream info.
3389 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3390 table_offset += 3; table_offset &= ~3;
3392 assembly->tstream.index = heapt_size;
3393 for (i = 0; i < 5; ++i) {
3394 int32val = (guint32*)p;
3395 stream_desc [i].stream->offset = table_offset;
3396 *int32val++ = GUINT32_TO_LE (table_offset);
3397 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3398 table_offset += GUINT32_FROM_LE (*int32val);
3399 table_offset += 3; table_offset &= ~3;
3401 strcpy (p, stream_desc [i].name);
3402 p += strlen (stream_desc [i].name) + 1;
3403 align_pointer (meta->raw_metadata, p);
3406 * now copy the data, the table stream header and contents goes first.
3408 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3409 p = meta->raw_metadata + assembly->tstream.offset;
3410 int32val = (guint32*)p;
3411 *int32val = GUINT32_TO_LE (0); /* reserved */
3414 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3415 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3416 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3417 *p++ = 1; /* version */
3420 *p++ = 1; /* version */
3424 if (meta->idx_string_wide)
3426 if (meta->idx_guid_wide)
3428 if (meta->idx_blob_wide)
3431 *p++ = 1; /* reserved */
3432 int64val = (guint64*)p;
3433 *int64val++ = GUINT64_TO_LE (valid_mask);
3434 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3436 int32val = (guint32*)p;
3437 for (i = 0; i < MONO_TABLE_NUM; i++){
3438 if (meta->tables [i].rows == 0)
3440 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3442 p = (unsigned char*)int32val;
3444 /* sort the tables that still need sorting */
3445 table = &assembly->tables [MONO_TABLE_CONSTANT];
3447 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3448 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3450 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3451 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3453 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3454 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3456 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3457 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3459 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3460 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3461 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3463 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3465 /* compress the tables */
3466 for (i = 0; i < MONO_TABLE_NUM; i++){
3469 guint32 bitfield = meta->tables [i].size_bitfield;
3470 if (!meta->tables [i].rows)
3472 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3473 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3474 meta->tables [i].base = p;
3475 for (row = 1; row <= meta->tables [i].rows; ++row) {
3476 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3477 for (col = 0; col < assembly->tables [i].columns; ++col) {
3478 switch (mono_metadata_table_size (bitfield, col)) {
3480 *p++ = values [col];
3483 *p++ = values [col] & 0xff;
3484 *p++ = (values [col] >> 8) & 0xff;
3487 *p++ = values [col] & 0xff;
3488 *p++ = (values [col] >> 8) & 0xff;
3489 *p++ = (values [col] >> 16) & 0xff;
3490 *p++ = (values [col] >> 24) & 0xff;
3493 g_assert_not_reached ();
3497 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3500 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3501 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3502 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3503 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3504 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3506 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3510 * Some tables in metadata need to be sorted according to some criteria, but
3511 * when methods and fields are first created with reflection, they may be assigned a token
3512 * that doesn't correspond to the final token they will get assigned after the sorting.
3513 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3514 * with the reflection objects that represent them. Once all the tables are set up, the
3515 * reflection objects will contains the correct table index. fixup_method() will fixup the
3516 * tokens for the method with ILGenerator @ilgen.
3519 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3520 guint32 code_idx = GPOINTER_TO_UINT (value);
3521 MonoReflectionILTokenInfo *iltoken;
3522 MonoReflectionFieldBuilder *field;
3523 MonoReflectionCtorBuilder *ctor;
3524 MonoReflectionMethodBuilder *method;
3525 MonoReflectionTypeBuilder *tb;
3526 MonoReflectionArrayMethod *am;
3528 unsigned char *target;
3530 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3531 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3532 target = assembly->code.data + code_idx + iltoken->code_pos;
3533 switch (target [3]) {
3534 case MONO_TABLE_FIELD:
3535 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3536 field = (MonoReflectionFieldBuilder *)iltoken->member;
3537 idx = field->table_idx;
3538 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3539 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3540 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3542 g_assert_not_reached ();
3545 case MONO_TABLE_METHOD:
3546 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3547 method = (MonoReflectionMethodBuilder *)iltoken->member;
3548 idx = method->table_idx;
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3550 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3551 idx = ctor->table_idx;
3552 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3553 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3554 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3555 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3557 g_assert_not_reached ();
3560 case MONO_TABLE_TYPEDEF:
3561 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3562 g_assert_not_reached ();
3563 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3564 idx = tb->table_idx;
3566 case MONO_TABLE_MEMBERREF:
3567 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3568 am = (MonoReflectionArrayMethod*)iltoken->member;
3569 idx = am->table_idx;
3570 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3571 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3572 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3573 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3574 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3575 g_assert (m->klass->generic_class || m->klass->generic_container);
3577 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3579 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3580 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3581 g_assert (f->generic_info);
3583 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3586 g_assert_not_reached ();
3589 case MONO_TABLE_METHODSPEC:
3590 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3591 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3592 g_assert (m->signature->generic_param_count);
3595 g_assert_not_reached ();
3599 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3601 target [0] = idx & 0xff;
3602 target [1] = (idx >> 8) & 0xff;
3603 target [2] = (idx >> 16) & 0xff;
3610 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3611 * value is not known when the table is emitted.
3614 fixup_cattrs (MonoDynamicImage *assembly)
3616 MonoDynamicTable *table;
3618 guint32 type, i, idx, token;
3621 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3623 for (i = 0; i < table->rows; ++i) {
3624 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3626 type = values [MONO_CUSTOM_ATTR_TYPE];
3627 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3628 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3629 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3630 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3633 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3634 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3635 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3636 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3643 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3645 MonoDynamicTable *table;
3649 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3651 alloc_table (table, table->rows);
3652 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3653 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3654 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3655 name = mono_string_to_utf8 (rsrc->name);
3656 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3658 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3663 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3665 MonoDynamicTable *table;
3669 char *b = blob_size;
3671 guint32 idx, offset;
3673 if (rsrc->filename) {
3674 name = mono_string_to_utf8 (rsrc->filename);
3675 sname = g_path_get_basename (name);
3677 table = &assembly->tables [MONO_TABLE_FILE];
3679 alloc_table (table, table->rows);
3680 values = table->values + table->next_idx * MONO_FILE_SIZE;
3681 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3682 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3685 mono_sha1_get_digest_from_file (name, hash);
3686 mono_metadata_encode_value (20, b, &b);
3687 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3688 mono_image_add_stream_data (&assembly->blob, hash, 20);
3690 idx = table->next_idx++;
3692 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3695 offset = mono_array_length (rsrc->data);
3696 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3697 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3698 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3699 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3703 * The entry should be emitted into the MANIFESTRESOURCE table of
3704 * the main module, but that needs to reference the FILE table
3705 * which isn't emitted yet.
3712 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3716 set_version_from_string (MonoString *version, guint32 *values)
3718 gchar *ver, *p, *str;
3721 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3722 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3723 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3724 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3727 ver = str = mono_string_to_utf8 (version);
3728 for (i = 0; i < 4; ++i) {
3729 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3735 /* handle Revision and Build */
3745 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3749 char *b = blob_size;
3754 len = mono_array_length (pkey);
3755 mono_metadata_encode_value (len, b, &b);
3756 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3757 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3759 /* need to get the actual value from the key type... */
3760 assembly->strong_name_size = 128;
3761 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3767 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3769 MonoDynamicTable *table;
3770 MonoDynamicImage *assembly;
3771 MonoReflectionAssemblyBuilder *assemblyb;
3776 guint32 module_index;
3778 assemblyb = moduleb->assemblyb;
3779 assembly = moduleb->dynamic_image;
3780 domain = mono_object_domain (assemblyb);
3782 /* Emit ASSEMBLY table */
3783 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3784 alloc_table (table, 1);
3785 values = table->values + MONO_ASSEMBLY_SIZE;
3786 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3787 name = mono_string_to_utf8 (assemblyb->name);
3788 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3790 if (assemblyb->culture) {
3791 name = mono_string_to_utf8 (assemblyb->culture);
3792 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3795 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3797 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3798 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3799 set_version_from_string (assemblyb->version, values);
3801 /* Emit FILE + EXPORTED_TYPE table */
3803 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3805 MonoReflectionModuleBuilder *file_module =
3806 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3807 if (file_module != moduleb) {
3808 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3810 if (file_module->types) {
3811 for (j = 0; j < file_module->num_types; ++j) {
3812 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3813 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3818 if (assemblyb->loaded_modules) {
3819 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3820 MonoReflectionModule *file_module =
3821 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3822 mono_image_fill_file_table (domain, file_module, assembly);
3824 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3828 /* Emit MANIFESTRESOURCE table */
3830 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3832 MonoReflectionModuleBuilder *file_module =
3833 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3834 /* The table for the main module is emitted later */
3835 if (file_module != moduleb) {
3837 if (file_module->resources) {
3838 int len = mono_array_length (file_module->resources);
3839 for (j = 0; j < len; ++j) {
3840 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3841 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3849 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3850 * for the modulebuilder @moduleb.
3851 * At the end of the process, method and field tokens are fixed up and the
3852 * on-disk compressed metadata representation is created.
3855 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3857 MonoDynamicTable *table;
3858 MonoDynamicImage *assembly;
3859 MonoReflectionAssemblyBuilder *assemblyb;
3864 assemblyb = moduleb->assemblyb;
3865 assembly = moduleb->dynamic_image;
3866 domain = mono_object_domain (assemblyb);
3868 if (assembly->text_rva)
3871 assembly->text_rva = START_TEXT_RVA;
3873 if (moduleb->is_main) {
3874 mono_image_emit_manifest (moduleb);
3877 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3878 table->rows = 1; /* .<Module> */
3880 alloc_table (table, table->rows);
3882 * Set the first entry.
3884 values = table->values + table->columns;
3885 values [MONO_TYPEDEF_FLAGS] = 0;
3886 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3887 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3888 values [MONO_TYPEDEF_EXTENDS] = 0;
3889 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3890 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3893 * handle global methods
3894 * FIXME: test what to do when global methods are defined in multiple modules.
3896 if (moduleb->global_methods) {
3897 table = &assembly->tables [MONO_TABLE_METHOD];
3898 table->rows += mono_array_length (moduleb->global_methods);
3899 alloc_table (table, table->rows);
3900 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3901 mono_image_get_method_info (
3902 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3904 if (moduleb->global_fields) {
3905 table = &assembly->tables [MONO_TABLE_FIELD];
3906 table->rows += mono_array_length (moduleb->global_fields);
3907 alloc_table (table, table->rows);
3908 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3909 mono_image_get_field_info (
3910 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3913 table = &assembly->tables [MONO_TABLE_MODULE];
3914 alloc_table (table, 1);
3915 mono_image_fill_module_table (domain, moduleb, assembly);
3919 /* Collect all types into a list sorted by their table_idx */
3920 GPtrArray *types = g_ptr_array_new ();
3923 for (i = 0; i < moduleb->num_types; ++i) {
3924 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3925 collect_types (types, type);
3928 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3929 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3930 table->rows += types->len;
3931 alloc_table (table, table->rows);
3933 for (i = 0; i < types->len; ++i) {
3934 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3935 mono_image_get_type_info (domain, type, assembly);
3937 g_ptr_array_free (types, TRUE);
3941 * table->rows is already set above and in mono_image_fill_module_table.
3943 /* add all the custom attributes at the end, once all the indexes are stable */
3944 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3946 /* CAS assembly permissions */
3947 if (assemblyb->permissions_minimum)
3948 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3949 if (assemblyb->permissions_optional)
3950 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3951 if (assemblyb->permissions_refused)
3952 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3954 module_add_cattrs (assembly, moduleb);
3957 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3958 fixup_cattrs (assembly);
3962 * mono_image_insert_string:
3963 * @module: module builder object
3966 * Insert @str into the user string stream of @module.
3969 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3971 MonoDynamicImage *assembly;
3976 MONO_ARCH_SAVE_REGS;
3978 if (!module->dynamic_image)
3979 mono_image_module_basic_init (module);
3981 assembly = module->dynamic_image;
3983 if (assembly->save) {
3984 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3985 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3986 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3988 char *swapped = g_malloc (2 * mono_string_length (str));
3989 const char *p = (const char*)mono_string_chars (str);
3991 swap_with_size (swapped, p, 2, mono_string_length (str));
3992 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3996 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3998 mono_image_add_stream_data (&assembly->us, "", 1);
4000 idx = assembly->us.index ++;
4003 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4005 return MONO_TOKEN_STRING | idx;
4009 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4014 klass = obj->vtable->klass;
4015 if (strcmp (klass->name, "MonoMethod") == 0) {
4016 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4017 MonoMethodSignature *sig, *old;
4018 guint32 sig_token, parent;
4021 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
4023 nargs = mono_array_length (opt_param_types);
4024 old = method->signature;
4025 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4027 sig->hasthis = old->hasthis;
4028 sig->explicit_this = old->explicit_this;
4029 sig->call_convention = old->call_convention;
4030 sig->generic_param_count = old->generic_param_count;
4031 sig->param_count = old->param_count + nargs;
4032 sig->sentinelpos = old->param_count;
4033 sig->ret = old->ret;
4035 for (i = 0; i < old->param_count; i++)
4036 sig->params [i] = old->params [i];
4038 for (i = 0; i < nargs; i++) {
4039 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4040 sig->params [old->param_count + i] = rt->type;
4043 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4044 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4045 parent >>= MONO_TYPEDEFORREF_BITS;
4047 parent <<= MONO_MEMBERREF_PARENT_BITS;
4048 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4050 sig_token = method_encode_signature (assembly, sig);
4051 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4052 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4053 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4054 ReflectionMethodBuilder rmb;
4055 guint32 parent, sig;
4057 reflection_methodbuilder_from_method_builder (&rmb, mb);
4058 rmb.opt_types = opt_param_types;
4060 sig = method_builder_encode_signature (assembly, &rmb);
4062 parent = mono_image_create_token (assembly, obj, TRUE);
4063 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4065 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4066 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4068 token = mono_image_get_varargs_method_token (
4069 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4071 g_error ("requested method token for %s\n", klass->name);
4078 * mono_image_create_token:
4079 * @assembly: a dynamic assembly
4082 * Get a token to insert in the IL code stream for the given MemberInfo.
4083 * @obj can be one of:
4084 * ConstructorBuilder
4094 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4099 klass = obj->vtable->klass;
4100 if (strcmp (klass->name, "MethodBuilder") == 0) {
4101 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4103 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4104 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4106 token = mono_image_get_methodbuilder_token (assembly, mb);
4107 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4108 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4109 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4111 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4112 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4114 token = mono_image_get_ctorbuilder_token (assembly, mb);
4115 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4116 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4117 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4118 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4119 if (tb->generic_params) {
4120 token = mono_image_get_generic_field_token (assembly, fb);
4122 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4124 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4125 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4126 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4127 } else if (strcmp (klass->name, "MonoType") == 0 ||
4128 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4129 MonoReflectionType *tb = (MonoReflectionType *)obj;
4130 token = mono_metadata_token_from_dor (
4131 mono_image_typedef_or_ref (assembly, tb->type));
4132 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4133 MonoReflectionType *tb = (MonoReflectionType *)obj;
4134 token = mono_metadata_token_from_dor (
4135 mono_image_typedef_or_ref (assembly, tb->type));
4136 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4137 strcmp (klass->name, "MonoMethod") == 0 ||
4138 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4139 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4140 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4141 if (m->method->is_inflated) {
4142 if (create_methodspec)
4143 token = mono_image_get_methodspec_token (assembly, m->method);
4145 token = mono_image_get_inflated_method_token (assembly, m->method);
4146 } else if ((m->method->klass->image == &assembly->image) &&
4147 !m->method->klass->generic_class) {
4148 static guint32 method_table_idx = 0xffffff;
4149 if (m->method->klass->wastypebuilder) {
4150 /* we use the same token as the one that was assigned
4151 * to the Methodbuilder.
4152 * FIXME: do the equivalent for Fields.
4154 token = m->method->token;
4157 * Each token should have a unique index, but the indexes are
4158 * assigned by managed code, so we don't know about them. An
4159 * easy solution is to count backwards...
4161 method_table_idx --;
4162 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4165 token = mono_image_get_methodref_token (assembly, m->method);
4167 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4168 } else if (strcmp (klass->name, "MonoField") == 0) {
4169 MonoReflectionField *f = (MonoReflectionField *)obj;
4170 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4171 static guint32 field_table_idx = 0xffffff;
4173 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4175 token = mono_image_get_fieldref_token (assembly, f);
4177 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4178 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4179 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4180 token = mono_image_get_array_token (assembly, m);
4181 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4182 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4183 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4185 g_error ("requested token for %s\n", klass->name);
4188 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4194 guint32 import_lookup_table;
4198 guint32 import_address_table_rva;
4206 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4208 static MonoDynamicImage*
4209 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4211 static const guchar entrycode [16] = {0xff, 0x25, 0};
4212 MonoDynamicImage *image;
4215 const char *version = mono_get_runtime_version ();
4218 image = GC_MALLOC (sizeof (MonoDynamicImage));
4220 image = g_new0 (MonoDynamicImage, 1);
4223 /* keep in sync with image.c */
4224 image->image.name = assembly_name;
4225 image->image.assembly_name = image->image.name; /* they may be different */
4226 image->image.module_name = module_name;
4227 image->image.version = g_strdup (version);
4228 image->image.dynamic = TRUE;
4230 image->image.references = g_new0 (MonoAssembly*, 1);
4231 image->image.references [0] = NULL;
4233 mono_image_init (&image->image);
4235 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4236 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4237 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4238 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4239 image->handleref = g_hash_table_new (NULL, NULL);
4240 image->tokens = mono_g_hash_table_new (NULL, NULL);
4241 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4242 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4243 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4244 image->gen_params = g_ptr_array_new ();
4246 string_heap_init (&image->sheap);
4247 mono_image_add_stream_data (&image->us, "", 1);
4248 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4249 /* import tables... */
4250 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4251 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4252 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4253 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4254 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4255 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4256 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4257 stream_data_align (&image->code);
4259 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4261 for (i=0; i < MONO_TABLE_NUM; ++i) {
4262 image->tables [i].next_idx = 1;
4263 image->tables [i].columns = table_sizes [i];
4266 image->image.assembly = (MonoAssembly*)assembly;
4267 image->run = assembly->run;
4268 image->save = assembly->save;
4269 image->pe_kind = 0x1; /* ILOnly */
4270 image->machine = 0x14c; /* I386 */
4276 * mono_image_basic_init:
4277 * @assembly: an assembly builder object
4279 * Create the MonoImage that represents the assembly builder and setup some
4280 * of the helper hash table and the basic metadata streams.
4283 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4285 MonoDynamicAssembly *assembly;
4286 MonoDynamicImage *image;
4288 MONO_ARCH_SAVE_REGS;
4290 if (assemblyb->dynamic_assembly)
4294 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4296 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4299 assembly->assembly.dynamic = TRUE;
4300 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4301 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4302 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4303 if (assemblyb->culture)
4304 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4306 assembly->assembly.aname.culture = g_strdup ("");
4308 assembly->run = assemblyb->access != 2;
4309 assembly->save = assemblyb->access != 1;
4311 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4312 image->initial_image = TRUE;
4313 assembly->assembly.aname.name = image->image.name;
4314 assembly->assembly.image = &image->image;
4316 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4317 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4321 calc_section_size (MonoDynamicImage *assembly)
4325 /* alignment constraints */
4326 assembly->code.index += 3;
4327 assembly->code.index &= ~3;
4328 assembly->meta_size += 3;
4329 assembly->meta_size &= ~3;
4330 assembly->resources.index += 3;
4331 assembly->resources.index &= ~3;
4333 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4334 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4337 if (assembly->win32_res) {
4338 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4340 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4341 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4345 assembly->sections [MONO_SECTION_RELOC].size = 12;
4346 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4356 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4360 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4362 ResTreeNode *t1 = (ResTreeNode*)a;
4363 ResTreeNode *t2 = (ResTreeNode*)b;
4365 return t1->id - t2->id;
4369 * resource_tree_create:
4371 * Organize the resources into a resource tree.
4373 static ResTreeNode *
4374 resource_tree_create (MonoArray *win32_resources)
4376 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4380 tree = g_new0 (ResTreeNode, 1);
4382 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4383 MonoReflectionWin32Resource *win32_res =
4384 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4388 lang_node = g_new0 (ResTreeNode, 1);
4389 lang_node->id = win32_res->lang_id;
4390 lang_node->win32_res = win32_res;
4392 /* Create type node if neccesary */
4394 for (l = tree->children; l; l = l->next)
4395 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4396 type_node = (ResTreeNode*)l->data;
4401 type_node = g_new0 (ResTreeNode, 1);
4402 type_node->id = win32_res->res_type;
4405 * The resource types have to be sorted otherwise
4406 * Windows Explorer can't display the version information.
4408 tree->children = g_slist_insert_sorted (tree->children,
4409 type_node, resource_tree_compare_by_id);
4412 /* Create res node if neccesary */
4414 for (l = type_node->children; l; l = l->next)
4415 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4416 res_node = (ResTreeNode*)l->data;
4421 res_node = g_new0 (ResTreeNode, 1);
4422 res_node->id = win32_res->res_id;
4423 type_node->children = g_slist_append (type_node->children, res_node);
4426 res_node->children = g_slist_append (res_node->children, lang_node);
4433 * resource_tree_encode:
4435 * Encode the resource tree into the format used in the PE file.
4438 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4441 MonoPEResourceDir dir;
4442 MonoPEResourceDirEntry dir_entry;
4443 MonoPEResourceDataEntry data_entry;
4447 * For the format of the resource directory, see the article
4448 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4452 memset (&dir, 0, sizeof (dir));
4453 memset (&dir_entry, 0, sizeof (dir_entry));
4454 memset (&data_entry, 0, sizeof (data_entry));
4456 g_assert (sizeof (dir) == 16);
4457 g_assert (sizeof (dir_entry) == 8);
4458 g_assert (sizeof (data_entry) == 16);
4460 node->offset = p - begin;
4462 /* IMAGE_RESOURCE_DIRECTORY */
4463 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4465 memcpy (p, &dir, sizeof (dir));
4468 /* Reserve space for entries */
4470 p += sizeof (dir_entry) * dir.res_id_entries;
4472 /* Write children */
4473 for (l = node->children; l; l = l->next) {
4474 ResTreeNode *child = (ResTreeNode*)l->data;
4476 if (child->win32_res) {
4478 child->offset = p - begin;
4480 /* IMAGE_RESOURCE_DATA_ENTRY */
4481 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4482 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4484 memcpy (p, &data_entry, sizeof (data_entry));
4485 p += sizeof (data_entry);
4487 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4488 p += data_entry.rde_size;
4490 resource_tree_encode (child, begin, p, &p);
4494 /* IMAGE_RESOURCE_ENTRY */
4495 for (l = node->children; l; l = l->next) {
4496 ResTreeNode *child = (ResTreeNode*)l->data;
4497 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4499 dir_entry.is_dir = child->win32_res ? 0 : 1;
4500 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4502 memcpy (entries, &dir_entry, sizeof (dir_entry));
4503 entries += sizeof (dir_entry);
4510 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4515 MonoReflectionWin32Resource *win32_res;
4518 if (!assemblyb->win32_resources)
4522 * Resources are stored in a three level tree inside the PE file.
4523 * - level one contains a node for each type of resource
4524 * - level two contains a node for each resource
4525 * - level three contains a node for each instance of a resource for a
4526 * specific language.
4529 tree = resource_tree_create (assemblyb->win32_resources);
4531 /* Estimate the size of the encoded tree */
4533 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4534 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4535 size += mono_array_length (win32_res->res_data);
4537 /* Directory structure */
4538 size += mono_array_length (assemblyb->win32_resources) * 256;
4539 p = buf = g_malloc (size);
4541 resource_tree_encode (tree, p, p, &p);
4543 g_assert (p - buf < size);
4545 assembly->win32_res = g_malloc (p - buf);
4546 assembly->win32_res_size = p - buf;
4547 memcpy (assembly->win32_res, buf, p - buf);
4553 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4555 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4558 p += sizeof (MonoPEResourceDir);
4559 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4560 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4561 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4562 if (dir_entry->is_dir) {
4563 fixup_resource_directory (res_section, child, rva);
4565 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4566 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4569 p += sizeof (MonoPEResourceDirEntry);
4574 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4577 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4578 g_error ("WriteFile returned %d\n", GetLastError ());
4582 * mono_image_create_pefile:
4583 * @mb: a module builder object
4585 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4586 * assembly->pefile where it can be easily retrieved later in chunks.
4589 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4590 MonoMSDOSHeader *msdos;
4591 MonoDotNetHeader *header;
4592 MonoSectionTable *section;
4593 MonoCLIHeader *cli_header;
4594 guint32 size, image_size, virtual_base, text_offset;
4595 guint32 header_start, section_start, file_offset, virtual_offset;
4596 MonoDynamicImage *assembly;
4597 MonoReflectionAssemblyBuilder *assemblyb;
4598 MonoDynamicStream pefile_stream = {0};
4599 MonoDynamicStream *pefile = &pefile_stream;
4601 guint32 *rva, value;
4603 static const unsigned char msheader[] = {
4604 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4605 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4607 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4608 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4609 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4610 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4611 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4614 assemblyb = mb->assemblyb;
4616 mono_image_basic_init (assemblyb);
4617 assembly = mb->dynamic_image;
4619 assembly->pe_kind = assemblyb->pe_kind;
4620 assembly->machine = assemblyb->machine;
4621 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4622 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4624 mono_image_build_metadata (mb);
4626 if (mb->is_main && assemblyb->resources) {
4627 int len = mono_array_length (assemblyb->resources);
4628 for (i = 0; i < len; ++i)
4629 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4632 if (mb->resources) {
4633 int len = mono_array_length (mb->resources);
4634 for (i = 0; i < len; ++i)
4635 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4638 build_compressed_metadata (assembly);
4641 assembly_add_win32_resources (assembly, assemblyb);
4643 nsections = calc_section_size (assembly);
4645 /* The DOS header and stub */
4646 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4647 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4649 /* the dotnet header */
4650 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4652 /* the section tables */
4653 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4655 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4656 virtual_offset = VIRT_ALIGN;
4659 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4660 if (!assembly->sections [i].size)
4663 file_offset += FILE_ALIGN - 1;
4664 file_offset &= ~(FILE_ALIGN - 1);
4665 virtual_offset += VIRT_ALIGN - 1;
4666 virtual_offset &= ~(VIRT_ALIGN - 1);
4668 assembly->sections [i].offset = file_offset;
4669 assembly->sections [i].rva = virtual_offset;
4671 file_offset += assembly->sections [i].size;
4672 virtual_offset += assembly->sections [i].size;
4673 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4676 file_offset += FILE_ALIGN - 1;
4677 file_offset &= ~(FILE_ALIGN - 1);
4679 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4681 /* back-patch info */
4682 msdos = (MonoMSDOSHeader*)pefile->data;
4683 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4685 header = (MonoDotNetHeader*)(pefile->data + header_start);
4686 header->pesig [0] = 'P';
4687 header->pesig [1] = 'E';
4689 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4690 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4691 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4692 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4693 if (assemblyb->pekind == 1) {
4695 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4698 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4701 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4703 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4704 header->pe.pe_major = 6;
4705 header->pe.pe_minor = 0;
4706 size = assembly->sections [MONO_SECTION_TEXT].size;
4707 size += FILE_ALIGN - 1;
4708 size &= ~(FILE_ALIGN - 1);
4709 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4710 size = assembly->sections [MONO_SECTION_RSRC].size;
4711 size += FILE_ALIGN - 1;
4712 size &= ~(FILE_ALIGN - 1);
4713 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4714 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4715 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4716 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4717 /* pe_rva_entry_point always at the beginning of the text section */
4718 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4720 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4721 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4722 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4723 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4724 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4725 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4726 size = section_start;
4727 size += FILE_ALIGN - 1;
4728 size &= ~(FILE_ALIGN - 1);
4729 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4731 size += VIRT_ALIGN - 1;
4732 size &= ~(VIRT_ALIGN - 1);
4733 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4736 // Translate the PEFileKind value to the value expected by the Windows loader
4742 // PEFileKinds.Dll == 1
4743 // PEFileKinds.ConsoleApplication == 2
4744 // PEFileKinds.WindowApplication == 3
4747 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4748 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4750 if (assemblyb->pekind == 3)
4755 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4757 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4758 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4759 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4760 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4761 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4762 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4764 /* fill data directory entries */
4766 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4767 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4769 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4770 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4772 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4773 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4774 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4775 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4776 /* patch entrypoint name */
4777 if (assemblyb->pekind == 1)
4778 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4780 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4781 /* patch imported function RVA name */
4782 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4783 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4785 /* the import table */
4786 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4787 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4788 /* patch imported dll RVA name and other entries in the dir */
4789 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4790 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4791 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4792 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4793 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4794 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4796 p = (assembly->code.data + assembly->ilt_offset);
4797 value = (assembly->text_rva + assembly->imp_names_offset);
4798 *p++ = (value) & 0xff;
4799 *p++ = (value >> 8) & (0xff);
4800 *p++ = (value >> 16) & (0xff);
4801 *p++ = (value >> 24) & (0xff);
4803 /* the CLI header info */
4804 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4805 cli_header->ch_size = GUINT32_FROM_LE (72);
4806 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4807 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4808 if (assemblyb->entry_point) {
4809 guint32 table_idx = 0;
4810 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4811 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4812 table_idx = methodb->table_idx;
4814 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4816 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4818 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4820 /* The embedded managed resources */
4821 text_offset = assembly->text_rva + assembly->code.index;
4822 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4823 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4824 text_offset += assembly->resources.index;
4825 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4826 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4827 text_offset += assembly->meta_size;
4828 if (assembly->strong_name_size) {
4829 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4830 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4831 text_offset += assembly->strong_name_size;
4834 /* write the section tables and section content */
4835 section = (MonoSectionTable*)(pefile->data + section_start);
4836 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4837 static const char *section_names [] = {
4838 ".text", ".rsrc", ".reloc"
4840 if (!assembly->sections [i].size)
4842 strcpy (section->st_name, section_names [i]);
4843 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4844 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4845 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4846 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4847 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4848 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4849 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4853 checked_write_file (file, pefile->data, pefile->index);
4855 mono_dynamic_stream_reset (pefile);
4857 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4858 if (!assembly->sections [i].size)
4861 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4862 g_error ("SetFilePointer returned %d\n", GetLastError ());
4865 case MONO_SECTION_TEXT:
4866 /* patch entry point */
4867 p = (assembly->code.data + 2);
4868 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4869 *p++ = (value) & 0xff;
4870 *p++ = (value >> 8) & 0xff;
4871 *p++ = (value >> 16) & 0xff;
4872 *p++ = (value >> 24) & 0xff;
4874 checked_write_file (file, assembly->code.data, assembly->code.index);
4875 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4876 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4877 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4880 g_free (assembly->image.raw_metadata);
4882 case MONO_SECTION_RELOC: {
4886 guint16 type_and_offset;
4890 g_assert (sizeof (reloc) == 12);
4892 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4893 reloc.block_size = GUINT32_FROM_LE (12);
4896 * the entrypoint is always at the start of the text section
4897 * 3 is IMAGE_REL_BASED_HIGHLOW
4898 * 2 is patch_size_rva - text_rva
4900 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4903 checked_write_file (file, &reloc, sizeof (reloc));
4907 case MONO_SECTION_RSRC:
4908 if (assembly->win32_res) {
4910 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4911 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4912 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4916 g_assert_not_reached ();
4920 /* check that the file is properly padded */
4921 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4922 g_error ("SetFilePointer returned %d\n", GetLastError ());
4923 if (! SetEndOfFile (file))
4924 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4926 mono_dynamic_stream_reset (&assembly->code);
4927 mono_dynamic_stream_reset (&assembly->us);
4928 mono_dynamic_stream_reset (&assembly->blob);
4929 mono_dynamic_stream_reset (&assembly->guid);
4930 string_heap_free (&assembly->sheap);
4932 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4933 g_hash_table_destroy (assembly->blob_cache);
4936 MonoReflectionModule *
4937 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4941 MonoImageOpenStatus status;
4942 MonoDynamicAssembly *assembly;
4943 guint32 module_count;
4944 MonoImage **new_modules;
4946 name = mono_string_to_utf8 (fileName);
4948 image = mono_image_open (name, &status);
4951 if (status == MONO_IMAGE_ERROR_ERRNO)
4952 exc = mono_get_exception_file_not_found (fileName);
4954 exc = mono_get_exception_bad_image_format (name);
4956 mono_raise_exception (exc);
4961 assembly = ab->dynamic_assembly;
4962 image->assembly = (MonoAssembly*)assembly;
4964 module_count = image->assembly->image->module_count;
4965 new_modules = g_new0 (MonoImage *, module_count + 1);
4967 if (image->assembly->image->modules)
4968 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
4969 new_modules [module_count] = image;
4971 g_free (image->assembly->image->modules);
4972 image->assembly->image->modules = new_modules;
4973 image->assembly->image->module_count ++;
4975 mono_assembly_load_references (image, &status);
4977 mono_image_close (image);
4978 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4981 return mono_module_get_object (mono_domain_get (), image);
4985 * We need to return always the same object for MethodInfo, FieldInfo etc..
4986 * but we need to consider the reflected type.
4987 * type uses a different hash, since it uses custom hash/equal functions.
4992 MonoClass *refclass;
4996 reflected_equal (gconstpointer a, gconstpointer b) {
4997 const ReflectedEntry *ea = a;
4998 const ReflectedEntry *eb = b;
5000 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5004 reflected_hash (gconstpointer a) {
5005 const ReflectedEntry *ea = a;
5006 return GPOINTER_TO_UINT (ea->item);
5009 #define CHECK_OBJECT(t,p,k) \
5015 mono_domain_lock (domain); \
5016 if (!domain->refobject_hash) \
5017 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5018 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5019 mono_domain_unlock (domain); \
5025 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5027 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5030 #define CACHE_OBJECT(p,o,k) \
5032 ReflectedEntry *e = ALLOC_REFENTRY; \
5034 e->refclass = (k); \
5035 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5036 mono_domain_unlock (domain); \
5040 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5042 /* this is done only once */
5043 mono_domain_lock (domain);
5044 CACHE_OBJECT (assembly, res, NULL);
5048 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5050 /* this is done only once */
5051 mono_domain_lock (domain);
5052 CACHE_OBJECT (module, res, NULL);
5056 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5058 MonoDynamicImage *image = moduleb->dynamic_image;
5059 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5062 * FIXME: we already created an image in mono_image_basic_init (), but
5063 * we don't know which module it belongs to, since that is only
5064 * determined at assembly save time.
5066 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5067 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5069 moduleb->module.image = &image->image;
5070 moduleb->dynamic_image = image;
5071 register_module (mono_object_domain (moduleb), moduleb, image);
5076 * mono_assembly_get_object:
5077 * @domain: an app domain
5078 * @assembly: an assembly
5080 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5082 MonoReflectionAssembly*
5083 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5085 static MonoClass *System_Reflection_Assembly;
5086 MonoReflectionAssembly *res;
5088 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5089 if (!System_Reflection_Assembly)
5090 System_Reflection_Assembly = mono_class_from_name (
5091 mono_defaults.corlib, "System.Reflection", "Assembly");
5092 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5093 res->assembly = assembly;
5095 CACHE_OBJECT (assembly, res, NULL);
5101 MonoReflectionModule*
5102 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5104 static MonoClass *System_Reflection_Module;
5105 MonoReflectionModule *res;
5108 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5109 if (!System_Reflection_Module)
5110 System_Reflection_Module = mono_class_from_name (
5111 mono_defaults.corlib, "System.Reflection", "Module");
5112 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5115 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5117 res->fqname = mono_string_new (domain, image->name);
5118 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5119 res->scopename = mono_string_new (domain, image->module_name);
5123 if (image->assembly->image == image) {
5124 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5127 g_assert (image->assembly->image->modules);
5129 for (i = 0; i < image->assembly->image->module_count; i++) {
5130 if (image->assembly->image->modules [i] == image)
5131 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5133 g_assert (res->token);
5136 mono_image_addref (image);
5138 CACHE_OBJECT (image, res, NULL);
5142 MonoReflectionModule*
5143 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5145 static MonoClass *System_Reflection_Module;
5146 MonoReflectionModule *res;
5147 MonoTableInfo *table;
5148 guint32 cols [MONO_FILE_SIZE];
5150 guint32 i, name_idx;
5153 if (!System_Reflection_Module)
5154 System_Reflection_Module = mono_class_from_name (
5155 mono_defaults.corlib, "System.Reflection", "Module");
5156 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5158 table = &image->tables [MONO_TABLE_FILE];
5159 g_assert (table_index < table->rows);
5160 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5163 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5164 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5166 /* Check whenever the row has a corresponding row in the moduleref table */
5167 table = &image->tables [MONO_TABLE_MODULEREF];
5168 for (i = 0; i < table->rows; ++i) {
5169 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5170 val = mono_metadata_string_heap (image, name_idx);
5171 if (strcmp (val, name) == 0)
5172 res->image = image->modules [i];
5175 res->fqname = mono_string_new (domain, name);
5176 res->name = mono_string_new (domain, name);
5177 res->scopename = mono_string_new (domain, name);
5178 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5179 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5185 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5187 if ((t1->type != t2->type) ||
5188 (t1->byref != t2->byref))
5192 case MONO_TYPE_VOID:
5193 case MONO_TYPE_BOOLEAN:
5194 case MONO_TYPE_CHAR:
5205 case MONO_TYPE_STRING:
5208 case MONO_TYPE_OBJECT:
5209 case MONO_TYPE_TYPEDBYREF:
5211 case MONO_TYPE_VALUETYPE:
5212 case MONO_TYPE_CLASS:
5213 case MONO_TYPE_SZARRAY:
5214 return t1->data.klass == t2->data.klass;
5216 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5217 case MONO_TYPE_ARRAY:
5218 if (t1->data.array->rank != t2->data.array->rank)
5220 return t1->data.array->eklass == t2->data.array->eklass;
5221 case MONO_TYPE_GENERICINST: {
5223 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5225 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5226 &t2->data.generic_class->container_class->byval_arg))
5228 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5229 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5235 case MONO_TYPE_MVAR:
5236 return t1->data.generic_param == t2->data.generic_param;
5238 g_error ("implement type compare for %0x!", t1->type);
5246 mymono_metadata_type_hash (MonoType *t1)
5252 hash |= t1->byref << 6; /* do not collide with t1->type values */
5254 case MONO_TYPE_VALUETYPE:
5255 case MONO_TYPE_CLASS:
5256 case MONO_TYPE_SZARRAY:
5257 /* check if the distribution is good enough */
5258 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5260 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5265 static MonoReflectionGenericClass*
5266 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5268 static MonoClass *System_Reflection_MonoGenericClass;
5269 MonoReflectionGenericClass *res;
5270 MonoGenericClass *gclass;
5273 if (!System_Reflection_MonoGenericClass) {
5274 System_Reflection_MonoGenericClass = mono_class_from_name (
5275 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5276 g_assert (System_Reflection_MonoGenericClass);
5279 gclass = geninst->data.generic_class;
5280 gklass = gclass->container_class;
5282 mono_class_init (gclass->klass);
5284 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5286 res->type.type = geninst;
5287 if (gklass->wastypebuilder && gklass->reflection_info)
5288 res->generic_type = gklass->reflection_info;
5290 res->generic_type = mono_type_get_object (domain, &gclass->container_class->byval_arg);
5296 * mono_type_get_object:
5297 * @domain: an app domain
5300 * Return an System.MonoType object representing the type @type.
5303 mono_type_get_object (MonoDomain *domain, MonoType *type)
5305 MonoReflectionType *res;
5306 MonoClass *klass = mono_class_from_mono_type (type);
5308 mono_domain_lock (domain);
5309 if (!domain->type_hash)
5310 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5311 (GCompareFunc)mymono_metadata_type_equal);
5312 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5313 mono_domain_unlock (domain);
5316 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5317 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5318 mono_g_hash_table_insert (domain->type_hash, type, res);
5319 mono_domain_unlock (domain);
5322 if (klass->reflection_info && !klass->wastypebuilder) {
5323 /* g_assert_not_reached (); */
5324 /* should this be considered an error condition? */
5326 mono_domain_unlock (domain);
5327 return klass->reflection_info;
5330 mono_class_init (klass);
5331 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5333 mono_g_hash_table_insert (domain->type_hash, type, res);
5334 mono_domain_unlock (domain);
5339 * mono_method_get_object:
5340 * @domain: an app domain
5342 * @refclass: the reflected type (can be NULL)
5344 * Return an System.Reflection.MonoMethod object representing the method @method.
5346 MonoReflectionMethod*
5347 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5350 * We use the same C representation for methods and constructors, but the type
5351 * name in C# is different.
5355 MonoReflectionMethod *ret;
5357 if (method->is_inflated) {
5358 MonoReflectionGenericMethod *gret;
5360 refclass = method->klass;
5361 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5362 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5363 cname = "MonoGenericCMethod";
5365 cname = "MonoGenericMethod";
5366 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5368 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5369 gret->method.method = method;
5370 gret->method.name = mono_string_new (domain, method->name);
5371 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5372 CACHE_OBJECT (method, gret, refclass);
5373 return (MonoReflectionMethod *) gret;
5377 refclass = method->klass;
5379 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5380 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5381 cname = "MonoCMethod";
5383 cname = "MonoMethod";
5384 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5386 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5387 ret->method = method;
5388 ret->name = mono_string_new (domain, method->name);
5389 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5390 CACHE_OBJECT (method, ret, refclass);
5395 * mono_field_get_object:
5396 * @domain: an app domain
5400 * Return an System.Reflection.MonoField object representing the field @field
5403 MonoReflectionField*
5404 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5406 MonoReflectionField *res;
5409 CHECK_OBJECT (MonoReflectionField *, field, klass);
5410 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5411 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5414 res->name = mono_string_new (domain, field->name);
5415 if (field->generic_info)
5416 res->attrs = field->generic_info->generic_type->attrs;
5418 res->attrs = field->type->attrs;
5419 res->type = mono_type_get_object (domain, field->type);
5420 CACHE_OBJECT (field, res, klass);
5425 * mono_property_get_object:
5426 * @domain: an app domain
5428 * @property: a property
5430 * Return an System.Reflection.MonoProperty object representing the property @property
5433 MonoReflectionProperty*
5434 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5436 MonoReflectionProperty *res;
5439 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5440 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5441 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5443 res->property = property;
5444 CACHE_OBJECT (property, res, klass);
5449 * mono_event_get_object:
5450 * @domain: an app domain
5454 * Return an System.Reflection.MonoEvent object representing the event @event
5457 MonoReflectionEvent*
5458 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5460 MonoReflectionEvent *res;
5463 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5464 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5465 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5468 CACHE_OBJECT (event, res, klass);
5473 * mono_param_get_objects:
5474 * @domain: an app domain
5477 * Return an System.Reflection.ParameterInfo array object representing the parameters
5478 * in the method @method.
5481 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5483 static MonoClass *System_Reflection_ParameterInfo;
5484 MonoArray *res = NULL;
5485 MonoReflectionMethod *member = NULL;
5486 MonoReflectionParameter *param = NULL;
5487 char **names, **blobs = NULL;
5488 MonoObject *dbnull = mono_get_dbnull_object (domain);
5489 MonoMarshalSpec **mspecs;
5492 if (!System_Reflection_ParameterInfo)
5493 System_Reflection_ParameterInfo = mono_class_from_name (
5494 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5496 if (!method->signature->param_count)
5497 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5499 /* Note: the cache is based on the address of the signature into the method
5500 * since we already cache MethodInfos with the method as keys.
5502 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5504 member = mono_method_get_object (domain, method, NULL);
5505 names = g_new (char *, method->signature->param_count);
5506 mono_method_get_param_names (method, (const char **) names);
5508 mspecs = g_new (MonoMarshalSpec*, method->signature->param_count + 1);
5509 mono_method_get_marshal_info (method, mspecs);
5511 res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5512 for (i = 0; i < method->signature->param_count; ++i) {
5513 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5514 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5515 param->MemberImpl = (MonoObject*)member;
5516 param->NameImpl = mono_string_new (domain, names [i]);
5517 param->PositionImpl = i;
5518 param->AttrsImpl = method->signature->params [i]->attrs;
5520 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5521 param->DefaultValueImpl = dbnull;
5523 MonoType *type = param->ClassImpl->type;
5526 blobs = g_new0 (char *, method->signature->param_count);
5527 get_default_param_value_blobs (method, blobs);
5530 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5532 if (!param->DefaultValueImpl) {
5533 param->DefaultValueImpl = dbnull;
5538 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5540 mono_array_set (res, gpointer, i, param);
5545 for (i = method->signature->param_count; i >= 0; i--)
5547 mono_metadata_free_marshal_spec (mspecs [i]);
5550 CACHE_OBJECT (&(method->signature), res, NULL);
5555 * mono_method_body_get_object:
5556 * @domain: an app domain
5559 * Return an System.Reflection.MethodBody object representing the method @method.
5561 MonoReflectionMethodBody*
5562 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5564 static MonoClass *System_Reflection_MethodBody = NULL;
5565 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5566 MonoReflectionMethodBody *ret;
5567 MonoMethodNormal *mn;
5568 MonoMethodHeader *header;
5569 guint32 method_rva, local_var_sig_token;
5571 unsigned char format, flags;
5574 if (!System_Reflection_MethodBody)
5575 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5576 if (!System_Reflection_LocalVariableInfo)
5577 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5579 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5581 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5582 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5583 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5584 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5586 mn = (MonoMethodNormal *)method;
5587 header = mono_method_get_header (method);
5589 /* Obtain local vars signature token */
5590 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5591 ptr = mono_image_rva_map (method->klass->image, method_rva);
5592 flags = *(const unsigned char *) ptr;
5593 format = flags & METHOD_HEADER_FORMAT_MASK;
5595 case METHOD_HEADER_TINY_FORMAT:
5596 case METHOD_HEADER_TINY_FORMAT1:
5597 local_var_sig_token = 0;
5599 case METHOD_HEADER_FAT_FORMAT:
5603 local_var_sig_token = read32 (ptr);
5606 g_assert_not_reached ();
5609 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5610 /* FIXME: Other fields */
5611 ret->init_locals = header->init_locals;
5612 ret->max_stack = header->max_stack;
5613 ret->local_var_sig_token = local_var_sig_token;
5614 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5615 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5616 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5617 for (i = 0; i < header->num_locals; ++i) {
5618 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5619 info->local_type = mono_type_get_object (domain, header->locals [i]);
5620 info->is_pinned = header->locals [i]->pinned;
5621 info->local_index = i;
5622 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5625 CACHE_OBJECT (method, ret, NULL);
5630 mono_get_dbnull_object (MonoDomain *domain)
5634 static MonoClassField *dbnull_value_field = NULL;
5636 if (!dbnull_value_field) {
5637 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5638 mono_class_init (klass);
5639 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5640 g_assert (dbnull_value_field);
5642 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5649 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5651 guint32 param_index, i, lastp, crow = 0;
5652 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5655 MonoClass *klass = method->klass;
5656 MonoImage *image = klass->image;
5657 MonoMethodSignature *methodsig = method->signature;
5659 MonoTableInfo *constt;
5660 MonoTableInfo *methodt;
5661 MonoTableInfo *paramt;
5663 if (!methodsig->param_count)
5666 if (klass->generic_class) {
5667 return; /* FIXME - ??? */
5670 mono_class_init (klass);
5672 if (klass->image->dynamic) {
5673 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5674 if (aux && aux->param_defaults)
5675 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5679 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5680 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5681 constt = &image->tables [MONO_TABLE_CONSTANT];
5683 for (i = 0; i < klass->method.count; ++i) {
5684 if (method == klass->methods [i]) {
5685 idx = klass->method.first + i;
5690 g_assert (idx != -1);
5692 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5693 if (idx + 1 < methodt->rows)
5694 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5696 lastp = paramt->rows + 1;
5698 for (i = param_index; i < lastp; ++i) {
5701 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5702 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5704 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5707 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5712 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5713 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5720 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5729 klass = mono_class_from_mono_type (type);
5730 if (klass->valuetype) {
5731 object = mono_object_new (domain, klass);
5732 retval = ((gchar *) object + sizeof (MonoObject));
5737 if (!mono_get_constant_value_from_blob (domain, type->type, blob, retval))
5744 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5748 memset (assembly, 0, sizeof (MonoAssemblyName));
5750 assembly->culture = "";
5751 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5753 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5756 while (g_ascii_isspace (*p) || *p == ',') {
5765 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5767 assembly->major = strtoul (p, &s, 10);
5768 if (s == p || *s != '.')
5771 assembly->minor = strtoul (p, &s, 10);
5772 if (s == p || *s != '.')
5775 assembly->build = strtoul (p, &s, 10);
5776 if (s == p || *s != '.')
5779 assembly->revision = strtoul (p, &s, 10);
5783 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5785 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5786 assembly->culture = "";
5789 assembly->culture = p;
5790 while (*p && *p != ',') {
5794 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5796 if (strncmp (p, "null", 4) == 0) {
5801 while (*p && *p != ',') {
5804 len = (p - start + 1);
5805 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5806 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5807 g_strlcpy (assembly->public_key_token, start, len);
5810 while (*p && *p != ',')
5814 while (g_ascii_isspace (*p) || *p == ',') {
5828 * mono_reflection_parse_type:
5831 * Parse a type name as accepted by the GetType () method and output the info
5832 * extracted in the info structure.
5833 * the name param will be mangled, so, make a copy before passing it to this function.
5834 * The fields in info will be valid until the memory pointed to by name is valid.
5836 * See also mono_type_get_name () below.
5838 * Returns: 0 on parse error.
5841 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5843 char *start, *p, *w, *last_point, *startn;
5844 int in_modifiers = 0;
5845 int isbyref = 0, rank;
5847 start = p = w = name;
5849 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5850 info->name = info->name_space = NULL;
5851 info->nested = NULL;
5852 info->modifiers = NULL;
5854 /* last_point separates the namespace from the name */
5860 *p = 0; /* NULL terminate the name */
5862 info->nested = g_list_append (info->nested, startn);
5863 /* we have parsed the nesting namespace + name */
5867 info->name_space = start;
5869 info->name = last_point + 1;
5871 info->name_space = (char *)"";
5897 info->name_space = start;
5899 info->name = last_point + 1;
5901 info->name_space = (char *)"";
5908 if (isbyref) /* only one level allowed by the spec */
5911 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5915 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5926 else if (*p != '*') /* '*' means unknown lower bound */
5932 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5937 if (g_ascii_isspace (*p)) {
5944 return 0; /* missing assembly name */
5945 if (!assembly_name_to_aname (&info->assembly, p))
5952 if (info->assembly.name)
5955 *w = 0; /* terminate class name */
5956 if (!info->name || !*info->name)
5958 /* add other consistency checks */
5963 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5970 image = mono_defaults.corlib;
5973 klass = mono_class_from_name_case (image, info->name_space, info->name);
5975 klass = mono_class_from_name (image, info->name_space, info->name);
5978 for (mod = info->nested; mod; mod = mod->next) {
5981 mono_class_init (klass);
5982 nested = klass->nested_classes;
5985 klass = nested->data;
5987 if (g_strcasecmp (klass->name, mod->data) == 0)
5990 if (strcmp (klass->name, mod->data) == 0)
5994 nested = nested->next;
6001 mono_class_init (klass);
6002 for (mod = info->modifiers; mod; mod = mod->next) {
6003 modval = GPOINTER_TO_UINT (mod->data);
6004 if (!modval) { /* byref: must be last modifier */
6005 return &klass->this_arg;
6006 } else if (modval == -1) {
6007 klass = mono_ptr_class_get (&klass->byval_arg);
6008 } else { /* array rank */
6009 klass = mono_array_class_get (klass, modval);
6011 mono_class_init (klass);
6014 return &klass->byval_arg;
6018 * mono_reflection_get_type:
6019 * @image: a metadata context
6020 * @info: type description structure
6021 * @ignorecase: flag for case-insensitive string compares
6022 * @type_resolve: whenever type resolve was already tried
6024 * Build a MonoType from the type description in @info.
6029 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6032 MonoReflectionAssembly *assembly;
6036 type = mono_reflection_get_type_internal (image, info, ignorecase);
6039 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6046 *type_resolve = TRUE;
6049 /* Reconstruct the type name */
6050 fullName = g_string_new ("");
6051 if (info->name_space && (info->name_space [0] != '\0'))
6052 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6054 g_string_printf (fullName, info->name);
6055 for (mod = info->nested; mod; mod = mod->next)
6056 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6058 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6060 if (assembly->assembly->dynamic) {
6061 /* Enumerate all modules */
6062 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6066 if (abuilder->modules) {
6067 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6068 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6069 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6075 if (!type && abuilder->loaded_modules) {
6076 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6077 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6078 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6085 type = mono_reflection_get_type_internal (assembly->assembly->image,
6088 g_string_free (fullName, TRUE);
6093 * mono_reflection_type_from_name:
6095 * @image: a metadata context (can be NULL).
6097 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6098 * it defaults to get the type from @image or, if @image is NULL or loading
6099 * from it fails, uses corlib.
6103 mono_reflection_type_from_name (char *name, MonoImage *image)
6106 MonoTypeNameParse info;
6107 MonoAssembly *assembly;
6109 gboolean type_resolve = FALSE;
6111 /* Make a copy since parse_type modifies its argument */
6112 tmp = g_strdup (name);
6114 /*g_print ("requested type %s\n", str);*/
6115 if (!mono_reflection_parse_type (tmp, &info)) {
6117 g_list_free (info.modifiers);
6118 g_list_free (info.nested);
6122 if (info.assembly.name) {
6123 assembly = mono_assembly_loaded (&info.assembly);
6125 /* then we must load the assembly ourselve - see #60439 */
6126 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
6129 g_list_free (info.modifiers);
6130 g_list_free (info.nested);
6134 image = assembly->image;
6135 } else if (image == NULL) {
6136 image = mono_defaults.corlib;
6139 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6140 if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
6141 image = mono_defaults.corlib;
6142 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
6146 g_list_free (info.modifiers);
6147 g_list_free (info.nested);
6152 * mono_reflection_get_token:
6154 * Return the metadata token of OBJ which should be an object
6155 * representing a metadata element.
6158 mono_reflection_get_token (MonoObject *obj)
6163 klass = obj->vtable->klass;
6165 if (strcmp (klass->name, "MethodBuilder") == 0) {
6166 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6168 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6169 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6170 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6172 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6173 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6174 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6175 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6176 if (tb->generic_params) {
6177 g_assert_not_reached ();
6179 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6181 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6182 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6183 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6184 } else if (strcmp (klass->name, "MonoType") == 0) {
6185 MonoReflectionType *tb = (MonoReflectionType *)obj;
6186 token = mono_class_from_mono_type (tb->type)->type_token;
6187 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6188 strcmp (klass->name, "MonoMethod") == 0) {
6189 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6190 if (m->method->is_inflated) {
6191 g_assert_not_reached ();
6192 } else if (m->method->signature->generic_param_count) {
6193 g_assert_not_reached ();
6194 } else if (m->method->klass->generic_class) {
6195 g_assert_not_reached ();
6197 token = m->method->token;
6199 } else if (strcmp (klass->name, "MonoField") == 0) {
6200 MonoReflectionField *f = (MonoReflectionField*)obj;
6202 token = mono_class_get_field_token (f->field);
6203 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6204 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6206 token = mono_class_get_property_token (p->property);
6207 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6208 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6210 token = mono_class_get_event_token (p->event);
6211 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6212 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6214 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6215 } else if (strcmp (klass->name, "Module") == 0) {
6216 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6219 } else if (strcmp (klass->name, "Assembly") == 0) {
6220 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6222 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6223 MonoException *ex = mono_get_exception_not_implemented (msg);
6225 mono_raise_exception (ex);
6232 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6234 int slen, type = t->type;
6239 case MONO_TYPE_BOOLEAN: {
6240 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6245 case MONO_TYPE_CHAR:
6247 case MONO_TYPE_I2: {
6248 guint16 *val = g_malloc (sizeof (guint16));
6253 #if SIZEOF_VOID_P == 4
6259 case MONO_TYPE_I4: {
6260 guint32 *val = g_malloc (sizeof (guint32));
6265 #if SIZEOF_VOID_P == 8
6266 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6271 case MONO_TYPE_I8: {
6272 guint64 *val = g_malloc (sizeof (guint64));
6277 case MONO_TYPE_VALUETYPE:
6278 if (t->data.klass->enumtype) {
6279 type = t->data.klass->enum_basetype->type;
6282 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6285 case MONO_TYPE_STRING:
6286 if (*p == (char)0xFF) {
6290 slen = mono_metadata_decode_value (p, &p);
6292 return mono_string_new_len (mono_domain_get (), p, slen);
6293 case MONO_TYPE_CLASS: {
6296 if (*p == (char)0xFF) {
6301 slen = mono_metadata_decode_value (p, &p);
6302 n = g_memdup (p, slen + 1);
6304 t = mono_reflection_type_from_name (n, image);
6306 g_warning ("Cannot load type '%s'", n);
6310 return mono_type_get_object (mono_domain_get (), t);
6314 case MONO_TYPE_OBJECT: {
6317 MonoClass *subc = NULL;
6322 } else if (subt == 0x0E) {
6323 type = MONO_TYPE_STRING;
6325 } else if (subt == 0x55) {
6328 slen = mono_metadata_decode_value (p, &p);
6329 n = g_memdup (p, slen + 1);
6331 t = mono_reflection_type_from_name (n, image);
6333 g_warning ("Cannot load type '%s'", n);
6336 subc = mono_class_from_mono_type (t);
6337 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6338 MonoType simple_type = {{0}};
6339 simple_type.type = subt;
6340 subc = mono_class_from_mono_type (&simple_type);
6342 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6344 val = load_cattr_value (image, &subc->byval_arg, p, end);
6345 obj = mono_object_new (mono_domain_get (), subc);
6346 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6350 case MONO_TYPE_SZARRAY: {
6352 guint32 i, alen, basetype;
6355 if (alen == 0xffffffff) {
6359 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6360 basetype = t->data.klass->byval_arg.type;
6365 case MONO_TYPE_BOOLEAN:
6366 for (i = 0; i < alen; i++) {
6367 MonoBoolean val = *p++;
6368 mono_array_set (arr, MonoBoolean, i, val);
6371 case MONO_TYPE_CHAR:
6374 for (i = 0; i < alen; i++) {
6375 guint16 val = read16 (p);
6376 mono_array_set (arr, guint16, i, val);
6383 for (i = 0; i < alen; i++) {
6384 guint32 val = read32 (p);
6385 mono_array_set (arr, guint32, i, val);
6392 for (i = 0; i < alen; i++) {
6393 guint64 val = read64 (p);
6394 mono_array_set (arr, guint64, i, val);
6398 case MONO_TYPE_CLASS:
6399 case MONO_TYPE_OBJECT:
6400 case MONO_TYPE_STRING:
6401 for (i = 0; i < alen; i++) {
6402 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6403 mono_array_set (arr, gpointer, i, item);
6407 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6413 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6419 type_is_reference (MonoType *type)
6421 switch (type->type) {
6422 case MONO_TYPE_BOOLEAN:
6423 case MONO_TYPE_CHAR:
6436 case MONO_TYPE_VALUETYPE:
6444 free_param_data (MonoMethodSignature *sig, void **params) {
6446 for (i = 0; i < sig->param_count; ++i) {
6447 if (!type_is_reference (sig->params [i]))
6448 g_free (params [i]);
6453 * Find the method index in the metadata methodDef table.
6454 * Later put these three helper methods in metadata and export them.
6457 find_method_index (MonoMethod *method) {
6458 MonoClass *klass = method->klass;
6461 for (i = 0; i < klass->method.count; ++i) {
6462 if (method == klass->methods [i])
6463 return klass->method.first + 1 + i;
6469 * Find the field index in the metadata FieldDef table.
6472 find_field_index (MonoClass *klass, MonoClassField *field) {
6475 for (i = 0; i < klass->field.count; ++i) {
6476 if (field == &klass->fields [i])
6477 return klass->field.first + 1 + i;
6483 * Find the property index in the metadata Property table.
6486 find_property_index (MonoClass *klass, MonoProperty *property) {
6489 for (i = 0; i < klass->property.count; ++i) {
6490 if (property == &klass->properties [i])
6491 return klass->property.first + 1 + i;
6497 * Find the event index in the metadata Event table.
6500 find_event_index (MonoClass *klass, MonoEvent *event) {
6503 for (i = 0; i < klass->event.count; ++i) {
6504 if (event == &klass->events [i])
6505 return klass->event.first + 1 + i;
6511 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6513 const char *p = data;
6515 guint32 i, j, num_named;
6519 mono_class_init (method->klass);
6522 attr = mono_object_new (mono_domain_get (), method->klass);
6523 mono_runtime_invoke (method, attr, NULL, NULL);
6527 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6530 /*g_print ("got attr %s\n", method->klass->name);*/
6532 params = g_new (void*, method->signature->param_count);
6536 for (i = 0; i < method->signature->param_count; ++i) {
6537 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6541 attr = mono_object_new (mono_domain_get (), method->klass);
6542 mono_runtime_invoke (method, attr, params, NULL);
6543 free_param_data (method->signature, params);
6545 num_named = read16 (named);
6547 for (j = 0; j < num_named; j++) {
6549 char *name, named_type, data_type;
6550 named_type = *named++;
6551 data_type = *named++; /* type of data */
6552 if (data_type == 0x55) {
6555 type_len = mono_metadata_decode_blob_size (named, &named);
6556 type_name = g_malloc (type_len + 1);
6557 memcpy (type_name, named, type_len);
6558 type_name [type_len] = 0;
6560 /* FIXME: lookup the type and check type consistency */
6561 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6562 /* this seems to be the type of the element of the array */
6563 /* g_print ("skipping 0x%02x after prop\n", *named); */
6566 name_len = mono_metadata_decode_blob_size (named, &named);
6567 name = g_malloc (name_len + 1);
6568 memcpy (name, named, name_len);
6569 name [name_len] = 0;
6571 if (named_type == 0x53) {
6572 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6573 void *val = load_cattr_value (image, field->type, named, &named);
6574 mono_field_set_value (attr, field, val);
6575 if (!type_is_reference (field->type))
6577 } else if (named_type == 0x54) {
6580 MonoType *prop_type;
6582 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6583 /* can we have more that 1 arg in a custom attr named property? */
6584 prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6585 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6586 mono_property_set_value (prop, attr, pparams, NULL);
6587 if (!type_is_reference (prop_type))
6588 g_free (pparams [0]);
6597 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6604 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6605 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6606 for (i = 0; i < cinfo->num_attrs; ++i) {
6607 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6608 mono_array_set (result, gpointer, i, attr);
6614 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6616 guint32 mtoken, i, len;
6617 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6619 MonoCustomAttrInfo *ainfo;
6620 GList *tmp, *list = NULL;
6623 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6625 i = mono_metadata_custom_attrs_from_index (image, idx);
6629 while (i < ca->rows) {
6630 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6632 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6635 len = g_list_length (list);
6638 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6639 ainfo->num_attrs = len;
6640 ainfo->image = image;
6641 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6642 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6643 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6644 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6645 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6646 mtoken |= MONO_TOKEN_METHOD_DEF;
6648 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6649 mtoken |= MONO_TOKEN_MEMBER_REF;
6652 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6655 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6656 if (!ainfo->attrs [i].ctor)
6657 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6658 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6659 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6660 ainfo->attrs [i].data = data;
6668 mono_custom_attrs_from_method (MonoMethod *method)
6670 MonoCustomAttrInfo *cinfo;
6673 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6675 idx = find_method_index (method);
6676 idx <<= MONO_CUSTOM_ATTR_BITS;
6677 idx |= MONO_CUSTOM_ATTR_METHODDEF;
6678 return mono_custom_attrs_from_index (method->klass->image, idx);
6682 mono_custom_attrs_from_class (MonoClass *klass)
6684 MonoCustomAttrInfo *cinfo;
6687 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6689 idx = mono_metadata_token_index (klass->type_token);
6690 idx <<= MONO_CUSTOM_ATTR_BITS;
6691 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6692 return mono_custom_attrs_from_index (klass->image, idx);
6696 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6698 MonoCustomAttrInfo *cinfo;
6701 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6703 idx = 1; /* there is only one assembly */
6704 idx <<= MONO_CUSTOM_ATTR_BITS;
6705 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6706 return mono_custom_attrs_from_index (assembly->image, idx);
6709 static MonoCustomAttrInfo*
6710 mono_custom_attrs_from_module (MonoImage *image)
6712 MonoCustomAttrInfo *cinfo;
6715 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6717 idx = 1; /* there is only one module */
6718 idx <<= MONO_CUSTOM_ATTR_BITS;
6719 idx |= MONO_CUSTOM_ATTR_MODULE;
6720 return mono_custom_attrs_from_index (image, idx);
6724 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6726 MonoCustomAttrInfo *cinfo;
6729 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6731 idx = find_property_index (klass, property);
6732 idx <<= MONO_CUSTOM_ATTR_BITS;
6733 idx |= MONO_CUSTOM_ATTR_PROPERTY;
6734 return mono_custom_attrs_from_index (klass->image, idx);
6738 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6740 MonoCustomAttrInfo *cinfo;
6743 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6745 idx = find_event_index (klass, event);
6746 idx <<= MONO_CUSTOM_ATTR_BITS;
6747 idx |= MONO_CUSTOM_ATTR_EVENT;
6748 return mono_custom_attrs_from_index (klass->image, idx);
6752 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6754 MonoCustomAttrInfo *cinfo;
6757 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6759 idx = find_field_index (klass, field);
6760 idx <<= MONO_CUSTOM_ATTR_BITS;
6761 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6762 return mono_custom_attrs_from_index (klass->image, idx);
6766 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6769 guint32 i, idx, method_index;
6770 guint32 param_list, param_last, param_pos, found;
6772 MonoReflectionMethodAux *aux;
6774 if (method->klass->image->dynamic) {
6775 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6776 if (!aux || !aux->param_cattr)
6778 return aux->param_cattr [param];
6781 image = method->klass->image;
6782 method_index = find_method_index (method);
6783 ca = &image->tables [MONO_TABLE_METHOD];
6785 if (method->klass->generic_class || method->signature->generic_param_count) {
6786 /* FIXME FIXME FIXME */
6790 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6791 if (method_index == ca->rows) {
6792 ca = &image->tables [MONO_TABLE_PARAM];
6793 param_last = ca->rows + 1;
6795 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6796 ca = &image->tables [MONO_TABLE_PARAM];
6799 for (i = param_list; i < param_last; ++i) {
6800 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6801 if (param_pos == param) {
6809 idx <<= MONO_CUSTOM_ATTR_BITS;
6810 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6811 return mono_custom_attrs_from_index (image, idx);
6815 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
6819 for (i = 0; i < ainfo->num_attrs; ++i) {
6820 klass = ainfo->attrs [i].ctor->klass;
6821 if (mono_class_has_parent (klass, attr_klass))
6828 * mono_reflection_get_custom_attrs_info:
6829 * @obj: a reflection object handle
6831 * Return the custom attribute info for attributes defined for the
6832 * reflection handle @obj. The objects.
6835 mono_reflection_get_custom_attrs_info (MonoObject *obj)
6838 MonoCustomAttrInfo *cinfo = NULL;
6840 klass = obj->vtable->klass;
6841 if (klass == mono_defaults.monotype_class) {
6842 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6843 klass = mono_class_from_mono_type (rtype->type);
6844 cinfo = mono_custom_attrs_from_class (klass);
6845 } else if (strcmp ("Assembly", klass->name) == 0) {
6846 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6847 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6848 } else if (strcmp ("Module", klass->name) == 0) {
6849 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6850 cinfo = mono_custom_attrs_from_module (module->image);
6851 } else if (strcmp ("MonoProperty", klass->name) == 0) {
6852 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6853 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6854 } else if (strcmp ("MonoEvent", klass->name) == 0) {
6855 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6856 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6857 } else if (strcmp ("MonoField", klass->name) == 0) {
6858 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6859 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6860 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6861 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6862 cinfo = mono_custom_attrs_from_method (rmethod->method);
6863 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
6864 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
6865 cinfo = mono_custom_attrs_from_method (method);
6866 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6867 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6868 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6869 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6870 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6871 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6872 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6873 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6874 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6875 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6876 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
6877 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
6878 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
6879 } else { /* handle other types here... */
6880 g_error ("get custom attrs not yet supported for %s", klass->name);
6887 * mono_reflection_get_custom_attrs:
6888 * @obj: a reflection object handle
6890 * Return an array with all the custom attributes defined of the
6891 * reflection handle @obj. The objects are fully build.
6894 mono_reflection_get_custom_attrs (MonoObject *obj)
6897 MonoCustomAttrInfo *cinfo;
6899 cinfo = mono_reflection_get_custom_attrs_info (obj);
6901 result = mono_custom_attrs_construct (cinfo);
6903 mono_custom_attrs_free (cinfo);
6906 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6907 result = mono_array_new (mono_domain_get (), klass, 0);
6913 static MonoMethodSignature*
6914 parameters_to_signature (MonoArray *parameters) {
6915 MonoMethodSignature *sig;
6918 count = parameters? mono_array_length (parameters): 0;
6920 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6921 sig->param_count = count;
6922 sig->sentinelpos = -1; /* FIXME */
6923 for (i = 0; i < count; ++i) {
6924 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6925 sig->params [i] = pt->type;
6930 static MonoMethodSignature*
6931 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6932 MonoMethodSignature *sig;
6934 sig = parameters_to_signature (ctor->parameters);
6935 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6936 sig->ret = &mono_defaults.void_class->byval_arg;
6940 static MonoMethodSignature*
6941 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6942 MonoMethodSignature *sig;
6944 sig = parameters_to_signature (method->parameters);
6945 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6946 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6947 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6951 static MonoMethodSignature*
6952 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6953 MonoMethodSignature *sig;
6955 sig = parameters_to_signature (method->parameters);
6956 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6957 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6958 sig->generic_param_count = 0;
6963 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6965 MonoClass *klass = mono_object_class (prop);
6966 if (strcmp (klass->name, "PropertyBuilder") == 0) {
6967 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6968 *name = mono_string_to_utf8 (pb->name);
6969 *type = pb->type->type;
6971 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6972 *name = g_strdup (p->property->name);
6973 if (p->property->get)
6974 *type = p->property->get->signature->ret;
6976 *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6981 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6983 MonoClass *klass = mono_object_class (field);
6984 if (strcmp (klass->name, "FieldBuilder") == 0) {
6985 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6986 *name = mono_string_to_utf8 (fb->name);
6987 *type = fb->type->type;
6989 MonoReflectionField *f = (MonoReflectionField *)field;
6990 *name = g_strdup (f->field->name);
6991 *type = f->field->type;
6996 * Encode a value in a custom attribute stream of bytes.
6997 * The value to encode is either supplied as an object in argument val
6998 * (valuetypes are boxed), or as a pointer to the data in the
7000 * @type represents the type of the value
7001 * @buffer is the start of the buffer
7002 * @p the current position in the buffer
7003 * @buflen contains the size of the buffer and is used to return the new buffer size
7004 * if this needs to be realloced.
7005 * @retbuffer and @retp return the start and the position of the buffer
7008 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7010 MonoTypeEnum simple_type;
7012 if ((p-buffer) + 10 >= *buflen) {
7015 newbuf = g_realloc (buffer, *buflen);
7016 p = newbuf + (p-buffer);
7020 argval = ((char*)arg + sizeof (MonoObject));
7021 simple_type = type->type;
7023 switch (simple_type) {
7024 case MONO_TYPE_BOOLEAN:
7029 case MONO_TYPE_CHAR:
7032 swap_with_size (p, argval, 2, 1);
7038 swap_with_size (p, argval, 4, 1);
7044 swap_with_size (p, argval, 8, 1);
7047 case MONO_TYPE_VALUETYPE:
7048 if (type->data.klass->enumtype) {
7049 simple_type = type->data.klass->enum_basetype->type;
7052 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7055 case MONO_TYPE_STRING: {
7062 str = mono_string_to_utf8 ((MonoString*)arg);
7063 slen = strlen (str);
7064 if ((p-buffer) + 10 + slen >= *buflen) {
7068 newbuf = g_realloc (buffer, *buflen);
7069 p = newbuf + (p-buffer);
7072 mono_metadata_encode_value (slen, p, &p);
7073 memcpy (p, str, slen);
7078 case MONO_TYPE_CLASS: {
7086 k = mono_object_class (arg);
7087 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7088 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7089 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7091 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7092 slen = strlen (str);
7093 if ((p-buffer) + 10 + slen >= *buflen) {
7097 newbuf = g_realloc (buffer, *buflen);
7098 p = newbuf + (p-buffer);
7101 mono_metadata_encode_value (slen, p, &p);
7102 memcpy (p, str, slen);
7107 case MONO_TYPE_SZARRAY: {
7109 MonoClass *eclass, *arg_eclass;
7112 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7115 len = mono_array_length ((MonoArray*)arg);
7117 *p++ = (len >> 8) & 0xff;
7118 *p++ = (len >> 16) & 0xff;
7119 *p++ = (len >> 24) & 0xff;
7121 *retbuffer = buffer;
7122 eclass = type->data.klass;
7123 arg_eclass = mono_object_class (arg)->element_class;
7124 if (eclass->valuetype && arg_eclass->valuetype) {
7125 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7126 int elsize = mono_class_array_element_size (eclass);
7127 for (i = 0; i < len; ++i) {
7128 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7132 for (i = 0; i < len; ++i) {
7133 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7138 /* it may be a boxed value or a Type */
7139 case MONO_TYPE_OBJECT: {
7145 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7150 klass = mono_object_class (arg);
7152 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7155 } else if (klass->enumtype) {
7157 } else if (klass == mono_defaults.string_class) {
7158 simple_type = MONO_TYPE_STRING;
7161 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7162 *p++ = simple_type = klass->byval_arg.type;
7165 g_error ("unhandled type in custom attr");
7167 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7168 slen = strlen (str);
7169 if ((p-buffer) + 10 + slen >= *buflen) {
7173 newbuf = g_realloc (buffer, *buflen);
7174 p = newbuf + (p-buffer);
7177 mono_metadata_encode_value (slen, p, &p);
7178 memcpy (p, str, slen);
7181 simple_type = klass->enum_basetype->type;
7185 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7188 *retbuffer = buffer;
7192 * mono_reflection_get_custom_attrs_blob:
7193 * @ctor: custom attribute constructor
7194 * @ctorArgs: arguments o the constructor
7200 * Creates the blob of data that needs to be saved in the metadata and that represents
7201 * the custom attributed described by @ctor, @ctorArgs etc.
7202 * Returns: a Byte array representing the blob of data.
7205 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7208 MonoMethodSignature *sig;
7213 MONO_ARCH_SAVE_REGS;
7215 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7216 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7218 sig = ((MonoReflectionMethod*)ctor)->method->signature;
7220 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7222 p = buffer = g_malloc (buflen);
7223 /* write the prolog */
7226 for (i = 0; i < sig->param_count; ++i) {
7227 arg = mono_array_get (ctorArgs, MonoObject*, i);
7228 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7232 i += mono_array_length (properties);
7234 i += mono_array_length (fields);
7236 *p++ = (i >> 8) & 0xff;
7239 for (i = 0; i < mono_array_length (properties); ++i) {
7244 prop = mono_array_get (properties, gpointer, i);
7245 get_prop_name_and_type (prop, &pname, &ptype);
7246 *p++ = 0x54; /* PROPERTY signature */
7248 /* Preallocate a large enough buffer */
7249 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7250 char *str = type_get_qualified_name (ptype, NULL);
7256 len += strlen (pname);
7258 if ((p-buffer) + 20 + len >= buflen) {
7262 newbuf = g_realloc (buffer, buflen);
7263 p = newbuf + (p-buffer);
7267 if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7268 char *str = type_get_qualified_name (ptype, NULL);
7269 int slen = strlen (str);
7273 * This seems to be optional...
7276 mono_metadata_encode_value (slen, p, &p);
7277 memcpy (p, str, slen);
7281 mono_metadata_encode_value (ptype->type, p, &p);
7282 if (ptype->type == MONO_TYPE_SZARRAY)
7283 mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7285 len = strlen (pname);
7286 mono_metadata_encode_value (len, p, &p);
7287 memcpy (p, pname, len);
7289 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7296 for (i = 0; i < mono_array_length (fields); ++i) {
7301 field = mono_array_get (fields, gpointer, i);
7302 get_field_name_and_type (field, &fname, &ftype);
7303 *p++ = 0x53; /* FIELD signature */
7304 if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7305 char *str = type_get_qualified_name (ftype, NULL);
7306 int slen = strlen (str);
7307 if ((p-buffer) + 10 + slen >= buflen) {
7311 newbuf = g_realloc (buffer, buflen);
7312 p = newbuf + (p-buffer);
7317 * This seems to be optional...
7320 mono_metadata_encode_value (slen, p, &p);
7321 memcpy (p, str, slen);
7325 mono_metadata_encode_value (ftype->type, p, &p);
7326 if (ftype->type == MONO_TYPE_SZARRAY)
7327 mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7329 len = strlen (fname);
7330 mono_metadata_encode_value (len, p, &p);
7331 memcpy (p, fname, len);
7333 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7338 g_assert (p - buffer <= buflen);
7339 buflen = p - buffer;
7340 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7341 p = mono_array_addr (result, char, 0);
7342 memcpy (p, buffer, buflen);
7344 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7350 * mono_reflection_setup_internal_class:
7351 * @tb: a TypeBuilder object
7353 * Creates a MonoClass that represents the TypeBuilder.
7354 * This is a trick that lets us simplify a lot of reflection code
7355 * (and will allow us to support Build and Run assemblies easier).
7358 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7360 MonoClass *klass, *parent;
7362 MONO_ARCH_SAVE_REGS;
7365 /* check so we can compile corlib correctly */
7366 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7367 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7368 parent = tb->parent->type->data.klass;
7370 parent = my_mono_class_from_mono_type (tb->parent->type);
7376 /* the type has already being created: it means we just have to change the parent */
7377 if (tb->type.type) {
7378 klass = mono_class_from_mono_type (tb->type.type);
7379 klass->parent = NULL;
7380 /* fool mono_class_setup_parent */
7381 g_free (klass->supertypes);
7382 klass->supertypes = NULL;
7383 mono_class_setup_parent (klass, parent);
7384 mono_class_setup_mono_type (klass);
7388 klass = g_new0 (MonoClass, 1);
7390 klass->image = &tb->module->dynamic_image->image;
7392 klass->inited = 1; /* we lie to the runtime */
7393 klass->name = mono_string_to_utf8 (tb->name);
7394 klass->name_space = mono_string_to_utf8 (tb->nspace);
7395 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7396 klass->flags = tb->attrs;
7398 klass->element_class = klass;
7399 klass->reflection_info = tb; /* need to pin. */
7401 /* Put into cache so mono_class_get () will find it */
7402 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7404 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7405 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7407 if (parent != NULL) {
7408 mono_class_setup_parent (klass, parent);
7409 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7410 const char *old_n = klass->name;
7411 /* trick to get relative numbering right when compiling corlib */
7412 klass->name = "BuildingObject";
7413 mono_class_setup_parent (klass, mono_defaults.object_class);
7414 klass->name = old_n;
7417 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7418 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7419 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7420 klass->instance_size = sizeof (MonoObject);
7421 klass->size_inited = 1;
7422 mono_class_setup_vtable (klass, NULL, 0);
7425 mono_class_setup_mono_type (klass);
7427 mono_class_setup_supertypes (klass);
7430 * FIXME: handle interfaces.
7433 tb->type.type = &klass->byval_arg;
7435 if (tb->nesting_type) {
7436 g_assert (tb->nesting_type->type);
7437 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7440 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7444 * mono_reflection_setup_generic_class:
7445 * @tb: a TypeBuilder object
7447 * Setup the generic class before adding the first generic parameter.
7450 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7454 MONO_ARCH_SAVE_REGS;
7456 klass = my_mono_class_from_mono_type (tb->type.type);
7457 if (tb->generic_container)
7460 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7461 tb->generic_container->klass = klass;
7463 tb->generic_container->context.container = tb->generic_container;
7467 * mono_reflection_create_generic_class:
7468 * @tb: a TypeBuilder object
7470 * Creates the generic class after all generic parameters have been added.
7473 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7478 MONO_ARCH_SAVE_REGS;
7480 klass = my_mono_class_from_mono_type (tb->type.type);
7482 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7484 if (klass->generic_container || (count == 0))
7487 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7489 klass->generic_container = tb->generic_container;
7491 klass->generic_container->type_argc = count;
7492 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7494 for (i = 0; i < count; i++) {
7495 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7496 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7497 g_assert (klass->generic_container->type_params [i].owner);
7500 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7504 * mono_reflection_create_internal_class:
7505 * @tb: a TypeBuilder object
7507 * Actually create the MonoClass that is associated with the TypeBuilder.
7510 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7514 MONO_ARCH_SAVE_REGS;
7516 klass = my_mono_class_from_mono_type (tb->type.type);
7518 if (klass->enumtype && klass->enum_basetype == NULL) {
7519 MonoReflectionFieldBuilder *fb;
7522 g_assert (tb->fields != NULL);
7523 g_assert (mono_array_length (tb->fields) >= 1);
7525 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7527 klass->enum_basetype = fb->type->type;
7528 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7529 if (!klass->element_class)
7530 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7533 * get the element_class from the current corlib.
7535 ec = default_class_from_mono_type (klass->enum_basetype);
7536 klass->instance_size = ec->instance_size;
7537 klass->size_inited = 1;
7539 * this is almost safe to do with enums and it's needed to be able
7540 * to create objects of the enum type (for use in SetConstant).
7542 /* FIXME: Does this mean enums can't have method overrides ? */
7543 mono_class_setup_vtable (klass, NULL, 0);
7547 static MonoMarshalSpec*
7548 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7549 MonoReflectionMarshal *minfo)
7551 MonoMarshalSpec *res;
7553 res = g_new0 (MonoMarshalSpec, 1);
7554 res->native = minfo->type;
7556 switch (minfo->type) {
7557 case MONO_NATIVE_LPARRAY:
7558 res->data.array_data.elem_type = minfo->eltype;
7559 res->data.array_data.param_num = 0; /* Not yet */
7560 res->data.array_data.num_elem = minfo->count;
7563 case MONO_NATIVE_BYVALTSTR:
7564 case MONO_NATIVE_BYVALARRAY:
7565 res->data.array_data.num_elem = minfo->count;
7568 case MONO_NATIVE_CUSTOM:
7569 if (minfo->marshaltyperef)
7570 res->data.custom_data.custom_name =
7571 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7573 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7583 MonoReflectionMarshal*
7584 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
7585 MonoMarshalSpec *spec)
7587 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
7588 MonoReflectionMarshal *minfo;
7591 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
7592 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
7593 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
7594 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
7597 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
7598 minfo->type = spec->native;
7600 switch (minfo->type) {
7601 case MONO_NATIVE_LPARRAY:
7602 minfo->eltype = spec->data.array_data.elem_type;
7603 minfo->count = spec->data.array_data.num_elem;
7606 case MONO_NATIVE_BYVALTSTR:
7607 case MONO_NATIVE_BYVALARRAY:
7608 minfo->count = spec->data.array_data.num_elem;
7611 case MONO_NATIVE_CUSTOM:
7612 if (spec->data.custom_data.custom_name) {
7613 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
7615 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
7617 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
7619 if (spec->data.custom_data.cookie)
7620 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
7631 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7632 ReflectionMethodBuilder *rmb,
7633 MonoMethodSignature *sig)
7636 MonoMethodNormal *pm;
7637 MonoMarshalSpec **specs;
7638 MonoReflectionMethodAux *method_aux;
7641 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7642 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7643 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7645 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7647 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7649 pm = (MonoMethodNormal*)m;
7652 m->flags = rmb->attrs;
7653 m->iflags = rmb->iattrs;
7654 m->name = mono_string_to_utf8 (rmb->name);
7658 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7660 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7661 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7664 m->signature->pinvoke = 1;
7665 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7666 m->signature->pinvoke = 1;
7668 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7670 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7671 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7673 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7675 if (klass->image->dynamic)
7676 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7679 } else if (!m->klass->dummy &&
7680 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7681 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7682 MonoMethodHeader *header;
7684 gint32 max_stack, i;
7685 gint32 num_locals = 0;
7686 gint32 num_clauses = 0;
7690 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7691 code_size = rmb->ilgen->code_len;
7692 max_stack = rmb->ilgen->max_stack;
7693 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7694 if (rmb->ilgen->ex_handlers)
7695 num_clauses = method_count_clauses (rmb->ilgen);
7698 code = mono_array_addr (rmb->code, guint8, 0);
7699 code_size = mono_array_length (rmb->code);
7700 /* we probably need to run a verifier on the code... */
7710 header = g_malloc0 (sizeof (MonoMethodHeader) +
7711 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7712 header->code_size = code_size;
7713 header->code = g_malloc (code_size);
7714 memcpy ((char*)header->code, code, code_size);
7715 header->max_stack = max_stack;
7716 header->init_locals = rmb->init_locals;
7717 header->num_locals = num_locals;
7719 for (i = 0; i < num_locals; ++i) {
7720 MonoReflectionLocalBuilder *lb =
7721 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7723 header->locals [i] = g_new0 (MonoType, 1);
7724 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7727 header->num_clauses = num_clauses;
7729 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7730 rmb->ilgen, num_clauses);
7733 pm->header = header;
7736 if (rmb->generic_params) {
7737 int count = mono_array_length (rmb->generic_params);
7738 MonoGenericContainer *container;
7740 pm->generic_container = container = rmb->generic_container;
7741 container->type_argc = count;
7742 container->type_params = g_new0 (MonoGenericParam, count);
7744 for (i = 0; i < count; i++) {
7745 MonoReflectionGenericParam *gp =
7746 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7748 container->type_params [i] = *gp->type.type->data.generic_param;
7753 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7757 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7759 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
7760 data [0] = GUINT_TO_POINTER (rmb->nrefs);
7761 for (i = 0; i < rmb->nrefs; ++i)
7762 data [i + 1] = rmb->refs [i];
7767 /* Parameter info */
7770 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7771 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7772 for (i = 0; i <= m->signature->param_count; ++i) {
7773 MonoReflectionParamBuilder *pb;
7774 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7776 m->signature->params [i - 1]->attrs = pb->attrs;
7778 if (pb->def_value) {
7779 MonoDynamicImage *assembly;
7780 guint32 idx, def_type, len;
7784 if (!method_aux->param_defaults)
7785 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
7786 assembly = (MonoDynamicImage*)klass->image;
7787 idx = encode_constant (assembly, pb->def_value, &def_type);
7788 /* Copy the data from the blob since it might get realloc-ed */
7789 p = assembly->blob.data + idx;
7790 len = mono_metadata_decode_blob_size (p, &p2);
7792 method_aux->param_defaults [i] = g_malloc (len);
7793 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
7797 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7799 if (!method_aux->param_cattr)
7800 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7801 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7807 /* Parameter marshalling */
7810 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7811 MonoReflectionParamBuilder *pb;
7812 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7813 if (pb->marshal_info) {
7815 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7816 specs [pb->position] =
7817 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7821 if (specs != NULL) {
7823 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7824 method_aux->param_marshall = specs;
7827 if (klass->image->dynamic && method_aux)
7828 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7834 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7836 ReflectionMethodBuilder rmb;
7837 MonoMethodSignature *sig;
7839 sig = ctor_builder_to_signature (mb);
7841 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7843 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7844 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7846 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7847 /* ilgen is no longer needed */
7855 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7857 ReflectionMethodBuilder rmb;
7858 MonoMethodSignature *sig;
7860 sig = method_builder_to_signature (mb);
7862 reflection_methodbuilder_from_method_builder (&rmb, mb);
7864 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7865 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7867 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7868 /* ilgen is no longer needed */
7874 static MonoClassField*
7875 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7877 MonoClassField *field;
7884 field = g_new0 (MonoClassField, 1);
7886 field->name = mono_string_to_utf8 (fb->name);
7888 /* FIXME: handle type modifiers */
7889 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7890 field->type->attrs = fb->attrs;
7892 field->type = fb->type->type;
7894 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7895 field->data = mono_array_addr (fb->rva_data, char, 0);
7896 if (fb->offset != -1)
7897 field->offset = fb->offset;
7898 field->parent = klass;
7900 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7902 if (fb->def_value) {
7903 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7904 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7905 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7906 /* Copy the data from the blob since it might get realloc-ed */
7907 p = assembly->blob.data + idx;
7908 len = mono_metadata_decode_blob_size (p, &p2);
7910 field->data = g_malloc (len);
7911 memcpy ((gpointer)field->data, p, len);
7918 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
7922 MonoReflectionTypeBuilder *tb = NULL;
7923 MonoGenericClass *gclass, *cached;
7924 MonoDynamicGenericClass *dgclass = NULL;
7925 gboolean is_dynamic = FALSE;
7930 klass = mono_class_from_mono_type (type->type);
7931 if (!klass->generic_container && !klass->generic_class &&
7932 !(klass->nested_in && klass->nested_in->generic_container))
7935 mono_loader_lock ();
7937 domain = mono_object_domain (type);
7939 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7940 tb = (MonoReflectionTypeBuilder *) type;
7942 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7944 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
7945 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
7946 MonoReflectionType *rgt = rgi->generic_type;
7948 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7949 tb = (MonoReflectionTypeBuilder *) rgt;
7951 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7954 icount = klass->interface_count;
7958 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7959 gclass = &dgclass->generic_class;
7960 gclass->is_dynamic = TRUE;
7962 gclass = g_new0 (MonoGenericClass, 1);
7964 gclass->inst = g_new0 (MonoGenericInst, 1);
7966 gclass->inst->type_argc = type_argc;
7967 gclass->inst->type_argv = types;
7968 gclass->inst->is_reference = 1;
7970 for (i = 0; i < gclass->inst->type_argc; ++i) {
7971 if (!gclass->inst->is_open)
7972 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
7973 if (gclass->inst->is_reference)
7974 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
7977 gclass->container_class = klass;
7979 if (klass->generic_class) {
7980 MonoGenericClass *kgclass = klass->generic_class;
7981 MonoGenericClass *ogclass = gclass;
7983 ogclass->context = g_new0 (MonoGenericContext, 1);
7984 ogclass->context->container = ogclass->container_class->generic_container;
7985 ogclass->context->gclass = ogclass;
7988 dgclass = g_new0 (MonoDynamicGenericClass, 1);
7989 gclass = &dgclass->generic_class;
7990 gclass->is_dynamic = TRUE;
7992 gclass = g_new0 (MonoGenericClass, 1);
7994 gclass->inst = g_new0 (MonoGenericInst, 1);
7996 gclass->inst->type_argc = kgclass->inst->type_argc;
7997 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
7998 gclass->inst->is_reference = 1;
8000 for (i = 0; i < gclass->inst->type_argc; i++) {
8001 MonoType *t = kgclass->inst->type_argv [i];
8003 t = mono_class_inflate_generic_type (t, ogclass->context);
8005 if (!gclass->inst->is_open)
8006 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8007 if (gclass->inst->is_reference)
8008 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8010 gclass->inst->type_argv [i] = t;
8013 gclass->container_class = kgclass->container_class;
8016 geninst = g_new0 (MonoType, 1);
8017 geninst->type = MONO_TYPE_GENERICINST;
8019 cached = mono_metadata_lookup_generic_class (gclass);
8022 mono_loader_unlock ();
8023 geninst->data.generic_class = cached;
8027 geninst->data.generic_class = gclass;
8029 gclass->parent = parent;
8031 gclass->context = g_new0 (MonoGenericContext, 1);
8032 gclass->context->container = gclass->container_class->generic_container;
8033 gclass->context->gclass = gclass;
8035 gclass->ifaces = g_new0 (MonoType *, icount);
8036 gclass->count_ifaces = icount;
8038 for (i = 0; i < icount; i++) {
8039 MonoReflectionType *itype;
8042 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8044 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8045 gclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8046 if (!gclass->ifaces [i])
8047 gclass->ifaces [i] = itype->type;
8050 mono_class_create_generic (gclass);
8052 mono_loader_unlock ();
8058 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8060 MonoClass *klass, *pklass = NULL;
8061 MonoReflectionType *parent = NULL;
8062 MonoType *the_parent = NULL, *geninst;
8063 MonoReflectionTypeBuilder *tb = NULL;
8064 MonoGenericClass *gclass;
8067 domain = mono_object_domain (type);
8068 klass = mono_class_from_mono_type (type->type);
8070 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8071 tb = (MonoReflectionTypeBuilder *) type;
8074 parent = tb->parent;
8075 pklass = mono_class_from_mono_type (parent->type);
8078 pklass = klass->parent;
8080 parent = mono_type_get_object (domain, &pklass->byval_arg);
8081 else if (klass->generic_class && klass->generic_class->parent) {
8082 parent = mono_type_get_object (domain, klass->generic_class->parent);
8083 pklass = mono_class_from_mono_type (klass->generic_class->parent);
8087 if (pklass && pklass->generic_class)
8088 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8090 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8094 gclass = geninst->data.generic_class;
8100 dup_type (const MonoType *original)
8102 MonoType *r = g_new0 (MonoType, 1);
8104 r->attrs = original->attrs;
8105 r->byref = original->byref;
8106 mono_stats.generics_metadata_size += sizeof (MonoType);
8110 MonoReflectionMethod*
8111 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8113 MonoMethod *method, *inflated;
8114 MonoReflectionMethodBuilder *mb = NULL;
8115 MonoGenericContainer *container;
8116 MonoGenericMethod *gmethod;
8117 MonoGenericContext *context;
8118 MonoGenericInst *ginst;
8121 MONO_ARCH_SAVE_REGS;
8122 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8123 MonoReflectionTypeBuilder *tb;
8126 mb = (MonoReflectionMethodBuilder *) rmethod;
8127 tb = (MonoReflectionTypeBuilder *) mb->type;
8128 klass = mono_class_from_mono_type (tb->type.type);
8130 method = methodbuilder_to_mono_method (klass, mb);
8132 method = rmethod->method;
8135 count = method->signature->generic_param_count;
8136 if (count != mono_array_length (types))
8139 container = ((MonoMethodNormal*) method)->generic_container;
8140 g_assert (container);
8142 if (!container->method_hash)
8143 container->method_hash = g_hash_table_new (
8144 (GHashFunc) mono_metadata_generic_method_hash,
8145 (GCompareFunc) mono_metadata_generic_method_equal);
8147 ginst = g_new0 (MonoGenericInst,1 );
8148 ginst->type_argc = count;
8149 ginst->type_argv = g_new0 (MonoType *, count);
8150 ginst->is_reference = 1;
8151 for (i = 0; i < count; i++) {
8152 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8153 ginst->type_argv [i] = dup_type (garg->type);
8155 if (!ginst->is_open)
8156 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8157 if (ginst->is_reference)
8158 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8160 ginst = mono_metadata_lookup_generic_inst (ginst);
8162 gmethod = g_new0 (MonoGenericMethod, 1);
8163 gmethod->container = container;
8164 gmethod->inst = ginst;
8166 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8170 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8173 gmethod->reflection_info = rmethod;
8175 context = g_new0 (MonoGenericContext, 1);
8176 context->container = container;
8177 context->gclass = method->klass->generic_class;
8178 context->gmethod = gmethod;
8180 inflated = mono_class_inflate_generic_method (method, context, NULL);
8181 g_hash_table_insert (container->method_hash, gmethod, inflated);
8183 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8187 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8189 MonoGenericMethod *gmethod;
8190 MonoGenericClass *gclass;
8191 MonoGenericContext *context;
8194 gclass = type->type.type->data.generic_class;
8196 gmethod = g_new0 (MonoGenericMethod, 1);
8197 gmethod->inst = g_new0 (MonoGenericInst, 1);
8198 gmethod->reflection_info = obj;
8200 gmethod->inst->type_argc = method->signature->generic_param_count;
8201 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8203 for (i = 0; i < gmethod->inst->type_argc; i++) {
8204 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8205 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8207 g_assert (gparam->pklass);
8208 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8211 context = g_new0 (MonoGenericContext, 1);
8212 context->container = gclass->container_class->generic_container;
8213 context->gclass = gclass;
8214 context->gmethod = gmethod;
8216 return mono_class_inflate_generic_method (method, context, gclass->klass);
8220 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8225 klass = mono_class_from_mono_type (type->type.type);
8227 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8228 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8229 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8230 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8231 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8232 method = ((MonoReflectionMethod *) obj)->method;
8234 method = NULL; /* prevent compiler warning */
8235 g_assert_not_reached ();
8238 return inflate_mono_method (type, method, obj);
8242 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8243 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8246 MonoGenericClass *gclass;
8247 MonoDynamicGenericClass *dgclass;
8248 MonoClass *klass, *gklass, *pklass;
8251 MONO_ARCH_SAVE_REGS;
8253 klass = mono_class_from_mono_type (type->type.type);
8254 gclass = type->type.type->data.generic_class;
8256 g_assert (gclass->is_dynamic);
8257 dgclass = (MonoDynamicGenericClass *) gclass;
8259 if (dgclass->initialized)
8262 gklass = gclass->container_class;
8263 mono_class_init (gklass);
8266 pklass = mono_class_from_mono_type (gclass->parent);
8268 pklass = gklass->parent;
8270 mono_class_setup_parent (klass, pklass);
8272 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8273 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8274 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8275 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8276 dgclass->count_events = events ? mono_array_length (events) : 0;
8278 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8279 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8280 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8281 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8282 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8284 for (i = 0; i < dgclass->count_methods; i++) {
8285 MonoObject *obj = mono_array_get (methods, gpointer, i);
8287 dgclass->methods [i] = inflate_method (type, obj);
8290 for (i = 0; i < dgclass->count_ctors; i++) {
8291 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8293 dgclass->ctors [i] = inflate_method (type, obj);
8296 for (i = 0; i < dgclass->count_fields; i++) {
8297 MonoObject *obj = mono_array_get (fields, gpointer, i);
8298 MonoClassField *field;
8299 MonoInflatedField *ifield;
8301 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8302 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8303 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8304 field = ((MonoReflectionField *) obj)->field;
8306 field = NULL; /* prevent compiler warning */
8307 g_assert_not_reached ();
8310 ifield = g_new0 (MonoInflatedField, 1);
8311 ifield->generic_type = field->type;
8312 ifield->reflection_info = obj;
8314 dgclass->fields [i] = *field;
8315 dgclass->fields [i].generic_info = ifield;
8316 dgclass->fields [i].type = mono_class_inflate_generic_type (field->type, gclass->context);
8319 for (i = 0; i < dgclass->count_properties; i++) {
8320 MonoObject *obj = mono_array_get (properties, gpointer, i);
8321 MonoProperty *property = &dgclass->properties [i];
8323 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8324 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8326 property->parent = klass;
8327 property->attrs = pb->attrs;
8328 property->name = mono_string_to_utf8 (pb->name);
8330 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8332 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8333 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8334 *property = *((MonoReflectionProperty *) obj)->property;
8337 property->get = inflate_mono_method (type, property->get, NULL);
8339 property->set = inflate_mono_method (type, property->set, NULL);
8341 g_assert_not_reached ();
8344 for (i = 0; i < dgclass->count_events; i++) {
8345 MonoObject *obj = mono_array_get (events, gpointer, i);
8346 MonoEvent *event = &dgclass->events [i];
8348 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8349 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8351 event->parent = klass;
8352 event->attrs = eb->attrs;
8353 event->name = mono_string_to_utf8 (eb->name);
8355 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8356 if (eb->remove_method)
8357 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8358 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8359 *event = *((MonoReflectionEvent *) obj)->event;
8362 event->add = inflate_mono_method (type, event->add, NULL);
8364 event->remove = inflate_mono_method (type, event->remove, NULL);
8366 g_assert_not_reached ();
8369 dgclass->initialized = TRUE;
8373 ensure_runtime_vtable (MonoClass *klass)
8375 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8376 int i, num, j, onum;
8377 MonoMethod **overrides;
8379 if (!tb || klass->wastypebuilder)
8382 ensure_runtime_vtable (klass->parent);
8384 num = tb->ctors? mono_array_length (tb->ctors): 0;
8385 num += tb->num_methods;
8386 klass->method.count = num;
8387 klass->methods = g_new (MonoMethod*, num);
8388 num = tb->ctors? mono_array_length (tb->ctors): 0;
8389 for (i = 0; i < num; ++i)
8390 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8391 num = tb->num_methods;
8393 for (i = 0; i < num; ++i)
8394 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8396 if (tb->interfaces) {
8397 klass->interface_count = mono_array_length (tb->interfaces);
8398 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8399 for (i = 0; i < klass->interface_count; ++i) {
8400 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8401 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8405 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8406 for (i = 0; i < klass->method.count; ++i)
8407 klass->methods [i]->slot = i;
8412 for (i = 0; i < tb->num_methods; ++i) {
8413 MonoReflectionMethodBuilder *mb =
8414 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8415 if (mb->override_method)
8420 overrides = g_new0 (MonoMethod*, onum * 2);
8424 for (i = 0; i < tb->num_methods; ++i) {
8425 MonoReflectionMethodBuilder *mb =
8426 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8427 if (mb->override_method) {
8428 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8429 overrides [onum * 2] =
8430 mb->override_method->method;
8431 overrides [onum * 2 + 1] =
8434 g_assert (mb->mhandle);
8441 mono_class_setup_vtable (klass, overrides, onum);
8446 typebuilder_setup_fields (MonoClass *klass)
8448 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8449 MonoReflectionFieldBuilder *fb;
8450 MonoClassField *field;
8455 klass->field.count = tb->num_fields;
8456 klass->field.first = 0;
8457 klass->field.last = klass->field.count;
8459 if (!klass->field.count)
8462 klass->fields = g_new0 (MonoClassField, klass->field.count);
8464 for (i = 0; i < klass->field.count; ++i) {
8465 fb = mono_array_get (tb->fields, gpointer, i);
8466 field = &klass->fields [i];
8467 field->name = mono_string_to_utf8 (fb->name);
8469 /* FIXME: handle type modifiers */
8470 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8471 field->type->attrs = fb->attrs;
8473 field->type = fb->type->type;
8475 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8476 field->data = mono_array_addr (fb->rva_data, char, 0);
8477 if (fb->offset != -1)
8478 field->offset = fb->offset;
8479 field->parent = klass;
8481 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8483 if (fb->def_value) {
8484 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8485 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8486 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8487 /* Copy the data from the blob since it might get realloc-ed */
8488 p = assembly->blob.data + idx;
8489 len = mono_metadata_decode_blob_size (p, &p2);
8491 field->data = g_malloc (len);
8492 memcpy ((gpointer)field->data, p, len);
8495 mono_class_layout_fields (klass);
8499 typebuilder_setup_properties (MonoClass *klass)
8501 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8502 MonoReflectionPropertyBuilder *pb;
8505 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8506 klass->property.first = 0;
8507 klass->property.last = klass->property.count;
8509 klass->properties = g_new0 (MonoProperty, klass->property.count);
8510 for (i = 0; i < klass->property.count; ++i) {
8511 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8512 klass->properties [i].parent = klass;
8513 klass->properties [i].attrs = pb->attrs;
8514 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8516 klass->properties [i].get = pb->get_method->mhandle;
8518 klass->properties [i].set = pb->set_method->mhandle;
8522 MonoReflectionEvent *
8523 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8525 MonoEvent *event = g_new0 (MonoEvent, 1);
8529 klass = my_mono_class_from_mono_type (tb->type.type);
8531 event->parent = klass;
8532 event->attrs = eb->attrs;
8533 event->name = mono_string_to_utf8 (eb->name);
8535 event->add = eb->add_method->mhandle;
8536 if (eb->remove_method)
8537 event->remove = eb->remove_method->mhandle;
8538 if (eb->raise_method)
8539 event->raise = eb->raise_method->mhandle;
8541 if (eb->other_methods) {
8542 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8543 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8544 MonoReflectionMethodBuilder *mb =
8545 mono_array_get (eb->other_methods,
8546 MonoReflectionMethodBuilder*, j);
8547 event->other [j] = mb->mhandle;
8551 return mono_event_get_object (mono_object_domain (tb), klass, event);
8555 typebuilder_setup_events (MonoClass *klass)
8557 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8558 MonoReflectionEventBuilder *eb;
8561 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8562 klass->event.first = 0;
8563 klass->event.last = klass->event.count;
8565 klass->events = g_new0 (MonoEvent, klass->event.count);
8566 for (i = 0; i < klass->event.count; ++i) {
8567 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8568 klass->events [i].parent = klass;
8569 klass->events [i].attrs = eb->attrs;
8570 klass->events [i].name = mono_string_to_utf8 (eb->name);
8572 klass->events [i].add = eb->add_method->mhandle;
8573 if (eb->remove_method)
8574 klass->events [i].remove = eb->remove_method->mhandle;
8575 if (eb->raise_method)
8576 klass->events [i].raise = eb->raise_method->mhandle;
8578 if (eb->other_methods) {
8579 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
8580 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8581 MonoReflectionMethodBuilder *mb =
8582 mono_array_get (eb->other_methods,
8583 MonoReflectionMethodBuilder*, j);
8584 klass->events [i].other [j] = mb->mhandle;
8591 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8594 MonoReflectionType* res;
8597 MONO_ARCH_SAVE_REGS;
8599 klass = my_mono_class_from_mono_type (tb->type.type);
8601 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8604 * Fields to set in klass:
8605 * the various flags: delegate/unicode/contextbound etc.
8607 klass->flags = tb->attrs;
8609 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8610 /* No need to fully construct the type */
8611 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8613 /* enums are done right away */
8614 if (!klass->enumtype)
8615 ensure_runtime_vtable (klass);
8618 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8619 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8620 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8624 /* fields and object layout */
8625 if (klass->parent) {
8626 if (!klass->parent->size_inited)
8627 mono_class_init (klass->parent);
8628 klass->instance_size += klass->parent->instance_size;
8629 klass->class_size += klass->parent->class_size;
8630 klass->min_align = klass->parent->min_align;
8632 klass->instance_size = sizeof (MonoObject);
8633 klass->min_align = 1;
8636 /* FIXME: handle packing_size and instance_size */
8637 typebuilder_setup_fields (klass);
8639 typebuilder_setup_properties (klass);
8641 typebuilder_setup_events (klass);
8643 klass->wastypebuilder = TRUE;
8645 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8646 g_assert (res != (MonoReflectionType*)tb);
8651 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8653 MonoGenericParam *param;
8656 MONO_ARCH_SAVE_REGS;
8658 param = g_new0 (MonoGenericParam, 1);
8660 if (gparam->mbuilder) {
8661 if (!gparam->mbuilder->generic_container)
8662 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
8663 param->owner = gparam->mbuilder->generic_container;
8664 } else if (gparam->tbuilder) {
8665 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
8666 MonoGenericContainer *container = gparam->tbuilder->generic_container;
8671 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
8672 if (gparam->index >= count)
8675 container = nesting->generic_container;
8676 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
8679 g_assert (container);
8680 param->owner = container;
8683 param->method = NULL;
8684 param->name = mono_string_to_utf8 (gparam->name);
8685 param->num = gparam->index;
8687 image = &gparam->tbuilder->module->dynamic_image->image;
8688 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8690 param->pklass->reflection_info = gparam;
8692 gparam->type.type = g_new0 (MonoType, 1);
8693 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8694 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8695 gparam->type.type->data.generic_param = param;
8699 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8701 MonoDynamicImage *assembly = sig->module->dynamic_image;
8702 guint32 na = mono_array_length (sig->arguments);
8707 MONO_ARCH_SAVE_REGS;
8709 p = buf = g_malloc (10 + na * 10);
8711 mono_metadata_encode_value (0x07, p, &p);
8712 mono_metadata_encode_value (na, p, &p);
8713 for (i = 0; i < na; ++i) {
8714 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8715 encode_reflection_type (assembly, type, p, &p);
8719 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8720 p = mono_array_addr (result, char, 0);
8721 memcpy (p, buf, buflen);
8728 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8730 MonoDynamicImage *assembly = sig->module->dynamic_image;
8731 guint32 na = mono_array_length (sig->arguments);
8736 MONO_ARCH_SAVE_REGS;
8738 p = buf = g_malloc (10 + na * 10);
8740 mono_metadata_encode_value (0x06, p, &p);
8741 for (i = 0; i < na; ++i) {
8742 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8743 encode_reflection_type (assembly, type, p, &p);
8747 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8748 p = mono_array_addr (result, char, 0);
8749 memcpy (p, buf, buflen);
8756 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8758 ReflectionMethodBuilder rmb;
8759 MonoMethodSignature *sig;
8762 sig = dynamic_method_to_signature (mb);
8764 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8767 * Resolve references.
8769 rmb.nrefs = mb->nrefs;
8770 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8771 for (i = 0; i < mb->nrefs; ++i) {
8772 gpointer ref = resolve_object (mb->module->image,
8773 mono_array_get (mb->refs, MonoObject*, i));
8776 mono_raise_exception (mono_get_exception_type_load (NULL));
8783 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8787 /* ilgen is no longer needed */
8792 * mono_reflection_lookup_dynamic_token:
8794 * Finish the Builder object pointed to by TOKEN and return the corresponding
8795 * runtime structure.
8798 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8800 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8803 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8806 return resolve_object (image, obj);
8810 resolve_object (MonoImage *image, MonoObject *obj)
8812 gpointer result = NULL;
8814 if (strcmp (obj->vtable->klass->name, "String") == 0) {
8815 result = mono_string_intern ((MonoString*)obj);
8817 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8818 MonoReflectionType *tb = (MonoReflectionType*)obj;
8819 result = mono_class_from_mono_type (tb->type);
8821 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8822 result = ((MonoReflectionMethod*)obj)->method;
8824 } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8825 result = ((MonoReflectionMethod*)obj)->method;
8827 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8828 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8829 result = mb->mhandle;
8831 /* Type is not yet created */
8832 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8834 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8837 * Hopefully this has been filled in by calling CreateType() on the
8841 * TODO: This won't work if the application finishes another
8842 * TypeBuilder instance instead of this one.
8844 result = mb->mhandle;
8846 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8847 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8849 result = cb->mhandle;
8851 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8853 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8854 result = cb->mhandle;
8856 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8857 result = ((MonoReflectionField*)obj)->field;
8859 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8860 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8861 result = fb->handle;
8864 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8866 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8867 result = fb->handle;
8869 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8870 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8873 klass = tb->type.type->data.klass;
8874 if (klass->wastypebuilder) {
8875 /* Already created */
8879 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8880 result = tb->type.type->data.klass;
8883 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8884 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8885 MonoMethodSignature *sig;
8888 if (helper->arguments)
8889 nargs = mono_array_length (helper->arguments);
8893 sig = mono_metadata_signature_alloc (image, nargs);
8894 sig->explicit_this = helper->call_conv & 64;
8895 sig->hasthis = helper->call_conv & 32;
8897 if (helper->call_conv == 0) /* unmanaged */
8898 sig->call_convention = helper->unmanaged_call_conv - 1;
8900 if (helper->call_conv & 0x02)
8901 sig->call_convention = MONO_CALL_VARARG;
8903 sig->call_convention = MONO_CALL_DEFAULT;
8905 sig->param_count = nargs;
8906 /* TODO: Copy type ? */
8907 sig->ret = helper->return_type->type;
8908 for (i = 0; i < nargs; ++i) {
8909 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8910 sig->params [i] = rt->type;
8915 g_print (obj->vtable->klass->name);
8916 g_assert_not_reached ();
8922 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
8923 const static guint32 declsec_flags_map[] = {
8924 0x00000000, /* empty */
8925 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
8926 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
8927 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
8928 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
8929 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
8930 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
8931 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
8932 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
8933 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
8934 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
8935 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
8936 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
8937 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
8938 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
8939 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
8940 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
8941 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
8942 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
8946 * Returns flags that includes all available security action associated to the handle.
8947 * @token: metadata token (either for a class or a method)
8948 * @image: image where resides the metadata.
8951 mono_declsec_get_flags (MonoImage *image, guint32 token)
8953 guint32 index = mono_metadata_declsec_from_index (image, token);
8954 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
8959 for (i = index; i < t->rows; i++) {
8960 guint32 cols [MONO_DECL_SECURITY_SIZE];
8962 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
8963 if (cols [MONO_DECL_SECURITY_PARENT] != token)
8966 action = cols [MONO_DECL_SECURITY_ACTION];
8967 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
8968 result |= declsec_flags_map [action];
8970 g_assert_not_reached ();
8977 * Get the security actions (in the form of flags) associated with the specified method.
8979 * @method: The method for which we want the declarative security flags.
8980 * Return the declarative security flags for the method (only).
8982 * Note: To keep MonoMethod size down we do not cache the declarative security flags
8983 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
8986 mono_declsec_flags_from_method (MonoMethod *method)
8988 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
8989 /* FIXME: No cache (for the moment) */
8990 guint32 idx = find_method_index (method);
8991 idx <<= MONO_HAS_DECL_SECURITY_BITS;
8992 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
8993 return mono_declsec_get_flags (method->klass->image, idx);
8999 * Get the security actions (in the form of flags) associated with the specified class.
9001 * @klass: The class for which we want the declarative security flags.
9002 * Return the declarative security flags for the class.
9004 * Note: We cache the flags inside the MonoClass structure as this will get
9005 * called very often (at least for each method).
9008 mono_declsec_flags_from_class (MonoClass *klass)
9010 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9011 if (!klass->declsec_flags) {
9012 guint32 idx = mono_metadata_token_index (klass->type_token);
9013 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9014 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9015 /* we cache the flags on classes */
9016 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9018 return klass->declsec_flags;
9024 * Get the security actions (in the form of flags) associated with the specified assembly.
9026 * @assembly: The assembly for which we want the declarative security flags.
9027 * Return the declarative security flags for the assembly.
9030 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9032 guint32 idx = 1; /* there is only one assembly */
9033 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9034 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9035 return mono_declsec_get_flags (assembly->image, idx);
9040 * Fill actions for the specific index (which may either be an encoded class token or
9041 * an encoded method token) from the metadata image.
9042 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9045 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions)
9047 MonoBoolean result = FALSE;
9049 guint32 cols [MONO_DECL_SECURITY_SIZE];
9050 int index = mono_metadata_declsec_from_index (image, token);
9053 t = &image->tables [MONO_TABLE_DECLSECURITY];
9054 for (i = index; i < t->rows; i++) {
9055 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9057 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9060 /* if present only replace (class) permissions with method permissions */
9061 /* if empty accept either class or method permissions */
9062 switch (cols [MONO_DECL_SECURITY_ACTION]) {
9063 case SECURITY_ACTION_DEMAND:
9064 if (!actions->demand.blob) {
9065 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9066 actions->demand.blob = (char*) (blob + 2);
9067 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9071 case SECURITY_ACTION_NONCASDEMAND:
9072 if (!actions->noncasdemand.blob) {
9073 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9074 actions->noncasdemand.blob = (char*) (blob + 2);
9075 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9079 case SECURITY_ACTION_DEMANDCHOICE:
9080 if (!actions->demandchoice.blob) {
9081 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9082 actions->demandchoice.blob = (char*) (blob + 2);
9083 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9094 * Collect all actions (that requires to generate code in mini) assigned for
9095 * the specified method.
9096 * Note: Don't use the content of actions if the function return FALSE.
9099 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9101 MonoImage *image = method->klass->image;
9102 MonoBoolean result = FALSE;
9105 /* quick exit if no declarative security is present in the metadata */
9106 if (!image->tables [MONO_TABLE_DECLSECURITY].rows)
9109 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9111 /* First we look for method-level attributes */
9112 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9113 guint32 idx = find_method_index (method);
9114 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9115 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9116 result = fill_actions_from_index (image, idx, demands);
9119 /* Next we fill holes with class-level attributes */
9120 /* Here we use (or create) the class declarative cache to look for demands */
9121 flags = mono_declsec_flags_from_class (method->klass);
9122 if (flags & (MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | MONO_DECLSEC_FLAG_DEMAND_CHOICE)) {
9123 guint32 idx = mono_metadata_token_index (method->klass->type_token);
9124 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9125 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9126 result |= fill_actions_from_index (image, idx, demands);
9129 /* The boolean return value is used as a shortcut in case nothing needs to
9130 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9135 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9137 guint32 cols [MONO_DECL_SECURITY_SIZE];
9141 int index = mono_metadata_declsec_from_index (image, token);
9145 t = &image->tables [MONO_TABLE_DECLSECURITY];
9146 for (i = index; i < t->rows; i++) {
9147 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9149 /* shortcut - index are ordered */
9150 if (token != cols [MONO_DECL_SECURITY_PARENT])
9153 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9154 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9155 entry->blob = (char*) (metadata + 2);
9156 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9165 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9167 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9168 guint32 idx = find_method_index (method);
9169 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9170 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9171 return get_declsec_action (method->klass->image, idx, action, entry);
9177 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9180 guint32 flags = mono_declsec_flags_from_class (klass);
9181 if (declsec_flags_map [action] & flags) {
9182 guint32 idx = mono_metadata_token_index (klass->type_token);
9183 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9184 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9185 return get_declsec_action (klass->image, idx, action, entry);
9191 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9193 guint32 idx = 1; /* there is only one assembly */
9194 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9195 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9197 return get_declsec_action (assembly->image, idx, action, entry);