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>
22 #include <mono/metadata/marshal.h>
31 #include "rawbuffer.h"
32 #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, extra_flags, 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, MonoClass **handle_class);
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, guint32 *types);
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 string_heap_insert (MonoDynamicStream *sh, const char *str)
182 gpointer oldkey, oldval;
184 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
185 return GPOINTER_TO_UINT (oldval);
187 len = strlen (str) + 1;
190 make_room_in_stream (sh, idx + len);
193 * We strdup the string even if we already copy them in sh->data
194 * so that the string pointers in the hash remain valid even if
195 * we need to realloc sh->data. We may want to avoid that later.
197 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
198 memcpy (sh->data + idx, str, len);
204 string_heap_init (MonoDynamicStream *sh)
207 sh->alloc_size = 4096;
208 sh->data = g_malloc (4096);
209 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
210 string_heap_insert (sh, "");
214 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
218 make_room_in_stream (stream, stream->index + len);
219 memcpy (stream->data + stream->index, data, len);
221 stream->index += len;
223 * align index? Not without adding an additional param that controls it since
224 * we may store a blob value in pieces.
230 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
234 make_room_in_stream (stream, stream->index + len);
235 memset (stream->data + stream->index, 0, len);
237 stream->index += len;
242 stream_data_align (MonoDynamicStream *stream)
245 guint32 count = stream->index % 4;
247 /* we assume the stream data will be aligned */
249 mono_image_add_stream_data (stream, buf, 4 - count);
253 mono_blob_entry_hash (const char* str)
257 len = mono_metadata_decode_blob_size (str, &str);
261 for (str += 1; str < end; str++)
262 h = (h << 5) - h + *str;
270 mono_blob_entry_equal (const char *str1, const char *str2) {
274 len = mono_metadata_decode_blob_size (str1, &end1);
275 len2 = mono_metadata_decode_blob_size (str2, &end2);
278 return memcmp (end1, end2, len) == 0;
282 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
286 gpointer oldkey, oldval;
288 copy = g_malloc (s1+s2);
289 memcpy (copy, b1, s1);
290 memcpy (copy + s1, b2, s2);
291 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
293 idx = GPOINTER_TO_UINT (oldval);
295 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
296 mono_image_add_stream_data (&assembly->blob, b2, s2);
297 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
303 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
304 * dest may be misaligned.
307 swap_with_size (char *dest, const char* val, int len, int nelem) {
308 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
311 for (elem = 0; elem < nelem; ++elem) {
337 g_assert_not_reached ();
343 memcpy (dest, val, len * nelem);
348 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
352 guint32 idx = 0, len;
354 len = str->length * 2;
355 mono_metadata_encode_value (len, b, &b);
356 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
358 char *swapped = g_malloc (2 * mono_string_length (str));
359 const char *p = (const char*)mono_string_chars (str);
361 swap_with_size (swapped, p, 2, mono_string_length (str));
362 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
366 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
371 /* modified version needed to handle building corlib */
373 my_mono_class_from_mono_type (MonoType *type) {
374 switch (type->type) {
375 case MONO_TYPE_ARRAY:
377 case MONO_TYPE_SZARRAY:
378 case MONO_TYPE_GENERICINST:
379 return mono_class_from_mono_type (type);
382 g_assert (type->data.generic_param->pklass);
383 return type->data.generic_param->pklass;
385 /* should be always valid when we reach this case... */
386 return type->data.klass;
391 default_class_from_mono_type (MonoType *type)
393 switch (type->type) {
394 case MONO_TYPE_OBJECT:
395 return mono_defaults.object_class;
397 return mono_defaults.void_class;
398 case MONO_TYPE_BOOLEAN:
399 return mono_defaults.boolean_class;
401 return mono_defaults.char_class;
403 return mono_defaults.sbyte_class;
405 return mono_defaults.byte_class;
407 return mono_defaults.int16_class;
409 return mono_defaults.uint16_class;
411 return mono_defaults.int32_class;
413 return mono_defaults.uint32_class;
415 return mono_defaults.int_class;
417 return mono_defaults.uint_class;
419 return mono_defaults.int64_class;
421 return mono_defaults.uint64_class;
423 return mono_defaults.single_class;
425 return mono_defaults.double_class;
426 case MONO_TYPE_STRING:
427 return mono_defaults.string_class;
429 g_warning ("implement me 0x%02x\n", type->type);
430 g_assert_not_reached ();
437 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, char *p, char **endbuf)
442 g_assert_not_reached ();
446 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
447 encode_type (assembly, &gclass->container_class->byval_arg, p, &p);
448 mono_metadata_encode_value (gclass->inst->type_argc, p, &p);
449 for (i = 0; i < gclass->inst->type_argc; ++i)
450 encode_type (assembly, gclass->inst->type_argv [i], p, &p);
456 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
459 g_assert_not_reached ();
464 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
468 case MONO_TYPE_BOOLEAN:
482 case MONO_TYPE_STRING:
483 case MONO_TYPE_OBJECT:
484 case MONO_TYPE_TYPEDBYREF:
485 mono_metadata_encode_value (type->type, p, &p);
488 mono_metadata_encode_value (type->type, p, &p);
489 encode_type (assembly, type->data.type, p, &p);
491 case MONO_TYPE_SZARRAY:
492 mono_metadata_encode_value (type->type, p, &p);
493 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
495 case MONO_TYPE_VALUETYPE:
496 case MONO_TYPE_CLASS: {
497 MonoClass *k = mono_class_from_mono_type (type);
498 mono_metadata_encode_value (type->type, p, &p);
500 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
501 * otherwise two typerefs could point to the same type, leading to
502 * verification errors.
504 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
507 case MONO_TYPE_ARRAY:
508 mono_metadata_encode_value (type->type, p, &p);
509 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
510 mono_metadata_encode_value (type->data.array->rank, p, &p);
511 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
512 mono_metadata_encode_value (0, p, &p);
514 case MONO_TYPE_GENERICINST:
515 encode_generic_class (assembly, type->data.generic_class, p, &p);
519 mono_metadata_encode_value (type->type, p, &p);
520 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
523 g_error ("need to encode type %x", type->type);
529 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
532 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
536 encode_type (assembly, type->type, p, endbuf);
540 g_assert_not_reached ();
545 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
550 for (i = 0; i < mono_array_length (modreq); ++i) {
551 MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
552 *p = MONO_TYPE_CMOD_REQD;
554 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
558 for (i = 0; i < mono_array_length (modopt); ++i) {
559 MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
560 *p = MONO_TYPE_CMOD_OPT;
562 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
569 generic_class_get_signature_size (MonoGenericClass *gclass)
575 g_assert_not_reached ();
578 size += 1 + type_get_signature_size (&gclass->container_class->byval_arg);
580 for (i = 0; i < gclass->inst->type_argc; ++i)
581 size += type_get_signature_size (gclass->inst->type_argv [i]);
587 type_get_signature_size (MonoType *type)
592 g_assert_not_reached ();
600 case MONO_TYPE_BOOLEAN:
614 case MONO_TYPE_STRING:
615 case MONO_TYPE_OBJECT:
616 case MONO_TYPE_TYPEDBYREF:
619 return size + 1 + type_get_signature_size (type->data.type);
620 case MONO_TYPE_SZARRAY:
621 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
622 case MONO_TYPE_VALUETYPE:
623 case MONO_TYPE_CLASS:
625 case MONO_TYPE_ARRAY:
626 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
627 case MONO_TYPE_GENERICINST:
628 return size + generic_class_get_signature_size (type->data.generic_class);
633 g_error ("need to encode type %x", type->type);
639 method_get_signature_size (MonoMethodSignature *sig)
644 size = type_get_signature_size (sig->ret);
645 for (i = 0; i < sig->param_count; i++)
646 size += type_get_signature_size (sig->params [i]);
648 if (sig->generic_param_count)
650 if (sig->sentinelpos >= 0)
657 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
662 guint32 nparams = sig->param_count;
663 guint32 size = 11 + method_get_signature_size (sig);
671 p = buf = g_malloc (size);
673 * FIXME: vararg, explicit_this, differenc call_conv values...
675 *p = sig->call_convention;
677 *p |= 0x20; /* hasthis */
678 if (sig->generic_param_count)
679 *p |= 0x10; /* generic */
681 if (sig->generic_param_count)
682 mono_metadata_encode_value (sig->generic_param_count, p, &p);
683 mono_metadata_encode_value (nparams, p, &p);
684 encode_type (assembly, sig->ret, p, &p);
685 for (i = 0; i < nparams; ++i) {
686 if (i == sig->sentinelpos)
687 *p++ = MONO_TYPE_SENTINEL;
688 encode_type (assembly, sig->params [i], p, &p);
691 g_assert (p - buf < size);
692 mono_metadata_encode_value (p-buf, b, &b);
693 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
699 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
702 * FIXME: reuse code from method_encode_signature().
707 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
708 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
709 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
710 guint32 size = 41 + nparams * 40 + notypes * 40;
715 p = buf = g_malloc (size);
716 /* LAMESPEC: all the call conv spec is foobared */
717 *p = mb->call_conv & 0x60; /* has-this, explicit-this */
718 if (mb->call_conv & 2)
719 *p |= 0x5; /* vararg */
720 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
721 *p |= 0x20; /* hasthis */
723 *p |= 0x10; /* generic */
726 mono_metadata_encode_value (ngparams, p, &p);
727 mono_metadata_encode_value (nparams + notypes, p, &p);
728 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
729 encode_reflection_type (assembly, mb->rtype, p, &p);
730 for (i = 0; i < nparams; ++i) {
731 MonoArray *modreq = NULL;
732 MonoArray *modopt = NULL;
733 MonoReflectionType *pt;
735 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
736 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
737 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
738 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
739 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
740 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
741 encode_reflection_type (assembly, pt, p, &p);
744 *p++ = MONO_TYPE_SENTINEL;
745 for (i = 0; i < notypes; ++i) {
746 MonoReflectionType *pt;
748 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
749 encode_reflection_type (assembly, pt, p, &p);
753 g_assert (p - buf < size);
754 mono_metadata_encode_value (p-buf, b, &b);
755 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
761 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
763 MonoDynamicTable *table;
766 guint32 idx, sig_idx, size;
767 guint nl = mono_array_length (ilgen->locals);
774 p = buf = g_malloc (size);
775 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
776 idx = table->next_idx ++;
778 alloc_table (table, table->rows);
779 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
781 mono_metadata_encode_value (0x07, p, &p);
782 mono_metadata_encode_value (nl, p, &p);
783 for (i = 0; i < nl; ++i) {
784 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
787 mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
789 encode_reflection_type (assembly, lb->type, p, &p);
791 g_assert (p - buf < size);
792 mono_metadata_encode_value (p-buf, b, &b);
793 sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
796 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
802 method_count_clauses (MonoReflectionILGen *ilgen)
804 guint32 num_clauses = 0;
807 MonoILExceptionInfo *ex_info;
808 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
809 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
810 if (ex_info->handlers)
811 num_clauses += mono_array_length (ex_info->handlers);
819 static MonoExceptionClause*
820 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
822 MonoExceptionClause *clauses;
823 MonoExceptionClause *clause;
824 MonoILExceptionInfo *ex_info;
825 MonoILExceptionBlock *ex_block;
826 guint32 finally_start;
827 int i, j, clause_index;;
829 clauses = g_new0 (MonoExceptionClause, num_clauses);
832 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
833 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
834 finally_start = ex_info->start + ex_info->len;
835 g_assert (ex_info->handlers);
836 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
837 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
838 clause = &(clauses [clause_index]);
840 clause->flags = ex_block->type;
841 clause->try_offset = ex_info->start;
843 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
844 clause->try_len = finally_start - ex_info->start;
846 clause->try_len = ex_info->len;
847 clause->handler_offset = ex_block->start;
848 clause->handler_len = ex_block->len;
849 if (ex_block->extype) {
850 clause->data.catch_class = mono_class_from_mono_type (ex_block->extype->type);
852 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
853 clause->data.filter_offset = ex_block->filter_offset;
855 clause->data.filter_offset = 0;
857 finally_start = ex_block->start + ex_block->len;
867 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
873 gint32 num_locals = 0;
874 gint32 num_exception = 0;
877 char fat_header [12];
880 guint32 local_sig = 0;
881 guint32 header_size = 12;
884 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
885 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
889 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
891 code = mb->ilgen->code;
892 code_size = mb->ilgen->code_len;
893 max_stack = mb->ilgen->max_stack;
894 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
895 if (mb->ilgen->ex_handlers)
896 num_exception = method_count_clauses (mb->ilgen);
900 char *name = mono_string_to_utf8 (mb->name);
901 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
902 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
905 mono_raise_exception (exception);
908 code_size = mono_array_length (code);
909 max_stack = 8; /* we probably need to run a verifier on the code... */
912 stream_data_align (&assembly->code);
914 /* check for exceptions, maxstack, locals */
915 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
917 if (code_size < 64 && !(code_size & 1)) {
918 flags = (code_size << 2) | 0x2;
919 } else if (code_size < 32 && (code_size & 1)) {
920 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
924 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
925 /* add to the fixup todo list */
926 if (mb->ilgen && mb->ilgen->num_token_fixups)
927 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
928 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
929 return assembly->text_rva + idx;
933 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
935 * FIXME: need to set also the header size in fat_flags.
936 * (and more sects and init locals flags)
940 fat_flags |= METHOD_HEADER_MORE_SECTS;
942 fat_flags |= METHOD_HEADER_INIT_LOCALS;
943 fat_header [0] = fat_flags;
944 fat_header [1] = (header_size / 4 ) << 4;
945 shortp = (guint16*)(fat_header + 2);
946 *shortp = GUINT16_TO_LE (max_stack);
947 intp = (guint32*)(fat_header + 4);
948 *intp = GUINT32_TO_LE (code_size);
949 intp = (guint32*)(fat_header + 8);
950 *intp = GUINT32_TO_LE (local_sig);
951 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
952 /* add to the fixup todo list */
953 if (mb->ilgen && mb->ilgen->num_token_fixups)
954 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
956 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
958 unsigned char sheader [4];
959 MonoILExceptionInfo * ex_info;
960 MonoILExceptionBlock * ex_block;
963 stream_data_align (&assembly->code);
964 /* always use fat format for now */
965 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
966 num_exception *= 6 * sizeof (guint32);
967 num_exception += 4; /* include the size of the header */
968 sheader [1] = num_exception & 0xff;
969 sheader [2] = (num_exception >> 8) & 0xff;
970 sheader [3] = (num_exception >> 16) & 0xff;
971 mono_image_add_stream_data (&assembly->code, sheader, 4);
972 /* fat header, so we are already aligned */
974 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
975 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
976 if (ex_info->handlers) {
977 int finally_start = ex_info->start + ex_info->len;
978 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
980 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
982 val = GUINT32_TO_LE (ex_block->type);
983 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
985 val = GUINT32_TO_LE (ex_info->start);
986 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
987 /* need fault, too, probably */
988 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
989 val = GUINT32_TO_LE (finally_start - ex_info->start);
991 val = GUINT32_TO_LE (ex_info->len);
992 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
994 val = GUINT32_TO_LE (ex_block->start);
995 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
997 val = GUINT32_TO_LE (ex_block->len);
998 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
999 finally_start = ex_block->start + ex_block->len;
1000 if (ex_block->extype) {
1001 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, ex_block->extype->type));
1003 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1004 val = ex_block->filter_offset;
1008 val = GUINT32_TO_LE (val);
1009 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1010 /*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",
1011 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);*/
1014 g_error ("No clauses for ex info block %d", i);
1018 return assembly->text_rva + idx;
1022 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1025 MonoDynamicTable *table;
1028 table = &assembly->tables [table_idx];
1030 g_assert (col < table->columns);
1032 values = table->values + table->columns;
1033 for (i = 1; i <= table->rows; ++i) {
1034 if (values [col] == token)
1036 values += table->columns;
1041 static GHashTable *dynamic_custom_attrs = NULL;
1043 static MonoCustomAttrInfo*
1044 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1047 MonoCustomAttrInfo *ainfo;
1048 MonoReflectionCustomAttr *cattr;
1052 /* FIXME: check in assembly the Run flag is set */
1054 count = mono_array_length (cattrs);
1056 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1058 ainfo->image = image;
1059 ainfo->num_attrs = count;
1060 for (i = 0; i < count; ++i) {
1061 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1062 ainfo->attrs [i].ctor = cattr->ctor->method;
1063 /* FIXME: might want to memdup the data here */
1064 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1065 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1072 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1074 MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1079 if (!dynamic_custom_attrs)
1080 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1082 g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1083 ainfo->cached = TRUE;
1087 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1089 /* they are cached, so we don't free them */
1090 if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1096 * idx is the table index of the object
1097 * type is one of MONO_CUSTOM_ATTR_*
1100 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1102 MonoDynamicTable *table;
1103 MonoReflectionCustomAttr *cattr;
1105 guint32 count, i, token;
1107 char *p = blob_size;
1109 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1112 count = mono_array_length (cattrs);
1113 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1114 table->rows += count;
1115 alloc_table (table, table->rows);
1116 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1117 idx <<= MONO_CUSTOM_ATTR_BITS;
1119 for (i = 0; i < count; ++i) {
1120 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1121 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1122 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1123 type = mono_metadata_token_index (token);
1124 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1125 switch (mono_metadata_token_table (token)) {
1126 case MONO_TABLE_METHOD:
1127 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1129 case MONO_TABLE_MEMBERREF:
1130 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1133 g_warning ("got wrong token in custom attr");
1136 values [MONO_CUSTOM_ATTR_TYPE] = type;
1138 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1139 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1140 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1141 values += MONO_CUSTOM_ATTR_SIZE;
1147 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1149 MonoDynamicTable *table;
1151 guint32 count, i, idx;
1152 MonoReflectionPermissionSet *perm;
1157 count = mono_array_length (permissions);
1158 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1159 table->rows += count;
1160 alloc_table (table, table->rows);
1162 for (i = 0; i < mono_array_length (permissions); ++i) {
1163 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1165 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1167 idx = mono_metadata_token_index (parent_token);
1168 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1169 switch (mono_metadata_token_table (parent_token)) {
1170 case MONO_TABLE_TYPEDEF:
1171 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1173 case MONO_TABLE_METHOD:
1174 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1176 case MONO_TABLE_ASSEMBLY:
1177 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1180 g_assert_not_reached ();
1183 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1184 values [MONO_DECL_SECURITY_PARENT] = idx;
1185 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1192 * Fill in the MethodDef and ParamDef tables for a method.
1193 * This is used for both normal methods and constructors.
1196 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1198 MonoDynamicTable *table;
1203 /* room in this table is already allocated */
1204 table = &assembly->tables [MONO_TABLE_METHOD];
1205 *mb->table_idx = table->next_idx ++;
1206 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1207 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1208 name = mono_string_to_utf8 (mb->name);
1209 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1211 values [MONO_METHOD_FLAGS] = mb->attrs;
1212 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1213 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1214 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1216 table = &assembly->tables [MONO_TABLE_PARAM];
1217 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1219 mono_image_add_decl_security (assembly,
1220 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1223 MonoDynamicTable *mtable;
1226 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1227 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1230 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1231 if (mono_array_get (mb->pinfo, gpointer, i))
1234 table->rows += count;
1235 alloc_table (table, table->rows);
1236 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1237 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1238 MonoReflectionParamBuilder *pb;
1239 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1240 values [MONO_PARAM_FLAGS] = pb->attrs;
1241 values [MONO_PARAM_SEQUENCE] = i;
1242 if (pb->name != NULL) {
1243 name = mono_string_to_utf8 (pb->name);
1244 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1247 values [MONO_PARAM_NAME] = 0;
1249 values += MONO_PARAM_SIZE;
1250 if (pb->marshal_info) {
1252 alloc_table (mtable, mtable->rows);
1253 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1254 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1255 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1257 pb->table_idx = table->next_idx++;
1258 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1259 guint32 field_type = 0;
1260 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1262 alloc_table (mtable, mtable->rows);
1263 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1264 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1265 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1266 mvalues [MONO_CONSTANT_TYPE] = field_type;
1267 mvalues [MONO_CONSTANT_PADDING] = 0;
1275 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1277 rmb->ilgen = mb->ilgen;
1278 rmb->rtype = mb->rtype;
1279 rmb->parameters = mb->parameters;
1280 rmb->generic_params = mb->generic_params;
1281 rmb->generic_container = mb->generic_container;
1282 rmb->opt_types = NULL;
1283 rmb->pinfo = mb->pinfo;
1284 rmb->attrs = mb->attrs;
1285 rmb->iattrs = mb->iattrs;
1286 rmb->call_conv = mb->call_conv;
1287 rmb->code = mb->code;
1288 rmb->type = mb->type;
1289 rmb->name = mb->name;
1290 rmb->table_idx = &mb->table_idx;
1291 rmb->init_locals = mb->init_locals;
1292 rmb->return_modreq = mb->return_modreq;
1293 rmb->return_modopt = mb->return_modopt;
1294 rmb->param_modreq = mb->param_modreq;
1295 rmb->param_modopt = mb->param_modopt;
1296 rmb->permissions = mb->permissions;
1297 rmb->mhandle = mb->mhandle;
1302 rmb->charset = mb->charset;
1303 rmb->extra_flags = mb->extra_flags;
1304 rmb->native_cc = mb->native_cc;
1305 rmb->dllentry = mb->dllentry;
1311 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1313 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1315 rmb->ilgen = mb->ilgen;
1316 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1317 rmb->parameters = mb->parameters;
1318 rmb->generic_params = NULL;
1319 rmb->generic_container = NULL;
1320 rmb->opt_types = NULL;
1321 rmb->pinfo = mb->pinfo;
1322 rmb->attrs = mb->attrs;
1323 rmb->iattrs = mb->iattrs;
1324 rmb->call_conv = mb->call_conv;
1326 rmb->type = mb->type;
1327 rmb->name = mono_string_new (mono_domain_get (), name);
1328 rmb->table_idx = &mb->table_idx;
1329 rmb->init_locals = mb->init_locals;
1330 rmb->return_modreq = NULL;
1331 rmb->return_modopt = NULL;
1332 rmb->param_modreq = mb->param_modreq;
1333 rmb->param_modopt = mb->param_modopt;
1334 rmb->permissions = mb->permissions;
1335 rmb->mhandle = mb->mhandle;
1341 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1343 rmb->ilgen = mb->ilgen;
1344 rmb->rtype = mb->rtype;
1345 rmb->parameters = mb->parameters;
1346 rmb->generic_params = NULL;
1347 rmb->generic_container = NULL;
1348 rmb->opt_types = NULL;
1350 rmb->attrs = mb->attrs;
1352 rmb->call_conv = mb->call_conv;
1355 rmb->name = mb->name;
1356 rmb->table_idx = NULL;
1357 rmb->init_locals = mb->init_locals;
1358 rmb->return_modreq = NULL;
1359 rmb->return_modopt = NULL;
1360 rmb->param_modreq = NULL;
1361 rmb->param_modopt = NULL;
1362 rmb->permissions = NULL;
1363 rmb->mhandle = mb->mhandle;
1369 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1371 MonoDynamicTable *table;
1374 ReflectionMethodBuilder rmb;
1377 reflection_methodbuilder_from_method_builder (&rmb, mb);
1379 mono_image_basic_method (&rmb, assembly);
1380 mb->table_idx = *rmb.table_idx;
1382 if (mb->dll) { /* It's a P/Invoke method */
1384 /* map CharSet values to on-disk values */
1385 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1386 int extra_flags = mb->extra_flags;
1387 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1389 alloc_table (table, table->rows);
1390 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1392 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1393 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1395 name = mono_string_to_utf8 (mb->dllentry);
1397 name = mono_string_to_utf8 (mb->name);
1398 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1400 name = mono_string_to_utf8 (mb->dll);
1401 moduleref = string_heap_insert (&assembly->sheap, name);
1403 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1404 table = &assembly->tables [MONO_TABLE_MODULEREF];
1406 alloc_table (table, table->rows);
1407 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1408 values [MONO_IMPLMAP_SCOPE] = table->rows;
1412 if (mb->override_method) {
1413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1415 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1417 alloc_table (table, table->rows);
1418 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1419 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1420 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1422 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1423 switch (mono_metadata_token_table (tok)) {
1424 case MONO_TABLE_MEMBERREF:
1425 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1427 case MONO_TABLE_METHOD:
1428 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1431 g_assert_not_reached ();
1433 values [MONO_METHODIMPL_DECLARATION] = tok;
1436 if (mb->generic_params) {
1437 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1438 table->rows += mono_array_length (mb->generic_params);
1439 alloc_table (table, table->rows);
1440 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1441 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1443 mono_image_get_generic_param_info (
1444 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1451 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1453 ReflectionMethodBuilder rmb;
1455 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1457 mono_image_basic_method (&rmb, assembly);
1458 mb->table_idx = *rmb.table_idx;
1462 type_get_fully_qualified_name (MonoType *type)
1464 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1468 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1472 klass = my_mono_class_from_mono_type (type);
1474 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1475 ta = klass->image->assembly;
1476 if (ta->dynamic || (ta == ass))
1477 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1479 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1483 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1485 char blob_size [64];
1486 char *b = blob_size;
1491 if (!assembly->save)
1494 p = buf = g_malloc (256);
1496 mono_metadata_encode_value (0x06, p, &p);
1497 /* encode custom attributes before the type */
1498 encode_type (assembly, type, p, &p);
1499 g_assert (p-buf < 256);
1500 mono_metadata_encode_value (p-buf, b, &b);
1501 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1507 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1509 char blob_size [64];
1510 char *b = blob_size;
1515 p = buf = g_malloc (256);
1517 mono_metadata_encode_value (0x06, p, &p);
1518 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1519 /* encode custom attributes before the type */
1520 encode_reflection_type (assembly, fb->type, p, &p);
1521 g_assert (p-buf < 256);
1522 mono_metadata_encode_value (p-buf, b, &b);
1523 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1529 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1530 char blob_size [64];
1531 char *b = blob_size;
1534 guint32 idx = 0, len = 0, dummy = 0;
1536 p = buf = g_malloc (64);
1538 *ret_type = MONO_TYPE_CLASS;
1540 box_val = (char*)&dummy;
1542 box_val = ((char*)val) + sizeof (MonoObject);
1543 *ret_type = val->vtable->klass->byval_arg.type;
1546 switch (*ret_type) {
1547 case MONO_TYPE_BOOLEAN:
1552 case MONO_TYPE_CHAR:
1567 case MONO_TYPE_VALUETYPE:
1568 if (val->vtable->klass->enumtype) {
1569 *ret_type = val->vtable->klass->enum_basetype->type;
1572 g_error ("we can't encode valuetypes");
1573 case MONO_TYPE_CLASS:
1575 case MONO_TYPE_STRING: {
1576 MonoString *str = (MonoString*)val;
1577 /* there is no signature */
1578 len = str->length * 2;
1579 mono_metadata_encode_value (len, b, &b);
1580 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1582 char *swapped = g_malloc (2 * mono_string_length (str));
1583 const char *p = (const char*)mono_string_chars (str);
1585 swap_with_size (swapped, p, 2, mono_string_length (str));
1586 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1590 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1597 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1600 /* there is no signature */
1601 mono_metadata_encode_value (len, b, &b);
1602 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1603 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1604 swap_with_size (blob_size, box_val, len, 1);
1605 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1607 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1615 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1616 char blob_size [64];
1617 char *b = blob_size;
1618 char *p, *buf, *str;
1619 guint32 idx, len, bufsize = 256;
1621 p = buf = g_malloc (bufsize);
1623 mono_metadata_encode_value (minfo->type, p, &p);
1625 switch (minfo->type) {
1626 case MONO_NATIVE_BYVALTSTR:
1627 case MONO_NATIVE_BYVALARRAY:
1628 mono_metadata_encode_value (minfo->count, p, &p);
1630 case MONO_NATIVE_LPARRAY:
1631 if (minfo->eltype || minfo->has_size) {
1632 mono_metadata_encode_value (minfo->eltype, p, &p);
1633 if (minfo->has_size) {
1634 if (minfo->param_num != -1)
1635 mono_metadata_encode_value (minfo->param_num, p, &p);
1637 mono_metadata_encode_value (0, p, &p);
1638 if (minfo->count != -1)
1639 mono_metadata_encode_value (minfo->count, p, &p);
1641 mono_metadata_encode_value (0, p, &p);
1643 /* LAMESPEC: ElemMult is undocumented */
1644 if (minfo->param_num != -1)
1645 mono_metadata_encode_value (1, p, &p);
1647 mono_metadata_encode_value (0, p, &p);
1651 case MONO_NATIVE_CUSTOM:
1653 str = mono_string_to_utf8 (minfo->guid);
1655 mono_metadata_encode_value (len, p, &p);
1656 memcpy (p, str, len);
1660 mono_metadata_encode_value (0, p, &p);
1662 /* native type name */
1663 mono_metadata_encode_value (0, p, &p);
1664 /* custom marshaler type name */
1665 if (minfo->marshaltype || minfo->marshaltyperef) {
1666 if (minfo->marshaltyperef)
1667 str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1669 str = mono_string_to_utf8 (minfo->marshaltype);
1671 mono_metadata_encode_value (len, p, &p);
1672 if (p + len >= buf + bufsize) {
1675 buf = g_realloc (buf, bufsize);
1678 memcpy (p, str, len);
1682 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1683 mono_metadata_encode_value (0, p, &p);
1685 if (minfo->mcookie) {
1686 str = mono_string_to_utf8 (minfo->mcookie);
1688 mono_metadata_encode_value (len, p, &p);
1689 if (p + len >= buf + bufsize) {
1692 buf = g_realloc (buf, bufsize);
1695 memcpy (p, str, len);
1699 mono_metadata_encode_value (0, p, &p);
1706 mono_metadata_encode_value (len, b, &b);
1707 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1713 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1715 MonoDynamicTable *table;
1719 /* maybe this fixup should be done in the C# code */
1720 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1721 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1722 table = &assembly->tables [MONO_TABLE_FIELD];
1723 fb->table_idx = table->next_idx ++;
1724 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1725 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1726 name = mono_string_to_utf8 (fb->name);
1727 values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1729 values [MONO_FIELD_FLAGS] = fb->attrs;
1730 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1732 if (fb->offset != -1) {
1733 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1735 alloc_table (table, table->rows);
1736 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1737 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1738 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1740 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1741 guint32 field_type = 0;
1742 table = &assembly->tables [MONO_TABLE_CONSTANT];
1744 alloc_table (table, table->rows);
1745 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1746 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1747 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1748 values [MONO_CONSTANT_TYPE] = field_type;
1749 values [MONO_CONSTANT_PADDING] = 0;
1751 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1753 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1755 alloc_table (table, table->rows);
1756 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1757 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1759 * We store it in the code section because it's simpler for now.
1762 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1764 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1765 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1767 if (fb->marshal_info) {
1768 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1770 alloc_table (table, table->rows);
1771 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1772 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1773 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1778 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1782 char *b = blob_size;
1783 guint32 nparams = 0;
1784 MonoReflectionMethodBuilder *mb = fb->get_method;
1785 MonoReflectionMethodBuilder *smb = fb->set_method;
1786 guint32 idx, i, size;
1788 if (mb && mb->parameters)
1789 nparams = mono_array_length (mb->parameters);
1790 if (!mb && smb && smb->parameters)
1791 nparams = mono_array_length (smb->parameters) - 1;
1792 size = 24 + nparams * 10;
1793 buf = p = g_malloc (size);
1796 mono_metadata_encode_value (nparams, p, &p);
1798 encode_reflection_type (assembly, mb->rtype, p, &p);
1799 for (i = 0; i < nparams; ++i) {
1800 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1801 encode_reflection_type (assembly, pt, p, &p);
1804 /* the property type is the last param */
1805 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1806 for (i = 0; i < nparams; ++i) {
1807 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1808 encode_reflection_type (assembly, pt, p, &p);
1812 encode_reflection_type (assembly, fb->type, p, &p);
1816 g_assert (p - buf < size);
1817 mono_metadata_encode_value (p-buf, b, &b);
1818 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1824 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1826 MonoDynamicTable *table;
1829 guint num_methods = 0;
1833 * we need to set things in the following tables:
1834 * PROPERTYMAP (info already filled in _get_type_info ())
1835 * PROPERTY (rows already preallocated in _get_type_info ())
1836 * METHOD (method info already done with the generic method code)
1839 table = &assembly->tables [MONO_TABLE_PROPERTY];
1840 pb->table_idx = table->next_idx ++;
1841 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1842 name = mono_string_to_utf8 (pb->name);
1843 values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1845 values [MONO_PROPERTY_FLAGS] = pb->attrs;
1846 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1848 /* FIXME: we still don't handle 'other' methods */
1849 if (pb->get_method) num_methods ++;
1850 if (pb->set_method) num_methods ++;
1852 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1853 table->rows += num_methods;
1854 alloc_table (table, table->rows);
1856 if (pb->get_method) {
1857 semaidx = table->next_idx ++;
1858 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1859 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1860 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1861 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1863 if (pb->set_method) {
1864 semaidx = table->next_idx ++;
1865 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1866 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1867 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1868 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1873 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1875 MonoDynamicTable *table;
1878 guint num_methods = 0;
1882 * we need to set things in the following tables:
1883 * EVENTMAP (info already filled in _get_type_info ())
1884 * EVENT (rows already preallocated in _get_type_info ())
1885 * METHOD (method info already done with the generic method code)
1888 table = &assembly->tables [MONO_TABLE_EVENT];
1889 eb->table_idx = table->next_idx ++;
1890 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1891 name = mono_string_to_utf8 (eb->name);
1892 values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1894 values [MONO_EVENT_FLAGS] = eb->attrs;
1895 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1898 * FIXME: we still don't handle 'other' methods
1900 if (eb->add_method) num_methods ++;
1901 if (eb->remove_method) num_methods ++;
1902 if (eb->raise_method) num_methods ++;
1904 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1905 table->rows += num_methods;
1906 alloc_table (table, table->rows);
1908 if (eb->add_method) {
1909 semaidx = table->next_idx ++;
1910 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1911 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1912 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1913 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1915 if (eb->remove_method) {
1916 semaidx = table->next_idx ++;
1917 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1918 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1919 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1920 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1922 if (eb->raise_method) {
1923 semaidx = table->next_idx ++;
1924 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1925 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1926 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1927 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1932 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1934 static MonoClass *NewConstraintAttr;
1935 static MonoMethod *NewConstraintAttr_ctor;
1936 MonoDynamicTable *table;
1938 guint32 token, type;
1939 char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1942 if (!NewConstraintAttr)
1943 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib,
1944 "System.Runtime.CompilerServices", "NewConstraintAttribute");
1945 g_assert (NewConstraintAttr);
1947 if (!NewConstraintAttr_ctor) {
1948 NewConstraintAttr_ctor = mono_class_get_method_from_name (NewConstraintAttr, ".ctor", -1);
1949 g_assert (NewConstraintAttr_ctor);
1952 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1954 alloc_table (table, table->rows);
1956 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1957 owner <<= MONO_CUSTOM_ATTR_BITS;
1958 owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1959 values [MONO_CUSTOM_ATTR_PARENT] = owner;
1961 token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1963 type = mono_metadata_token_index (token);
1964 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1965 switch (mono_metadata_token_table (token)) {
1966 case MONO_TABLE_METHOD:
1967 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1969 case MONO_TABLE_MEMBERREF:
1970 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1973 g_warning ("got wrong token in custom attr");
1976 values [MONO_CUSTOM_ATTR_TYPE] = type;
1978 buf = p = g_malloc (1);
1979 mono_metadata_encode_value (4, p, &p);
1980 g_assert (p-buf == 1);
1982 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
1984 values += MONO_CUSTOM_ATTR_SIZE;
1989 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
1991 MonoDynamicTable *table;
1992 guint32 num_constraints, i;
1996 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
1997 num_constraints = gparam->iface_constraints ?
1998 mono_array_length (gparam->iface_constraints) : 0;
1999 table->rows += num_constraints;
2000 if (gparam->base_type)
2002 alloc_table (table, table->rows);
2004 if (gparam->base_type) {
2005 table_idx = table->next_idx ++;
2006 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2008 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2009 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2010 assembly, gparam->base_type->type);
2013 for (i = 0; i < num_constraints; i++) {
2014 MonoReflectionType *constraint = mono_array_get (
2015 gparam->iface_constraints, gpointer, i);
2017 table_idx = table->next_idx ++;
2018 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2020 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2021 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2022 assembly, constraint->type);
2025 if (gparam->attrs & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT)
2026 encode_new_constraint (assembly, owner);
2030 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2032 GenericParamTableEntry *entry;
2035 * The GenericParam table must be sorted according to the `owner' field.
2036 * We need to do this sorting prior to writing the GenericParamConstraint
2037 * table, since we have to use the final GenericParam table indices there
2038 * and they must also be sorted.
2041 entry = g_new0 (GenericParamTableEntry, 1);
2042 entry->owner = owner;
2043 entry->gparam = gparam;
2045 g_ptr_array_add (assembly->gen_params, entry);
2049 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2051 MonoDynamicTable *table;
2052 MonoGenericParam *param;
2056 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2057 table_idx = table->next_idx ++;
2058 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2060 param = entry->gparam->type.type->data.generic_param;
2062 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2063 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2064 values [MONO_GENERICPARAM_NUMBER] = param->num;
2065 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2067 encode_constraints (entry->gparam, table_idx, assembly);
2071 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2073 MonoDynamicTable *table;
2076 guint32 cols [MONO_ASSEMBLY_SIZE];
2080 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2083 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2084 table = &assembly->tables [MONO_TABLE_MODULEREF];
2085 token = table->next_idx ++;
2087 alloc_table (table, table->rows);
2088 values = table->values + token * MONO_MODULEREF_SIZE;
2089 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2091 token <<= MONO_RESOLTION_SCOPE_BITS;
2092 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2093 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2098 if (image->assembly->dynamic)
2100 memset (cols, 0, sizeof (cols));
2102 /* image->assembly->image is the manifest module */
2103 image = image->assembly->image;
2104 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2107 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2108 token = table->next_idx ++;
2110 alloc_table (table, table->rows);
2111 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2112 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2113 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2114 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2115 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2116 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2117 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2118 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2119 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2121 if (strcmp ("", image->assembly->aname.culture)) {
2122 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2123 image->assembly->aname.culture);
2126 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2127 guchar pubtoken [9];
2129 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2130 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2132 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2134 token <<= MONO_RESOLTION_SCOPE_BITS;
2135 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2136 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2141 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2143 MonoDynamicTable *table;
2149 char *b = blob_size;
2151 switch (type->type) {
2152 case MONO_TYPE_FNPTR:
2154 case MONO_TYPE_SZARRAY:
2155 case MONO_TYPE_ARRAY:
2157 case MONO_TYPE_MVAR:
2158 case MONO_TYPE_GENERICINST:
2159 encode_type (assembly, type, p, &p);
2161 case MONO_TYPE_CLASS:
2162 case MONO_TYPE_VALUETYPE: {
2163 MonoClass *k = mono_class_from_mono_type (type);
2164 if (!k || !k->generic_class)
2166 encode_generic_class (assembly, k->generic_class, p, &p);
2173 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2174 if (assembly->save) {
2175 g_assert (p-sig < 128);
2176 mono_metadata_encode_value (p-sig, b, &b);
2177 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2178 alloc_table (table, table->rows + 1);
2179 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2180 values [MONO_TYPESPEC_SIGNATURE] = token;
2183 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2184 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2190 * Despite the name, we handle also TypeSpec (with the above helper).
2193 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2195 MonoDynamicTable *table;
2197 guint32 token, scope, enclosing;
2200 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2203 token = create_typespec (assembly, type);
2206 klass = my_mono_class_from_mono_type (type);
2208 klass = mono_class_from_mono_type (type);
2211 * If it's in the same module and not a generic type parameter:
2213 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2214 (type->type != MONO_TYPE_MVAR)) {
2215 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2216 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2217 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2221 if (klass->nested_in) {
2222 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2223 /* get the typeref idx of the enclosing type */
2224 enclosing >>= MONO_TYPEDEFORREF_BITS;
2225 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2227 scope = resolution_scope_from_image (assembly, klass->image);
2229 table = &assembly->tables [MONO_TABLE_TYPEREF];
2230 if (assembly->save) {
2231 alloc_table (table, table->rows + 1);
2232 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2233 values [MONO_TYPEREF_SCOPE] = scope;
2234 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2235 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2237 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2238 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2240 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2245 * Insert a memberef row into the metadata: the token that point to the memberref
2246 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2247 * mono_image_get_fieldref_token()).
2248 * The sig param is an index to an already built signature.
2251 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2253 MonoDynamicTable *table;
2255 guint32 token, pclass;
2258 parent = mono_image_typedef_or_ref (assembly, type);
2259 switch (parent & MONO_TYPEDEFORREF_MASK) {
2260 case MONO_TYPEDEFORREF_TYPEREF:
2261 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2263 case MONO_TYPEDEFORREF_TYPESPEC:
2264 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2266 case MONO_TYPEDEFORREF_TYPEDEF:
2267 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2270 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2273 /* extract the index */
2274 parent >>= MONO_TYPEDEFORREF_BITS;
2276 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2278 if (assembly->save) {
2279 alloc_table (table, table->rows + 1);
2280 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2281 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2282 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2283 values [MONO_MEMBERREF_SIGNATURE] = sig;
2286 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2293 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2296 MonoMethodSignature *sig;
2298 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2303 * A methodref signature can't contain an unmanaged calling convention.
2305 sig = mono_metadata_signature_dup (mono_method_signature (method));
2306 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2307 sig->call_convention = MONO_CALL_DEFAULT;
2308 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2309 method->name, method_encode_signature (assembly, sig));
2311 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2316 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2317 const gchar *name, guint32 sig)
2319 MonoDynamicTable *table;
2323 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2325 if (assembly->save) {
2326 alloc_table (table, table->rows + 1);
2327 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2328 values [MONO_MEMBERREF_CLASS] = original;
2329 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2330 values [MONO_MEMBERREF_SIGNATURE] = sig;
2333 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2340 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2343 ReflectionMethodBuilder rmb;
2345 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2349 reflection_methodbuilder_from_method_builder (&rmb, mb);
2351 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2352 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2353 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2358 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2361 ReflectionMethodBuilder rmb;
2363 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2367 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2369 token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2370 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2371 g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2376 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2381 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2384 g_assert (f->field->parent);
2385 type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2386 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2387 f->field->name, fieldref_encode_signature (assembly, type));
2388 g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2393 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2398 guint32 nparams = gmethod->inst->type_argc;
2399 guint32 size = 10 + nparams * 30;
2402 char *b = blob_size;
2404 if (!assembly->save)
2407 p = buf = g_malloc (size);
2409 * FIXME: vararg, explicit_this, differenc call_conv values...
2411 mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2412 mono_metadata_encode_value (nparams, p, &p);
2414 for (i = 0; i < nparams; i++)
2415 encode_type (assembly, gmethod->inst->type_argv [i], p, &p);
2418 g_assert (p - buf < size);
2419 mono_metadata_encode_value (p-buf, b, &b);
2420 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2426 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2428 MonoDynamicTable *table;
2430 guint32 token, mtoken = 0, sig;
2431 MonoMethodInflated *imethod;
2432 MonoMethod *declaring;
2434 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2436 g_assert (method->is_inflated);
2437 method = mono_get_inflated_method (method);
2438 imethod = (MonoMethodInflated *) method;
2439 declaring = imethod->declaring;
2441 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2442 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2444 if (!mono_method_signature (declaring)->generic_param_count)
2447 switch (mono_metadata_token_table (mtoken)) {
2448 case MONO_TABLE_MEMBERREF:
2449 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2451 case MONO_TABLE_METHOD:
2452 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2455 g_assert_not_reached ();
2458 sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2460 if (assembly->save) {
2461 alloc_table (table, table->rows + 1);
2462 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2463 values [MONO_METHODSPEC_METHOD] = mtoken;
2464 values [MONO_METHODSPEC_SIGNATURE] = sig;
2467 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2474 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2476 MonoMethodInflated *imethod;
2479 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2483 g_assert (m->is_inflated);
2484 m = mono_get_inflated_method (m);
2485 imethod = (MonoMethodInflated *) m;
2487 if (mono_method_signature (imethod->declaring)->generic_param_count) {
2488 token = method_encode_methodspec (assembly, m);
2490 guint32 sig = method_encode_signature (
2491 assembly, mono_method_signature (imethod->declaring));
2492 token = mono_image_get_memberref_token (
2493 assembly, &m->klass->byval_arg, m->name, sig);
2496 g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2501 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2503 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2506 m = mono_get_inflated_method (m);
2508 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
2509 token = mono_image_get_memberref_token (
2510 assembly, &m->klass->byval_arg, m->name, sig);
2516 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2518 MonoDynamicTable *table;
2525 char *b = blob_size;
2529 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2530 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2531 * Because of this, we must not insert it into the `typeref' hash table.
2534 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2538 g_assert (tb->generic_params);
2539 klass = mono_class_from_mono_type (tb->type.type);
2541 mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2542 encode_type (assembly, &klass->byval_arg, p, &p);
2544 count = mono_array_length (tb->generic_params);
2545 mono_metadata_encode_value (count, p, &p);
2546 for (i = 0; i < count; i++) {
2547 MonoReflectionGenericParam *gparam;
2549 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2551 encode_type (assembly, gparam->type.type, p, &p);
2554 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2555 g_assert (p-sig < 128);
2557 if (assembly->save) {
2558 mono_metadata_encode_value (p-sig, b, &b);
2559 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2560 alloc_table (table, table->rows + 1);
2561 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2562 values [MONO_TYPESPEC_SIGNATURE] = token;
2565 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2566 g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2572 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2574 MonoDynamicTable *table;
2577 guint32 token, pclass, parent, sig;
2580 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2584 klass = mono_class_from_mono_type (fb->typeb->type);
2585 name = mono_string_to_utf8 (fb->name);
2587 sig = fieldref_encode_signature (assembly, fb->type->type);
2589 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2590 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2592 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2593 parent >>= MONO_TYPEDEFORREF_BITS;
2595 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2597 if (assembly->save) {
2598 alloc_table (table, table->rows + 1);
2599 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2600 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2601 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2602 values [MONO_MEMBERREF_SIGNATURE] = sig;
2605 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2607 g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2612 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2620 char *b = blob_size;
2622 if (!assembly->save)
2626 g_assert (helper->type == 2);
2628 if (helper->arguments)
2629 nargs = mono_array_length (helper->arguments);
2633 size = 10 + (nargs * 10);
2635 p = buf = g_malloc (size);
2637 /* Encode calling convention */
2638 /* Change Any to Standard */
2639 if ((helper->call_conv & 0x03) == 0x03)
2640 helper->call_conv = 0x01;
2641 /* explicit_this implies has_this */
2642 if (helper->call_conv & 0x40)
2643 helper->call_conv &= 0x20;
2645 if (helper->call_conv == 0) { /* Unmanaged */
2646 *p = helper->unmanaged_call_conv - 1;
2649 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2650 if (helper->call_conv & 0x02) /* varargs */
2655 mono_metadata_encode_value (nargs, p, &p);
2656 encode_reflection_type (assembly, helper->return_type, p, &p);
2657 for (i = 0; i < nargs; ++i) {
2658 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2659 encode_reflection_type (assembly, pt, p, &p);
2662 g_assert (p - buf < size);
2663 mono_metadata_encode_value (p-buf, b, &b);
2664 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2671 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2674 MonoDynamicTable *table;
2677 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2678 idx = table->next_idx ++;
2680 alloc_table (table, table->rows);
2681 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2683 values [MONO_STAND_ALONE_SIGNATURE] =
2684 mono_reflection_encode_sighelper (assembly, helper);
2690 reflection_cc_to_file (int call_conv) {
2691 switch (call_conv & 0x3) {
2693 case 1: return MONO_CALL_DEFAULT;
2694 case 2: return MONO_CALL_VARARG;
2696 g_assert_not_reached ();
2703 MonoMethodSignature *sig;
2709 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2714 MonoMethodSignature *sig;
2717 name = mono_string_to_utf8 (m->name);
2718 nparams = mono_array_length (m->parameters);
2719 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2721 sig->sentinelpos = -1;
2722 sig->call_convention = reflection_cc_to_file (m->call_conv);
2723 sig->param_count = nparams;
2724 sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2725 for (i = 0; i < nparams; ++i) {
2726 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2727 sig->params [i] = t->type;
2730 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2732 if (strcmp (name, am->name) == 0 &&
2733 mono_metadata_type_equal (am->parent, m->parent->type) &&
2734 mono_metadata_signature_equal (am->sig, sig)) {
2737 m->table_idx = am->token & 0xffffff;
2741 am = g_new0 (ArrayMethod, 1);
2744 am->parent = m->parent->type;
2745 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2746 method_encode_signature (assembly, sig));
2747 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2748 m->table_idx = am->token & 0xffffff;
2753 * Insert into the metadata tables all the info about the TypeBuilder tb.
2754 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2757 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2759 MonoDynamicTable *table;
2761 int i, is_object = 0, is_system = 0;
2764 table = &assembly->tables [MONO_TABLE_TYPEDEF];
2765 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2766 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2767 n = mono_string_to_utf8 (tb->name);
2768 if (strcmp (n, "Object") == 0)
2770 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2772 n = mono_string_to_utf8 (tb->nspace);
2773 if (strcmp (n, "System") == 0)
2775 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2777 if (tb->parent && !(is_system && is_object) &&
2778 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2779 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2781 values [MONO_TYPEDEF_EXTENDS] = 0;
2783 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2784 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2787 * if we have explicitlayout or sequentiallayouts, output data in the
2788 * ClassLayout table.
2790 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2791 ((tb->class_size > 0) || (tb->packing_size > 0))) {
2792 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2794 alloc_table (table, table->rows);
2795 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2796 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2797 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2798 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2801 /* handle interfaces */
2802 if (tb->interfaces) {
2803 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2805 table->rows += mono_array_length (tb->interfaces);
2806 alloc_table (table, table->rows);
2807 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2808 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2809 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2810 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2811 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2812 values += MONO_INTERFACEIMPL_SIZE;
2818 table = &assembly->tables [MONO_TABLE_FIELD];
2819 table->rows += tb->num_fields;
2820 alloc_table (table, table->rows);
2821 for (i = 0; i < tb->num_fields; ++i)
2822 mono_image_get_field_info (
2823 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2826 /* handle constructors */
2828 table = &assembly->tables [MONO_TABLE_METHOD];
2829 table->rows += mono_array_length (tb->ctors);
2830 alloc_table (table, table->rows);
2831 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2832 mono_image_get_ctor_info (domain,
2833 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2836 /* handle methods */
2838 table = &assembly->tables [MONO_TABLE_METHOD];
2839 table->rows += tb->num_methods;
2840 alloc_table (table, table->rows);
2841 for (i = 0; i < tb->num_methods; ++i)
2842 mono_image_get_method_info (
2843 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2846 /* Do the same with properties etc.. */
2847 if (tb->events && mono_array_length (tb->events)) {
2848 table = &assembly->tables [MONO_TABLE_EVENT];
2849 table->rows += mono_array_length (tb->events);
2850 alloc_table (table, table->rows);
2851 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2853 alloc_table (table, table->rows);
2854 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2855 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2856 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2857 for (i = 0; i < mono_array_length (tb->events); ++i)
2858 mono_image_get_event_info (
2859 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2861 if (tb->properties && mono_array_length (tb->properties)) {
2862 table = &assembly->tables [MONO_TABLE_PROPERTY];
2863 table->rows += mono_array_length (tb->properties);
2864 alloc_table (table, table->rows);
2865 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2867 alloc_table (table, table->rows);
2868 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2869 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2870 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2871 for (i = 0; i < mono_array_length (tb->properties); ++i)
2872 mono_image_get_property_info (
2873 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2876 /* handle generic parameters */
2877 if (tb->generic_params) {
2878 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2879 table->rows += mono_array_length (tb->generic_params);
2880 alloc_table (table, table->rows);
2881 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2882 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2884 mono_image_get_generic_param_info (
2885 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2889 mono_image_add_decl_security (assembly,
2890 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2893 MonoDynamicTable *ntable;
2895 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2896 ntable->rows += mono_array_length (tb->subtypes);
2897 alloc_table (ntable, ntable->rows);
2898 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2900 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2901 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2903 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2904 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2905 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2906 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2907 mono_string_to_utf8 (tb->name), tb->table_idx,
2908 ntable->next_idx, ntable->rows);*/
2909 values += MONO_NESTED_CLASS_SIZE;
2916 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2920 g_ptr_array_add (types, type);
2922 if (!type->subtypes)
2925 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2926 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2927 collect_types (types, subtype);
2932 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2934 if ((*type1)->table_idx < (*type2)->table_idx)
2937 if ((*type1)->table_idx > (*type2)->table_idx)
2944 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2949 for (i = 0; i < mono_array_length (pinfo); ++i) {
2950 MonoReflectionParamBuilder *pb;
2951 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2954 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2959 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2962 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2964 for (i = 0; i < tb->num_fields; ++i) {
2965 MonoReflectionFieldBuilder* fb;
2966 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2967 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2971 for (i = 0; i < mono_array_length (tb->events); ++i) {
2972 MonoReflectionEventBuilder* eb;
2973 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2974 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2977 if (tb->properties) {
2978 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2979 MonoReflectionPropertyBuilder* pb;
2980 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2981 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
2985 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2986 MonoReflectionCtorBuilder* cb;
2987 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2988 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
2989 params_add_cattrs (assembly, cb->pinfo);
2994 for (i = 0; i < tb->num_methods; ++i) {
2995 MonoReflectionMethodBuilder* mb;
2996 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2997 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
2998 params_add_cattrs (assembly, mb->pinfo);
3003 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3004 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3009 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3012 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3014 /* no types in the module */
3018 for (i = 0; i < mb->num_types; ++i)
3019 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3023 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3025 MonoDynamicTable *table;
3029 char *b = blob_size;
3032 table = &assembly->tables [MONO_TABLE_FILE];
3034 alloc_table (table, table->rows);
3035 values = table->values + table->next_idx * MONO_FILE_SIZE;
3036 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3037 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3038 if (module->image->dynamic) {
3039 /* This depends on the fact that the main module is emitted last */
3040 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3041 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3044 path = g_strdup (module->image->name);
3046 mono_sha1_get_digest_from_file (path, hash);
3049 mono_metadata_encode_value (20, b, &b);
3050 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3051 mono_image_add_stream_data (&assembly->blob, hash, 20);
3056 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3058 MonoDynamicTable *table;
3062 table = &assembly->tables [MONO_TABLE_MODULE];
3063 mb->table_idx = table->next_idx ++;
3064 name = mono_string_to_utf8 (mb->module.name);
3065 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3067 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3070 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3071 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3072 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3073 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3077 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3078 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3080 MonoDynamicTable *table;
3084 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3085 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3088 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3090 alloc_table (table, table->rows);
3091 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3093 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3094 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3095 if (klass->nested_in)
3096 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3098 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3099 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3100 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3102 res = table->next_idx;
3106 /* Emit nested types */
3107 if (klass->nested_classes) {
3110 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3111 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3118 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3119 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3124 klass = mono_class_from_mono_type (tb->type.type);
3126 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3128 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3129 parent_index, assembly);
3133 * We need to do this ourselves since klass->nested_classes is not set up.
3136 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3137 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3142 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3143 guint32 module_index, MonoDynamicImage *assembly)
3145 MonoImage *image = module->image;
3149 t = &image->tables [MONO_TABLE_TYPEDEF];
3151 for (i = 0; i < t->rows; ++i) {
3152 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3154 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3155 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3159 #define align_pointer(base,p)\
3161 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3163 (p) += 4 - (__diff & 3);\
3167 compare_constants (const void *a, const void *b)
3169 const guint32 *a_values = a;
3170 const guint32 *b_values = b;
3171 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3175 compare_semantics (const void *a, const void *b)
3177 const guint32 *a_values = a;
3178 const guint32 *b_values = b;
3179 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3182 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3186 compare_custom_attrs (const void *a, const void *b)
3188 const guint32 *a_values = a;
3189 const guint32 *b_values = b;
3191 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3195 compare_field_marshal (const void *a, const void *b)
3197 const guint32 *a_values = a;
3198 const guint32 *b_values = b;
3200 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3204 compare_nested (const void *a, const void *b)
3206 const guint32 *a_values = a;
3207 const guint32 *b_values = b;
3209 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3213 compare_genericparam (const void *a, const void *b)
3215 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3216 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3218 if ((*b_entry)->owner == (*a_entry)->owner)
3220 (*a_entry)->gparam->type.type->data.generic_param->num -
3221 (*b_entry)->gparam->type.type->data.generic_param->num;
3223 return (*a_entry)->owner - (*b_entry)->owner;
3227 compare_declsecurity_attrs (const void *a, const void *b)
3229 const guint32 *a_values = a;
3230 const guint32 *b_values = b;
3232 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3236 pad_heap (MonoDynamicStream *sh)
3238 if (sh->index & 3) {
3239 int sz = 4 - (sh->index & 3);
3240 memset (sh->data + sh->index, 0, sz);
3247 MonoDynamicStream *stream;
3251 * build_compressed_metadata() fills in the blob of data that represents the
3252 * raw metadata as it will be saved in the PE file. The five streams are output
3253 * and the metadata tables are comnpressed from the guint32 array representation,
3254 * to the compressed on-disk format.
3257 build_compressed_metadata (MonoDynamicImage *assembly)
3259 MonoDynamicTable *table;
3261 guint64 valid_mask = 0;
3262 guint64 sorted_mask;
3263 guint32 heapt_size = 0;
3264 guint32 meta_size = 256; /* allow for header and other stuff */
3265 guint32 table_offset;
3266 guint32 ntables = 0;
3272 struct StreamDesc stream_desc [5];
3274 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3275 for (i = 0; i < assembly->gen_params->len; i++){
3276 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3277 write_generic_param_entry (assembly, entry);
3280 stream_desc [0].name = "#~";
3281 stream_desc [0].stream = &assembly->tstream;
3282 stream_desc [1].name = "#Strings";
3283 stream_desc [1].stream = &assembly->sheap;
3284 stream_desc [2].name = "#US";
3285 stream_desc [2].stream = &assembly->us;
3286 stream_desc [3].name = "#Blob";
3287 stream_desc [3].stream = &assembly->blob;
3288 stream_desc [4].name = "#GUID";
3289 stream_desc [4].stream = &assembly->guid;
3291 /* tables that are sorted */
3292 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3293 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3294 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3295 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3296 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3297 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3299 /* Compute table sizes */
3300 /* the MonoImage has already been created in mono_image_basic_init() */
3301 meta = &assembly->image;
3303 /* sizes should be multiple of 4 */
3304 pad_heap (&assembly->blob);
3305 pad_heap (&assembly->guid);
3306 pad_heap (&assembly->sheap);
3307 pad_heap (&assembly->us);
3309 /* Setup the info used by compute_sizes () */
3310 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3311 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3312 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3314 meta_size += assembly->blob.index;
3315 meta_size += assembly->guid.index;
3316 meta_size += assembly->sheap.index;
3317 meta_size += assembly->us.index;
3319 for (i=0; i < MONO_TABLE_NUM; ++i)
3320 meta->tables [i].rows = assembly->tables [i].rows;
3322 for (i = 0; i < MONO_TABLE_NUM; i++){
3323 if (meta->tables [i].rows == 0)
3325 valid_mask |= (guint64)1 << i;
3327 meta->tables [i].row_size = mono_metadata_compute_size (
3328 meta, i, &meta->tables [i].size_bitfield);
3329 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3331 heapt_size += 24; /* #~ header size */
3332 heapt_size += ntables * 4;
3333 /* make multiple of 4 */
3336 meta_size += heapt_size;
3337 meta->raw_metadata = g_malloc0 (meta_size);
3338 p = meta->raw_metadata;
3339 /* the metadata signature */
3340 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3341 /* version numbers and 4 bytes reserved */
3342 int16val = (guint16*)p;
3343 *int16val++ = GUINT16_TO_LE (1);
3344 *int16val = GUINT16_TO_LE (1);
3346 /* version string */
3347 int32val = (guint32*)p;
3348 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3350 memcpy (p, meta->version, strlen (meta->version));
3351 p += GUINT32_FROM_LE (*int32val);
3352 align_pointer (meta->raw_metadata, p);
3353 int16val = (guint16*)p;
3354 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3355 *int16val = GUINT16_TO_LE (5); /* number of streams */
3359 * write the stream info.
3361 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3362 table_offset += 3; table_offset &= ~3;
3364 assembly->tstream.index = heapt_size;
3365 for (i = 0; i < 5; ++i) {
3366 int32val = (guint32*)p;
3367 stream_desc [i].stream->offset = table_offset;
3368 *int32val++ = GUINT32_TO_LE (table_offset);
3369 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3370 table_offset += GUINT32_FROM_LE (*int32val);
3371 table_offset += 3; table_offset &= ~3;
3373 strcpy (p, stream_desc [i].name);
3374 p += strlen (stream_desc [i].name) + 1;
3375 align_pointer (meta->raw_metadata, p);
3378 * now copy the data, the table stream header and contents goes first.
3380 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3381 p = meta->raw_metadata + assembly->tstream.offset;
3382 int32val = (guint32*)p;
3383 *int32val = GUINT32_TO_LE (0); /* reserved */
3386 if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3387 (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3388 (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3389 *p++ = 2; /* version */
3392 *p++ = 1; /* version */
3396 if (meta->idx_string_wide)
3398 if (meta->idx_guid_wide)
3400 if (meta->idx_blob_wide)
3403 *p++ = 1; /* reserved */
3404 int64val = (guint64*)p;
3405 *int64val++ = GUINT64_TO_LE (valid_mask);
3406 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
3408 int32val = (guint32*)p;
3409 for (i = 0; i < MONO_TABLE_NUM; i++){
3410 if (meta->tables [i].rows == 0)
3412 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3414 p = (unsigned char*)int32val;
3416 /* sort the tables that still need sorting */
3417 table = &assembly->tables [MONO_TABLE_CONSTANT];
3419 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
3420 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3422 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3423 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3425 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3426 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3428 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3429 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3431 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3432 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3433 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3435 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3437 /* compress the tables */
3438 for (i = 0; i < MONO_TABLE_NUM; i++){
3441 guint32 bitfield = meta->tables [i].size_bitfield;
3442 if (!meta->tables [i].rows)
3444 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3445 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3446 meta->tables [i].base = p;
3447 for (row = 1; row <= meta->tables [i].rows; ++row) {
3448 values = assembly->tables [i].values + row * assembly->tables [i].columns;
3449 for (col = 0; col < assembly->tables [i].columns; ++col) {
3450 switch (mono_metadata_table_size (bitfield, col)) {
3452 *p++ = values [col];
3455 *p++ = values [col] & 0xff;
3456 *p++ = (values [col] >> 8) & 0xff;
3459 *p++ = values [col] & 0xff;
3460 *p++ = (values [col] >> 8) & 0xff;
3461 *p++ = (values [col] >> 16) & 0xff;
3462 *p++ = (values [col] >> 24) & 0xff;
3465 g_assert_not_reached ();
3469 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3472 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3473 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3474 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3475 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3476 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3478 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 * Some tables in metadata need to be sorted according to some criteria, but
3483 * when methods and fields are first created with reflection, they may be assigned a token
3484 * that doesn't correspond to the final token they will get assigned after the sorting.
3485 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3486 * with the reflection objects that represent them. Once all the tables are set up, the
3487 * reflection objects will contains the correct table index. fixup_method() will fixup the
3488 * tokens for the method with ILGenerator @ilgen.
3491 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3492 guint32 code_idx = GPOINTER_TO_UINT (value);
3493 MonoReflectionILTokenInfo *iltoken;
3494 MonoReflectionFieldBuilder *field;
3495 MonoReflectionCtorBuilder *ctor;
3496 MonoReflectionMethodBuilder *method;
3497 MonoReflectionTypeBuilder *tb;
3498 MonoReflectionArrayMethod *am;
3500 unsigned char *target;
3502 for (i = 0; i < ilgen->num_token_fixups; ++i) {
3503 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3504 target = assembly->code.data + code_idx + iltoken->code_pos;
3505 switch (target [3]) {
3506 case MONO_TABLE_FIELD:
3507 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3508 field = (MonoReflectionFieldBuilder *)iltoken->member;
3509 idx = field->table_idx;
3510 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3511 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3512 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
3514 g_assert_not_reached ();
3517 case MONO_TABLE_METHOD:
3518 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3519 method = (MonoReflectionMethodBuilder *)iltoken->member;
3520 idx = method->table_idx;
3521 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3522 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3523 idx = ctor->table_idx;
3524 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3525 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3526 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3527 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3529 g_assert_not_reached ();
3532 case MONO_TABLE_TYPEDEF:
3533 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3534 g_assert_not_reached ();
3535 tb = (MonoReflectionTypeBuilder *)iltoken->member;
3536 idx = tb->table_idx;
3538 case MONO_TABLE_MEMBERREF:
3539 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3540 am = (MonoReflectionArrayMethod*)iltoken->member;
3541 idx = am->table_idx;
3542 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3543 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
3544 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
3545 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
3546 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3547 g_assert (m->klass->generic_class || m->klass->generic_container);
3549 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3551 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3552 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3553 g_assert (f->generic_info);
3555 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3558 g_assert_not_reached ();
3561 case MONO_TABLE_METHODSPEC:
3562 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
3563 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3564 g_assert (mono_method_signature (m)->generic_param_count);
3567 g_assert_not_reached ();
3571 g_error ("got unexpected table 0x%02x in fixup", target [3]);
3573 target [0] = idx & 0xff;
3574 target [1] = (idx >> 8) & 0xff;
3575 target [2] = (idx >> 16) & 0xff;
3582 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3583 * value is not known when the table is emitted.
3586 fixup_cattrs (MonoDynamicImage *assembly)
3588 MonoDynamicTable *table;
3590 guint32 type, i, idx, token;
3593 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3595 for (i = 0; i < table->rows; ++i) {
3596 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3598 type = values [MONO_CUSTOM_ATTR_TYPE];
3599 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3600 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3601 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3602 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3605 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3606 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3607 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
3608 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3617 * The METHODIMPL table might contain METHODDEF tokens whose final
3618 * value is not known when the table is emitted.
3621 fixup_methodimpl (MonoDynamicImage *assembly)
3623 MonoDynamicTable *table;
3625 guint32 decl, i, idx, token;
3628 table = &assembly->tables [MONO_TABLE_METHODIMPL];
3630 for (i = 0; i < table->rows; ++i) {
3631 values = table->values + ((i + 1) * MONO_METHODIMPL_SIZE);
3632 decl = values [MONO_METHODIMPL_DECLARATION];
3634 idx = decl >> MONO_METHODDEFORREF_BITS;
3635 if ((decl & MONO_METHODDEFORREF_MASK) != MONO_METHODDEFORREF_METHODDEF)
3638 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3639 method = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3642 if (!strcmp (method->vtable->klass->name, "MethodBuilder")) {
3643 token = mono_image_create_token (assembly, method, FALSE);
3644 idx = mono_metadata_token_index (token);
3645 values [MONO_METHODIMPL_DECLARATION] = (idx << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3651 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3653 MonoDynamicTable *table;
3657 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3659 alloc_table (table, table->rows);
3660 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3661 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3662 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3663 name = mono_string_to_utf8 (rsrc->name);
3664 values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3666 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3671 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3673 MonoDynamicTable *table;
3677 char *b = blob_size;
3679 guint32 idx, offset;
3681 if (rsrc->filename) {
3682 name = mono_string_to_utf8 (rsrc->filename);
3683 sname = g_path_get_basename (name);
3685 table = &assembly->tables [MONO_TABLE_FILE];
3687 alloc_table (table, table->rows);
3688 values = table->values + table->next_idx * MONO_FILE_SIZE;
3689 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3690 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3693 mono_sha1_get_digest_from_file (name, hash);
3694 mono_metadata_encode_value (20, b, &b);
3695 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3696 mono_image_add_stream_data (&assembly->blob, hash, 20);
3698 idx = table->next_idx++;
3700 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3703 offset = mono_array_length (rsrc->data);
3704 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3705 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3706 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3707 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3711 * The entry should be emitted into the MANIFESTRESOURCE table of
3712 * the main module, but that needs to reference the FILE table
3713 * which isn't emitted yet.
3720 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3724 set_version_from_string (MonoString *version, guint32 *values)
3726 gchar *ver, *p, *str;
3729 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3730 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3731 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3732 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3735 ver = str = mono_string_to_utf8 (version);
3736 for (i = 0; i < 4; ++i) {
3737 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3743 /* handle Revision and Build */
3753 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3757 char *b = blob_size;
3762 len = mono_array_length (pkey);
3763 mono_metadata_encode_value (len, b, &b);
3764 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3765 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3767 /* need to get the actual value from the key type... */
3768 assembly->strong_name_size = 128;
3769 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3775 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3777 MonoDynamicTable *table;
3778 MonoDynamicImage *assembly;
3779 MonoReflectionAssemblyBuilder *assemblyb;
3784 guint32 module_index;
3786 assemblyb = moduleb->assemblyb;
3787 assembly = moduleb->dynamic_image;
3788 domain = mono_object_domain (assemblyb);
3790 /* Emit ASSEMBLY table */
3791 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3792 alloc_table (table, 1);
3793 values = table->values + MONO_ASSEMBLY_SIZE;
3794 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3795 name = mono_string_to_utf8 (assemblyb->name);
3796 values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3798 if (assemblyb->culture) {
3799 name = mono_string_to_utf8 (assemblyb->culture);
3800 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3803 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3805 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3806 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3807 set_version_from_string (assemblyb->version, values);
3809 /* Emit FILE + EXPORTED_TYPE table */
3811 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3813 MonoReflectionModuleBuilder *file_module =
3814 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3815 if (file_module != moduleb) {
3816 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3818 if (file_module->types) {
3819 for (j = 0; j < file_module->num_types; ++j) {
3820 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3821 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3826 if (assemblyb->loaded_modules) {
3827 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3828 MonoReflectionModule *file_module =
3829 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3830 mono_image_fill_file_table (domain, file_module, assembly);
3832 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3836 /* Emit MANIFESTRESOURCE table */
3838 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3840 MonoReflectionModuleBuilder *file_module =
3841 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3842 /* The table for the main module is emitted later */
3843 if (file_module != moduleb) {
3845 if (file_module->resources) {
3846 int len = mono_array_length (file_module->resources);
3847 for (j = 0; j < len; ++j) {
3848 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3849 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3857 * mono_image_build_metadata() will fill the info in all the needed metadata tables
3858 * for the modulebuilder @moduleb.
3859 * At the end of the process, method and field tokens are fixed up and the
3860 * on-disk compressed metadata representation is created.
3863 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3865 MonoDynamicTable *table;
3866 MonoDynamicImage *assembly;
3867 MonoReflectionAssemblyBuilder *assemblyb;
3872 assemblyb = moduleb->assemblyb;
3873 assembly = moduleb->dynamic_image;
3874 domain = mono_object_domain (assemblyb);
3876 if (assembly->text_rva)
3879 assembly->text_rva = START_TEXT_RVA;
3881 if (moduleb->is_main) {
3882 mono_image_emit_manifest (moduleb);
3885 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3886 table->rows = 1; /* .<Module> */
3888 alloc_table (table, table->rows);
3890 * Set the first entry.
3892 values = table->values + table->columns;
3893 values [MONO_TYPEDEF_FLAGS] = 0;
3894 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3895 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3896 values [MONO_TYPEDEF_EXTENDS] = 0;
3897 values [MONO_TYPEDEF_FIELD_LIST] = 1;
3898 values [MONO_TYPEDEF_METHOD_LIST] = 1;
3901 * handle global methods
3902 * FIXME: test what to do when global methods are defined in multiple modules.
3904 if (moduleb->global_methods) {
3905 table = &assembly->tables [MONO_TABLE_METHOD];
3906 table->rows += mono_array_length (moduleb->global_methods);
3907 alloc_table (table, table->rows);
3908 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3909 mono_image_get_method_info (
3910 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3912 if (moduleb->global_fields) {
3913 table = &assembly->tables [MONO_TABLE_FIELD];
3914 table->rows += mono_array_length (moduleb->global_fields);
3915 alloc_table (table, table->rows);
3916 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3917 mono_image_get_field_info (
3918 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3921 table = &assembly->tables [MONO_TABLE_MODULE];
3922 alloc_table (table, 1);
3923 mono_image_fill_module_table (domain, moduleb, assembly);
3927 /* Collect all types into a list sorted by their table_idx */
3928 GPtrArray *types = g_ptr_array_new ();
3931 for (i = 0; i < moduleb->num_types; ++i) {
3932 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3933 collect_types (types, type);
3936 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3937 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3938 table->rows += types->len;
3939 alloc_table (table, table->rows);
3941 for (i = 0; i < types->len; ++i) {
3942 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3943 mono_image_get_type_info (domain, type, assembly);
3945 g_ptr_array_free (types, TRUE);
3949 * table->rows is already set above and in mono_image_fill_module_table.
3951 /* add all the custom attributes at the end, once all the indexes are stable */
3952 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3954 /* CAS assembly permissions */
3955 if (assemblyb->permissions_minimum)
3956 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3957 if (assemblyb->permissions_optional)
3958 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3959 if (assemblyb->permissions_refused)
3960 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3962 module_add_cattrs (assembly, moduleb);
3965 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3966 fixup_cattrs (assembly);
3967 fixup_methodimpl (assembly);
3971 * mono_image_insert_string:
3972 * @module: module builder object
3975 * Insert @str into the user string stream of @module.
3978 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3980 MonoDynamicImage *assembly;
3985 MONO_ARCH_SAVE_REGS;
3987 if (!module->dynamic_image)
3988 mono_image_module_basic_init (module);
3990 assembly = module->dynamic_image;
3992 if (assembly->save) {
3993 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3994 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3995 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3997 char *swapped = g_malloc (2 * mono_string_length (str));
3998 const char *p = (const char*)mono_string_chars (str);
4000 swap_with_size (swapped, p, 2, mono_string_length (str));
4001 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4005 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4007 mono_image_add_stream_data (&assembly->us, "", 1);
4009 idx = assembly->us.index ++;
4012 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4014 return MONO_TOKEN_STRING | idx;
4018 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4023 klass = obj->vtable->klass;
4024 if (strcmp (klass->name, "MonoMethod") == 0) {
4025 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4026 MonoMethodSignature *sig, *old;
4027 guint32 sig_token, parent;
4030 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4032 nargs = mono_array_length (opt_param_types);
4033 old = mono_method_signature (method);
4034 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4036 sig->hasthis = old->hasthis;
4037 sig->explicit_this = old->explicit_this;
4038 sig->call_convention = old->call_convention;
4039 sig->generic_param_count = old->generic_param_count;
4040 sig->param_count = old->param_count + nargs;
4041 sig->sentinelpos = old->param_count;
4042 sig->ret = old->ret;
4044 for (i = 0; i < old->param_count; i++)
4045 sig->params [i] = old->params [i];
4047 for (i = 0; i < nargs; i++) {
4048 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4049 sig->params [old->param_count + i] = rt->type;
4052 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4053 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4054 parent >>= MONO_TYPEDEFORREF_BITS;
4056 parent <<= MONO_MEMBERREF_PARENT_BITS;
4057 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4059 sig_token = method_encode_signature (assembly, sig);
4060 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4061 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4062 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4063 ReflectionMethodBuilder rmb;
4064 guint32 parent, sig;
4066 reflection_methodbuilder_from_method_builder (&rmb, mb);
4067 rmb.opt_types = opt_param_types;
4069 sig = method_builder_encode_signature (assembly, &rmb);
4071 parent = mono_image_create_token (assembly, obj, TRUE);
4072 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4074 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4075 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4077 token = mono_image_get_varargs_method_token (
4078 assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4080 g_error ("requested method token for %s\n", klass->name);
4087 * mono_image_create_token:
4088 * @assembly: a dynamic assembly
4091 * Get a token to insert in the IL code stream for the given MemberInfo.
4092 * @obj can be one of:
4093 * ConstructorBuilder
4103 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4108 klass = obj->vtable->klass;
4109 if (strcmp (klass->name, "MethodBuilder") == 0) {
4110 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4112 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4113 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4115 token = mono_image_get_methodbuilder_token (assembly, mb);
4116 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4117 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4118 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4120 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4121 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4123 token = mono_image_get_ctorbuilder_token (assembly, mb);
4124 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4125 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4126 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4127 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4128 if (tb->generic_params) {
4129 token = mono_image_get_generic_field_token (assembly, fb);
4131 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4133 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4134 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4135 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4136 } else if (strcmp (klass->name, "MonoType") == 0 ||
4137 strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4138 MonoReflectionType *tb = (MonoReflectionType *)obj;
4139 token = mono_metadata_token_from_dor (
4140 mono_image_typedef_or_ref (assembly, tb->type));
4141 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4142 MonoReflectionType *tb = (MonoReflectionType *)obj;
4143 token = mono_metadata_token_from_dor (
4144 mono_image_typedef_or_ref (assembly, tb->type));
4145 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4146 strcmp (klass->name, "MonoMethod") == 0 ||
4147 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4148 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4149 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4150 if (m->method->is_inflated) {
4151 if (create_methodspec)
4152 token = mono_image_get_methodspec_token (assembly, m->method);
4154 token = mono_image_get_inflated_method_token (assembly, m->method);
4155 } else if ((m->method->klass->image == &assembly->image) &&
4156 !m->method->klass->generic_class) {
4157 static guint32 method_table_idx = 0xffffff;
4158 if (m->method->klass->wastypebuilder) {
4159 /* we use the same token as the one that was assigned
4160 * to the Methodbuilder.
4161 * FIXME: do the equivalent for Fields.
4163 token = m->method->token;
4166 * Each token should have a unique index, but the indexes are
4167 * assigned by managed code, so we don't know about them. An
4168 * easy solution is to count backwards...
4170 method_table_idx --;
4171 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4174 token = mono_image_get_methodref_token (assembly, m->method);
4176 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4177 } else if (strcmp (klass->name, "MonoField") == 0) {
4178 MonoReflectionField *f = (MonoReflectionField *)obj;
4179 if ((f->field->parent->image == &assembly->image) && !f->field->generic_info) {
4180 static guint32 field_table_idx = 0xffffff;
4182 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4184 token = mono_image_get_fieldref_token (assembly, f);
4186 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4187 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4188 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4189 token = mono_image_get_array_token (assembly, m);
4190 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4191 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4192 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4194 g_error ("requested token for %s\n", klass->name);
4197 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4203 guint32 import_lookup_table;
4207 guint32 import_address_table_rva;
4215 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4217 static MonoDynamicImage*
4218 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4220 static const guchar entrycode [16] = {0xff, 0x25, 0};
4221 MonoDynamicImage *image;
4224 const char *version = mono_get_runtime_info ()->runtime_version;
4227 image = GC_MALLOC (sizeof (MonoDynamicImage));
4229 image = g_new0 (MonoDynamicImage, 1);
4232 /*g_print ("created image %p\n", image);*/
4233 /* keep in sync with image.c */
4234 image->image.name = assembly_name;
4235 image->image.assembly_name = image->image.name; /* they may be different */
4236 image->image.module_name = module_name;
4237 image->image.version = version;
4238 image->image.dynamic = TRUE;
4239 image->image.ref_count = 1;
4241 image->image.references = g_new0 (MonoAssembly*, 1);
4242 image->image.references [0] = NULL;
4244 mono_image_init (&image->image);
4246 image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4247 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
4248 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
4249 image->method_aux_hash = g_hash_table_new (NULL, NULL);
4250 image->handleref = g_hash_table_new (NULL, NULL);
4251 image->tokens = mono_g_hash_table_new (NULL, NULL);
4252 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4253 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4254 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4255 image->gen_params = g_ptr_array_new ();
4257 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4258 string_heap_init (&image->sheap);
4259 mono_image_add_stream_data (&image->us, "", 1);
4260 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4261 /* import tables... */
4262 mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4263 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4264 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4265 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4266 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4267 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4268 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4269 stream_data_align (&image->code);
4271 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4273 for (i=0; i < MONO_TABLE_NUM; ++i) {
4274 image->tables [i].next_idx = 1;
4275 image->tables [i].columns = table_sizes [i];
4278 image->image.assembly = (MonoAssembly*)assembly;
4279 image->run = assembly->run;
4280 image->save = assembly->save;
4281 image->pe_kind = 0x1; /* ILOnly */
4282 image->machine = 0x14c; /* I386 */
4288 * mono_image_basic_init:
4289 * @assembly: an assembly builder object
4291 * Create the MonoImage that represents the assembly builder and setup some
4292 * of the helper hash table and the basic metadata streams.
4295 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4297 MonoDynamicAssembly *assembly;
4298 MonoDynamicImage *image;
4299 MonoDomain *domain = mono_object_domain (assemblyb);
4301 MONO_ARCH_SAVE_REGS;
4303 if (assemblyb->dynamic_assembly)
4307 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4309 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
4312 assembly->assembly.ref_count = 1;
4313 assembly->assembly.dynamic = TRUE;
4314 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
4315 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4316 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4317 if (assemblyb->culture)
4318 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4320 assembly->assembly.aname.culture = g_strdup ("");
4322 if (assemblyb->version) {
4323 char **version = g_strsplit (mono_string_to_utf8 (assemblyb->version), ".", 4);
4324 char **parts = version;
4325 assembly->assembly.aname.major = atoi (*parts++);
4326 assembly->assembly.aname.minor = atoi (*parts++);
4327 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
4328 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
4330 g_strfreev (version);
4332 assembly->assembly.aname.major = 0;
4333 assembly->assembly.aname.minor = 0;
4334 assembly->assembly.aname.build = 0;
4335 assembly->assembly.aname.revision = 0;
4338 assembly->run = assemblyb->access != 2;
4339 assembly->save = assemblyb->access != 1;
4341 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4342 image->initial_image = TRUE;
4343 assembly->assembly.aname.name = image->image.name;
4344 assembly->assembly.image = &image->image;
4346 mono_domain_assemblies_lock (domain);
4347 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
4348 mono_domain_assemblies_unlock (domain);
4350 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4351 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4355 calc_section_size (MonoDynamicImage *assembly)
4359 /* alignment constraints */
4360 assembly->code.index += 3;
4361 assembly->code.index &= ~3;
4362 assembly->meta_size += 3;
4363 assembly->meta_size &= ~3;
4364 assembly->resources.index += 3;
4365 assembly->resources.index &= ~3;
4367 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4368 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4371 if (assembly->win32_res) {
4372 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4374 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4375 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4379 assembly->sections [MONO_SECTION_RELOC].size = 12;
4380 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4390 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4394 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4396 ResTreeNode *t1 = (ResTreeNode*)a;
4397 ResTreeNode *t2 = (ResTreeNode*)b;
4399 return t1->id - t2->id;
4403 * resource_tree_create:
4405 * Organize the resources into a resource tree.
4407 static ResTreeNode *
4408 resource_tree_create (MonoArray *win32_resources)
4410 ResTreeNode *tree, *res_node, *type_node, *lang_node;
4414 tree = g_new0 (ResTreeNode, 1);
4416 for (i = 0; i < mono_array_length (win32_resources); ++i) {
4417 MonoReflectionWin32Resource *win32_res =
4418 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4422 lang_node = g_new0 (ResTreeNode, 1);
4423 lang_node->id = win32_res->lang_id;
4424 lang_node->win32_res = win32_res;
4426 /* Create type node if neccesary */
4428 for (l = tree->children; l; l = l->next)
4429 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4430 type_node = (ResTreeNode*)l->data;
4435 type_node = g_new0 (ResTreeNode, 1);
4436 type_node->id = win32_res->res_type;
4439 * The resource types have to be sorted otherwise
4440 * Windows Explorer can't display the version information.
4442 tree->children = g_slist_insert_sorted (tree->children,
4443 type_node, resource_tree_compare_by_id);
4446 /* Create res node if neccesary */
4448 for (l = type_node->children; l; l = l->next)
4449 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4450 res_node = (ResTreeNode*)l->data;
4455 res_node = g_new0 (ResTreeNode, 1);
4456 res_node->id = win32_res->res_id;
4457 type_node->children = g_slist_append (type_node->children, res_node);
4460 res_node->children = g_slist_append (res_node->children, lang_node);
4467 * resource_tree_encode:
4469 * Encode the resource tree into the format used in the PE file.
4472 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4475 MonoPEResourceDir dir;
4476 MonoPEResourceDirEntry dir_entry;
4477 MonoPEResourceDataEntry data_entry;
4481 * For the format of the resource directory, see the article
4482 * "An In-Depth Look into the Win32 Portable Executable File Format" by
4486 memset (&dir, 0, sizeof (dir));
4487 memset (&dir_entry, 0, sizeof (dir_entry));
4488 memset (&data_entry, 0, sizeof (data_entry));
4490 g_assert (sizeof (dir) == 16);
4491 g_assert (sizeof (dir_entry) == 8);
4492 g_assert (sizeof (data_entry) == 16);
4494 node->offset = p - begin;
4496 /* IMAGE_RESOURCE_DIRECTORY */
4497 dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4499 memcpy (p, &dir, sizeof (dir));
4502 /* Reserve space for entries */
4504 p += sizeof (dir_entry) * dir.res_id_entries;
4506 /* Write children */
4507 for (l = node->children; l; l = l->next) {
4508 ResTreeNode *child = (ResTreeNode*)l->data;
4510 if (child->win32_res) {
4512 child->offset = p - begin;
4514 /* IMAGE_RESOURCE_DATA_ENTRY */
4515 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4516 data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4518 memcpy (p, &data_entry, sizeof (data_entry));
4519 p += sizeof (data_entry);
4521 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4522 p += data_entry.rde_size;
4524 resource_tree_encode (child, begin, p, &p);
4528 /* IMAGE_RESOURCE_ENTRY */
4529 for (l = node->children; l; l = l->next) {
4530 ResTreeNode *child = (ResTreeNode*)l->data;
4531 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4533 dir_entry.is_dir = child->win32_res ? 0 : 1;
4534 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4536 memcpy (entries, &dir_entry, sizeof (dir_entry));
4537 entries += sizeof (dir_entry);
4544 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4549 MonoReflectionWin32Resource *win32_res;
4552 if (!assemblyb->win32_resources)
4556 * Resources are stored in a three level tree inside the PE file.
4557 * - level one contains a node for each type of resource
4558 * - level two contains a node for each resource
4559 * - level three contains a node for each instance of a resource for a
4560 * specific language.
4563 tree = resource_tree_create (assemblyb->win32_resources);
4565 /* Estimate the size of the encoded tree */
4567 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4568 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4569 size += mono_array_length (win32_res->res_data);
4571 /* Directory structure */
4572 size += mono_array_length (assemblyb->win32_resources) * 256;
4573 p = buf = g_malloc (size);
4575 resource_tree_encode (tree, p, p, &p);
4577 g_assert (p - buf < size);
4579 assembly->win32_res = g_malloc (p - buf);
4580 assembly->win32_res_size = p - buf;
4581 memcpy (assembly->win32_res, buf, p - buf);
4587 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4589 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4592 p += sizeof (MonoPEResourceDir);
4593 for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4594 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4595 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4596 if (dir_entry->is_dir) {
4597 fixup_resource_directory (res_section, child, rva);
4599 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4600 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4603 p += sizeof (MonoPEResourceDirEntry);
4608 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
4611 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
4612 g_error ("WriteFile returned %d\n", GetLastError ());
4616 * mono_image_create_pefile:
4617 * @mb: a module builder object
4619 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
4620 * assembly->pefile where it can be easily retrieved later in chunks.
4623 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file) {
4624 MonoMSDOSHeader *msdos;
4625 MonoDotNetHeader *header;
4626 MonoSectionTable *section;
4627 MonoCLIHeader *cli_header;
4628 guint32 size, image_size, virtual_base, text_offset;
4629 guint32 header_start, section_start, file_offset, virtual_offset;
4630 MonoDynamicImage *assembly;
4631 MonoReflectionAssemblyBuilder *assemblyb;
4632 MonoDynamicStream pefile_stream = {0};
4633 MonoDynamicStream *pefile = &pefile_stream;
4635 guint32 *rva, value;
4637 static const unsigned char msheader[] = {
4638 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4639 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4642 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4643 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4644 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4645 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4648 assemblyb = mb->assemblyb;
4650 mono_image_basic_init (assemblyb);
4651 assembly = mb->dynamic_image;
4653 assembly->pe_kind = assemblyb->pe_kind;
4654 assembly->machine = assemblyb->machine;
4655 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
4656 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
4658 mono_image_build_metadata (mb);
4660 if (mb->is_main && assemblyb->resources) {
4661 int len = mono_array_length (assemblyb->resources);
4662 for (i = 0; i < len; ++i)
4663 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4666 if (mb->resources) {
4667 int len = mono_array_length (mb->resources);
4668 for (i = 0; i < len; ++i)
4669 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4672 build_compressed_metadata (assembly);
4675 assembly_add_win32_resources (assembly, assemblyb);
4677 nsections = calc_section_size (assembly);
4679 /* The DOS header and stub */
4680 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4681 mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4683 /* the dotnet header */
4684 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4686 /* the section tables */
4687 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4689 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4690 virtual_offset = VIRT_ALIGN;
4693 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4694 if (!assembly->sections [i].size)
4697 file_offset += FILE_ALIGN - 1;
4698 file_offset &= ~(FILE_ALIGN - 1);
4699 virtual_offset += VIRT_ALIGN - 1;
4700 virtual_offset &= ~(VIRT_ALIGN - 1);
4702 assembly->sections [i].offset = file_offset;
4703 assembly->sections [i].rva = virtual_offset;
4705 file_offset += assembly->sections [i].size;
4706 virtual_offset += assembly->sections [i].size;
4707 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4710 file_offset += FILE_ALIGN - 1;
4711 file_offset &= ~(FILE_ALIGN - 1);
4713 image_size += section_start + sizeof (MonoSectionTable) * nsections;
4715 /* back-patch info */
4716 msdos = (MonoMSDOSHeader*)pefile->data;
4717 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4719 header = (MonoDotNetHeader*)(pefile->data + header_start);
4720 header->pesig [0] = 'P';
4721 header->pesig [1] = 'E';
4723 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
4724 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4725 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4726 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4727 if (assemblyb->pekind == 1) {
4729 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4732 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4735 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4737 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4738 header->pe.pe_major = 6;
4739 header->pe.pe_minor = 0;
4740 size = assembly->sections [MONO_SECTION_TEXT].size;
4741 size += FILE_ALIGN - 1;
4742 size &= ~(FILE_ALIGN - 1);
4743 header->pe.pe_code_size = GUINT32_FROM_LE(size);
4744 size = assembly->sections [MONO_SECTION_RSRC].size;
4745 size += FILE_ALIGN - 1;
4746 size &= ~(FILE_ALIGN - 1);
4747 header->pe.pe_data_size = GUINT32_FROM_LE(size);
4748 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4749 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4750 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4751 /* pe_rva_entry_point always at the beginning of the text section */
4752 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4754 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4755 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4756 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4757 header->nt.pe_os_major = GUINT16_FROM_LE (4);
4758 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4759 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4760 size = section_start;
4761 size += FILE_ALIGN - 1;
4762 size &= ~(FILE_ALIGN - 1);
4763 header->nt.pe_header_size = GUINT32_FROM_LE (size);
4765 size += VIRT_ALIGN - 1;
4766 size &= ~(VIRT_ALIGN - 1);
4767 header->nt.pe_image_size = GUINT32_FROM_LE (size);
4770 // Translate the PEFileKind value to the value expected by the Windows loader
4776 // PEFileKinds.Dll == 1
4777 // PEFileKinds.ConsoleApplication == 2
4778 // PEFileKinds.WindowApplication == 3
4781 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4782 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4784 if (assemblyb->pekind == 3)
4789 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4791 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4792 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4793 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4794 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4795 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4796 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4798 /* fill data directory entries */
4800 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4801 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4803 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4804 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4806 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4807 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4808 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4809 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4810 /* patch entrypoint name */
4811 if (assemblyb->pekind == 1)
4812 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
4814 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
4815 /* patch imported function RVA name */
4816 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4817 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4819 /* the import table */
4820 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4821 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4822 /* patch imported dll RVA name and other entries in the dir */
4823 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4824 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
4825 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4826 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4827 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4828 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4830 p = (assembly->code.data + assembly->ilt_offset);
4831 value = (assembly->text_rva + assembly->imp_names_offset);
4832 *p++ = (value) & 0xff;
4833 *p++ = (value >> 8) & (0xff);
4834 *p++ = (value >> 16) & (0xff);
4835 *p++ = (value >> 24) & (0xff);
4837 /* the CLI header info */
4838 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4839 cli_header->ch_size = GUINT32_FROM_LE (72);
4840 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4841 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
4842 if (assemblyb->entry_point) {
4843 guint32 table_idx = 0;
4844 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4845 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4846 table_idx = methodb->table_idx;
4848 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4850 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4852 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4854 /* The embedded managed resources */
4855 text_offset = assembly->text_rva + assembly->code.index;
4856 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4857 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4858 text_offset += assembly->resources.index;
4859 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4860 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4861 text_offset += assembly->meta_size;
4862 if (assembly->strong_name_size) {
4863 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4864 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4865 text_offset += assembly->strong_name_size;
4868 /* write the section tables and section content */
4869 section = (MonoSectionTable*)(pefile->data + section_start);
4870 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4871 static const char *section_names [] = {
4872 ".text", ".rsrc", ".reloc"
4874 if (!assembly->sections [i].size)
4876 strcpy (section->st_name, section_names [i]);
4877 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4878 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4879 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4880 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4881 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4882 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4883 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4887 checked_write_file (file, pefile->data, pefile->index);
4889 mono_dynamic_stream_reset (pefile);
4891 for (i = 0; i < MONO_SECTION_MAX; ++i) {
4892 if (!assembly->sections [i].size)
4895 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4896 g_error ("SetFilePointer returned %d\n", GetLastError ());
4899 case MONO_SECTION_TEXT:
4900 /* patch entry point */
4901 p = (assembly->code.data + 2);
4902 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4903 *p++ = (value) & 0xff;
4904 *p++ = (value >> 8) & 0xff;
4905 *p++ = (value >> 16) & 0xff;
4906 *p++ = (value >> 24) & 0xff;
4908 checked_write_file (file, assembly->code.data, assembly->code.index);
4909 checked_write_file (file, assembly->resources.data, assembly->resources.index);
4910 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
4911 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
4914 g_free (assembly->image.raw_metadata);
4916 case MONO_SECTION_RELOC: {
4920 guint16 type_and_offset;
4924 g_assert (sizeof (reloc) == 12);
4926 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
4927 reloc.block_size = GUINT32_FROM_LE (12);
4930 * the entrypoint is always at the start of the text section
4931 * 3 is IMAGE_REL_BASED_HIGHLOW
4932 * 2 is patch_size_rva - text_rva
4934 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
4937 checked_write_file (file, &reloc, sizeof (reloc));
4941 case MONO_SECTION_RSRC:
4942 if (assembly->win32_res) {
4944 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4945 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4946 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
4950 g_assert_not_reached ();
4954 /* check that the file is properly padded */
4955 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
4956 g_error ("SetFilePointer returned %d\n", GetLastError ());
4957 if (! SetEndOfFile (file))
4958 g_error ("SetEndOfFile returned %d\n", GetLastError ());
4960 mono_dynamic_stream_reset (&assembly->code);
4961 mono_dynamic_stream_reset (&assembly->us);
4962 mono_dynamic_stream_reset (&assembly->blob);
4963 mono_dynamic_stream_reset (&assembly->guid);
4964 mono_dynamic_stream_reset (&assembly->sheap);
4966 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
4967 g_hash_table_destroy (assembly->blob_cache);
4968 assembly->blob_cache = NULL;
4971 MonoReflectionModule *
4972 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4976 MonoImageOpenStatus status;
4977 MonoDynamicAssembly *assembly;
4978 guint32 module_count;
4979 MonoImage **new_modules;
4981 name = mono_string_to_utf8 (fileName);
4983 image = mono_image_open (name, &status);
4986 if (status == MONO_IMAGE_ERROR_ERRNO)
4987 exc = mono_get_exception_file_not_found (fileName);
4989 exc = mono_get_exception_bad_image_format (name);
4991 mono_raise_exception (exc);
4996 assembly = ab->dynamic_assembly;
4997 image->assembly = (MonoAssembly*)assembly;
4999 module_count = image->assembly->image->module_count;
5000 new_modules = g_new0 (MonoImage *, module_count + 1);
5002 if (image->assembly->image->modules)
5003 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5004 new_modules [module_count] = image;
5006 g_free (image->assembly->image->modules);
5007 image->assembly->image->modules = new_modules;
5008 image->assembly->image->module_count ++;
5010 mono_assembly_load_references (image, &status);
5012 mono_image_close (image);
5013 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5016 return mono_module_get_object (mono_domain_get (), image);
5020 * We need to return always the same object for MethodInfo, FieldInfo etc..
5021 * but we need to consider the reflected type.
5022 * type uses a different hash, since it uses custom hash/equal functions.
5027 MonoClass *refclass;
5031 reflected_equal (gconstpointer a, gconstpointer b) {
5032 const ReflectedEntry *ea = a;
5033 const ReflectedEntry *eb = b;
5035 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5039 reflected_hash (gconstpointer a) {
5040 const ReflectedEntry *ea = a;
5041 return GPOINTER_TO_UINT (ea->item);
5044 #define CHECK_OBJECT(t,p,k) \
5050 mono_domain_lock (domain); \
5051 if (!domain->refobject_hash) \
5052 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5053 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5054 mono_domain_unlock (domain); \
5057 mono_domain_unlock (domain); \
5061 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
5063 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5066 #define CACHE_OBJECT(t,p,o,k) \
5069 ReflectedEntry pe; \
5071 pe.refclass = (k); \
5072 mono_domain_lock (domain); \
5073 if (!domain->refobject_hash) \
5074 domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal); \
5075 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5077 ReflectedEntry *e = ALLOC_REFENTRY; \
5079 e->refclass = (k); \
5080 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5083 mono_domain_unlock (domain); \
5088 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
5090 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5094 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
5096 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
5100 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
5102 MonoDynamicImage *image = moduleb->dynamic_image;
5103 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
5106 MonoImage **new_modules;
5109 * FIXME: we already created an image in mono_image_basic_init (), but
5110 * we don't know which module it belongs to, since that is only
5111 * determined at assembly save time.
5113 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5114 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
5116 moduleb->module.image = &image->image;
5117 moduleb->dynamic_image = image;
5118 register_module (mono_object_domain (moduleb), moduleb, image);
5120 /* register the module with the assembly */
5121 ass = ab->dynamic_assembly->assembly.image;
5122 module_count = ass->module_count;
5123 new_modules = g_new0 (MonoImage *, module_count + 1);
5126 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
5127 new_modules [module_count] = &image->image;
5129 g_free (ass->modules);
5130 ass->modules = new_modules;
5131 ass->module_count ++;
5136 * mono_assembly_get_object:
5137 * @domain: an app domain
5138 * @assembly: an assembly
5140 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5142 MonoReflectionAssembly*
5143 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5145 static MonoClass *System_Reflection_Assembly;
5146 MonoReflectionAssembly *res;
5148 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5149 if (!System_Reflection_Assembly)
5150 System_Reflection_Assembly = mono_class_from_name (
5151 mono_defaults.corlib, "System.Reflection", "Assembly");
5152 res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5153 res->assembly = assembly;
5155 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
5160 MonoReflectionModule*
5161 mono_module_get_object (MonoDomain *domain, MonoImage *image)
5163 static MonoClass *System_Reflection_Module;
5164 MonoReflectionModule *res;
5167 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5168 if (!System_Reflection_Module)
5169 System_Reflection_Module = mono_class_from_name (
5170 mono_defaults.corlib, "System.Reflection", "Module");
5171 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5174 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5176 res->fqname = mono_string_new (domain, image->name);
5177 res->name = mono_string_new (domain, basename = g_path_get_basename (image->name));
5178 res->scopename = mono_string_new (domain, image->module_name);
5182 if (image->assembly->image == image) {
5183 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5186 g_assert (image->assembly->image->modules);
5188 for (i = 0; i < image->assembly->image->module_count; i++) {
5189 if (image->assembly->image->modules [i] == image)
5190 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5192 g_assert (res->token);
5195 mono_image_addref (image);
5197 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
5200 MonoReflectionModule*
5201 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5203 static MonoClass *System_Reflection_Module;
5204 MonoReflectionModule *res;
5205 MonoTableInfo *table;
5206 guint32 cols [MONO_FILE_SIZE];
5208 guint32 i, name_idx;
5211 if (!System_Reflection_Module)
5212 System_Reflection_Module = mono_class_from_name (
5213 mono_defaults.corlib, "System.Reflection", "Module");
5214 res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5216 table = &image->tables [MONO_TABLE_FILE];
5217 g_assert (table_index < table->rows);
5218 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5221 res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5222 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5224 /* Check whenever the row has a corresponding row in the moduleref table */
5225 table = &image->tables [MONO_TABLE_MODULEREF];
5226 for (i = 0; i < table->rows; ++i) {
5227 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5228 val = mono_metadata_string_heap (image, name_idx);
5229 if (strcmp (val, name) == 0)
5230 res->image = image->modules [i];
5233 res->fqname = mono_string_new (domain, name);
5234 res->name = mono_string_new (domain, name);
5235 res->scopename = mono_string_new (domain, name);
5236 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5237 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5243 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5245 if ((t1->type != t2->type) ||
5246 (t1->byref != t2->byref))
5250 case MONO_TYPE_VOID:
5251 case MONO_TYPE_BOOLEAN:
5252 case MONO_TYPE_CHAR:
5263 case MONO_TYPE_STRING:
5266 case MONO_TYPE_OBJECT:
5267 case MONO_TYPE_TYPEDBYREF:
5269 case MONO_TYPE_VALUETYPE:
5270 case MONO_TYPE_CLASS:
5271 case MONO_TYPE_SZARRAY:
5272 return t1->data.klass == t2->data.klass;
5274 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5275 case MONO_TYPE_ARRAY:
5276 if (t1->data.array->rank != t2->data.array->rank)
5278 return t1->data.array->eklass == t2->data.array->eklass;
5279 case MONO_TYPE_GENERICINST: {
5281 if (t1->data.generic_class->inst->type_argc != t2->data.generic_class->inst->type_argc)
5283 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
5284 &t2->data.generic_class->container_class->byval_arg))
5286 for (i = 0; i < t1->data.generic_class->inst->type_argc; ++i) {
5287 if (!mono_metadata_type_equal (t1->data.generic_class->inst->type_argv [i], t2->data.generic_class->inst->type_argv [i]))
5293 case MONO_TYPE_MVAR:
5294 return t1->data.generic_param == t2->data.generic_param;
5296 g_error ("implement type compare for %0x!", t1->type);
5304 mymono_metadata_type_hash (MonoType *t1)
5310 hash |= t1->byref << 6; /* do not collide with t1->type values */
5312 case MONO_TYPE_VALUETYPE:
5313 case MONO_TYPE_CLASS:
5314 case MONO_TYPE_SZARRAY:
5315 /* check if the distribution is good enough */
5316 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5318 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5319 case MONO_TYPE_GENERICINST: {
5321 MonoGenericInst *inst = t1->data.generic_class->inst;
5322 hash += g_str_hash (t1->data.generic_class->container_class->name);
5324 for (i = 0; i < inst->type_argc; ++i) {
5325 hash += mymono_metadata_type_hash (inst->type_argv [i]);
5334 static MonoReflectionGenericClass*
5335 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
5337 static MonoClass *System_Reflection_MonoGenericClass;
5338 MonoReflectionGenericClass *res;
5339 MonoInflatedGenericClass *gclass;
5342 if (!System_Reflection_MonoGenericClass) {
5343 System_Reflection_MonoGenericClass = mono_class_from_name (
5344 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
5345 g_assert (System_Reflection_MonoGenericClass);
5348 gclass = mono_get_inflated_generic_class (geninst->data.generic_class);
5349 gklass = gclass->generic_class.container_class;
5351 mono_class_init (gclass->klass);
5353 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
5355 res->type.type = geninst;
5356 if (gklass->wastypebuilder && gklass->reflection_info)
5357 res->generic_type = gklass->reflection_info;
5359 res->generic_type = mono_type_get_object (
5360 domain, &gclass->generic_class.container_class->byval_arg);
5366 * mono_type_get_object:
5367 * @domain: an app domain
5370 * Return an System.MonoType object representing the type @type.
5373 mono_type_get_object (MonoDomain *domain, MonoType *type)
5375 MonoReflectionType *res;
5376 MonoClass *klass = mono_class_from_mono_type (type);
5378 mono_domain_lock (domain);
5379 if (!domain->type_hash)
5380 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash,
5381 (GCompareFunc)mymono_metadata_type_equal);
5382 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5383 mono_domain_unlock (domain);
5386 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic) {
5387 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
5388 mono_g_hash_table_insert (domain->type_hash, type, res);
5389 mono_domain_unlock (domain);
5392 if (klass->reflection_info && !klass->wastypebuilder) {
5393 /* g_assert_not_reached (); */
5394 /* should this be considered an error condition? */
5396 mono_domain_unlock (domain);
5397 return klass->reflection_info;
5400 mono_class_init (klass);
5401 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5403 mono_g_hash_table_insert (domain->type_hash, type, res);
5404 mono_domain_unlock (domain);
5409 * mono_method_get_object:
5410 * @domain: an app domain
5412 * @refclass: the reflected type (can be NULL)
5414 * Return an System.Reflection.MonoMethod object representing the method @method.
5416 MonoReflectionMethod*
5417 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5420 * We use the same C representation for methods and constructors, but the type
5421 * name in C# is different.
5425 MonoReflectionMethod *ret;
5427 if (method->is_inflated) {
5428 MonoReflectionGenericMethod *gret;
5430 refclass = method->klass;
5431 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5432 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor")))
5433 cname = "MonoGenericCMethod";
5435 cname = "MonoGenericMethod";
5436 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5438 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
5439 gret->method.method = method;
5440 gret->method.name = mono_string_new (domain, method->name);
5441 gret->method.reftype = mono_type_get_object (domain, &refclass->byval_arg);
5442 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
5446 refclass = method->klass;
5448 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5449 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5450 cname = "MonoCMethod";
5452 cname = "MonoMethod";
5453 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5455 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5456 ret->method = method;
5457 ret->name = mono_string_new (domain, method->name);
5458 ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5459 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
5463 * mono_field_get_object:
5464 * @domain: an app domain
5468 * Return an System.Reflection.MonoField object representing the field @field
5471 MonoReflectionField*
5472 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5474 MonoReflectionField *res;
5477 CHECK_OBJECT (MonoReflectionField *, field, klass);
5478 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5479 res = (MonoReflectionField *)mono_object_new (domain, oklass);
5482 res->name = mono_string_new (domain, field->name);
5483 if (field->generic_info)
5484 res->attrs = field->generic_info->generic_type->attrs;
5486 res->attrs = field->type->attrs;
5487 res->type = mono_type_get_object (domain, field->type);
5488 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
5492 * mono_property_get_object:
5493 * @domain: an app domain
5495 * @property: a property
5497 * Return an System.Reflection.MonoProperty object representing the property @property
5500 MonoReflectionProperty*
5501 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5503 MonoReflectionProperty *res;
5506 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5507 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5508 res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5510 res->property = property;
5511 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
5515 * mono_event_get_object:
5516 * @domain: an app domain
5520 * Return an System.Reflection.MonoEvent object representing the event @event
5523 MonoReflectionEvent*
5524 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5526 MonoReflectionEvent *res;
5529 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5530 oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5531 res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5534 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
5538 * mono_param_get_objects:
5539 * @domain: an app domain
5542 * Return an System.Reflection.ParameterInfo array object representing the parameters
5543 * in the method @method.
5546 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5548 static MonoClass *System_Reflection_ParameterInfo;
5549 MonoArray *res = NULL;
5550 MonoReflectionMethod *member = NULL;
5551 MonoReflectionParameter *param = NULL;
5552 char **names, **blobs = NULL;
5553 guint32 *types = NULL;
5554 MonoType *type = NULL;
5555 MonoObject *dbnull = mono_get_dbnull_object (domain);
5556 MonoMarshalSpec **mspecs;
5559 if (!System_Reflection_ParameterInfo)
5560 System_Reflection_ParameterInfo = mono_class_from_name (
5561 mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5563 if (!mono_method_signature (method)->param_count)
5564 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5566 /* Note: the cache is based on the address of the signature into the method
5567 * since we already cache MethodInfos with the method as keys.
5569 CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5571 member = mono_method_get_object (domain, method, NULL);
5572 names = g_new (char *, mono_method_signature (method)->param_count);
5573 mono_method_get_param_names (method, (const char **) names);
5575 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
5576 mono_method_get_marshal_info (method, mspecs);
5578 res = mono_array_new (domain, System_Reflection_ParameterInfo, mono_method_signature (method)->param_count);
5579 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
5580 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5581 param->ClassImpl = mono_type_get_object (domain, mono_method_signature (method)->params [i]);
5582 param->MemberImpl = (MonoObject*)member;
5583 param->NameImpl = mono_string_new (domain, names [i]);
5584 param->PositionImpl = i;
5585 param->AttrsImpl = mono_method_signature (method)->params [i]->attrs;
5587 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5588 param->DefaultValueImpl = dbnull;
5592 blobs = g_new0 (char *, mono_method_signature (method)->param_count);
5593 types = g_new0 (guint32, mono_method_signature (method)->param_count);
5594 get_default_param_value_blobs (method, blobs, types);
5597 /* Build MonoType for the type from the Constant Table */
5599 type = g_new0 (MonoType, 1);
5600 type->type = types [i];
5601 type->data.klass = NULL;
5602 if (types [i] == MONO_TYPE_CLASS)
5603 type->data.klass = mono_defaults.object_class;
5605 type->data.klass = mono_class_from_mono_type (type);
5607 param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5609 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
5610 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl)
5611 param->DefaultValueImpl = dbnull;
5616 param->MarshalAsImpl = (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]);
5618 mono_array_set (res, gpointer, i, param);
5625 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
5627 mono_metadata_free_marshal_spec (mspecs [i]);
5630 CACHE_OBJECT (MonoArray *, &(method->signature), res, NULL);
5634 * mono_method_body_get_object:
5635 * @domain: an app domain
5638 * Return an System.Reflection.MethodBody object representing the method @method.
5640 MonoReflectionMethodBody*
5641 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
5643 static MonoClass *System_Reflection_MethodBody = NULL;
5644 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
5645 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
5646 MonoReflectionMethodBody *ret;
5647 MonoMethodNormal *mn;
5648 MonoMethodHeader *header;
5649 guint32 method_rva, local_var_sig_token;
5651 unsigned char format, flags;
5654 if (!System_Reflection_MethodBody)
5655 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
5656 if (!System_Reflection_LocalVariableInfo)
5657 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
5658 if (!System_Reflection_ExceptionHandlingClause)
5659 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
5661 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
5663 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
5664 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
5665 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
5666 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
5668 mn = (MonoMethodNormal *)method;
5669 header = mono_method_get_header (method);
5671 /* Obtain local vars signature token */
5672 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
5673 ptr = mono_image_rva_map (method->klass->image, method_rva);
5674 flags = *(const unsigned char *) ptr;
5675 format = flags & METHOD_HEADER_FORMAT_MASK;
5677 case METHOD_HEADER_TINY_FORMAT:
5678 case METHOD_HEADER_TINY_FORMAT1:
5679 local_var_sig_token = 0;
5681 case METHOD_HEADER_FAT_FORMAT:
5685 local_var_sig_token = read32 (ptr);
5688 g_assert_not_reached ();
5691 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
5693 ret->init_locals = header->init_locals;
5694 ret->max_stack = header->max_stack;
5695 ret->local_var_sig_token = local_var_sig_token;
5696 ret->il = mono_array_new (domain, mono_defaults.byte_class, header->code_size);
5697 memcpy (mono_array_addr (ret->il, guint8*, 0), header->code, header->code_size);
5700 ret->locals = mono_array_new (domain, System_Reflection_LocalVariableInfo, header->num_locals);
5701 for (i = 0; i < header->num_locals; ++i) {
5702 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
5703 info->local_type = mono_type_get_object (domain, header->locals [i]);
5704 info->is_pinned = header->locals [i]->pinned;
5705 info->local_index = i;
5706 mono_array_set (ret->locals, MonoReflectionLocalVariableInfo*, i, info);
5710 ret->clauses = mono_array_new (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses);
5711 for (i = 0; i < header->num_clauses; ++i) {
5712 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
5713 MonoExceptionClause *clause = &header->clauses [i];
5715 info->flags = clause->flags;
5716 info->try_offset = clause->try_offset;
5717 info->try_length = clause->try_len;
5718 info->handler_offset = clause->handler_offset;
5719 info->handler_length = clause->handler_len;
5720 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
5721 info->filter_offset = clause->data.filter_offset;
5722 else if (clause->data.catch_class)
5723 info->catch_type = mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg);
5725 mono_array_set (ret->clauses, MonoReflectionExceptionHandlingClause*, i, info);
5728 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
5733 mono_get_dbnull_object (MonoDomain *domain)
5737 static MonoClassField *dbnull_value_field = NULL;
5739 if (!dbnull_value_field) {
5740 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5741 mono_class_init (klass);
5742 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5743 g_assert (dbnull_value_field);
5745 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
5752 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
5754 guint32 param_index, i, lastp, crow = 0;
5755 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5758 MonoClass *klass = method->klass;
5759 MonoImage *image = klass->image;
5760 MonoMethodSignature *methodsig = mono_method_signature (method);
5762 MonoTableInfo *constt;
5763 MonoTableInfo *methodt;
5764 MonoTableInfo *paramt;
5766 if (!methodsig->param_count)
5769 if (klass->generic_class) {
5770 return; /* FIXME - ??? */
5773 mono_class_init (klass);
5775 if (klass->image->dynamic) {
5776 MonoReflectionMethodAux *aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
5777 if (aux && aux->param_defaults) {
5778 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
5779 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
5784 methodt = &klass->image->tables [MONO_TABLE_METHOD];
5785 paramt = &klass->image->tables [MONO_TABLE_PARAM];
5786 constt = &image->tables [MONO_TABLE_CONSTANT];
5788 idx = mono_method_get_index (method) - 1;
5789 g_assert (idx != -1);
5791 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5792 if (idx + 1 < methodt->rows)
5793 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5795 lastp = paramt->rows + 1;
5797 for (i = param_index; i < lastp; ++i) {
5800 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5801 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5803 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT)
5806 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5811 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5812 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5813 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
5820 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5825 MonoType *basetype = type;
5830 klass = mono_class_from_mono_type (type);
5831 if (klass->valuetype) {
5832 object = mono_object_new (domain, klass);
5833 retval = ((gchar *) object + sizeof (MonoObject));
5834 if (klass->enumtype)
5835 basetype = klass->enum_basetype;
5840 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
5847 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5851 memset (assembly, 0, sizeof (MonoAssemblyName));
5853 assembly->culture = "";
5854 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5856 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5859 while (g_ascii_isspace (*p) || *p == ',') {
5868 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5870 assembly->major = strtoul (p, &s, 10);
5871 if (s == p || *s != '.')
5874 assembly->minor = strtoul (p, &s, 10);
5875 if (s == p || *s != '.')
5878 assembly->build = strtoul (p, &s, 10);
5879 if (s == p || *s != '.')
5882 assembly->revision = strtoul (p, &s, 10);
5886 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5888 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5889 assembly->culture = "";
5892 assembly->culture = p;
5893 while (*p && *p != ',') {
5897 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5899 if (strncmp (p, "null", 4) == 0) {
5904 while (*p && *p != ',') {
5907 len = (p - start + 1);
5908 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5909 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5910 g_strlcpy (assembly->public_key_token, start, len);
5913 while (*p && *p != ',')
5917 while (g_ascii_isspace (*p) || *p == ',') {
5931 * mono_reflection_parse_type:
5934 * Parse a type name as accepted by the GetType () method and output the info
5935 * extracted in the info structure.
5936 * the name param will be mangled, so, make a copy before passing it to this function.
5937 * The fields in info will be valid until the memory pointed to by name is valid.
5939 * See also mono_type_get_name () below.
5941 * Returns: 0 on parse error.
5944 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
5945 MonoTypeNameParse *info)
5947 char *start, *p, *w, *temp, *last_point, *startn;
5948 int in_modifiers = 0;
5949 int isbyref = 0, rank, arity = 0, i;
5951 start = p = w = name;
5953 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5954 info->name = info->name_space = NULL;
5955 info->nested = NULL;
5956 info->modifiers = NULL;
5957 info->type_arguments = NULL;
5959 /* last_point separates the namespace from the name */
5965 *p = 0; /* NULL terminate the name */
5967 info->nested = g_list_append (info->nested, startn);
5968 /* we have parsed the nesting namespace + name */
5972 info->name_space = start;
5974 info->name = last_point + 1;
5976 info->name_space = (char *)"";
5995 i = strtol (p, &temp, 10);
6012 info->name_space = start;
6014 info->name = last_point + 1;
6016 info->name_space = (char *)"";
6023 if (isbyref) /* only one level allowed by the spec */
6026 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
6030 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
6036 info->type_arguments = g_ptr_array_new ();
6037 for (i = 0; i < arity; i++) {
6038 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
6039 gboolean fqname = FALSE;
6041 g_ptr_array_add (info->type_arguments, subinfo);
6048 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
6059 while (*p && (*p != ']'))
6067 if (g_ascii_isspace (*aname)) {
6074 !assembly_name_to_aname (&subinfo->assembly, aname))
6078 if (i + 1 < arity) {
6098 else if (*p != '*') /* '*' means unknown lower bound */
6104 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
6115 if (g_ascii_isspace (*p)) {
6122 return 0; /* missing assembly name */
6123 if (!assembly_name_to_aname (&info->assembly, p))
6129 if (info->assembly.name)
6132 // *w = 0; /* terminate class name */
6134 if (!info->name || !*info->name)
6138 /* add other consistency checks */
6143 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
6145 return _mono_reflection_parse_type (name, NULL, FALSE, info);
6149 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
6151 gboolean type_resolve = FALSE;
6154 if (info->assembly.name) {
6155 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
6157 /* then we must load the assembly ourselve - see #60439 */
6158 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
6162 image = assembly->image;
6163 } else if (!image) {
6164 image = mono_defaults.corlib;
6167 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6168 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
6169 image = mono_defaults.corlib;
6170 type = mono_reflection_get_type (image, info, ignorecase, &type_resolve);
6177 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
6184 image = mono_defaults.corlib;
6187 klass = mono_class_from_name_case (image, info->name_space, info->name);
6189 klass = mono_class_from_name (image, info->name_space, info->name);
6192 for (mod = info->nested; mod; mod = mod->next) {
6195 mono_class_init (klass);
6196 nested = klass->nested_classes;
6199 klass = nested->data;
6201 if (g_strcasecmp (klass->name, mod->data) == 0)
6204 if (strcmp (klass->name, mod->data) == 0)
6208 nested = nested->next;
6215 mono_class_init (klass);
6217 if (info->type_arguments) {
6218 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
6219 MonoReflectionType *the_type;
6223 for (i = 0; i < info->type_arguments->len; i++) {
6224 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6226 type_args [i] = _mono_reflection_get_type_from_info (subinfo, image, ignorecase);
6227 if (!type_args [i]) {
6233 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6235 instance = mono_reflection_bind_generic_parameters (
6236 the_type, info->type_arguments->len, type_args);
6243 klass = mono_class_from_mono_type (instance);
6246 for (mod = info->modifiers; mod; mod = mod->next) {
6247 modval = GPOINTER_TO_UINT (mod->data);
6248 if (!modval) { /* byref: must be last modifier */
6249 return &klass->this_arg;
6250 } else if (modval == -1) {
6251 klass = mono_ptr_class_get (&klass->byval_arg);
6252 } else { /* array rank */
6253 klass = mono_array_class_get (klass, modval);
6255 mono_class_init (klass);
6258 return &klass->byval_arg;
6262 * mono_reflection_get_type:
6263 * @image: a metadata context
6264 * @info: type description structure
6265 * @ignorecase: flag for case-insensitive string compares
6266 * @type_resolve: whenever type resolve was already tried
6268 * Build a MonoType from the type description in @info.
6273 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
6276 MonoReflectionAssembly *assembly;
6280 type = mono_reflection_get_type_internal (image, info, ignorecase);
6283 if (!mono_domain_has_type_resolve (mono_domain_get ()))
6290 *type_resolve = TRUE;
6293 /* Reconstruct the type name */
6294 fullName = g_string_new ("");
6295 if (info->name_space && (info->name_space [0] != '\0'))
6296 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
6298 g_string_printf (fullName, info->name);
6299 for (mod = info->nested; mod; mod = mod->next)
6300 g_string_append_printf (fullName, "+%s", (char*)mod->data);
6302 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
6304 if (assembly->assembly->dynamic) {
6305 /* Enumerate all modules */
6306 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
6310 if (abuilder->modules) {
6311 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
6312 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
6313 type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
6319 if (!type && abuilder->loaded_modules) {
6320 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
6321 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
6322 type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
6329 type = mono_reflection_get_type_internal (assembly->assembly->image,
6332 g_string_free (fullName, TRUE);
6337 free_type_info (MonoTypeNameParse *info)
6339 g_list_free (info->modifiers);
6340 g_list_free (info->nested);
6342 if (info->type_arguments) {
6345 for (i = 0; i < info->type_arguments->len; i++) {
6346 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
6348 free_type_info (subinfo);
6351 g_ptr_array_free (info->type_arguments, TRUE);
6356 * mono_reflection_type_from_name:
6358 * @image: a metadata context (can be NULL).
6360 * Retrieves a MonoType from its @name. If the name is not fully qualified,
6361 * it defaults to get the type from @image or, if @image is NULL or loading
6362 * from it fails, uses corlib.
6366 mono_reflection_type_from_name (char *name, MonoImage *image)
6368 MonoType *type = NULL;
6369 MonoTypeNameParse info;
6372 /* Make a copy since parse_type modifies its argument */
6373 tmp = g_strdup (name);
6375 /*g_print ("requested type %s\n", str);*/
6376 if (mono_reflection_parse_type (tmp, &info)) {
6377 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
6381 free_type_info (&info);
6386 * mono_reflection_get_token:
6388 * Return the metadata token of OBJ which should be an object
6389 * representing a metadata element.
6392 mono_reflection_get_token (MonoObject *obj)
6397 klass = obj->vtable->klass;
6399 if (strcmp (klass->name, "MethodBuilder") == 0) {
6400 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
6402 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6403 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
6404 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
6406 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
6407 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
6408 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
6409 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
6410 if (tb->generic_params) {
6411 g_assert_not_reached ();
6413 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
6415 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
6416 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
6417 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
6418 } else if (strcmp (klass->name, "MonoType") == 0) {
6419 MonoReflectionType *tb = (MonoReflectionType *)obj;
6420 token = mono_class_from_mono_type (tb->type)->type_token;
6421 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6422 strcmp (klass->name, "MonoMethod") == 0) {
6423 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6424 if (m->method->is_inflated) {
6425 g_assert_not_reached ();
6426 } else if (mono_method_signature (m->method)->generic_param_count) {
6427 g_assert_not_reached ();
6428 } else if (m->method->klass->generic_class) {
6429 g_assert_not_reached ();
6431 token = m->method->token;
6433 } else if (strcmp (klass->name, "MonoField") == 0) {
6434 MonoReflectionField *f = (MonoReflectionField*)obj;
6436 token = mono_class_get_field_token (f->field);
6437 } else if (strcmp (klass->name, "MonoProperty") == 0) {
6438 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6440 token = mono_class_get_property_token (p->property);
6441 } else if (strcmp (klass->name, "MonoEvent") == 0) {
6442 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6444 token = mono_class_get_event_token (p->event);
6445 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6446 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6448 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6449 } else if (strcmp (klass->name, "Module") == 0) {
6450 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6453 } else if (strcmp (klass->name, "Assembly") == 0) {
6454 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6456 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6457 MonoException *ex = mono_get_exception_not_implemented (msg);
6459 mono_raise_exception (ex);
6466 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6468 int slen, type = t->type;
6473 case MONO_TYPE_BOOLEAN: {
6474 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6479 case MONO_TYPE_CHAR:
6481 case MONO_TYPE_I2: {
6482 guint16 *val = g_malloc (sizeof (guint16));
6487 #if SIZEOF_VOID_P == 4
6493 case MONO_TYPE_I4: {
6494 guint32 *val = g_malloc (sizeof (guint32));
6499 #if SIZEOF_VOID_P == 8
6500 case MONO_TYPE_U: /* error out instead? this should probably not happen */
6505 case MONO_TYPE_I8: {
6506 guint64 *val = g_malloc (sizeof (guint64));
6511 case MONO_TYPE_VALUETYPE:
6512 if (t->data.klass->enumtype) {
6513 type = t->data.klass->enum_basetype->type;
6516 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6519 case MONO_TYPE_STRING:
6520 if (*p == (char)0xFF) {
6524 slen = mono_metadata_decode_value (p, &p);
6526 return mono_string_new_len (mono_domain_get (), p, slen);
6527 case MONO_TYPE_CLASS: {
6530 if (*p == (char)0xFF) {
6535 slen = mono_metadata_decode_value (p, &p);
6536 n = g_memdup (p, slen + 1);
6538 t = mono_reflection_type_from_name (n, image);
6540 g_warning ("Cannot load type '%s'", n);
6544 return mono_type_get_object (mono_domain_get (), t);
6548 case MONO_TYPE_OBJECT: {
6551 MonoClass *subc = NULL;
6556 } else if (subt == 0x0E) {
6557 type = MONO_TYPE_STRING;
6559 } else if (subt == 0x55) {
6562 slen = mono_metadata_decode_value (p, &p);
6563 n = g_memdup (p, slen + 1);
6565 t = mono_reflection_type_from_name (n, image);
6567 g_warning ("Cannot load type '%s'", n);
6570 subc = mono_class_from_mono_type (t);
6571 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6572 MonoType simple_type = {{0}};
6573 simple_type.type = subt;
6574 subc = mono_class_from_mono_type (&simple_type);
6576 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6578 val = load_cattr_value (image, &subc->byval_arg, p, end);
6579 obj = mono_object_new (mono_domain_get (), subc);
6580 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6584 case MONO_TYPE_SZARRAY: {
6586 guint32 i, alen, basetype;
6589 if (alen == 0xffffffff) {
6593 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6594 basetype = t->data.klass->byval_arg.type;
6599 case MONO_TYPE_BOOLEAN:
6600 for (i = 0; i < alen; i++) {
6601 MonoBoolean val = *p++;
6602 mono_array_set (arr, MonoBoolean, i, val);
6605 case MONO_TYPE_CHAR:
6608 for (i = 0; i < alen; i++) {
6609 guint16 val = read16 (p);
6610 mono_array_set (arr, guint16, i, val);
6617 for (i = 0; i < alen; i++) {
6618 guint32 val = read32 (p);
6619 mono_array_set (arr, guint32, i, val);
6626 for (i = 0; i < alen; i++) {
6627 guint64 val = read64 (p);
6628 mono_array_set (arr, guint64, i, val);
6632 case MONO_TYPE_CLASS:
6633 case MONO_TYPE_OBJECT:
6634 case MONO_TYPE_STRING:
6635 for (i = 0; i < alen; i++) {
6636 MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6637 mono_array_set (arr, gpointer, i, item);
6641 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6647 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6653 create_cattr_typed_arg (MonoType *t, MonoObject *val)
6655 static MonoClass *klass;
6656 static MonoMethod *ctor;
6658 void *params [2], *unboxed;
6661 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
6663 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6665 params [0] = mono_type_get_object (mono_domain_get (), t);
6667 retval = mono_object_new (mono_domain_get (), klass);
6668 unboxed = mono_object_unbox (retval);
6669 mono_runtime_invoke (ctor, unboxed, params, NULL);
6675 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
6677 static MonoClass *klass;
6678 static MonoMethod *ctor;
6680 void *unboxed, *params [2];
6683 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
6685 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
6688 params [1] = typedarg;
6689 retval = mono_object_new (mono_domain_get (), klass);
6690 unboxed = mono_object_unbox (retval);
6691 mono_runtime_invoke (ctor, unboxed, params, NULL);
6697 type_is_reference (MonoType *type)
6699 switch (type->type) {
6700 case MONO_TYPE_BOOLEAN:
6701 case MONO_TYPE_CHAR:
6714 case MONO_TYPE_VALUETYPE:
6722 free_param_data (MonoMethodSignature *sig, void **params) {
6724 for (i = 0; i < sig->param_count; ++i) {
6725 if (!type_is_reference (sig->params [i]))
6726 g_free (params [i]);
6731 * Find the field index in the metadata FieldDef table.
6734 find_field_index (MonoClass *klass, MonoClassField *field) {
6737 for (i = 0; i < klass->field.count; ++i) {
6738 if (field == &klass->fields [i])
6739 return klass->field.first + 1 + i;
6745 * Find the property index in the metadata Property table.
6748 find_property_index (MonoClass *klass, MonoProperty *property) {
6751 for (i = 0; i < klass->property.count; ++i) {
6752 if (property == &klass->properties [i])
6753 return klass->property.first + 1 + i;
6759 * Find the event index in the metadata Event table.
6762 find_event_index (MonoClass *klass, MonoEvent *event) {
6765 for (i = 0; i < klass->event.count; ++i) {
6766 if (event == &klass->events [i])
6767 return klass->event.first + 1 + i;
6773 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6775 const char *p = data;
6777 guint32 i, j, num_named;
6781 mono_class_init (method->klass);
6784 attr = mono_object_new (mono_domain_get (), method->klass);
6785 mono_runtime_invoke (method, attr, NULL, NULL);
6789 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6792 /*g_print ("got attr %s\n", method->klass->name);*/
6794 /* Allocate using alloca so it gets GC tracking */
6795 params = alloca (mono_method_signature (method)->param_count * sizeof (void*));
6799 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6800 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6804 attr = mono_object_new (mono_domain_get (), method->klass);
6805 mono_runtime_invoke (method, attr, params, NULL);
6806 free_param_data (method->signature, params);
6807 num_named = read16 (named);
6809 for (j = 0; j < num_named; j++) {
6811 gboolean is_boxed = FALSE;
6812 char *name, named_type, data_type;
6813 named_type = *named++;
6814 data_type = *named++; /* type of data */
6815 if (data_type == 0x51)
6818 if (data_type == 0x55) {
6821 type_len = mono_metadata_decode_blob_size (named, &named);
6822 type_name = g_malloc (type_len + 1);
6823 memcpy (type_name, named, type_len);
6824 type_name [type_len] = 0;
6826 /* FIXME: lookup the type and check type consistency */
6828 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6829 /* this seems to be the type of the element of the array */
6830 /* g_print ("skipping 0x%02x after prop\n", *named); */
6833 name_len = mono_metadata_decode_blob_size (named, &named);
6834 name = g_malloc (name_len + 1);
6835 memcpy (name, named, name_len);
6836 name [name_len] = 0;
6838 if (named_type == 0x53) {
6839 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6840 void *val = load_cattr_value (image, field->type, named, &named);
6841 mono_field_set_value (attr, field, val);
6842 if (!type_is_reference (field->type))
6844 } else if (named_type == 0x54) {
6847 MonoType *prop_type;
6849 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6850 /* can we have more that 1 arg in a custom attr named property? */
6851 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6852 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6853 pparams [0] = load_cattr_value (image, prop_type, named, &named);
6854 mono_property_set_value (prop, attr, pparams, NULL);
6855 if (!type_is_reference (prop_type))
6856 g_free (pparams [0]);
6865 create_custom_attr_data (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6867 MonoArray *typedargs, *namedargs;
6868 MonoClass *attrklass;
6869 static MonoClass *klass;
6870 static MonoMethod *ctor;
6873 const char *p = data;
6875 guint32 i, j, num_named;
6878 mono_class_init (method->klass);
6881 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
6883 ctor = mono_class_get_method_from_name (klass, ".ctor", 3);
6885 domain = mono_domain_get ();
6887 /* This is for Attributes with no parameters */
6888 attr = mono_object_new (domain, klass);
6889 params [0] = mono_method_get_object (domain, method, NULL);
6890 params [1] = params [2] = NULL;
6891 mono_runtime_invoke (method, attr, params, NULL);
6895 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6898 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
6902 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
6903 MonoObject *obj, *typedarg;
6906 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
6907 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
6908 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
6909 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
6910 mono_array_set (typedargs, void*, i, typedarg);
6912 if (!type_is_reference (mono_method_signature (method)->params [i]))
6917 num_named = read16 (named);
6918 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
6920 attrklass = method->klass;
6921 for (j = 0; j < num_named; j++) {
6923 char *name, named_type, data_type;
6924 named_type = *named++;
6925 data_type = *named++; /* type of data */
6926 if (data_type == 0x55) {
6929 type_len = mono_metadata_decode_blob_size (named, &named);
6930 type_name = g_malloc (type_len + 1);
6931 memcpy (type_name, named, type_len);
6932 type_name [type_len] = 0;
6934 /* FIXME: lookup the type and check type consistency */
6936 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6937 /* this seems to be the type of the element of the array */
6938 /* g_print ("skipping 0x%02x after prop\n", *named); */
6941 name_len = mono_metadata_decode_blob_size (named, &named);
6942 name = g_malloc (name_len + 1);
6943 memcpy (name, named, name_len);
6944 name [name_len] = 0;
6946 if (named_type == 0x53) {
6947 MonoObject *obj, *typedarg, *namedarg;
6948 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
6949 void *minfo, *val = load_cattr_value (image, field->type, named, &named);
6951 minfo = mono_field_get_object (domain, NULL, field);
6952 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
6953 typedarg = create_cattr_typed_arg (field->type, obj);
6954 namedarg = create_cattr_named_arg (minfo, typedarg);
6955 mono_array_set (namedargs, void*, j, namedarg);
6956 if (!type_is_reference (field->type))
6958 } else if (named_type == 0x54) {
6959 MonoObject *obj, *typedarg, *namedarg;
6960 MonoType *prop_type;
6962 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
6964 prop_type = prop->get? mono_method_signature (prop->get)->ret :
6965 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
6966 minfo = mono_property_get_object (domain, NULL, prop);
6967 val = load_cattr_value (image, prop_type, named, &named);
6968 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
6969 typedarg = create_cattr_typed_arg (prop_type, obj);
6970 namedarg = create_cattr_named_arg (minfo, typedarg);
6971 mono_array_set (namedargs, void*, j, namedarg);
6972 if (!type_is_reference (prop_type))
6977 attr = mono_object_new (domain, klass);
6978 params [0] = mono_method_get_object (domain, method, NULL);
6979 params [1] = typedargs;
6980 params [2] = namedargs;
6981 mono_runtime_invoke (ctor, attr, params, NULL);
6986 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6993 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6994 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6995 for (i = 0; i < cinfo->num_attrs; ++i) {
6996 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6997 mono_array_set (result, gpointer, i, attr);
7003 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
7006 static MonoClass *klass;
7011 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7013 result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
7014 for (i = 0; i < cinfo->num_attrs; ++i) {
7015 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
7016 mono_array_set (result, gpointer, i, attr);
7022 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
7024 guint32 mtoken, i, len;
7025 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
7027 MonoCustomAttrInfo *ainfo;
7028 GList *tmp, *list = NULL;
7031 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
7033 i = mono_metadata_custom_attrs_from_index (image, idx);
7037 while (i < ca->rows) {
7038 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
7040 list = g_list_prepend (list, GUINT_TO_POINTER (i));
7043 len = g_list_length (list);
7046 ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
7047 ainfo->num_attrs = len;
7048 ainfo->image = image;
7049 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
7050 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
7051 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
7052 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
7053 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
7054 mtoken |= MONO_TOKEN_METHOD_DEF;
7056 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
7057 mtoken |= MONO_TOKEN_MEMBER_REF;
7060 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
7063 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
7064 if (!ainfo->attrs [i].ctor)
7065 g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
7066 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
7067 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
7068 ainfo->attrs [i].data = data;
7076 mono_custom_attrs_from_method (MonoMethod *method)
7078 MonoCustomAttrInfo *cinfo;
7081 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
7083 idx = mono_method_get_index (method);
7084 idx <<= MONO_CUSTOM_ATTR_BITS;
7085 idx |= MONO_CUSTOM_ATTR_METHODDEF;
7086 return mono_custom_attrs_from_index (method->klass->image, idx);
7090 mono_custom_attrs_from_class (MonoClass *klass)
7092 MonoCustomAttrInfo *cinfo;
7095 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
7097 idx = mono_metadata_token_index (klass->type_token);
7098 idx <<= MONO_CUSTOM_ATTR_BITS;
7099 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
7100 return mono_custom_attrs_from_index (klass->image, idx);
7104 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
7106 MonoCustomAttrInfo *cinfo;
7109 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
7111 idx = 1; /* there is only one assembly */
7112 idx <<= MONO_CUSTOM_ATTR_BITS;
7113 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
7114 return mono_custom_attrs_from_index (assembly->image, idx);
7117 static MonoCustomAttrInfo*
7118 mono_custom_attrs_from_module (MonoImage *image)
7120 MonoCustomAttrInfo *cinfo;
7123 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
7125 idx = 1; /* there is only one module */
7126 idx <<= MONO_CUSTOM_ATTR_BITS;
7127 idx |= MONO_CUSTOM_ATTR_MODULE;
7128 return mono_custom_attrs_from_index (image, idx);
7132 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
7134 MonoCustomAttrInfo *cinfo;
7137 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
7139 idx = find_property_index (klass, property);
7140 idx <<= MONO_CUSTOM_ATTR_BITS;
7141 idx |= MONO_CUSTOM_ATTR_PROPERTY;
7142 return mono_custom_attrs_from_index (klass->image, idx);
7146 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
7148 MonoCustomAttrInfo *cinfo;
7151 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
7153 idx = find_event_index (klass, event);
7154 idx <<= MONO_CUSTOM_ATTR_BITS;
7155 idx |= MONO_CUSTOM_ATTR_EVENT;
7156 return mono_custom_attrs_from_index (klass->image, idx);
7160 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
7162 MonoCustomAttrInfo *cinfo;
7165 if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
7167 idx = find_field_index (klass, field);
7168 idx <<= MONO_CUSTOM_ATTR_BITS;
7169 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
7170 return mono_custom_attrs_from_index (klass->image, idx);
7174 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
7177 guint32 i, idx, method_index;
7178 guint32 param_list, param_last, param_pos, found;
7180 MonoReflectionMethodAux *aux;
7182 if (method->klass->image->dynamic) {
7183 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7184 if (!aux || !aux->param_cattr)
7186 return aux->param_cattr [param];
7189 image = method->klass->image;
7190 method_index = mono_method_get_index (method);
7191 ca = &image->tables [MONO_TABLE_METHOD];
7193 if (method->klass->generic_class || mono_method_signature (method)->generic_param_count) {
7194 /* FIXME FIXME FIXME */
7198 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
7199 if (method_index == ca->rows) {
7200 ca = &image->tables [MONO_TABLE_PARAM];
7201 param_last = ca->rows + 1;
7203 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
7204 ca = &image->tables [MONO_TABLE_PARAM];
7207 for (i = param_list; i < param_last; ++i) {
7208 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
7209 if (param_pos == param) {
7217 idx <<= MONO_CUSTOM_ATTR_BITS;
7218 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
7219 return mono_custom_attrs_from_index (image, idx);
7223 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7227 for (i = 0; i < ainfo->num_attrs; ++i) {
7228 klass = ainfo->attrs [i].ctor->klass;
7229 if (mono_class_has_parent (klass, attr_klass))
7236 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
7243 for (i = 0; i < ainfo->num_attrs; ++i) {
7244 klass = ainfo->attrs [i].ctor->klass;
7245 if (mono_class_has_parent (klass, attr_klass)) {
7250 if (attr_index == -1)
7253 attrs = mono_custom_attrs_construct (ainfo);
7255 return mono_array_get (attrs, MonoObject*, attr_index);
7261 * mono_reflection_get_custom_attrs_info:
7262 * @obj: a reflection object handle
7264 * Return the custom attribute info for attributes defined for the
7265 * reflection handle @obj. The objects.
7268 mono_reflection_get_custom_attrs_info (MonoObject *obj)
7271 MonoCustomAttrInfo *cinfo = NULL;
7273 klass = obj->vtable->klass;
7274 if (klass == mono_defaults.monotype_class) {
7275 MonoReflectionType *rtype = (MonoReflectionType*)obj;
7276 klass = mono_class_from_mono_type (rtype->type);
7277 cinfo = mono_custom_attrs_from_class (klass);
7278 } else if (strcmp ("Assembly", klass->name) == 0) {
7279 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
7280 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
7281 } else if (strcmp ("Module", klass->name) == 0) {
7282 MonoReflectionModule *module = (MonoReflectionModule*)obj;
7283 cinfo = mono_custom_attrs_from_module (module->image);
7284 } else if (strcmp ("MonoProperty", klass->name) == 0) {
7285 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
7286 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
7287 } else if (strcmp ("MonoEvent", klass->name) == 0) {
7288 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
7289 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
7290 } else if (strcmp ("MonoField", klass->name) == 0) {
7291 MonoReflectionField *rfield = (MonoReflectionField*)obj;
7292 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
7293 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
7294 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
7295 cinfo = mono_custom_attrs_from_method (rmethod->method);
7296 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
7297 MonoMethod *method = mono_get_inflated_method (((MonoReflectionMethod*)obj)->method);
7298 cinfo = mono_custom_attrs_from_method (method);
7299 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
7300 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
7301 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7302 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
7303 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
7304 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
7305 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
7306 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
7307 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7308 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
7309 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
7310 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
7311 cinfo = mono_custom_attrs_from_builders (&mb->dynamic_image->image, mb->cattrs);
7312 } else { /* handle other types here... */
7313 g_error ("get custom attrs not yet supported for %s", klass->name);
7320 * mono_reflection_get_custom_attrs:
7321 * @obj: a reflection object handle
7323 * Return an array with all the custom attributes defined of the
7324 * reflection handle @obj. The objects are fully build.
7327 mono_reflection_get_custom_attrs (MonoObject *obj)
7330 MonoCustomAttrInfo *cinfo;
7332 cinfo = mono_reflection_get_custom_attrs_info (obj);
7334 result = mono_custom_attrs_construct (cinfo);
7336 mono_custom_attrs_free (cinfo);
7339 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
7340 result = mono_array_new (mono_domain_get (), klass, 0);
7347 * mono_reflection_get_custom_attrs_data:
7348 * @obj: a reflection obj handle
7350 * Returns an array of System.Reflection.CustomAttributeData,
7351 * which include information about attributes reflected on
7352 * types loaded using the Reflection Only methods
7355 mono_reflection_get_custom_attrs_data (MonoObject *obj)
7358 MonoCustomAttrInfo *cinfo;
7360 cinfo = mono_reflection_get_custom_attrs_info (obj);
7362 result = mono_custom_attrs_data_construct (cinfo);
7364 mono_custom_attrs_free (cinfo);
7367 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
7368 result = mono_array_new (mono_domain_get (), klass, 0);
7374 static MonoMethodSignature*
7375 parameters_to_signature (MonoArray *parameters) {
7376 MonoMethodSignature *sig;
7379 count = parameters? mono_array_length (parameters): 0;
7381 sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
7382 sig->param_count = count;
7383 sig->sentinelpos = -1; /* FIXME */
7384 for (i = 0; i < count; ++i) {
7385 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
7386 sig->params [i] = pt->type;
7391 static MonoMethodSignature*
7392 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
7393 MonoMethodSignature *sig;
7395 sig = parameters_to_signature (ctor->parameters);
7396 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7397 sig->ret = &mono_defaults.void_class->byval_arg;
7401 static MonoMethodSignature*
7402 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
7403 MonoMethodSignature *sig;
7405 sig = parameters_to_signature (method->parameters);
7406 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7407 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7408 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
7412 static MonoMethodSignature*
7413 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
7414 MonoMethodSignature *sig;
7416 sig = parameters_to_signature (method->parameters);
7417 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
7418 sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
7419 sig->generic_param_count = 0;
7424 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
7426 MonoClass *klass = mono_object_class (prop);
7427 if (strcmp (klass->name, "PropertyBuilder") == 0) {
7428 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
7429 *name = mono_string_to_utf8 (pb->name);
7430 *type = pb->type->type;
7432 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
7433 *name = g_strdup (p->property->name);
7434 if (p->property->get)
7435 *type = mono_method_signature (p->property->get)->ret;
7437 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
7442 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
7444 MonoClass *klass = mono_object_class (field);
7445 if (strcmp (klass->name, "FieldBuilder") == 0) {
7446 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
7447 *name = mono_string_to_utf8 (fb->name);
7448 *type = fb->type->type;
7450 MonoReflectionField *f = (MonoReflectionField *)field;
7451 *name = g_strdup (f->field->name);
7452 *type = f->field->type;
7457 * Encode a value in a custom attribute stream of bytes.
7458 * The value to encode is either supplied as an object in argument val
7459 * (valuetypes are boxed), or as a pointer to the data in the
7461 * @type represents the type of the value
7462 * @buffer is the start of the buffer
7463 * @p the current position in the buffer
7464 * @buflen contains the size of the buffer and is used to return the new buffer size
7465 * if this needs to be realloced.
7466 * @retbuffer and @retp return the start and the position of the buffer
7469 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
7471 MonoTypeEnum simple_type;
7473 if ((p-buffer) + 10 >= *buflen) {
7476 newbuf = g_realloc (buffer, *buflen);
7477 p = newbuf + (p-buffer);
7481 argval = ((char*)arg + sizeof (MonoObject));
7482 simple_type = type->type;
7484 switch (simple_type) {
7485 case MONO_TYPE_BOOLEAN:
7490 case MONO_TYPE_CHAR:
7493 swap_with_size (p, argval, 2, 1);
7499 swap_with_size (p, argval, 4, 1);
7505 swap_with_size (p, argval, 8, 1);
7508 case MONO_TYPE_VALUETYPE:
7509 if (type->data.klass->enumtype) {
7510 simple_type = type->data.klass->enum_basetype->type;
7513 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
7516 case MONO_TYPE_STRING: {
7523 str = mono_string_to_utf8 ((MonoString*)arg);
7524 slen = strlen (str);
7525 if ((p-buffer) + 10 + slen >= *buflen) {
7529 newbuf = g_realloc (buffer, *buflen);
7530 p = newbuf + (p-buffer);
7533 mono_metadata_encode_value (slen, p, &p);
7534 memcpy (p, str, slen);
7539 case MONO_TYPE_CLASS: {
7547 k = mono_object_class (arg);
7548 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
7549 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
7550 g_error ("only types allowed, not %s.%s", k->name_space, k->name);
7552 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
7553 slen = strlen (str);
7554 if ((p-buffer) + 10 + slen >= *buflen) {
7558 newbuf = g_realloc (buffer, *buflen);
7559 p = newbuf + (p-buffer);
7562 mono_metadata_encode_value (slen, p, &p);
7563 memcpy (p, str, slen);
7568 case MONO_TYPE_SZARRAY: {
7570 MonoClass *eclass, *arg_eclass;
7573 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
7576 len = mono_array_length ((MonoArray*)arg);
7578 *p++ = (len >> 8) & 0xff;
7579 *p++ = (len >> 16) & 0xff;
7580 *p++ = (len >> 24) & 0xff;
7582 *retbuffer = buffer;
7583 eclass = type->data.klass;
7584 arg_eclass = mono_object_class (arg)->element_class;
7585 if (eclass->valuetype && arg_eclass->valuetype) {
7586 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
7587 int elsize = mono_class_array_element_size (eclass);
7588 for (i = 0; i < len; ++i) {
7589 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
7593 for (i = 0; i < len; ++i) {
7594 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
7599 /* it may be a boxed value or a Type */
7600 case MONO_TYPE_OBJECT: {
7606 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
7611 klass = mono_object_class (arg);
7613 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
7616 } else if (klass->enumtype) {
7618 } else if (klass == mono_defaults.string_class) {
7619 simple_type = MONO_TYPE_STRING;
7622 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
7623 *p++ = simple_type = klass->byval_arg.type;
7626 g_error ("unhandled type in custom attr");
7628 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
7629 slen = strlen (str);
7630 if ((p-buffer) + 10 + slen >= *buflen) {
7634 newbuf = g_realloc (buffer, *buflen);
7635 p = newbuf + (p-buffer);
7638 mono_metadata_encode_value (slen, p, &p);
7639 memcpy (p, str, slen);
7642 simple_type = klass->enum_basetype->type;
7646 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
7649 *retbuffer = buffer;
7653 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
7656 /* Preallocate a large enough buffer */
7657 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7658 char *str = type_get_qualified_name (type, NULL);
7664 len += strlen (name);
7666 if ((p-buffer) + 20 + len >= *buflen) {
7670 newbuf = g_realloc (buffer, *buflen);
7671 p = newbuf + (p-buffer);
7675 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
7676 char *str = type_get_qualified_name (type, NULL);
7677 int slen = strlen (str);
7681 * This seems to be optional...
7684 mono_metadata_encode_value (slen, p, &p);
7685 memcpy (p, str, slen);
7688 } else if (type->type == MONO_TYPE_OBJECT) {
7690 } else if (type->type == MONO_TYPE_CLASS) {
7691 /* it should be a type: encode_cattr_value () has the check */
7694 mono_metadata_encode_value (type->type, p, &p);
7695 if (type->type == MONO_TYPE_SZARRAY)
7696 mono_metadata_encode_value (type->data.klass->this_arg.type, p, &p);
7698 len = strlen (name);
7699 mono_metadata_encode_value (len, p, &p);
7700 memcpy (p, name, len);
7702 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
7704 *retbuffer = buffer;
7708 * mono_reflection_get_custom_attrs_blob:
7709 * @ctor: custom attribute constructor
7710 * @ctorArgs: arguments o the constructor
7716 * Creates the blob of data that needs to be saved in the metadata and that represents
7717 * the custom attributed described by @ctor, @ctorArgs etc.
7718 * Returns: a Byte array representing the blob of data.
7721 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
7724 MonoMethodSignature *sig;
7729 MONO_ARCH_SAVE_REGS;
7731 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
7732 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
7734 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
7736 g_assert (mono_array_length (ctorArgs) == sig->param_count);
7738 p = buffer = g_malloc (buflen);
7739 /* write the prolog */
7742 for (i = 0; i < sig->param_count; ++i) {
7743 arg = mono_array_get (ctorArgs, MonoObject*, i);
7744 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7748 i += mono_array_length (properties);
7750 i += mono_array_length (fields);
7752 *p++ = (i >> 8) & 0xff;
7755 for (i = 0; i < mono_array_length (properties); ++i) {
7759 prop = mono_array_get (properties, gpointer, i);
7760 get_prop_name_and_type (prop, &pname, &ptype);
7761 *p++ = 0x54; /* PROPERTY signature */
7762 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
7769 for (i = 0; i < mono_array_length (fields); ++i) {
7773 field = mono_array_get (fields, gpointer, i);
7774 get_field_name_and_type (field, &fname, &ftype);
7775 *p++ = 0x53; /* FIELD signature */
7776 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
7781 g_assert (p - buffer <= buflen);
7782 buflen = p - buffer;
7783 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7784 p = mono_array_addr (result, char, 0);
7785 memcpy (p, buffer, buflen);
7787 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7793 * mono_reflection_setup_internal_class:
7794 * @tb: a TypeBuilder object
7796 * Creates a MonoClass that represents the TypeBuilder.
7797 * This is a trick that lets us simplify a lot of reflection code
7798 * (and will allow us to support Build and Run assemblies easier).
7801 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7803 MonoClass *klass, *parent;
7805 MONO_ARCH_SAVE_REGS;
7807 mono_loader_lock ();
7810 /* check so we can compile corlib correctly */
7811 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7812 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7813 parent = tb->parent->type->data.klass;
7815 parent = my_mono_class_from_mono_type (tb->parent->type);
7821 /* the type has already being created: it means we just have to change the parent */
7822 if (tb->type.type) {
7823 klass = mono_class_from_mono_type (tb->type.type);
7824 klass->parent = NULL;
7825 /* fool mono_class_setup_parent */
7826 g_free (klass->supertypes);
7827 klass->supertypes = NULL;
7828 mono_class_setup_parent (klass, parent);
7829 mono_class_setup_mono_type (klass);
7830 mono_loader_unlock ();
7834 klass = g_new0 (MonoClass, 1);
7836 klass->image = &tb->module->dynamic_image->image;
7838 klass->inited = 1; /* we lie to the runtime */
7839 klass->name = mono_string_to_utf8 (tb->name);
7840 klass->name_space = mono_string_to_utf8 (tb->nspace);
7841 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7842 klass->flags = tb->attrs;
7844 klass->element_class = klass;
7845 klass->reflection_info = tb; /* need to pin. */
7847 /* Put into cache so mono_class_get () will find it */
7848 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7850 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7851 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7853 if (parent != NULL) {
7854 mono_class_setup_parent (klass, parent);
7855 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7856 const char *old_n = klass->name;
7857 /* trick to get relative numbering right when compiling corlib */
7858 klass->name = "BuildingObject";
7859 mono_class_setup_parent (klass, mono_defaults.object_class);
7860 klass->name = old_n;
7863 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7864 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7865 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7866 klass->instance_size = sizeof (MonoObject);
7867 klass->size_inited = 1;
7868 mono_class_setup_vtable_general (klass, NULL, 0);
7871 mono_class_setup_mono_type (klass);
7873 mono_class_setup_supertypes (klass);
7876 * FIXME: handle interfaces.
7879 tb->type.type = &klass->byval_arg;
7881 if (tb->nesting_type) {
7882 g_assert (tb->nesting_type->type);
7883 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7886 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7888 mono_loader_unlock ();
7892 * mono_reflection_setup_generic_class:
7893 * @tb: a TypeBuilder object
7895 * Setup the generic class before adding the first generic parameter.
7898 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7902 MONO_ARCH_SAVE_REGS;
7904 klass = my_mono_class_from_mono_type (tb->type.type);
7905 if (tb->generic_container)
7908 tb->generic_container = g_new0 (MonoGenericContainer, 1);
7909 tb->generic_container->klass = klass;
7911 tb->generic_container->context.container = tb->generic_container;
7915 * mono_reflection_create_generic_class:
7916 * @tb: a TypeBuilder object
7918 * Creates the generic class after all generic parameters have been added.
7921 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
7926 MONO_ARCH_SAVE_REGS;
7928 klass = my_mono_class_from_mono_type (tb->type.type);
7930 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7932 if (klass->generic_container || (count == 0))
7935 g_assert (tb->generic_container && (tb->generic_container->klass == klass));
7937 klass->generic_container = tb->generic_container;
7939 klass->generic_container->type_argc = count;
7940 klass->generic_container->type_params = g_new0 (MonoGenericParam, count);
7942 for (i = 0; i < count; i++) {
7943 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7944 klass->generic_container->type_params [i] = *gparam->type.type->data.generic_param;
7945 g_assert (klass->generic_container->type_params [i].owner);
7948 klass->generic_container->context.gclass = mono_get_shared_generic_class (klass->generic_container, TRUE);
7952 * mono_reflection_create_internal_class:
7953 * @tb: a TypeBuilder object
7955 * Actually create the MonoClass that is associated with the TypeBuilder.
7958 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7962 MONO_ARCH_SAVE_REGS;
7964 klass = my_mono_class_from_mono_type (tb->type.type);
7966 mono_loader_lock ();
7967 if (klass->enumtype && klass->enum_basetype == NULL) {
7968 MonoReflectionFieldBuilder *fb;
7971 g_assert (tb->fields != NULL);
7972 g_assert (mono_array_length (tb->fields) >= 1);
7974 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7976 klass->enum_basetype = fb->type->type;
7977 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7978 if (!klass->element_class)
7979 klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7982 * get the element_class from the current corlib.
7984 ec = default_class_from_mono_type (klass->enum_basetype);
7985 klass->instance_size = ec->instance_size;
7986 klass->size_inited = 1;
7988 * this is almost safe to do with enums and it's needed to be able
7989 * to create objects of the enum type (for use in SetConstant).
7991 /* FIXME: Does this mean enums can't have method overrides ? */
7992 mono_class_setup_vtable_general (klass, NULL, 0);
7994 mono_loader_unlock ();
7997 static MonoMarshalSpec*
7998 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7999 MonoReflectionMarshal *minfo)
8001 MonoMarshalSpec *res;
8003 res = g_new0 (MonoMarshalSpec, 1);
8004 res->native = minfo->type;
8006 switch (minfo->type) {
8007 case MONO_NATIVE_LPARRAY:
8008 res->data.array_data.elem_type = minfo->eltype;
8009 if (minfo->has_size) {
8010 res->data.array_data.param_num = minfo->param_num;
8011 res->data.array_data.num_elem = minfo->count;
8012 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
8015 res->data.array_data.param_num = -1;
8016 res->data.array_data.num_elem = -1;
8017 res->data.array_data.elem_mult = -1;
8021 case MONO_NATIVE_BYVALTSTR:
8022 case MONO_NATIVE_BYVALARRAY:
8023 res->data.array_data.num_elem = minfo->count;
8026 case MONO_NATIVE_CUSTOM:
8027 if (minfo->marshaltyperef)
8028 res->data.custom_data.custom_name =
8029 type_get_fully_qualified_name (minfo->marshaltyperef->type);
8031 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
8041 MonoReflectionMarshal*
8042 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
8043 MonoMarshalSpec *spec)
8045 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
8046 MonoReflectionMarshal *minfo;
8049 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
8050 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
8051 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
8052 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
8055 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
8056 minfo->type = spec->native;
8058 switch (minfo->type) {
8059 case MONO_NATIVE_LPARRAY:
8060 minfo->eltype = spec->data.array_data.elem_type;
8061 minfo->count = spec->data.array_data.num_elem;
8062 minfo->param_num = spec->data.array_data.param_num;
8065 case MONO_NATIVE_BYVALTSTR:
8066 case MONO_NATIVE_BYVALARRAY:
8067 minfo->count = spec->data.array_data.num_elem;
8070 case MONO_NATIVE_CUSTOM:
8071 if (spec->data.custom_data.custom_name) {
8072 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
8074 minfo->marshaltyperef = mono_type_get_object (domain, mtype);
8076 minfo->marshaltype = mono_string_new (domain, spec->data.custom_data.custom_name);
8078 if (spec->data.custom_data.cookie)
8079 minfo->mcookie = mono_string_new (domain, spec->data.custom_data.cookie);
8090 reflection_methodbuilder_to_mono_method (MonoClass *klass,
8091 ReflectionMethodBuilder *rmb,
8092 MonoMethodSignature *sig)
8095 MonoMethodNormal *pm;
8096 MonoMarshalSpec **specs;
8097 MonoReflectionMethodAux *method_aux;
8100 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
8101 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
8102 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
8104 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
8106 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
8108 pm = (MonoMethodNormal*)m;
8111 m->flags = rmb->attrs;
8112 m->iflags = rmb->iattrs;
8113 m->name = mono_string_to_utf8 (rmb->name);
8117 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
8119 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
8120 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
8123 m->signature->pinvoke = 1;
8124 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
8125 m->signature->pinvoke = 1;
8127 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8129 method_aux->dllentry = rmb->dllentry ? g_strdup (mono_string_to_utf8 (rmb->dllentry)) : g_strdup (m->name);
8130 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
8132 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
8134 if (klass->image->dynamic)
8135 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8138 } else if (!m->klass->dummy &&
8139 !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
8140 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
8141 MonoMethodHeader *header;
8143 gint32 max_stack, i;
8144 gint32 num_locals = 0;
8145 gint32 num_clauses = 0;
8149 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
8150 code_size = rmb->ilgen->code_len;
8151 max_stack = rmb->ilgen->max_stack;
8152 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
8153 if (rmb->ilgen->ex_handlers)
8154 num_clauses = method_count_clauses (rmb->ilgen);
8157 code = mono_array_addr (rmb->code, guint8, 0);
8158 code_size = mono_array_length (rmb->code);
8159 /* we probably need to run a verifier on the code... */
8169 header = g_malloc0 (sizeof (MonoMethodHeader) +
8170 (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
8171 header->code_size = code_size;
8172 header->code = g_malloc (code_size);
8173 memcpy ((char*)header->code, code, code_size);
8174 header->max_stack = max_stack;
8175 header->init_locals = rmb->init_locals;
8176 header->num_locals = num_locals;
8178 for (i = 0; i < num_locals; ++i) {
8179 MonoReflectionLocalBuilder *lb =
8180 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
8182 header->locals [i] = g_new0 (MonoType, 1);
8183 memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
8186 header->num_clauses = num_clauses;
8188 header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
8189 rmb->ilgen, num_clauses);
8192 pm->header = header;
8195 if (rmb->generic_params) {
8196 int count = mono_array_length (rmb->generic_params);
8197 MonoGenericContainer *container;
8199 pm->generic_container = container = rmb->generic_container;
8200 container->type_argc = count;
8201 container->type_params = g_new0 (MonoGenericParam, count);
8203 for (i = 0; i < count; i++) {
8204 MonoReflectionGenericParam *gp =
8205 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
8207 container->type_params [i] = *gp->type.type->data.generic_param;
8212 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
8216 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
8218 mw->method_data = data = g_new (gpointer, rmb->nrefs + 1);
8219 data [0] = GUINT_TO_POINTER (rmb->nrefs);
8220 for (i = 0; i < rmb->nrefs; ++i)
8221 data [i + 1] = rmb->refs [i];
8226 /* Parameter info */
8229 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8230 method_aux->param_names = g_new0 (char *, mono_method_signature (m)->param_count + 1);
8231 for (i = 0; i <= m->signature->param_count; ++i) {
8232 MonoReflectionParamBuilder *pb;
8233 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8234 if ((i > 0) && (pb->attrs)) {
8235 /* Make a copy since it might point to a shared type structure */
8236 m->signature->params [i - 1] = g_memdup (m->signature->params [i - 1], sizeof (MonoType) + ((m->signature->params [i - 1]->num_mods - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod)));
8237 m->signature->params [i - 1]->attrs = pb->attrs;
8240 if (pb->def_value) {
8241 MonoDynamicImage *assembly;
8242 guint32 idx, def_type, len;
8246 if (!method_aux->param_defaults) {
8247 method_aux->param_defaults = g_new0 (guint8*, m->signature->param_count + 1);
8248 method_aux->param_default_types = g_new0 (guint32, m->signature->param_count + 1);
8250 assembly = (MonoDynamicImage*)klass->image;
8251 idx = encode_constant (assembly, pb->def_value, &def_type);
8252 /* Copy the data from the blob since it might get realloc-ed */
8253 p = assembly->blob.data + idx;
8254 len = mono_metadata_decode_blob_size (p, &p2);
8256 method_aux->param_defaults [i] = g_malloc (len);
8257 method_aux->param_default_types [i] = def_type;
8258 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
8262 method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
8264 if (!method_aux->param_cattr)
8265 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
8266 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
8272 /* Parameter marshalling */
8275 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
8276 MonoReflectionParamBuilder *pb;
8277 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
8278 if (pb->marshal_info) {
8280 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
8281 specs [pb->position] =
8282 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
8286 if (specs != NULL) {
8288 method_aux = g_new0 (MonoReflectionMethodAux, 1);
8289 method_aux->param_marshall = specs;
8292 if (klass->image->dynamic && method_aux)
8293 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
8299 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
8301 ReflectionMethodBuilder rmb;
8302 MonoMethodSignature *sig;
8304 sig = ctor_builder_to_signature (mb);
8306 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
8308 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8309 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8311 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8312 /* ilgen is no longer needed */
8320 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
8322 ReflectionMethodBuilder rmb;
8323 MonoMethodSignature *sig;
8325 sig = method_builder_to_signature (mb);
8327 reflection_methodbuilder_from_method_builder (&rmb, mb);
8329 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
8330 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
8332 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
8333 /* ilgen is no longer needed */
8339 static MonoClassField*
8340 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
8342 MonoClassField *field;
8349 field = g_new0 (MonoClassField, 1);
8351 field->name = mono_string_to_utf8 (fb->name);
8353 /* FIXME: handle type modifiers */
8354 field->type = g_memdup (fb->type->type, sizeof (MonoType));
8355 field->type->attrs = fb->attrs;
8357 field->type = fb->type->type;
8359 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8360 field->data = mono_array_addr (fb->rva_data, char, 0);
8361 if (fb->offset != -1)
8362 field->offset = fb->offset;
8363 field->parent = klass;
8365 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8367 if (fb->def_value) {
8368 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8369 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8370 idx = encode_constant (assembly, fb->def_value, &field->def_type);
8371 /* Copy the data from the blob since it might get realloc-ed */
8372 p = assembly->blob.data + idx;
8373 len = mono_metadata_decode_blob_size (p, &p2);
8375 field->data = g_malloc (len);
8376 memcpy ((gpointer)field->data, p, len);
8383 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types,
8387 MonoReflectionTypeBuilder *tb = NULL;
8388 MonoGenericClass *gclass, *cached;
8389 MonoInflatedGenericClass *igclass;
8390 MonoDynamicGenericClass *dgclass = NULL;
8391 gboolean is_dynamic = FALSE;
8396 klass = mono_class_from_mono_type (type->type);
8397 if (!klass->generic_container && !klass->generic_class &&
8398 !(klass->nested_in && klass->nested_in->generic_container))
8401 mono_loader_lock ();
8403 domain = mono_object_domain (type);
8405 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8406 tb = (MonoReflectionTypeBuilder *) type;
8408 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8410 } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericClass")) {
8411 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
8412 MonoReflectionType *rgt = rgi->generic_type;
8414 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
8415 tb = (MonoReflectionTypeBuilder *) rgt;
8417 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8419 } else if (klass->wastypebuilder) {
8420 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8422 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
8425 icount = klass->interface_count;
8429 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8430 igclass = &dgclass->generic_class;
8431 gclass = &igclass->generic_class;
8432 gclass->is_dynamic = TRUE;
8433 gclass->is_inflated = TRUE;
8435 igclass = g_new0 (MonoInflatedGenericClass, 1);
8436 gclass = &igclass->generic_class;
8437 gclass->is_inflated = TRUE;
8440 gclass->inst = g_new0 (MonoGenericInst, 1);
8442 gclass->inst->type_argc = type_argc;
8443 gclass->inst->type_argv = types;
8444 gclass->inst->is_reference = 1;
8446 for (i = 0; i < gclass->inst->type_argc; ++i) {
8447 if (!gclass->inst->is_open)
8448 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8449 if (gclass->inst->is_reference)
8450 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8453 gclass->container_class = klass;
8455 if (klass->generic_class) {
8456 MonoGenericClass *kgclass = klass->generic_class;
8457 MonoGenericClass *ogclass = gclass;
8459 ogclass->context = g_new0 (MonoGenericContext, 1);
8460 ogclass->context->container = gclass->container_class->generic_container;
8461 ogclass->context->gclass = gclass;
8464 dgclass = g_new0 (MonoDynamicGenericClass, 1);
8465 igclass = &dgclass->generic_class;
8466 gclass = &igclass->generic_class;
8467 gclass->is_dynamic = TRUE;
8468 gclass->is_inflated = TRUE;
8470 igclass = g_new0 (MonoInflatedGenericClass, 1);
8471 gclass = &igclass->generic_class;
8472 gclass->is_inflated = TRUE;
8475 gclass->inst = g_new0 (MonoGenericInst, 1);
8477 gclass->inst->type_argc = kgclass->inst->type_argc;
8478 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8479 gclass->inst->is_reference = 1;
8481 for (i = 0; i < gclass->inst->type_argc; i++) {
8482 MonoType *t = kgclass->inst->type_argv [i];
8484 t = mono_class_inflate_generic_type (t, ogclass->context);
8486 if (!gclass->inst->is_open)
8487 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8488 if (gclass->inst->is_reference)
8489 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8491 gclass->inst->type_argv [i] = t;
8494 gclass->container_class = kgclass->container_class;
8497 geninst = g_new0 (MonoType, 1);
8498 geninst->type = MONO_TYPE_GENERICINST;
8500 cached = mono_metadata_lookup_generic_class (gclass);
8503 mono_loader_unlock ();
8504 geninst->data.generic_class = cached;
8508 geninst->data.generic_class = gclass;
8510 gclass->context = g_new0 (MonoGenericContext, 1);
8511 gclass->context->container = gclass->container_class->generic_container;
8512 gclass->context->gclass = gclass;
8515 dgclass->parent = parent;
8516 dgclass->ifaces = g_new0 (MonoType *, icount);
8517 dgclass->count_ifaces = icount;
8519 for (i = 0; i < icount; i++) {
8520 MonoReflectionType *itype;
8523 itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
8525 itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
8526 dgclass->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
8527 if (!dgclass->ifaces [i])
8528 dgclass->ifaces [i] = itype->type;
8532 mono_loader_unlock ();
8538 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
8540 MonoClass *klass, *pklass = NULL;
8541 MonoReflectionType *parent = NULL;
8542 MonoType *the_parent = NULL, *geninst;
8543 MonoReflectionTypeBuilder *tb = NULL;
8544 MonoGenericClass *gclass;
8547 domain = mono_object_domain (type);
8548 klass = mono_class_from_mono_type (type->type);
8550 if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
8551 tb = (MonoReflectionTypeBuilder *) type;
8554 parent = tb->parent;
8555 pklass = mono_class_from_mono_type (parent->type);
8557 } else if (klass->wastypebuilder) {
8558 tb = (MonoReflectionTypeBuilder *) klass->reflection_info;
8560 parent = tb->parent;
8561 pklass = mono_class_from_mono_type (parent->type);
8564 pklass = klass->parent;
8566 parent = mono_type_get_object (domain, &pklass->byval_arg);
8567 else if (klass->generic_class && klass->generic_class->is_dynamic) {
8568 MonoDynamicGenericClass *dgclass;
8570 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
8571 if (dgclass->parent) {
8572 parent = mono_type_get_object (domain, dgclass->parent);
8573 pklass = mono_class_from_mono_type (dgclass->parent);
8578 if (pklass && pklass->generic_class)
8579 the_parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
8581 geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, the_parent);
8585 gclass = geninst->data.generic_class;
8591 mono_class_bind_generic_parameters (MonoType *type, int type_argc, MonoType **types)
8594 MonoGenericClass *gclass, *cached;
8595 MonoInflatedGenericClass *igclass;
8599 klass = mono_class_from_mono_type (type);
8600 if (!klass->generic_container && !klass->generic_class &&
8601 !(klass->nested_in && klass->nested_in->generic_container))
8604 mono_loader_lock ();
8606 icount = klass->interface_count;
8608 igclass = g_new0 (MonoInflatedGenericClass, 1);
8609 gclass = &igclass->generic_class;
8610 gclass->is_inflated = TRUE;
8612 gclass->inst = g_new0 (MonoGenericInst, 1);
8613 gclass->inst->type_argc = type_argc;
8614 gclass->inst->type_argv = types;
8615 gclass->inst->is_reference = 1;
8617 for (i = 0; i < gclass->inst->type_argc; ++i) {
8618 if (!gclass->inst->is_open)
8619 gclass->inst->is_open = mono_class_is_open_constructed_type (types [i]);
8620 if (gclass->inst->is_reference)
8621 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (types [i]);
8624 gclass->container_class = klass;
8626 if (klass->generic_class) {
8627 MonoGenericClass *kgclass = klass->generic_class;
8628 MonoGenericClass *ogclass = gclass;
8630 gclass->context = g_new0 (MonoGenericContext, 1);
8631 gclass->context->container = gclass->container_class->generic_container;
8632 gclass->context->gclass = gclass;
8634 igclass = g_new0 (MonoInflatedGenericClass, 1);
8635 gclass = &igclass->generic_class;
8636 gclass->is_inflated = TRUE;
8638 gclass->inst = g_new0 (MonoGenericInst, 1);
8639 gclass->inst->type_argc = kgclass->inst->type_argc;
8640 gclass->inst->type_argv = g_new0 (MonoType *, gclass->inst->type_argc);
8641 gclass->inst->is_reference = 1;
8643 for (i = 0; i < gclass->inst->type_argc; i++) {
8644 MonoType *t = kgclass->inst->type_argv [i];
8646 t = mono_class_inflate_generic_type (t, ogclass->context);
8648 if (!gclass->inst->is_open)
8649 gclass->inst->is_open = mono_class_is_open_constructed_type (t);
8650 if (gclass->inst->is_reference)
8651 gclass->inst->is_reference = MONO_TYPE_IS_REFERENCE (t);
8653 gclass->inst->type_argv [i] = t;
8656 gclass->container_class = kgclass->container_class;
8659 geninst = g_new0 (MonoType, 1);
8660 geninst->type = MONO_TYPE_GENERICINST;
8662 cached = mono_metadata_lookup_generic_class (gclass);
8665 mono_loader_unlock ();
8666 geninst->data.generic_class = cached;
8670 geninst->data.generic_class = gclass;
8672 gclass->context = g_new0 (MonoGenericContext, 1);
8673 gclass->context->container = gclass->container_class->generic_container;
8674 gclass->context->gclass = gclass;
8676 mono_loader_unlock ();
8681 static inline MonoType*
8682 dup_type (const MonoType *original)
8684 MonoType *r = g_new0 (MonoType, 1);
8686 r->attrs = original->attrs;
8687 r->byref = original->byref;
8688 if (original->type == MONO_TYPE_PTR)
8689 r->data.type = dup_type (original->data.type);
8690 mono_stats.generics_metadata_size += sizeof (MonoType);
8694 MonoReflectionMethod*
8695 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
8697 MonoMethod *method, *inflated;
8698 MonoReflectionMethodBuilder *mb = NULL;
8699 MonoGenericContainer *container;
8700 MonoGenericMethod *gmethod;
8701 MonoGenericContext *context;
8702 MonoGenericInst *ginst;
8705 MONO_ARCH_SAVE_REGS;
8706 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
8707 MonoReflectionTypeBuilder *tb;
8710 mb = (MonoReflectionMethodBuilder *) rmethod;
8711 tb = (MonoReflectionTypeBuilder *) mb->type;
8712 klass = mono_class_from_mono_type (tb->type.type);
8714 method = methodbuilder_to_mono_method (klass, mb);
8716 method = rmethod->method;
8719 method = mono_get_inflated_method (method);
8721 count = mono_method_signature (method)->generic_param_count;
8722 if (count != mono_array_length (types))
8725 container = ((MonoMethodNormal*) method)->generic_container;
8726 g_assert (container);
8728 if (!container->method_hash)
8729 container->method_hash = g_hash_table_new (
8730 (GHashFunc) mono_metadata_generic_method_hash,
8731 (GCompareFunc) mono_metadata_generic_method_equal);
8733 ginst = g_new0 (MonoGenericInst,1 );
8734 ginst->type_argc = count;
8735 ginst->type_argv = g_new0 (MonoType *, count);
8736 ginst->is_reference = 1;
8737 for (i = 0; i < count; i++) {
8738 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
8739 ginst->type_argv [i] = dup_type (garg->type);
8741 if (!ginst->is_open)
8742 ginst->is_open = mono_class_is_open_constructed_type (ginst->type_argv [i]);
8743 if (ginst->is_reference)
8744 ginst->is_reference = MONO_TYPE_IS_REFERENCE (ginst->type_argv [i]);
8746 ginst = mono_metadata_lookup_generic_inst (ginst);
8748 gmethod = g_new0 (MonoGenericMethod, 1);
8749 gmethod->generic_class = method->klass->generic_class;
8750 gmethod->container = container;
8751 gmethod->inst = ginst;
8753 inflated = g_hash_table_lookup (container->method_hash, gmethod);
8757 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8760 gmethod->reflection_info = rmethod;
8762 context = g_new0 (MonoGenericContext, 1);
8763 context->container = container;
8764 context->gclass = method->klass->generic_class;
8765 context->gmethod = gmethod;
8767 if (method->is_inflated)
8768 method = ((MonoMethodInflated *) method)->declaring;
8770 inflated = mono_class_inflate_generic_method (method, context);
8771 g_hash_table_insert (container->method_hash, gmethod, inflated);
8773 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
8777 inflate_mono_method (MonoReflectionGenericClass *type, MonoMethod *method, MonoObject *obj)
8779 MonoGenericMethod *gmethod;
8780 MonoInflatedGenericClass *gclass;
8781 MonoGenericContext *context;
8784 gclass = mono_get_inflated_generic_class (type->type.type->data.generic_class);
8786 gmethod = g_new0 (MonoGenericMethod, 1);
8787 gmethod->generic_class = &gclass->generic_class;
8788 gmethod->inst = g_new0 (MonoGenericInst, 1);
8789 gmethod->reflection_info = obj;
8791 gmethod->inst->type_argc = mono_method_signature (method)->generic_param_count;
8792 gmethod->inst->type_argv = g_new0 (MonoType *, gmethod->inst->type_argc);
8794 for (i = 0; i < gmethod->inst->type_argc; i++) {
8795 MonoMethodNormal *mn = (MonoMethodNormal *) method;
8796 MonoGenericParam *gparam = &mn->generic_container->type_params [i];
8798 g_assert (gparam->pklass);
8799 gmethod->inst->type_argv [i] = &gparam->pklass->byval_arg;
8802 context = g_new0 (MonoGenericContext, 1);
8803 context->container = gclass->generic_class.container_class->generic_container;
8804 context->gclass = &gclass->generic_class;
8805 context->gmethod = gmethod;
8807 return mono_class_inflate_generic_method (method, context);
8811 inflate_method (MonoReflectionGenericClass *type, MonoObject *obj)
8816 klass = mono_class_from_mono_type (type->type.type);
8818 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
8819 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
8820 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
8821 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
8822 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
8823 method = ((MonoReflectionMethod *) obj)->method;
8825 method = NULL; /* prevent compiler warning */
8826 g_assert_not_reached ();
8829 return inflate_mono_method (type, method, obj);
8833 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
8834 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
8837 MonoGenericClass *gclass;
8838 MonoDynamicGenericClass *dgclass;
8839 MonoClass *klass, *gklass, *pklass;
8842 MONO_ARCH_SAVE_REGS;
8844 klass = mono_class_from_mono_type (type->type.type);
8845 gclass = type->type.type->data.generic_class;
8847 g_assert (gclass->is_dynamic);
8848 dgclass = (MonoDynamicGenericClass *) gclass;
8850 if (dgclass->initialized)
8853 gklass = gclass->container_class;
8854 mono_class_init (gklass);
8856 if (dgclass->parent)
8857 pklass = mono_class_from_mono_type (dgclass->parent);
8859 pklass = gklass->parent;
8861 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
8862 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
8863 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
8864 dgclass->count_properties = properties ? mono_array_length (properties) : 0;
8865 dgclass->count_events = events ? mono_array_length (events) : 0;
8867 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
8868 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
8869 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
8870 dgclass->properties = g_new0 (MonoProperty, dgclass->count_properties);
8871 dgclass->events = g_new0 (MonoEvent, dgclass->count_events);
8873 for (i = 0; i < dgclass->count_methods; i++) {
8874 MonoObject *obj = mono_array_get (methods, gpointer, i);
8876 dgclass->methods [i] = inflate_method (type, obj);
8879 for (i = 0; i < dgclass->count_ctors; i++) {
8880 MonoObject *obj = mono_array_get (ctors, gpointer, i);
8882 dgclass->ctors [i] = inflate_method (type, obj);
8885 for (i = 0; i < dgclass->count_fields; i++) {
8886 MonoObject *obj = mono_array_get (fields, gpointer, i);
8887 MonoClassField *field;
8888 MonoInflatedField *ifield;
8890 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
8891 field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
8892 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
8893 field = ((MonoReflectionField *) obj)->field;
8895 field = NULL; /* prevent compiler warning */
8896 g_assert_not_reached ();
8899 ifield = g_new0 (MonoInflatedField, 1);
8900 ifield->generic_type = field->type;
8901 ifield->reflection_info = obj;
8903 dgclass->fields [i] = *field;
8904 dgclass->fields [i].parent = klass;
8905 dgclass->fields [i].generic_info = ifield;
8906 dgclass->fields [i].type = mono_class_inflate_generic_type (
8907 field->type, dgclass->generic_class.generic_class.context);
8910 for (i = 0; i < dgclass->count_properties; i++) {
8911 MonoObject *obj = mono_array_get (properties, gpointer, i);
8912 MonoProperty *property = &dgclass->properties [i];
8914 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
8915 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
8917 property->parent = klass;
8918 property->attrs = pb->attrs;
8919 property->name = mono_string_to_utf8 (pb->name);
8921 property->get = inflate_method (type, (MonoObject *) pb->get_method);
8923 property->set = inflate_method (type, (MonoObject *) pb->set_method);
8924 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
8925 *property = *((MonoReflectionProperty *) obj)->property;
8928 property->get = inflate_mono_method (type, property->get, NULL);
8930 property->set = inflate_mono_method (type, property->set, NULL);
8932 g_assert_not_reached ();
8935 for (i = 0; i < dgclass->count_events; i++) {
8936 MonoObject *obj = mono_array_get (events, gpointer, i);
8937 MonoEvent *event = &dgclass->events [i];
8939 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
8940 MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
8942 event->parent = klass;
8943 event->attrs = eb->attrs;
8944 event->name = mono_string_to_utf8 (eb->name);
8946 event->add = inflate_method (type, (MonoObject *) eb->add_method);
8947 if (eb->remove_method)
8948 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
8949 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
8950 *event = *((MonoReflectionEvent *) obj)->event;
8953 event->add = inflate_mono_method (type, event->add, NULL);
8955 event->remove = inflate_mono_method (type, event->remove, NULL);
8957 g_assert_not_reached ();
8960 dgclass->initialized = TRUE;
8964 ensure_runtime_vtable (MonoClass *klass)
8966 MonoReflectionTypeBuilder *tb = klass->reflection_info;
8967 int i, num, j, onum;
8968 MonoMethod **overrides;
8970 if (!tb || klass->wastypebuilder)
8973 ensure_runtime_vtable (klass->parent);
8975 num = tb->ctors? mono_array_length (tb->ctors): 0;
8976 num += tb->num_methods;
8977 klass->method.count = num;
8978 klass->methods = g_new (MonoMethod*, num);
8979 num = tb->ctors? mono_array_length (tb->ctors): 0;
8980 for (i = 0; i < num; ++i)
8981 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
8982 num = tb->num_methods;
8984 for (i = 0; i < num; ++i)
8985 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
8987 if (tb->interfaces) {
8988 klass->interface_count = mono_array_length (tb->interfaces);
8989 klass->interfaces = g_new (MonoClass*, klass->interface_count);
8990 for (i = 0; i < klass->interface_count; ++i) {
8991 MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
8992 klass->interfaces [i] = mono_class_from_mono_type (iface->type);
8996 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
8997 for (i = 0; i < klass->method.count; ++i)
8998 klass->methods [i]->slot = i;
9000 if (!((MonoDynamicImage*)klass->image)->run)
9001 /* No need to create a generic vtable */
9007 for (i = 0; i < tb->num_methods; ++i) {
9008 MonoReflectionMethodBuilder *mb =
9009 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9010 if (mb->override_method)
9015 overrides = g_new0 (MonoMethod*, onum * 2);
9019 for (i = 0; i < tb->num_methods; ++i) {
9020 MonoReflectionMethodBuilder *mb =
9021 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
9022 if (mb->override_method) {
9023 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9024 overrides [onum * 2] =
9025 mb->override_method->method;
9026 overrides [onum * 2 + 1] =
9029 g_assert (mb->mhandle);
9036 mono_class_setup_vtable_general (klass, overrides, onum);
9041 typebuilder_setup_fields (MonoClass *klass)
9043 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9044 MonoReflectionFieldBuilder *fb;
9045 MonoClassField *field;
9050 klass->field.count = tb->num_fields;
9051 klass->field.first = 0;
9052 klass->field.last = klass->field.count;
9054 if (!klass->field.count)
9057 klass->fields = g_new0 (MonoClassField, klass->field.count);
9059 for (i = 0; i < klass->field.count; ++i) {
9060 fb = mono_array_get (tb->fields, gpointer, i);
9061 field = &klass->fields [i];
9062 field->name = mono_string_to_utf8 (fb->name);
9064 /* FIXME: handle type modifiers */
9065 field->type = g_memdup (fb->type->type, sizeof (MonoType));
9066 field->type->attrs = fb->attrs;
9068 field->type = fb->type->type;
9070 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
9071 field->data = mono_array_addr (fb->rva_data, char, 0);
9072 if (fb->offset != -1)
9073 field->offset = fb->offset;
9074 field->parent = klass;
9076 mono_save_custom_attrs (klass->image, field, fb->cattrs);
9078 if (fb->def_value) {
9079 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
9080 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
9081 idx = encode_constant (assembly, fb->def_value, &field->def_type);
9082 /* Copy the data from the blob since it might get realloc-ed */
9083 p = assembly->blob.data + idx;
9084 len = mono_metadata_decode_blob_size (p, &p2);
9086 field->data = g_malloc (len);
9087 memcpy ((gpointer)field->data, p, len);
9090 mono_class_layout_fields (klass);
9094 typebuilder_setup_properties (MonoClass *klass)
9096 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9097 MonoReflectionPropertyBuilder *pb;
9100 klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
9101 klass->property.first = 0;
9102 klass->property.last = klass->property.count;
9104 klass->properties = g_new0 (MonoProperty, klass->property.count);
9105 for (i = 0; i < klass->property.count; ++i) {
9106 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
9107 klass->properties [i].parent = klass;
9108 klass->properties [i].attrs = pb->attrs;
9109 klass->properties [i].name = mono_string_to_utf8 (pb->name);
9111 klass->properties [i].get = pb->get_method->mhandle;
9113 klass->properties [i].set = pb->set_method->mhandle;
9117 MonoReflectionEvent *
9118 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
9120 MonoEvent *event = g_new0 (MonoEvent, 1);
9124 klass = my_mono_class_from_mono_type (tb->type.type);
9126 event->parent = klass;
9127 event->attrs = eb->attrs;
9128 event->name = mono_string_to_utf8 (eb->name);
9130 event->add = eb->add_method->mhandle;
9131 if (eb->remove_method)
9132 event->remove = eb->remove_method->mhandle;
9133 if (eb->raise_method)
9134 event->raise = eb->raise_method->mhandle;
9136 if (eb->other_methods) {
9137 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9138 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9139 MonoReflectionMethodBuilder *mb =
9140 mono_array_get (eb->other_methods,
9141 MonoReflectionMethodBuilder*, j);
9142 event->other [j] = mb->mhandle;
9146 return mono_event_get_object (mono_object_domain (tb), klass, event);
9150 typebuilder_setup_events (MonoClass *klass)
9152 MonoReflectionTypeBuilder *tb = klass->reflection_info;
9153 MonoReflectionEventBuilder *eb;
9156 klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
9157 klass->event.first = 0;
9158 klass->event.last = klass->event.count;
9160 klass->events = g_new0 (MonoEvent, klass->event.count);
9161 for (i = 0; i < klass->event.count; ++i) {
9162 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
9163 klass->events [i].parent = klass;
9164 klass->events [i].attrs = eb->attrs;
9165 klass->events [i].name = mono_string_to_utf8 (eb->name);
9167 klass->events [i].add = eb->add_method->mhandle;
9168 if (eb->remove_method)
9169 klass->events [i].remove = eb->remove_method->mhandle;
9170 if (eb->raise_method)
9171 klass->events [i].raise = eb->raise_method->mhandle;
9173 if (eb->other_methods) {
9174 klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
9175 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
9176 MonoReflectionMethodBuilder *mb =
9177 mono_array_get (eb->other_methods,
9178 MonoReflectionMethodBuilder*, j);
9179 klass->events [i].other [j] = mb->mhandle;
9186 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
9190 MonoReflectionType* res;
9193 MONO_ARCH_SAVE_REGS;
9195 domain = mono_object_domain (tb);
9196 klass = my_mono_class_from_mono_type (tb->type.type);
9198 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
9201 * we need to lock the domain because the lock will be taken inside
9202 * So, we need to keep the locking order correct.
9204 mono_domain_lock (domain);
9205 mono_loader_lock ();
9206 if (klass->wastypebuilder) {
9207 mono_loader_unlock ();
9208 mono_domain_unlock (domain);
9209 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9212 * Fields to set in klass:
9213 * the various flags: delegate/unicode/contextbound etc.
9215 klass->flags = tb->attrs;
9216 klass->has_cctor = 1;
9217 klass->has_finalize = 1;
9220 if (!((MonoDynamicImage*)klass->image)->run) {
9221 if (klass->generic_container) {
9222 /* FIXME: The code below can't handle generic classes */
9223 klass->wastypebuilder = TRUE;
9224 mono_loader_unlock ();
9225 mono_domain_unlock (domain);
9226 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9231 /* enums are done right away */
9232 if (!klass->enumtype)
9233 ensure_runtime_vtable (klass);
9236 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
9237 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
9238 klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
9242 /* fields and object layout */
9243 if (klass->parent) {
9244 if (!klass->parent->size_inited)
9245 mono_class_init (klass->parent);
9246 klass->instance_size += klass->parent->instance_size;
9247 klass->class_size += klass->parent->class_size;
9248 klass->min_align = klass->parent->min_align;
9249 /* if the type has no fields we won't call the field_setup
9250 * routine which sets up klass->has_references.
9252 klass->has_references |= klass->parent->has_references;
9254 klass->instance_size = sizeof (MonoObject);
9255 klass->min_align = 1;
9258 /* FIXME: handle packing_size and instance_size */
9259 typebuilder_setup_fields (klass);
9261 typebuilder_setup_properties (klass);
9263 typebuilder_setup_events (klass);
9265 klass->wastypebuilder = TRUE;
9266 mono_loader_unlock ();
9267 mono_domain_unlock (domain);
9269 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
9270 g_assert (res != (MonoReflectionType*)tb);
9275 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
9277 MonoGenericParam *param;
9280 MONO_ARCH_SAVE_REGS;
9282 param = g_new0 (MonoGenericParam, 1);
9284 if (gparam->mbuilder) {
9285 if (!gparam->mbuilder->generic_container)
9286 gparam->mbuilder->generic_container = g_new0 (MonoGenericContainer, 1);
9287 param->owner = gparam->mbuilder->generic_container;
9288 } else if (gparam->tbuilder) {
9289 MonoReflectionTypeBuilder *nesting = (MonoReflectionTypeBuilder*) gparam->tbuilder->nesting_type;
9290 MonoGenericContainer *container = gparam->tbuilder->generic_container;
9295 count = nesting->generic_params ? mono_array_length (nesting->generic_params) : 0;
9296 if (gparam->index >= count)
9299 container = nesting->generic_container;
9300 nesting = (MonoReflectionTypeBuilder*) nesting->nesting_type;
9303 g_assert (container);
9304 param->owner = container;
9307 param->method = NULL;
9308 param->name = mono_string_to_utf8 (gparam->name);
9309 param->num = gparam->index;
9311 image = &gparam->tbuilder->module->dynamic_image->image;
9312 mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
9314 param->pklass->reflection_info = gparam;
9316 gparam->type.type = g_new0 (MonoType, 1);
9317 gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
9318 gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
9319 gparam->type.type->data.generic_param = param;
9323 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
9325 MonoDynamicImage *assembly = sig->module->dynamic_image;
9326 guint32 na = mono_array_length (sig->arguments);
9327 guint32 buflen, i, size;
9331 MONO_ARCH_SAVE_REGS;
9333 p = buf = g_malloc (size = 10 + na * 10);
9335 mono_metadata_encode_value (0x07, p, &p);
9336 mono_metadata_encode_value (na, p, &p);
9337 for (i = 0; i < na; ++i) {
9338 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9339 encode_reflection_type (assembly, type, p, &p);
9343 g_assert (buflen < size);
9344 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9345 p = mono_array_addr (result, char, 0);
9346 memcpy (p, buf, buflen);
9353 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
9355 MonoDynamicImage *assembly = sig->module->dynamic_image;
9356 guint32 na = mono_array_length (sig->arguments);
9357 guint32 buflen, i, size;
9361 MONO_ARCH_SAVE_REGS;
9363 p = buf = g_malloc (size = 10 + na * 10);
9365 mono_metadata_encode_value (0x06, p, &p);
9366 for (i = 0; i < na; ++i) {
9367 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
9368 encode_reflection_type (assembly, type, p, &p);
9372 g_assert (buflen < size);
9373 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9374 p = mono_array_addr (result, char, 0);
9375 memcpy (p, buf, buflen);
9382 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
9384 ReflectionMethodBuilder rmb;
9385 MonoMethodSignature *sig;
9388 sig = dynamic_method_to_signature (mb);
9390 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
9393 * Resolve references.
9396 * Every second entry in the refs array is reserved for storing handle_class,
9397 * which is needed by the ldtoken implementation in the JIT.
9399 rmb.nrefs = mb->nrefs;
9400 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
9401 for (i = 0; i < mb->nrefs; i += 2) {
9402 MonoClass *handle_class;
9403 gpointer ref = resolve_object (mb->module->image,
9404 mono_array_get (mb->refs, MonoObject*, i), &handle_class);
9407 mono_raise_exception (mono_get_exception_type_load (NULL));
9411 rmb.refs [i + 1] = handle_class;
9415 mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
9419 /* ilgen is no longer needed */
9424 * mono_reflection_lookup_dynamic_token:
9426 * Finish the Builder object pointed to by TOKEN and return the corresponding
9427 * runtime structure. HANDLE_CLASS is set to the class required by
9431 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, MonoClass **handle_class)
9433 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
9436 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
9439 return resolve_object (image, obj, handle_class);
9443 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class)
9445 gpointer result = NULL;
9447 if (strcmp (obj->vtable->klass->name, "String") == 0) {
9448 result = mono_string_intern ((MonoString*)obj);
9449 *handle_class = NULL;
9451 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
9452 MonoReflectionType *tb = (MonoReflectionType*)obj;
9453 result = mono_class_from_mono_type (tb->type);
9454 *handle_class = mono_defaults.typehandle_class;
9456 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
9457 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
9458 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
9459 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
9460 result = ((MonoReflectionMethod*)obj)->method;
9461 *handle_class = mono_defaults.methodhandle_class;
9463 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
9464 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9465 result = mb->mhandle;
9467 /* Type is not yet created */
9468 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
9470 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9473 * Hopefully this has been filled in by calling CreateType() on the
9477 * TODO: This won't work if the application finishes another
9478 * TypeBuilder instance instead of this one.
9480 result = mb->mhandle;
9482 *handle_class = mono_defaults.methodhandle_class;
9483 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
9484 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9486 result = cb->mhandle;
9488 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
9490 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9491 result = cb->mhandle;
9493 *handle_class = mono_defaults.methodhandle_class;
9494 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
9495 result = ((MonoReflectionField*)obj)->field;
9496 *handle_class = mono_defaults.fieldhandle_class;
9498 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
9499 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9500 result = fb->handle;
9503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
9505 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9506 result = fb->handle;
9508 *handle_class = mono_defaults.fieldhandle_class;
9509 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
9510 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9513 klass = tb->type.type->data.klass;
9514 if (klass->wastypebuilder) {
9515 /* Already created */
9519 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
9520 result = tb->type.type->data.klass;
9523 *handle_class = mono_defaults.typehandle_class;
9524 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
9525 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
9526 MonoMethodSignature *sig;
9529 if (helper->arguments)
9530 nargs = mono_array_length (helper->arguments);
9534 sig = mono_metadata_signature_alloc (image, nargs);
9535 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
9536 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
9538 if (helper->call_conv == 0) /* unmanaged */
9539 sig->call_convention = helper->unmanaged_call_conv - 1;
9541 if (helper->call_conv & 0x02)
9542 sig->call_convention = MONO_CALL_VARARG;
9544 sig->call_convention = MONO_CALL_DEFAULT;
9546 sig->param_count = nargs;
9547 /* TODO: Copy type ? */
9548 sig->ret = helper->return_type->type;
9549 for (i = 0; i < nargs; ++i) {
9550 MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
9551 sig->params [i] = rt->type;
9555 *handle_class = NULL;
9557 g_print (obj->vtable->klass->name);
9558 g_assert_not_reached ();
9564 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
9565 const static guint32 declsec_flags_map[] = {
9566 0x00000000, /* empty */
9567 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
9568 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
9569 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
9570 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
9571 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
9572 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
9573 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
9574 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
9575 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
9576 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
9577 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
9578 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
9579 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
9580 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
9581 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
9582 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
9583 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
9584 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
9588 * Returns flags that includes all available security action associated to the handle.
9589 * @token: metadata token (either for a class or a method)
9590 * @image: image where resides the metadata.
9593 mono_declsec_get_flags (MonoImage *image, guint32 token)
9595 guint32 index = mono_metadata_declsec_from_index (image, token);
9596 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
9601 for (i = index; i < t->rows; i++) {
9602 guint32 cols [MONO_DECL_SECURITY_SIZE];
9604 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9605 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9608 action = cols [MONO_DECL_SECURITY_ACTION];
9609 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
9610 result |= declsec_flags_map [action];
9612 g_assert_not_reached ();
9619 * Get the security actions (in the form of flags) associated with the specified method.
9621 * @method: The method for which we want the declarative security flags.
9622 * Return the declarative security flags for the method (only).
9624 * Note: To keep MonoMethod size down we do not cache the declarative security flags
9625 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
9628 mono_declsec_flags_from_method (MonoMethod *method)
9630 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9631 /* FIXME: No cache (for the moment) */
9632 guint32 idx = mono_method_get_index (method);
9633 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9634 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9635 return mono_declsec_get_flags (method->klass->image, idx);
9641 * Get the security actions (in the form of flags) associated with the specified class.
9643 * @klass: The class for which we want the declarative security flags.
9644 * Return the declarative security flags for the class.
9646 * Note: We cache the flags inside the MonoClass structure as this will get
9647 * called very often (at least for each method).
9650 mono_declsec_flags_from_class (MonoClass *klass)
9652 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
9653 if (!klass->declsec_flags) {
9654 guint32 idx = mono_metadata_token_index (klass->type_token);
9655 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9656 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9657 /* we cache the flags on classes */
9658 klass->declsec_flags = mono_declsec_get_flags (klass->image, idx);
9660 return klass->declsec_flags;
9666 * Get the security actions (in the form of flags) associated with the specified assembly.
9668 * @assembly: The assembly for which we want the declarative security flags.
9669 * Return the declarative security flags for the assembly.
9672 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
9674 guint32 idx = 1; /* there is only one assembly */
9675 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9676 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9677 return mono_declsec_get_flags (assembly->image, idx);
9682 * Fill actions for the specific index (which may either be an encoded class token or
9683 * an encoded method token) from the metadata image.
9684 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
9687 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
9688 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9690 MonoBoolean result = FALSE;
9692 guint32 cols [MONO_DECL_SECURITY_SIZE];
9693 int index = mono_metadata_declsec_from_index (image, token);
9696 t = &image->tables [MONO_TABLE_DECLSECURITY];
9697 for (i = index; i < t->rows; i++) {
9698 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9700 if (cols [MONO_DECL_SECURITY_PARENT] != token)
9703 /* if present only replace (class) permissions with method permissions */
9704 /* if empty accept either class or method permissions */
9705 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
9706 if (!actions->demand.blob) {
9707 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9708 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9709 actions->demand.blob = (char*) (blob + 2);
9710 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
9713 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
9714 if (!actions->noncasdemand.blob) {
9715 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9716 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9717 actions->noncasdemand.blob = (char*) (blob + 2);
9718 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
9721 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
9722 if (!actions->demandchoice.blob) {
9723 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9724 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
9725 actions->demandchoice.blob = (char*) (blob + 2);
9726 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
9736 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
9737 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9739 guint32 idx = mono_metadata_token_index (klass->type_token);
9740 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9741 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9742 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
9746 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
9747 guint32 id_std, guint32 id_noncas, guint32 id_choice)
9749 guint32 idx = mono_method_get_index (method);
9750 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9751 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9752 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
9756 * Collect all actions (that requires to generate code in mini) assigned for
9757 * the specified method.
9758 * Note: Don't use the content of actions if the function return FALSE.
9761 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
9763 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
9764 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
9765 MonoBoolean result = FALSE;
9768 /* quick exit if no declarative security is present in the metadata */
9769 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9772 /* we want the original as the wrapper is "free" of the security informations */
9773 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9774 method = mono_marshal_method_from_wrapper (method);
9779 /* First we look for method-level attributes */
9780 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9781 mono_class_init (method->klass);
9782 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9784 result = mono_declsec_get_method_demands_params (method, demands,
9785 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9788 /* Here we use (or create) the class declarative cache to look for demands */
9789 flags = mono_declsec_flags_from_class (method->klass);
9792 mono_class_init (method->klass);
9793 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9795 result |= mono_declsec_get_class_demands_params (method->klass, demands,
9796 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
9799 /* The boolean return value is used as a shortcut in case nothing needs to
9800 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
9806 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
9808 * Note: Don't use the content of actions if the function return FALSE.
9811 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
9813 MonoBoolean result = FALSE;
9816 /* quick exit if no declarative security is present in the metadata */
9817 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9820 /* we want the original as the wrapper is "free" of the security informations */
9821 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9822 method = mono_marshal_method_from_wrapper (method);
9827 /* results are independant - zeroize both */
9828 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
9829 memset (klass, 0, sizeof (MonoDeclSecurityActions));
9831 /* First we look for method-level attributes */
9832 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9833 mono_class_init (method->klass);
9835 result = mono_declsec_get_method_demands_params (method, cmethod,
9836 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9839 /* Here we use (or create) the class declarative cache to look for demands */
9840 flags = mono_declsec_flags_from_class (method->klass);
9841 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
9842 mono_class_init (method->klass);
9844 result |= mono_declsec_get_class_demands_params (method->klass, klass,
9845 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
9852 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9854 * @klass The inherited class - this is the class that provides the security check (attributes)
9856 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
9858 * Note: Don't use the content of actions if the function return FALSE.
9861 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
9863 MonoBoolean result = FALSE;
9866 /* quick exit if no declarative security is present in the metadata */
9867 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9870 /* Here we use (or create) the class declarative cache to look for demands */
9871 flags = mono_declsec_flags_from_class (klass);
9872 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
9873 mono_class_init (klass);
9874 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9876 result |= mono_declsec_get_class_demands_params (klass, demands,
9877 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9884 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
9886 * Note: Don't use the content of actions if the function return FALSE.
9889 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
9891 /* quick exit if no declarative security is present in the metadata */
9892 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
9895 /* we want the original as the wrapper is "free" of the security informations */
9896 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
9897 method = mono_marshal_method_from_wrapper (method);
9902 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9903 mono_class_init (method->klass);
9904 memset (demands, 0, sizeof (MonoDeclSecurityActions));
9906 return mono_declsec_get_method_demands_params (method, demands,
9907 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
9914 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
9916 guint32 cols [MONO_DECL_SECURITY_SIZE];
9920 int index = mono_metadata_declsec_from_index (image, token);
9924 t = &image->tables [MONO_TABLE_DECLSECURITY];
9925 for (i = index; i < t->rows; i++) {
9926 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
9928 /* shortcut - index are ordered */
9929 if (token != cols [MONO_DECL_SECURITY_PARENT])
9932 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
9933 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
9934 entry->blob = (char*) (metadata + 2);
9935 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
9944 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
9946 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
9947 guint32 idx = mono_method_get_index (method);
9948 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9949 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
9950 return get_declsec_action (method->klass->image, idx, action, entry);
9956 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
9959 guint32 flags = mono_declsec_flags_from_class (klass);
9960 if (declsec_flags_map [action] & flags) {
9961 guint32 idx = mono_metadata_token_index (klass->type_token);
9962 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9963 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
9964 return get_declsec_action (klass->image, idx, action, entry);
9970 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
9972 guint32 idx = 1; /* there is only one assembly */
9973 idx <<= MONO_HAS_DECL_SECURITY_BITS;
9974 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
9976 return get_declsec_action (assembly->image, idx, action, entry);
9980 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
9982 MonoObject *res, *exc;
9984 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
9985 static MonoMethod *method = NULL;
9987 if (!System_Reflection_Emit_TypeBuilder) {
9988 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
9989 g_assert (System_Reflection_Emit_TypeBuilder);
9991 if (method == NULL) {
9992 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
9997 * The result of mono_type_get_object () might be a System.MonoType but we
9998 * need a TypeBuilder so use klass->reflection_info.
10000 g_assert (klass->reflection_info);
10001 g_assert (!strcmp (((MonoObject*)(klass->reflection_info))->vtable->klass->name, "TypeBuilder"));
10003 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
10005 res = mono_runtime_invoke (method, (MonoObject*)(klass->reflection_info), params, &exc);
10009 return *(MonoBoolean*)mono_object_unbox (res);